#include "global.h"
#include "dungeon_pokemon_attributes.h"
#include "dungeon_util.h"
#include "dungeon_message.h"
#include "moves.h"
#include "status_checks_1.h"
#include "dungeon_ai_targeting.h"
#include "structs/str_damage.h"
#include "constants/ability.h"
#include "constants/status.h"
#include "constants/weather.h"
#include "constants/iq_skill.h"
#include "type_chart.h"
#include "position_util.h"
#include "dungeon_items.h"
#include "code_806CD90.h"
#include "move_util.h"
#include "code_808417C.h"
#include "dungeon_capabilities.h"
#include "move_effects_target.h"
#include "status.h"
#include "weather.h"
#include "code_8077274_1.h"
#include "charge_move.h"
#include "dungeon_random.h"
#include "targeting_flags.h"
#include "targeting.h"
#include "called_move_data.h"
#include "dungeon_map_access.h"
#include "math.h"
#include "code_800DAC0.h"
#include "text_util.h"
#include "dungeon_visibility.h"
#include "code_807CD9C.h"
#include "dungeon_engine.h"
#include "status_actions.h"
#include "code_8045A00.h"
#include "code_803E668.h"
#include "code_803E724.h"
#include "code_803E46C.h"
#include "code_8041AD0.h"

extern void sub_80429C8(Entity *r0);
extern bool8 sub_8045888(Entity *r0);
extern void HandleDealingDamage(Entity *attacker, Entity *target, struct DamageStruct *dmgStruct, bool32 isFalseSwipe, bool32 giveExp, s16 arg4, bool32 arg8, s32 argC);
extern void CalcDamage(Entity *, Entity *, u8, u32, u32, struct DamageStruct *dmgStruct, u32, u16, u32);
extern s16 sub_8057600(Move *move, s32 itemID);
extern void sub_803ED30(s32, Entity *r0, u8, s32);
extern void sub_8042238(Entity *pokemon, Entity *target);
extern void sub_806A1E8(Entity *pokemon);
extern bool8 sub_8044B28(void);
extern void sub_804178C(u32);
extern void sub_8071DA4(Entity *);
extern void sub_80428A0(Entity *r0);
extern bool8 sub_8040BB0(Entity *entity, Move *move, bool8);
extern void sub_8040DA0(Entity *entity, Move *move);
extern u16 sub_80412E0(u16 moveId, u8 weather, u8 a2);
extern void sub_800569C(DungeonPos *, axdata *, u8);
extern u8 GetBodySize(s16 index);
extern void sub_800EF10(u16 r0);
extern s32 sub_800E710(s16 a0, u16 a1);
extern void sub_800E3AC(s32 a0, DungeonPos *pos, s32 a2);
extern void sub_8041168(Entity *entity, Entity *entity2, Move *,DungeonPos *);
extern Entity *sub_80696A8(Entity *a0);
extern Entity *GetMonsterAtPos(DungeonPos *pos);
extern Entity *sub_80696FC(Entity *);
extern Entity *sub_806977C(Entity *);
extern void sub_806F2BC(Entity *attacker, Entity *target, u8 moveType, s32 a2, struct DamageStruct *dmgStruct);
extern void sub_806ACE8(Entity *entity, Move *move);
extern s32 sub_8057070(Move *move);
extern bool8 MoveRequiresCharging(Entity* pokemon,u16 param_2);
extern s32 sub_800ED20(u16 param_1);
extern bool32 sub_8058F04(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern void sub_8042930(Entity *r0);
extern void sub_8041B48(Entity *pokemon);
extern void sub_8041BA8(Entity *pokemon);
extern void sub_8042950(Entity *r0);
extern bool8 sub_8057634(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 YawnMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 NightmareMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805783C(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 EncoreMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8057974(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 PainSplitMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 TormentMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8057BC4(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8057C88(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 WhirlpoolMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 SurfMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805889C(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8057D7C(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8057D9C(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 SmokescreenMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8057FCC(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8057FF4(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805805C(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805816C(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_80581D0(Entity *pokemon, Entity *target, Move *move, u32 param_4);
extern bool8 sub_8058B3C(Entity *pokemon, Entity *target, Move *move, u32 param_4);
extern bool8 sub_8058270(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_80582C4(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_80583D8(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8058430(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8058478(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_80584C0(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8058548(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8058580(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 BrickBreakMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8058638(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_80586DC(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8058770(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_80587E8(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8058838(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8058858(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_80588B8(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_80588F4(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8058930(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8058C00(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8058A18(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8058BF0(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8058E5C(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8058FBC(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_80590D4(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8059190(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_80591E4(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 SkillSwapMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8059424(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805946C(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8059528(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8059540(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_80595A0(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_80595EC(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805C138(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_80598CC(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8059928(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8059988(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8059A2C(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8059AA8(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8059AB8(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8059AF8(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8059D00(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8059D48(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8059D98(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8059DA4(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8059DB4(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8059DC4(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8059E0C(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 TriAttackMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805A120(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805A210(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805A258(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805A2A0(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 RolePlayMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805A3DC(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805A464(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 CurseMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805A568(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 FocusEnergyMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 TickleMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805A688(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 KnockOffMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 SecretPowerMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805AC90(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805AD04(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805AD34(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805AD54(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805AE3C(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805AE74(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805AECC(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 PresentMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805AFA4(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805B028(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805B074(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805B0BC(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805B17C(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 WrapMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805B264(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805B324(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 DestinyBondMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805B388(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805B3E0(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805B454(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 MimicMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805B53C(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 LeechSeedMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805B668(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805B910(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805B808(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805A408(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8059050(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8059FC8(Entity * pokemon,Entity * target,Move * move,u32 param_4,u8 param_5);
extern bool8 sub_8059E54(Entity * pokemon,Entity * target,Move * move,u32 param_4,u8 param_5);
extern void SetShopkeeperAggression(Entity *, Entity *);
extern bool8 MoveCausesPaused(Move *move);
extern void sub_8069F9C(Entity *pokemon,Entity * target,Move *move);
extern void sub_806A120(Entity *pokemon,Entity * target,Move *move);
extern bool8 sub_8058C98(Entity *pokemon, Entity *target, Move *move, u32 param_4, u32 param_5);
extern bool8 sub_805B3FC(Entity *pokemon, Entity *target, Move *move, u32 param_4, u32 param_5);
extern bool8 sub_805A5E8(Entity *pokemon, Entity *target, Move *move, u32 param_4, u32 param_5);
extern bool8 sub_8058B84(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8059714(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_80576F8(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8059080(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8059D58(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805B164(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8059A18(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 BulkUpMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_80582D4(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 RageMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8059B94(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805B3B4(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8059588(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805A2B0(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805B2FC(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8059CD8(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8058A7C(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8057F7C(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8057ED0(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8058CEC(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805A2C8(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8057C68(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 SolarBeamMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 SkyAttackMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8058D38(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 SandstormMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 SafeguardMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 MistMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 LightScreenMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805768C(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8057F24(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_80599EC(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_80589D4(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8059AC4(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805A4D4(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8058EE0(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8058A08(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 CounterMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 BideMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805836C(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 TrapperOrbAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805A450(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 RazorWindMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 FocusPunchMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 MagicCoatMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8057748(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 MudWaterSportMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805A4FC(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8058C48(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 SpikesMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_80578EC(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_80588A8(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 WishMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8057E6C(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8059CF0(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_80582AC(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8058A54(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 VitalThrowMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 FlyMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8059F38(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 DiveMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 DigMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8057824(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805825C(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 GrudgeMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805A4C0(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805AAD0(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805B314(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 ProtectMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8059004(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_80597F0(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 ChargeMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8058D44(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 StockpileMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 SpitUpMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 SwallowMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 RainDanceMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 InvisifyOrbAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 MirrorCoatMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 PerishSongMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8057CD0(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 SunnyDayMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 EndureMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 HelpingHandMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 BellyDrumMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_80578FC(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8057BB4(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 TransformMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 HailMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8058234(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805A85C(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 ReboundOrbAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 NaturePowerMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 SketchMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_8057E50(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 ConversionMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 SnatchMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 HandleColorChange(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 PsychUpMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 SnoreMoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 sub_805B618(Entity *pokemon, Entity *target, Move *move, s32 param_4);
extern bool8 Conversion2MoveAction(Entity *pokemon, Entity *target, Move *move, s32 param_4);

s32 HandleDamagingMove(Entity *, Entity *, Move *, s32, s32);
static s32 TryHitTarget(Entity *attacker, Entity *target, Move *move, struct DamageStruct *dmgStruct, s16 unk);
static void TriggerTargetAbilityEffect(Entity *attacker);
static bool8 AccuracyCalc(Entity *attacker, Entity *target, Move *move, s32 accuracyType, bool8 selfAlwaysHits);
bool8 TryUseChosenMove(struct Entity *attacker, u32 r6, s32 itemId, u32 var_30, bool32 isLinkedMove, struct Move *move);
bool8 sub_8056468(Entity *entity, Move *move, const u8 *str, Entity **unkArray, bool32 itemId, bool8 arg_4, bool32 unused);
bool8 sub_805744C(Entity * pokemon, Move *move, bool8 param_3);
static void SetTargetsForMove(Entity **targetsArray, Entity *attacker, Move *move);
void sub_80566F8(Entity *attacker, Move *move, s32 a2, bool8 a3, s32 itemId, s32 isLinkedMove);
static s32 SetNewTarget(s32 targetArrId, Entity **targetsArray, s32 targetFlags_, Entity *attacker, Entity *target, Move *move, bool32 canHitAnyone_);
bool8 sub_8055988(Entity *r2, Entity *r4);
void sub_80559DC(Entity *entity1, Entity *entity2);
static void SortTargets(Entity **targetsArray, Entity *attacker);

extern const s32 gUnknown_8106A50;
extern const s32 gUnknown_8106A4C;
extern const s16 gUnknown_80F5006;
extern const s32 gUnknown_80F519C;
extern const s32 gUnknown_80F51A0;
extern const s32 gUnknown_80F50F4[2][21];
extern const s16 gUnknown_80F4E70[];
extern const s16 gUnknown_80F4E74[];
extern const u16 gUnknown_80F5004;
extern const u8 *const gUnknown_80FEEA4;
extern const u8 *const gUnknown_80FEEC8;
extern const u8 *const gUnknown_80FEEEC;
extern const u8 *const gUnknown_80FEF0C;
extern const u8 *const gUnknown_80FEF30;
extern const u8 *const gUnknown_80FEF4C;
extern const u8 *const gUnknown_80FEF50;
extern const u8 *const gUnknown_80FEF54;
extern const u8 *const gUnknown_80FEF74;
extern const u8 *const gUnknown_80FEF98;
extern const u8 *const gUnknown_80FEFD0;
extern const u8 *const gUnknown_80FECA4;
extern const u8 *const gUnknown_80F9158;
extern const u8 *const gUnknown_80FC72C;
extern const u8 *const gUnknown_80FC700;
extern const u8 *const gUnknown_80FC6D0;
extern const u8 *const gUnknown_80FC710;
extern const u8 *const gUnknown_80FC6FC;
extern const u8 *const gUnknown_80FECBC;
extern const u8 *const gUnknown_80FECE0;
extern const u8 *const gUnknown_80F9688;
extern const u8 *const gUnknown_80FC714;
extern const u8 *const gUnknown_80FC718;
extern const u8 *const gUnknown_80FC6A8;
extern const u8 *const gUnknown_80FD2D0;
extern const u8 *const gUnknown_80FD2DC;
extern const u8 *const gUnknown_80F93C8;
extern const u8 *const gUnknown_80FC690;
extern const u8 *const gUnknown_80FC6A4;
extern const u8 *const gUnknown_80FCD28;
extern const u8 *const gUnknown_80FCD0C;
extern const u8 *const gUnknown_80FDD88;
extern const u8 *const gUnknown_80FDD20;
extern const u8 *const gUnknown_80FDDA8;
extern const u8 *const gUnknown_80FDD48;
extern const u8 *const gUnknown_80FDDAC;
extern const u8 *const gUnknown_80FC52C;
extern const u8 *const gUnknown_80FC558;
extern const u8 *const gUnknown_80FC574;
extern const u8 *const gUnknown_8100524;
extern const u8 *const gUnknown_80F9364;
extern const u8 *const gUnknown_80F93A4;
extern const u8 *const gUnknown_80F9384;
extern const u8 *const gUnknown_80F9380;

extern Entity *gUnknown_203B438;

EWRAM_DATA s32 gUnknown_202F208 = 0;
EWRAM_DATA s32 gUnknown_202F20C = 0;
EWRAM_DATA s32 gUnknown_202F210 = 0;
EWRAM_DATA s32 gUnknown_202F214 = 0;
EWRAM_DATA u8 gUnknown_202F218 = 0;
EWRAM_DATA u8 gUnknown_202F219 = 0;
EWRAM_DATA u8 gUnknown_202F21A = 0;
EWRAM_DATA s32 gUnknown_202F21C = 0;
EWRAM_DATA u8 gUnknown_202F220 = 0;
EWRAM_DATA u8 gUnknown_202F221 = 0;
EWRAM_DATA u8 gUnknown_202F222 = 0;
EWRAM_DATA s32 gUnknown_202F224 = 0;
EWRAM_DATA s32 gMetronomeCalledArrayId = 0;

#define MAX_MOVE_TARGETS 64

static void UseMoveAgainstTargets(Entity **targetsArray, Entity *attacker, Move *move, s32 itemId, bool32 isLinkedMove)
{
    s32 i = 0;
    u16 moveId;
    Entity *originalAttacker;
    Entity *currTargetSaved;
    Entity *currTarget;
    EntityInfo *targetInfo;
    bool32 moveHits;
    bool32 lightRodRedirect;
    bool32 moveRedirected;

    moveId = move->id;
    for (i = 0; i < MAX_MOVE_TARGETS; i++) {
        currTargetSaved = NULL; // Only for Pass Scarf
        currTarget = targetsArray[i];
        moveHits = TRUE;
        lightRodRedirect = FALSE;
        moveRedirected = FALSE;
        if (currTarget == NULL)
            break;
        if (!EntityExists(attacker))
            break;
        if (EntityExists(currTarget)) {
            bool32 r4;
            bool8 moveHadEffect;

            originalAttacker = attacker;
            targetInfo = GetEntInfo(currTarget);
            targetInfo->unk15A = 0;
            if (CanBeSnatched(moveId) && gDungeon->snatchPokemon != NULL) {
                Entity *snatchMon = gDungeon->snatchPokemon;
                if (GetEntityType(snatchMon) == ENTITY_MONSTER
                    && snatchMon != attacker
                    &&  GetEntInfo(snatchMon)->unk98 == gDungeon->unk17B3C
                    && targetInfo->unkFF == 0)
                {
                    TryDisplayDungeonLoggableMessage3(attacker, currTarget, gUnknown_80FCD28); // The move was snatched.
                    currTarget = snatchMon;
                }
            }
            else if (GetMoveTypeForMonster(attacker, move) == TYPE_ELECTRIC && gDungeon->lightningRodPokemon != NULL) {
                Entity *lightRodMon = gDungeon->lightningRodPokemon;
                if (GetEntityType(lightRodMon) == ENTITY_MONSTER) {
                    EntityInfo *lightRodInfo = GetEntInfo(lightRodMon);
                    if (lightRodInfo->unk98 == gDungeon->unk17B38
                        && GetTreatmentBetweenMonsters(lightRodMon, attacker, TRUE, FALSE) == 1
                        && ((targetInfo->unkFF == 0 && lightRodInfo->unkFF == 0) || currTarget == lightRodMon))
                    {
                        sub_8042930(lightRodMon);
                        TryDisplayDungeonLoggableMessage3(attacker, currTarget, gUnknown_80FCD0C); // A Lightningrod took the move
                        currTarget = lightRodMon;
                        lightRodRedirect = TRUE;
                    }
                }
            }
            else if (HasHeldItem(currTarget, ITEM_PASS_SCARF)) {
                if (!CannotAttack(currTarget, FALSE)
                    && (GetMoveTargetAndRangeForPokemon(attacker, move, FALSE) & 0xF0) == 0
                    && FixedPointToInt(targetInfo->belly) >= gUnknown_80F5006
                    && targetInfo->unkFF == 0)
                {
                    s32 direction1 = targetInfo->action.direction;
                    s32 direction2 = targetInfo->action.direction;
                    if (IsBossFight()) {
                        TryDisplayDungeonLoggableMessage3(attacker, currTarget, gUnknown_80FDD88); // A mysterious force prevents moves from being passed off!
                    }
                    else {
                        s32 j;
                        Entity *tileEntity;

                        for (j = 0; j < 8; j++) {
                            direction2++;
                            direction2 &= DIRECTION_MASK;
                            tileEntity = GetTile(currTarget->pos.x + gAdjacentTileOffsets[direction2].x, currTarget->pos.y + gAdjacentTileOffsets[direction2].y)->monster;
                            if (EntityExists(tileEntity) && GetEntityType(tileEntity) == ENTITY_MONSTER) {
                                if (sub_8045888(currTarget)) {
                                    s32 k;
                                    for (k = 0; k < 24; k++) {
                                        sub_806CE68(currTarget, direction1);
                                        sub_803E708(2, 0x43);
                                        direction1++;
                                        direction1 &= DIRECTION_MASK;
                                    }
                                    while (direction1 != direction2) {
                                        sub_806CE68(currTarget, direction1);
                                        sub_803E708(2, 0x43);
                                        direction1++;
                                        direction1 &= DIRECTION_MASK;
                                    }
                                    sub_806CE68(currTarget, direction1);
                                    sub_803E708(2, 0x43);
                                }
                                targetInfo->belly = FixedPoint_Subtract(targetInfo->belly, IntToFixedPoint(gUnknown_80F5006));
                                if (move->id == MOVE_REGULAR_ATTACK) {
                                    TryDisplayDungeonLoggableMessage3(attacker, currTarget, gUnknown_80FDDA8); // Attack was passed off
                                }
                                else {
                                    TryDisplayDungeonLoggableMessage3(attacker, currTarget, gUnknown_80FDD20); // Move was passed off
                                }
                                currTargetSaved = currTarget;
                                currTarget = tileEntity;
                                break;
                            }
                        }
                        if (j == 8) {
                            if (move->id == MOVE_REGULAR_ATTACK) {
                                TryDisplayDungeonLoggableMessage3(attacker, currTarget, gUnknown_80FDDAC); // There's no one to pass off to!
                            }
                            else {
                                TryDisplayDungeonLoggableMessage3(attacker, currTarget, gUnknown_80FDD48); //There's no one to pass off to!
                            }
                        }
                    }
                }
            }

            gUnknown_202F208++;
            gUnknown_202F20C++;
            targetInfo = GetEntInfo(currTarget); // currTarget could've been changed, hence info pointers needs to be reloaded
            targetInfo->unk15A = 0;
            if (targetInfo->isNotTeamMember) {
                targetInfo->targetPos = attacker->pos;
            }
            sub_806A1E8(currTarget);
            TrySendImmobilizeSleepEndMsg(attacker, currTarget);
            r4 = FALSE;
            if (!MoveMatchesBideClassStatus(attacker, move)) {
                r4 = (MoveRequiresCharging(attacker, move->id) != 0);
            }

            if (!lightRodRedirect) {
                if (targetInfo->reflectClassStatus.status == STATUS_MAGIC_COAT) {
                    if (IsReflectedByMagicCoat(moveId) && sub_8055988(attacker, currTarget)) {
                        TryDisplayDungeonLoggableMessage3(attacker, currTarget, gUnknown_80FC52C); // The target~27s Magic Coat bounced it back!
                        sub_8041B48(currTarget);
                        sub_80559DC(currTarget, attacker);
                        currTarget = attacker;
                        targetInfo = GetEntInfo(attacker);
                        targetInfo->unk15A = 0;
                        moveRedirected = TRUE;
                    }
                }
                else if (targetInfo->reflectClassStatus.status == STATUS_MIRROR_MOVE) {
                    s32 target = GetMoveTargetAndRangeForPokemon(attacker, move, FALSE);
                    if (moveId != MOVE_REGULAR_ATTACK
                        && moveId != MOVE_PROJECTILE
                        && !r4
                        && ((target & 0xF) == 0 || (target & 0xF) == 4 || (target & 0xF) == 5 || (target & 0xF) == 2)
                        && sub_8055988(attacker, currTarget))
                    {
                        TryDisplayDungeonLoggableMessage3(attacker, currTarget, gUnknown_80FC558); // The target~27s Mirror Move returned it!
                        sub_8041BA8(currTarget);
                        sub_80559DC(currTarget, attacker);
                        currTarget = attacker;
                        targetInfo = GetEntInfo(attacker);
                        targetInfo->unk15A = 0;
                        moveRedirected = TRUE;
                    }
                }
            }
            if (!lightRodRedirect) {
                if (targetInfo->reflectClassStatus.status == STATUS_PROTECT) {
                    s16 targetFlags = GetMoveTargetAndRangeForPokemon(attacker, move, FALSE);
                    s32 targetFlagsAnd = targetFlags & 0xF;
                    if ((targetFlagsAnd == 0 || targetFlagsAnd == 4 || targetFlagsAnd == 5 || targetFlagsAnd == 2) && !r4) {
                        SubstitutePlaceholderStringTags(gFormatBuffer_Monsters[1], currTarget, 0);
                        TryDisplayDungeonLoggableMessage3(attacker, currTarget, gUnknown_80FC574); // protected itself!
                        moveHits = FALSE;
                    }
                }
            }

            if (sub_80571F0(currTarget, move)) {
                moveHits = FALSE;
            }

            if (moveHits) {
                if (HasAbility(currTarget, ABILITY_SOUNDPROOF) && IsSoundMove(move)) {
                    SubstitutePlaceholderStringTags(gFormatBuffer_Monsters[1], currTarget, 0);
                    TryDisplayDungeonLoggableMessage3(attacker, currTarget, gUnknown_8100524); // Soundproof suppressed the sound move!
                    moveHits = FALSE;
                }
            }
            if (moveHits) {
                bool8 selfAlwaysHits = (moveRedirected == FALSE);
                if (move->id == MOVE_ENDURE || move->id == MOVE_DETECT || move->id == MOVE_PROTECT) {
                    selfAlwaysHits = FALSE;
                }
                if (!AccuracyCalc(attacker, currTarget, move, ACCURACY_1, selfAlwaysHits)) {
                    moveHits = FALSE;
                }
            }

            if (moveHits && lightRodRedirect) {
                moveHits = FALSE;
            }

            if (sub_8045888(currTarget)) {
                sub_803E708(4, 0x4A);
                sub_8041168(attacker, currTarget, move, NULL);
            }

            if (!moveHits) {
                if (GetEntInfo(attacker)->isTeamLeader) {
                    sub_80421C0(attacker, 0x156);
                }
                else {
                    sub_80421C0(attacker, 0x157);
                }
                SetMessageArgument_2(gFormatBuffer_Monsters[1], GetEntInfo(currTarget), 0);
                // Interesting that these 3 strings are the same. Curious if that's the case in Blue/Europe versions.
                if (attacker == currTarget) {
                    TryDisplayDungeonLoggableMessage3(attacker, attacker, gUnknown_80F9380); // The move missed
                }
                else if (GetTreatmentBetweenMonsters(attacker, currTarget, TRUE, FALSE) == 0) {
                    TryDisplayDungeonLoggableMessage3(attacker, currTarget, gUnknown_80F9384); // The move missed
                }
                else if (lightRodRedirect) {
                    TryDisplayDungeonLoggableMessage3(attacker, currTarget, gUnknown_80F93A4); // The move missed
                }
                else {
                    TryDisplayDungeonLoggableMessage3(attacker, currTarget, gUnknown_80F9364); // is unaffected!
                }

                if (sub_8045888(currTarget)) {
                    sub_803ED30(9999, currTarget, 1, -1);
                }

                switch (moveId) {
                    case MOVE_HI_JUMP_KICK:
                        sub_8059FC8(attacker, currTarget, move, itemId, 1);
                        break;
                    case MOVE_JUMP_KICK:
                        sub_8059E54(attacker, currTarget, move, itemId, 1);
                        break;
                }

                if (sub_8044B28())
                    break; // breaks out of the loop
            }
            else {
                s32 expMultiplierBeforeMove = targetInfo->expMultiplier;
                if (targetInfo->isNotTeamMember) {
                    if (move->id != MOVE_REGULAR_ATTACK && itemId == 0 && expMultiplierBeforeMove == EXP_HALVED) {
                        targetInfo->expMultiplier = EXP_REGULAR;
                    }
                    if (isLinkedMove == TRUE) {
                        targetInfo->expMultiplier = EXP_BOOSTED;
                    }
                }

                if (targetInfo->unk164 == 0xFF && sub_80717A4(currTarget, MOVE_SLEEP_TALK)) {
                    targetInfo->unk164 = GetDirectionTowardsPosition(&currTarget->pos, &attacker->pos);
                }
                if (targetInfo->unk165 == 0xFF && sub_80717A4(currTarget, MOVE_SNORE)) {
                    targetInfo->unk165 = GetDirectionTowardsPosition(&currTarget->pos, &attacker->pos);
                }

                if (HasAbility(currTarget, ABILITY_PRESSURE)
                    && GetTreatmentBetweenMonsters(attacker, currTarget, TRUE, FALSE) == 1
                    && move->id != MOVE_REGULAR_ATTACK
                    && move->id != MOVE_STRUGGLE
                    && itemId == 0
                    && move->PP != 0)
                {
                    if (!(move->moveFlags2 & MOVE_FLAG2_x10)) {
                        sub_8042950(attacker);
                    }
                    move->moveFlags2 |= MOVE_FLAG2_x10;
                }

                if ((GetMoveTargetAndRangeForPokemon(attacker, move, FALSE) & 0xF) == 0) {
                    SetShopkeeperAggression(attacker, currTarget);
                }
                targetInfo->unk158 = 1;

                // They really must've had a soft spot for all these giant switches
                switch (moveId) {
                    case MOVE_THRASH:
                    case MOVE_CUT:
                    case MOVE_ROCK_THROW:
                    case MOVE_DOUBLESLAP:
                    case MOVE_SHADOW_PUNCH:
                    case MOVE_EXTREMESPEED:
                    case MOVE_SKY_UPPERCUT:
                    case MOVE_SWIFT:
                    case MOVE_TACKLE:
                    case MOVE_WATERFALL:
                    case MOVE_SLAM:
                    case MOVE_BULLET_SEED:
                    case MOVE_EGG_BOMB:
                    case MOVE_FAINT_ATTACK:
                    case MOVE_BARRAGE:
                    case MOVE_PECK:
                    case MOVE_ARM_THRUST:
                    case MOVE_HORN_ATTACK:
                    case MOVE_WING_ATTACK:
                    case MOVE_AERIAL_ACE:
                    case MOVE_ICICLE_SPEAR:
                    case MOVE_VINE_WHIP:
                    case MOVE_SHOCK_WAVE:
                    case MOVE_QUICK_ATTACK:
                    case MOVE_SPIKE_CANNON:
                    case MOVE_DRAGON_CLAW:
                    case MOVE_DRILL_PECK:
                    case MOVE_DOUBLE_KICK:
                    case MOVE_HYDRO_PUMP:
                    case MOVE_HYPER_VOICE:
                    case MOVE_VICEGRIP:
                    case MOVE_POUND:
                    case MOVE_SCRATCH:
                    case MOVE_BONE_RUSH:
                    case MOVE_BONEMERANG:
                    case MOVE_MAGICAL_LEAF:
                    case MOVE_MACH_PUNCH:
                    case MOVE_PIN_MISSILE:
                    case MOVE_WATER_GUN:
                    case MOVE_FURY_ATTACK:
                    case MOVE_FURY_SWIPES:
                    case MOVE_MEGA_KICK:
                    case MOVE_MEGA_PUNCH:
                    case MOVE_MEGAHORN:
                    case MOVE_FURY_CUTTER:
                    case MOVE_COMET_PUNCH:
                    case MOVE_ROCK_BLAST:
                    case MOVE_AEROBLAST:
                    case MOVE_WIDE_SLASH:
                    case MOVE_SPIN_SLASH:
                    case MOVE_BLOOP_SLASH:
                        moveHadEffect = (HandleDamagingMove(attacker, currTarget, move, 0x100, itemId) != 0);
                        break;
                    case MOVE_REGULAR_ATTACK:
                        moveHadEffect = (HandleDamagingMove(attacker, currTarget, move, 0x80, itemId) != 0);
                        break;
                    case MOVE_NOTHING:
                        moveHadEffect = (HandleDamagingMove(attacker, currTarget, move, 0, itemId) != 0);
                        break;
                    case MOVE_EARTHQUAKE:
                        moveHadEffect = sub_8058F04(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_GUST:
                        moveHadEffect = sub_8058270(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_STRUGGLE:
                        moveHadEffect = sub_805B968(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_FLAME_WHEEL:
                        moveHadEffect = sub_805816C(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_FLAMETHROWER:
                    case MOVE_FIRE_BLAST:
                    case MOVE_HEAT_WAVE:
                    case MOVE_EMBER:
                    case MOVE_FIRE_PUNCH:
                        moveHadEffect = sub_80581D0(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_POWDER_SNOW:
                    case MOVE_BLIZZARD:
                    case MOVE_ICE_PUNCH:
                    case MOVE_ICE_BEAM:
                        moveHadEffect = sub_8058B3C(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_FRENZY_PLANT:
                    case MOVE_HYDRO_CANNON:
                    case MOVE_HYPER_BEAM:
                        moveHadEffect = sub_805A568(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_FOCUS_ENERGY:
                        moveHadEffect = FocusEnergyMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_AIR_CUTTER:
                    case MOVE_KARATE_CHOP:
                    case MOVE_SLASH:
                    case MOVE_CRABHAMMER:
                    case MOVE_CROSS_CHOP:
                    case MOVE_RAZOR_LEAF:
                    case MOVE_LEAF_BLADE:
                        moveHadEffect = (HandleDamagingMove(attacker, currTarget, move, 0x100, itemId) != 0);
                        break;
                    case MOVE_FISSURE:
                        moveHadEffect = sub_80590D4(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SHEER_COLD:
                    case MOVE_GUILLOTINE:
                        moveHadEffect = sub_80595EC(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_ONE_SHOT:
                        moveHadEffect = sub_805C138(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_CLAMP:
                    case MOVE_BIND:
                    case MOVE_SAND_TOMB:
                    case MOVE_FIRE_SPIN:
                        moveHadEffect = sub_805B17C(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_WHIRLPOOL:
                        moveHadEffect = WhirlpoolMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SURF:
                        moveHadEffect = SurfMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SPIDER_WEB:
                    case MOVE_MEAN_LOOK:
                        moveHadEffect = sub_805889C(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_POISON_STING:
                    case MOVE_SLUDGE:
                    case MOVE_SLUDGE_BOMB:
                        moveHadEffect = sub_8059E0C(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_PSYCHIC:
                        moveHadEffect = sub_8058C98(attacker, currTarget, move, gUnknown_8106A50, itemId);
                        break;
                    case MOVE_ACID:
                        moveHadEffect = sub_8058C98(attacker, currTarget, move, gUnknown_8106A4C, itemId);
                        break;
                    case MOVE_METAL_CLAW:
                        moveHadEffect = sub_805B3FC(attacker, currTarget, move, gUnknown_8106A4C, itemId);
                        break;
                    case MOVE_STEEL_WING:
                        moveHadEffect = sub_805A5E8(attacker, currTarget, move, gUnknown_8106A4C, itemId);
                        break;
                    case MOVE_POISON_TAIL:
                        moveHadEffect = sub_805B074(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_TWISTER:
                        moveHadEffect = sub_8059928(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_CONSTRICT:
                    case MOVE_BUBBLEBEAM:
                        moveHadEffect = sub_8058580(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SILVER_WIND:
                    case MOVE_ANCIENTPOWER:
                        moveHadEffect = sub_8058930(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_PSYBEAM:
                    case MOVE_SIGNAL_BEAM:
                    case MOVE_CONFUSION:
                        moveHadEffect = sub_8058C00(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_MIST_BALL:
                        moveHadEffect = sub_805B324(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_LUSTER_PURGE:
                        moveHadEffect = sub_805B910(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_CRUSH_CLAW:
                        moveHadEffect = sub_805AE74(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SMOG:
                        moveHadEffect = sub_8059540(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SACRED_FIRE:
                        moveHadEffect = sub_80595A0(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_THUNDERSHOCK:
                        moveHadEffect = sub_8059D00(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_LICK:
                    case MOVE_SPARK:
                    case MOVE_BODY_SLAM:
                    case MOVE_DRAGONBREATH:
                        moveHadEffect = sub_8058FBC(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_EXTRASENSORY:
                    case MOVE_HYPER_FANG:
                    case MOVE_BONE_CLUB:
                        moveHadEffect = sub_8059190(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_BITE:
                    case MOVE_NEEDLE_ARM:
                    case MOVE_STOMP:
                    case MOVE_ROLLING_KICK:
                        moveHadEffect = sub_8058430(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_HEADBUTT:
                        moveHadEffect = sub_8059424(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_ROCK_SLIDE:
                    case MOVE_ASTONISH:
                        moveHadEffect = sub_8057C88(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_CRUNCH:
                    case MOVE_SHADOW_BALL:
                        moveHadEffect = sub_80583D8(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_DIZZY_PUNCH:
                    case MOVE_WATER_PULSE:
                        moveHadEffect = sub_805AC90(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_TRI_ATTACK:
                        moveHadEffect = TriAttackMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_METEOR_MASH:
                        moveHadEffect = sub_8058B84(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_BLAZE_KICK:
                        moveHadEffect = sub_805AECC(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_ATTRACT:
                        moveHadEffect = sub_805B454(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_DISABLE:
                        moveHadEffect = sub_80582C4(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_FAKE_OUT:
                        moveHadEffect = sub_805A408(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SONICBOOM:
                        moveHadEffect = sub_8059714(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_DRAGON_RAGE:
                        moveHadEffect = sub_805B808(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_STUN_SPORE:
                        moveHadEffect = sub_8059050(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_THUNDER:
                    case MOVE_THUNDERPUNCH:
                        moveHadEffect = sub_8058478(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_LOVELY_KISS:
                    case MOVE_SING:
                    case MOVE_SPORE:
                    case MOVE_GRASSWHISTLE:
                    case MOVE_HYPNOSIS:
                    case MOVE_SLEEP_POWDER:
                        moveHadEffect = sub_80576F8(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_YAWN:
                        moveHadEffect = YawnMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_THUNDERBOLT:
                        moveHadEffect = sub_8059080(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_BLOCK:
                        moveHadEffect = sub_8059D98(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_HORN_DRILL:
                        moveHadEffect = sub_8059AF8(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_CONFUSE_RAY:
                    case MOVE_SUPERSONIC:
                    case MOVE_SWEET_KISS:
                    case MOVE_TEETER_DANCE:
                    case MOVE_TOTTER:
                        moveHadEffect = sub_8059AA8(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_POISON_GAS:
                    case MOVE_POISONPOWDER:
                        moveHadEffect = sub_8059DA4(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_THUNDER_WAVE:
                        moveHadEffect = sub_8059D48(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_GLARE:
                        moveHadEffect = sub_805B028(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_ZAP_CANNON:
                        moveHadEffect = sub_8059D58(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SUPERPOWER:
                        moveHadEffect = TickleMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_ROCK_TOMB:
                    case MOVE_ICY_WIND:
                    case MOVE_MUD_SHOT:
                        moveHadEffect = sub_8058638(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_DYNAMICPUNCH:
                        moveHadEffect = sub_805A688(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_FAKE_TEARS:
                        moveHadEffect = sub_8057D7C(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_WHIRLWIND:
                    case MOVE_ROAR:
                    case MOVE_BLOWBACK:
                        moveHadEffect = sub_805B0BC(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_PAIN_SPLIT:
                        moveHadEffect = PainSplitMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_TAIL_GLOW:
                        moveHadEffect = sub_805B164(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_MINIMIZE:
                        moveHadEffect = sub_8059A18(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_DRAGON_DANCE:
                        moveHadEffect = sub_805B884(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_BULK_UP:
                        moveHadEffect = BulkUpMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SHARPEN:
                    case MOVE_HOWL:
                    case MOVE_MEDITATE:
                        moveHadEffect = sub_80582D4(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_RAGE:
                        moveHadEffect = RageMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SWORDS_DANCE:
                        moveHadEffect = sub_8059B94(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_CALM_MIND:
                        moveHadEffect = sub_805B3B4(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_GROWTH:
                        moveHadEffect = sub_8059588(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_AMNESIA:
                        moveHadEffect = sub_805A2B0(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_DEFENSE_CURL:
                        moveHadEffect = sub_805B2FC(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_IRON_DEFENSE:
                    case MOVE_ACID_ARMOR:
                    case MOVE_BARRIER:
                        moveHadEffect = sub_8059CD8(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_COSMIC_POWER:
                        moveHadEffect = sub_8058A7C(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_MUDDY_WATER:
                        moveHadEffect = sub_80598CC(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_OCTAZOOKA:
                        moveHadEffect = sub_8057F7C(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_AURORA_BEAM:
                        moveHadEffect = sub_8057ED0(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_PSYCHO_BOOST:
                        moveHadEffect = sub_8058CEC(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SCARY_FACE:
                    case MOVE_COTTON_SPORE:
                        moveHadEffect = sub_8058BF0(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_GROWL:
                        moveHadEffect = sub_805A2C8(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_FEATHERDANCE:
                        moveHadEffect = sub_805AD34(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SCREECH:
                        moveHadEffect = sub_8057C68(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SEISMIC_TOSS:
                    case MOVE_NIGHT_SHADE:
                        moveHadEffect = sub_8059A2C(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_GIGA_DRAIN:
                    case MOVE_LEECH_LIFE:
                    case MOVE_MEGA_DRAIN:
                        moveHadEffect = sub_80586DC(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_DOUBLE_EDGE:
                        moveHadEffect = sub_805946C(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SUBMISSION:
                    case MOVE_TAKE_DOWN:
                    case MOVE_VOLT_TACKLE:
                        moveHadEffect = sub_8058E5C(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_ABSORB:
                        moveHadEffect = sub_80591E4(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SWAGGER:
                        moveHadEffect = sub_8057BC4(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_TRIPLE_KICK:
                        moveHadEffect = sub_805A210(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_TWINEEDLE:
                        moveHadEffect = sub_8059988(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SOLARBEAM:
                        moveHadEffect = SolarBeamMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SKY_ATTACK:
                        moveHadEffect = SkyAttackMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SLOW_DOWN:
                        moveHadEffect = sub_805BE90(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_OUTRAGE:
                    case MOVE_PETAL_DANCE:
                        moveHadEffect = sub_80588B8(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_WRAP:
                        moveHadEffect = WrapMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_UPROAR:
                        moveHadEffect = sub_8058D38(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_POISON_FANG:
                        moveHadEffect = sub_8059DC4(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_PRESENT:
                        moveHadEffect = PresentMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_REFLECT:
                        moveHadEffect = ReflectMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SANDSTORM:
                        moveHadEffect = SandstormMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SAFEGUARD:
                        moveHadEffect = SafeguardMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_MIST:
                        moveHadEffect = MistMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_LIGHT_SCREEN:
                        moveHadEffect = LightScreenMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_ICE_BALL:
                    case MOVE_ROLLOUT:
                        moveHadEffect = sub_805768C(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_MEMENTO:
                        moveHadEffect = sub_8057F24(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SOFTBOILED:
                    case MOVE_MILK_DRINK:
                        moveHadEffect = sub_80599EC(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SYNTHESIS:
                        moveHadEffect = sub_80589D4(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_MOONLIGHT:
                        moveHadEffect = sub_8059AC4(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_REST:
                        moveHadEffect = sub_805A4D4(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_RECOVER:
                    case MOVE_SLACK_OFF:
                        moveHadEffect = sub_8058EE0(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SCAN:
                        moveHadEffect = ScannerOrbAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_TRICK:
                        moveHadEffect = sub_805A120(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_TAKEAWAY:
                        moveHadEffect = sub_805BA50(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_THIEF:
                    case MOVE_COVET:
                        moveHadEffect = sub_805A2A0(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_AGILITY:
                    case MOVE_SPEED_BOOST:
                        moveHadEffect = sub_8058A08(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_PURSUIT:
                    case MOVE_COUNTER:
                        moveHadEffect = CounterMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_BIDE:
                    case MOVE_REVENGE:
                        moveHadEffect = BideMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_BIDE_2:
                        moveHadEffect = sub_805836C(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_TRAPPER:
                        moveHadEffect = TrapperOrbAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SLEEP_TALK:
                        moveHadEffect = sub_805A450(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_CURSE:
                        moveHadEffect = CurseMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_HI_JUMP_KICK:
                        moveHadEffect = sub_8059FC8(attacker, currTarget, move, itemId, 0);
                        break;
                    case MOVE_BLAST_BURN:
                        moveHadEffect = sub_805AE3C(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_HIDDEN_POWER:
                        moveHadEffect = sub_805B3E0(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_RAZOR_WIND:
                        moveHadEffect = RazorWindMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_FOCUS_PUNCH:
                        moveHadEffect = FocusPunchMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_MAGIC_COAT:
                        moveHadEffect = MagicCoatMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_NIGHTMARE:
                        moveHadEffect = NightmareMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_MORNING_SUN:
                        moveHadEffect = sub_8057748(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_VACUUM_CUT:
                        moveHadEffect = sub_805C1BC(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_MUD_SPORT:
                    case MOVE_WATER_SPORT:
                        moveHadEffect = MudWaterSportMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_IRON_TAIL:
                        moveHadEffect = sub_8057634(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_TAIL_WHIP:
                    case MOVE_LEER:
                        moveHadEffect = sub_805A3DC(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_WILL_O_WISP:
                        moveHadEffect = sub_8057FF4(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_INGRAIN:
                        moveHadEffect = sub_805A4FC(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_PSYWAVE:
                        moveHadEffect = sub_8058C48(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_LEECH_SEED:
                        moveHadEffect = LeechSeedMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SPIKES:
                        moveHadEffect = SpikesMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_AROMATHERAPY:
                    case MOVE_HEAL_BELL:
                    case MOVE_REFRESH:
                        moveHadEffect = sub_80578EC(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_HAZE:
                        moveHadEffect = sub_80588A8(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_POWER_EARS:
                        moveHadEffect = RadarOrbAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SIESTA:
                        moveHadEffect = sub_805BC70(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SMELLINGSALT:
                        moveHadEffect = sub_80587E8(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_MAGNITUDE:
                        moveHadEffect = sub_805B264(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SKULL_BASH:
                        moveHadEffect = SkullBashMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_WISH:
                        moveHadEffect = WishMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_FLATTER:
                        moveHadEffect = sub_8057FCC(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_MUD_SLAP:
                        moveHadEffect = sub_805A258(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SAND_ATTACK:
                    case MOVE_KINESIS:
                    case MOVE_FLASH:
                        moveHadEffect = sub_8059528(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_OVERHEAT:
                        moveHadEffect = sub_8057E6C(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_TOXIC:
                        moveHadEffect = sub_8059DB4(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_METAL_SOUND:
                        moveHadEffect = sub_8058838(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_TORMENT:
                        moveHadEffect = TormentMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SUPER_FANG:
                        moveHadEffect = sub_8057974(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_FALSE_SWIPE:
                        moveHadEffect = sub_805B388(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_TWO_EDGE:
                        moveHadEffect = sub_805BC98(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_ENDEAVOR:
                        moveHadEffect = sub_80584C0(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_BATON_PASS:
                    case MOVE_SWITCHER:
                        moveHadEffect = sub_805BB74(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_DREAM_EATER:
                        moveHadEffect = sub_805B668(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SEARCHLIGHT:
                        moveHadEffect = LuminousOrbAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_FILL_IN:
                        moveHadEffect = FillInOrbAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_TELEPORT:
                    case MOVE_WARP:
                        moveHadEffect = sub_8059CF0(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_DROUGHT:
                        moveHadEffect = sub_805BF34(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SEE_STAIRS:
                        moveHadEffect = StairsOrbAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_BRICK_BREAK:
                        moveHadEffect = BrickBreakMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_HARDEN:
                    case MOVE_WITHDRAW:
                        moveHadEffect = sub_80582AC(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_MIND_READER:
                    case MOVE_LOCK_ON:
                        moveHadEffect = sub_8058A54(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_VITAL_THROW:
                        moveHadEffect = VitalThrowMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_FLY:
                        moveHadEffect = FlyMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_BOUNCE:
                        moveHadEffect = sub_8059F38(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_DIVE:
                        moveHadEffect = DiveMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_DIG:
                        moveHadEffect = DigMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SWEET_SCENT:
                        moveHadEffect = sub_8057824(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_DOUBLE_TEAM:
                        moveHadEffect = sub_805825C(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_KNOCK_OFF:
                        moveHadEffect = KnockOffMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_TRAP_BUSTER:
                        moveHadEffect = TrapbustOrbAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_LONG_TOSS:
                        moveHadEffect = LongtossOrbAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_PIERCE:
                        moveHadEffect = PierceOrbAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_GRUDGE:
                        moveHadEffect = GrudgeMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_PETRIFY:
                        moveHadEffect = PetrifyOrbAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_ASSIST:
                        moveHadEffect = sub_805A4C0(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_DOOM_DESIRE:
                    case MOVE_FUTURE_SIGHT:
                        moveHadEffect = sub_805AAD0(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SHOCKER:
                        moveHadEffect = ShockerOrbAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_FOLLOW_ME:
                    case MOVE_SUBSTITUTE:
                    case MOVE_DECOY_MAKER:
                        moveHadEffect = sub_805B314(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_JUMP_KICK:
                        moveHadEffect = sub_8059E54(attacker, currTarget, move, itemId, 0);
                        break;
                    case MOVE_PROTECT:
                    case MOVE_DETECT:
                        moveHadEffect = ProtectMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_TAUNT:
                        moveHadEffect = sub_8059AB8(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_TICKLE:
                        moveHadEffect = sub_8058858(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_REVERSAL:
                    case MOVE_FLAIL:
                        moveHadEffect = sub_8058770(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SELFDESTRUCT:
                        moveHadEffect = sub_8059004(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_EXPLOSION:
                        moveHadEffect = sub_80597F0(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_CHARGE:
                        moveHadEffect = ChargeMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_FACADE:
                        moveHadEffect = sub_8058548(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_LOW_KICK:
                        moveHadEffect = sub_80588F4(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_WATER_SPOUT:
                        moveHadEffect = sub_8058D44(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_ERUPTION:
                        moveHadEffect = sub_805AFA4(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SMOKESCREEN:
                        moveHadEffect = SmokescreenMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SEE_TRAP:
                        moveHadEffect = sub_805BA44(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_STOCKPILE:
                        moveHadEffect = StockpileMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SPIT_UP:
                        moveHadEffect = SpitUpMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SWALLOW:
                        moveHadEffect = SwallowMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_RAIN_DANCE:
                        moveHadEffect = RainDanceMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SPITE:
                        moveHadEffect = sub_8057D9C(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_INVISIFY:
                        moveHadEffect = InvisifyOrbAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_MIRROR_COAT:
                        moveHadEffect = MirrorCoatMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_PERISH_SONG:
                        moveHadEffect = PerishSongMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_RAPID_SPIN:
                        moveHadEffect = sub_8058A18(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_DESTINY_BOND:
                        moveHadEffect = DestinyBondMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_ENCORE:
                        moveHadEffect = EncoreMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_WEATHER_BALL:
                        moveHadEffect = sub_8057CD0(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SUNNY_DAY:
                        moveHadEffect = SunnyDayMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_PAY_DAY:
                        moveHadEffect = sub_805A464(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_ONE_ROOM:
                        moveHadEffect = sub_805C2A0(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_ENDURE:
                        moveHadEffect = EndureMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_HELPING_HAND:
                        moveHadEffect = HelpingHandMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_BELLY_DRUM:
                        moveHadEffect = BellyDrumMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_FAMISH:
                        moveHadEffect = sub_805C288(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_CHARM:
                        moveHadEffect = sub_805783C(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_BUBBLE:
                        moveHadEffect = sub_80578FC(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_STRING_SHOT:
                        moveHadEffect = sub_8057BB4(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_ROCK_SMASH:
                    case MOVE_EXCAVATE:
                        moveHadEffect = RockSmashMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_TRANSFORM:
                        moveHadEffect = TransformMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_HAIL:
                        moveHadEffect = HailMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_MOBILE:
                        moveHadEffect = MobileOrbAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_ODOR_SLEUTH:
                    case MOVE_FORESIGHT:
                        moveHadEffect = sub_8058234(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SPLASH:
                        moveHadEffect = sub_805A85C(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_TRANSFER:
                        moveHadEffect = TransferOrbAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_STAY_AWAY:
                        moveHadEffect = sub_805BB98(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_BEAT_UP:
                        moveHadEffect = sub_805AD54(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_REBOUND:
                        moveHadEffect = ReboundOrbAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_IMPRISON:
                    case MOVE_OBSERVER:
                        moveHadEffect = sub_805AD04(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_WILD_CALL:
                        moveHadEffect = sub_805C080(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_REVIVER:
                        moveHadEffect = sub_805C1E4(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_ESCAPE:
                        moveHadEffect = EscapeOrbAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SECRET_POWER:
                        moveHadEffect = SecretPowerMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_NATURE_POWER:
                        moveHadEffect = NaturePowerMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_ITEMIZE:
                        moveHadEffect = sub_805C3F8(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SKETCH:
                        moveHadEffect = SketchMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_MIRROR_MOVE:
                        moveHadEffect = sub_8057E50(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_ROLE_PLAY:
                        moveHadEffect = RolePlayMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SKILL_SWAP:
                        moveHadEffect = SkillSwapMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_CONVERSION:
                        moveHadEffect = ConversionMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_CLEANSE:
                        moveHadEffect = CleanseOrbAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_RETURN:
                        moveHadEffect = sub_805805C(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SNATCH:
                        moveHadEffect = SnatchMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_CAMOUFLAGE:
                        moveHadEffect = HandleColorChange(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_FRUSTRATION:
                        moveHadEffect = sub_805B53C(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_PSYCH_UP:
                        moveHadEffect = PsychUpMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_SNORE:
                        moveHadEffect = SnoreMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_RECYCLE:
                        moveHadEffect = RecycleMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_NO_MOVE:
                        moveHadEffect = SilenceOrbAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_METRONOME:
                        moveHadEffect = sub_805B618(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_HP_GAUGE:
                        moveHadEffect = IdentifyOrbAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_CONVERSION_2:
                        moveHadEffect = Conversion2MoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_POUNCE:
                        moveHadEffect = sub_805BEB8(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_TRAWL:
                        moveHadEffect = sub_805BEC8(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_MIMIC:
                        moveHadEffect = MimicMoveAction(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_STRENGTH:
                    case MOVE_HURL:
                        moveHadEffect = sub_805C45C(attacker, currTarget, move, itemId);
                        break;
                    case MOVE_ECHO:
                        moveHadEffect = sub_805C208(attacker, currTarget, move, itemId);
                        break;
                    default:
                        moveHadEffect = FALSE;
                        break;
                }

                if (sub_8044B28()) {
                    break;
                }

                if (EntityExists(currTargetSaved)) {
                    sub_806CE68(currTargetSaved, GetEntInfo(currTargetSaved)->action.direction);
                }

                if (!moveHadEffect) {
                    if (EntityExists(attacker) && EntityExists(currTarget) && targetInfo->isNotTeamMember) {
                        targetInfo->expMultiplier = expMultiplierBeforeMove;
                    }
                }
                else {
                    if (MoveCausesPaused(move) && RollSecondaryEffect(attacker, 0)) {
                        gUnknown_202F222 = 1;
                    }
                }

                if (EntityExists(currTarget)) {
                    targetInfo->unk158 = 1;
                }

                if (moveId != MOVE_SKILL_SWAP) {
                    TriggerTargetAbilityEffect(attacker);
                    sub_8069F9C(attacker, currTarget, move);
                    sub_806A120(attacker, currTarget, move);
                }
            }

            attacker = originalAttacker;
        }
    }

    if (!sub_8044B28()) {
        if (EntityExists(attacker) && GetEntInfo(attacker)->unk154 != 0) {
            GetEntInfo(attacker)->unk154 = 0;
            sub_807D148(attacker, attacker, 0, NULL);
        }
        if (EntityExists(attacker) && GetEntInfo(attacker)->unk155 != 0) {
            GetEntInfo(attacker)->unk155 = 0;
            LowerAttackStageTarget(attacker, attacker, gUnknown_8106A50, 2, 0, FALSE);
        }
    }
}

bool32 HandleRegularDamagingMove(Entity *attacker, Entity *target, Move *move, s32 itemId)
{
    return (HandleDamagingMove(attacker, target, move, 0x100, itemId) != 0);
}

s32 HandleDamagingMove(Entity *attacker, Entity *target, Move *move, s32 r9, s32 itemId)
{
    struct DamageStruct dmgStruct;
    s16 unk;
    s32 moveType = GetMoveTypeForMonster(attacker, move);
    s32 movePower = GetMovePower(attacker, move);
    s32 critChance = GetMoveCritChance(move);

    CalcDamage(attacker, target, moveType, movePower, critChance, &dmgStruct, r9, move->id, 1);
    unk = sub_8057600(move, itemId);
    return TryHitTarget(attacker, target, move, &dmgStruct, unk);
}

s32 sub_80556BC(Entity *attacker, Entity *target, u8 moveType, Move *move, s32 r9, s32 itemId)
{
    struct DamageStruct dmgStruct;
    s16 unk;
    s32 movePower = GetMovePower(attacker, move);
    s32 critChance = GetMoveCritChance(move);

    CalcDamage(attacker, target, moveType, movePower, critChance, &dmgStruct, r9, move->id, 1);
    unk = sub_8057600(move, itemId);
    return TryHitTarget(attacker, target, move, &dmgStruct, unk);
}

static s32 TryHitTarget(Entity *attacker, Entity *target, Move *move, struct DamageStruct *dmgStruct, s16 unk_)
{
    s32 unk = unk_; // It's happening again...
    if (AccuracyCalc(attacker, target, move, ACCURACY_2, TRUE)) { // Move hits
        bool32 isFalseSwipe = (move->id == MOVE_FALSE_SWIPE);

        if (HasAbility(target, ABILITY_ILLUMINATE)) {
            gDungeon->unk644.unk1E = 999;
            gDungeon->unk17B34 = target;
            gDungeon->unk17B40 = target->spawnGenID;
        }

        HandleDealingDamage(attacker, target, dmgStruct, isFalseSwipe, TRUE, unk, TRUE, 0);
    }
    else {
        SetMessageArgument_2(gFormatBuffer_Monsters[1], GetEntInfo(target), 0);
        if (sub_8045888(attacker) && sub_8045888(target)) {
            sub_803ED30(9999, target, 1, -1);
            TryDisplayDungeonLoggableMessage4(attacker, target, gUnknown_80F9688); // It took no damage!
            sub_8042238(attacker, target);
        }
        else {
            TryDisplayDungeonLoggableMessage3(attacker, target, gUnknown_80F9688); // It took no damage!
        }
        dmgStruct->tookNoDamage = TRUE;
    }

    if (dmgStruct->tookNoDamage) {
        return 0;
    }

    if (EntityExists(target)) {
        GetEntInfo(target)->unk15A = 1;
    }

    return dmgStruct->dmg;
}

s32 sub_8055864(Entity *attacker, Entity *target, Move *move, s32 param_4, s32 itemId)
{
    struct DamageStruct dmgStruct;
    s32 moveType = GetMoveTypeForMonster(attacker, move);

    sub_806F2BC(attacker, target, moveType, param_4, &dmgStruct);
    HandleDealingDamage(attacker, target, &dmgStruct, FALSE, TRUE, sub_8057600(move, itemId), TRUE, 0);
    if (dmgStruct.tookNoDamage) {
        return 0;
    }

    if (EntityExists(target)) {
        GetEntInfo(target)->unk15A = 1;
    }
    return dmgStruct.dmg;
}

// This unused function returns FALSE if target's typing makes it immune to move's type.
UNUSED bool32 TargetNotImmuneTo(Move *move, Entity *target)
{
    s32 i;
    s32 dmg = 1;
    bool32 ghostImmunity = FALSE;
    EntityInfo *targetInfo = GetEntInfo(target);
    s32 moveType = GetMoveType(move);

    if (moveType == TYPE_NORMAL || moveType == TYPE_FIGHTING) {
        ghostImmunity = TRUE;
    }

    for (i = 0; i < 2; i++) {
        s32 multiplier[4] = {0, 1, 1, 1}; // EFFECTIVENESS_IMMUNE is 0, others are 1
        s32 effectiveness;

        if (ghostImmunity && targetInfo->types[i] == TYPE_GHOST && !targetInfo->exposed) {
            effectiveness = EFFECTIVENESS_IMMUNE;
        }
        else {
            effectiveness = gTypeEffectivenessChart[moveType][targetInfo->types[i]];
        }

        dmg *= multiplier[effectiveness];
        if (dmg == 0)
            break;
    }

    return (dmg != 0);
}

bool8 sub_8055988(Entity *r2, Entity *r4)
{
    if (r2 != r4
        && abs(r2->pos.x - r4->pos.x) <= 1 && abs(r2->pos.y - r4->pos.y) <= 1
        && CanAttackInDirection(r4, GetDirectionTowardsPosition(&r4->pos, &r2->pos)))
    {
        return TRUE;
    }

    return FALSE;
}

void sub_80559DC(Entity *entity1, Entity *entity2)
{
    EntityInfo *entInfo = GetEntInfo(entity1);
    s32 direction = GetDirectionTowardsPosition(&entity1->pos, &entity2->pos);

    entInfo->action.direction = direction & DIRECTION_MASK;
    sub_806CE68(entity1, direction);
}

bool32 sub_8055A00(Entity *attacker, s32 firstMoveId, s32 var_34, s32 itemId, s32 arg_0)
{
    s32 i, j;
    s32 moveId;
    EntityInfo *attackerInfo = GetEntInfo(attacker);
    bool32 isLinkedMove;

    moveId = firstMoveId;
    if (firstMoveId >= MAX_MON_MOVES)
        return FALSE;

    attackerInfo->abilityEffectFlags = 0;
    attackerInfo->unk159 = 0;
    if (attackerInfo->cringeClassStatus.status == STATUS_CRINGE) {
        SubstitutePlaceholderStringTags(gFormatBuffer_Monsters[0], attacker, 0);
        LogMessageByIdWithPopupCheckUser(attacker, gUnknown_80FC714); // is cringing!
        return FALSE;
    }
    else if (attackerInfo->cringeClassStatus.status == STATUS_INFATUATED) {
        SubstitutePlaceholderStringTags(gFormatBuffer_Monsters[0], attacker, 0);
        LogMessageByIdWithPopupCheckUser(attacker, gUnknown_80FC718); // is infatuated!
        return FALSE;
    }
    else if (attackerInfo->burnClassStatus.status == STATUS_PARALYSIS) {
        SubstitutePlaceholderStringTags(gFormatBuffer_Monsters[0], attacker, 0);
        LogMessageByIdWithPopupCheckUser(attacker, gUnknown_80FC6A8); // is paralyzed!
        return FALSE;
    }

    gUnknown_202F222 = 0;
    gUnknown_202F208 = 0;
    gUnknown_202F221 = 0;
    for (i = 0; i < MAX_MON_MOVES; i++) {
        attackerInfo->mimicMoveIDs[i] = 0;
    }

    for (i = 0, j = 0; i < MAX_MON_MOVES; i++) {
        j++;
        if (++moveId >= MAX_MON_MOVES)
            break;
        if (!(attackerInfo->moves.moves[moveId].moveFlags & MOVE_FLAG_SUBSEQUENT_IN_LINK_CHAIN))
            break;
    }

    isLinkedMove = (j > 1);
    moveId = firstMoveId;

    while (1) {
        Move *currMove = &attackerInfo->moves.moves[moveId];
        if (!EntityExists(attacker) || sub_8044B28())
            break;

        if (currMove->id == MOVE_SNORE || currMove->id == MOVE_SLEEP_TALK) {
            if (!IsSleeping(attacker)) {
                if (CannotAttack(attacker, TRUE))
                    break;
            }
        }
        else {
            if (CannotAttack(attacker, FALSE))
                break;
        }

        if (gUnknown_202F221 != 0)
            break;

        if (MoveFlagExists(currMove)) {
            bool32 moveUsable = TRUE;
            bool32 var_28 = FALSE;
            bool32 statusMoveMatch = MoveMatchesBideClassStatus(attacker, currMove);

            if (currMove->PP != 0) {
                if (!statusMoveMatch) {
                    var_28 = TRUE;
                }
            }
            else {
                if (!statusMoveMatch) {
                    sub_80928C0(gFormatBuffer_Items[0],  currMove, NULL);
                    LogMessageByIdWithPopupCheckUser(attacker, gUnknown_80F93C8); // The move can't be used!
                    moveUsable = FALSE;
                }
            }

            if (moveUsable) {
                bool32 moveWasUsed;
                s32 unkBefore = gUnknown_202F208;

                attackerInfo->unk159 = statusMoveMatch;
                if (currMove->id == MOVE_ASSIST) {
                    Move assistMove = *currMove;

                    assistMove.id = sub_8057144(attacker);
                    sub_80928C0(gFormatBuffer_Items[0], &assistMove, NULL);
                    LogMessageByIdWithPopupCheckUser(attacker, gUnknown_80FD2DC); // Assist:
                    moveWasUsed = TryUseChosenMove(attacker, var_34, itemId, arg_0, isLinkedMove, &assistMove);
                }
                else {
                    moveWasUsed = TryUseChosenMove(attacker, var_34, itemId, arg_0, isLinkedMove, currMove);
                }

                if (var_28 && moveWasUsed) {
                    if (currMove->moveFlags2 & MOVE_FLAG2_UNK4) {
                        currMove->moveFlags2 &= ~(MOVE_FLAG2_UNK4);
                    }
                    else {
                        currMove->moveFlags2 |= MOVE_FLAG_TEMPORARY;
                    }
                }

                if (unkBefore == gUnknown_202F208) {
                    if (itemId == 0) {
                        LogMessageByIdWithPopupCheckUser(attacker, gUnknown_80FC690); // The currMove failed!
                    }
                    else {
                        LogMessageByIdWithPopupCheckUser(attacker, gUnknown_80FC6A4); // The Orb failed!
                    }
                }
            }
        }

        sub_804178C(1);
        if (!EntityExists(attacker) || sub_8044B28())
            break;
        if (++moveId >= MAX_MON_MOVES)
            break;
        if (!MoveFlagLinkChain(&attackerInfo->moves.moves[moveId]))
            break;
    }

    if (EntityExists(attacker)) {
        for (i = 0; i < MAX_MON_MOVES; i++) {
            if (attackerInfo->mimicMoveIDs[i] != 0) {
                Move mimicMove, assistMove;
                Move *movePtr;

                movePtr = &mimicMove;
                sub_8092AA8(&mimicMove, attackerInfo->mimicMoveIDs[i]);
                if (MoveFlagExists(&mimicMove)) {
                    if (mimicMove.id == MOVE_ASSIST) {
                        assistMove = mimicMove;
                        assistMove.id = sub_8057144(attacker);
                        movePtr = &assistMove;
                        sub_80928C0(gFormatBuffer_Items[0], &assistMove, NULL);
                        LogMessageByIdWithPopupCheckUser(attacker, gUnknown_80FD2DC); // Assist:
                    }
                    TryUseChosenMove(attacker, 0, itemId, arg_0, isLinkedMove, movePtr);
                }
                sub_804178C(1);
            }
        }
    }

    if (EntityExists(attacker)) {
        sub_8071DA4(attacker);
        if (EntityExists(attacker) && gUnknown_202F222 != 0) {
            gUnknown_202F222 = 0;
            if (EntityExists(attacker)) {
                EntityInfo *attackerInfo = GetEntInfo(attacker);
                s32 statusTurns = CalculateStatusTurns(attacker, gUnknown_80F4E70, TRUE);
                PausedStatusTarget(attacker, attacker, 1, statusTurns, FALSE);
                SetExpMultplier(attackerInfo);
            }
        }
    }

    return TRUE;
}

static void TriggerTargetAbilityEffect(Entity *attacker)
{
    if (EntityExists(attacker)) {
        EntityInfo *entInfo = GetEntInfo(attacker);

        if (entInfo->abilityEffectFlags & ABILITY_FLAG_ARENA_TRAP) {
            LogMessageByIdWithPopupCheckUser(attacker, gUnknown_80FEEA4); // Arena Trap prevents movement!
            ImmobilizedStatusTarget(attacker, attacker);
        }
        if (entInfo->abilityEffectFlags & ABILITY_FLAG_SHADOW_TAG) {
            LogMessageByIdWithPopupCheckUser(attacker, gUnknown_80FEEC8); // Shadow Tag prevents movement!
            ImmobilizedStatusTarget(attacker, attacker);
        }
        if (entInfo->abilityEffectFlags & ABILITY_FLAG_MAGNET_PULL) {
            LogMessageByIdWithPopupCheckUser(attacker, gUnknown_80FEEEC); // Magnet Pull prevents movement!
            ImmobilizedStatusTarget(attacker, attacker);
        }
        if (entInfo->abilityEffectFlags & ABILITY_FLAG_STATIC) {
            LogMessageByIdWithPopupCheckUser(attacker, gUnknown_80FEF0C); // Static caused paralysis!
            ParalyzeStatusTarget(attacker, attacker, TRUE);
        }
        if (entInfo->abilityEffectFlags & ABILITY_FLAG_EFFECT_SPORE_PRLZ) {
            LogMessageByIdWithPopupCheckUser(attacker, gUnknown_80FEF30); // Effect Spore scattered spores
            ParalyzeStatusTarget(attacker, attacker, TRUE);
        }
        if (entInfo->abilityEffectFlags & ABILITY_FLAG_POISON_POINT) {
            LogMessageByIdWithPopupCheckUser(attacker, gUnknown_80FEF4C); // Poison Point struck!
            PoisonedStatusTarget(attacker, attacker, TRUE);
        }
        if (entInfo->abilityEffectFlags & ABILITY_FLAG_EFFECT_SPORE_PSN) {
            LogMessageByIdWithPopupCheckUser(attacker, gUnknown_80FEF50); // Effect Spore scattered spores!
            PoisonedStatusTarget(attacker, attacker, TRUE);
        }
        if (entInfo->abilityEffectFlags & ABILITY_FLAG_EFFECT_SPORE_SLP) {
            LogMessageByIdWithPopupCheckUser(attacker, gUnknown_80FEF54); // Effect Spore scattered spores!
            sub_8075C58(attacker, attacker, CalculateStatusTurns(attacker, gUnknown_80F4E74, TRUE), TRUE);
        }
        if (entInfo->abilityEffectFlags & ABILITY_FLAG_FLAME_BODY) {
            LogMessageByIdWithPopupCheckUser(attacker, gUnknown_80FEF74); // Flame Body caused a burn!
            BurnedStatusTarget(attacker, attacker, TRUE, TRUE);
        }
        if (entInfo->abilityEffectFlags & ABILITY_FLAG_CUTE_CHARM) {
            LogMessageByIdWithPopupCheckUser(attacker, gUnknown_80FEF98); // Cute Charm caused infatuation
            InfatuateStatusTarget(attacker, attacker, TRUE);
        }
        if (entInfo->abilityEffectFlags & ABILITY_FLAG_STENCH) {
            SubstitutePlaceholderStringTags(gFormatBuffer_Monsters[0], attacker, 0);
            LogMessageByIdWithPopupCheckUser(attacker, gUnknown_80FEFD0); // A horrid stench billowed out
            sub_80428A0(attacker);
            entInfo->terrifiedTurns = gUnknown_80F5004;
        }

        entInfo->abilityEffectFlags = 0;
    }
}

bool8 TryUseChosenMove(struct Entity *attacker, u32 r6, s32 itemId, u32 var_30, bool32 isLinkedMove, struct Move *move)
{
    s32 i;
    Entity *targetsArray[MAX_MOVE_TARGETS + 1];
    const u8 *msg;
    Move metronomeMove, naturePwrMove;
    s32 var_2C;
    s32 var_28;
    s32 var_24;
    bool8 moveUsable;

    msg = NULL;
    targetsArray[0] = NULL;

    sub_804178C(1);
    if (move->id == MOVE_METRONOME) {
        gMetronomeCalledArrayId = DungeonRandInt(METRONOME_AVAILABLE_CALLED_MOVES);
        InitPokemonMove(&metronomeMove, gMetronomeCalledMoves[gMetronomeCalledArrayId].moveID);
        metronomeMove.moveFlags = move->moveFlags;
        metronomeMove.moveFlags2 = move->moveFlags2;
        sub_8056468(attacker, move, gUnknown_80FECBC, targetsArray, itemId, TRUE, FALSE);
        sub_804178C(1);
        move = &metronomeMove;
    }
    else if (move->id == MOVE_NATURE_POWER)
    {
        s32 tileset = gDungeon->tileset;

        if (tileset < 0)
            tileset = 0;
        if (tileset > 74)
            tileset = 74;

        InitPokemonMove(&naturePwrMove, gNaturePowerCalledMoves[tileset].moveID);
        naturePwrMove.moveFlags = move->moveFlags;
        naturePwrMove.moveFlags2 = move->moveFlags2;
        sub_8056468(attacker, move, gUnknown_80FECE0, targetsArray, itemId, TRUE, FALSE);
        sub_804178C(1);
        move = &naturePwrMove;
    }

    var_28 = 0;
    if ((GetMoveTargetAndRangeForPokemon(attacker, move, TRUE)
         & (0xF0)) == TARGETING_FLAG_TARGET_LINE)
    {
        var_28 = 10;
    }
    if ((GetMoveTargetAndRangeForPokemon(attacker, move, TRUE)
         & (0xF0)) == TARGETING_FLAG_CUT_CORNERS)
        {
        var_28 = 1;
        if ((move->id != MOVE_SOLARBEAM || GetApparentWeather(attacker) != WEATHER_SUNNY) && DoesMoveCharge(move->id)) {
            if (!MoveMatchesBideClassStatus(attacker, move)) {
                var_28 = 0;
            }
        }
    }

    SetMessageArgument_2(gFormatBuffer_Monsters[0], GetEntInfo(attacker), 0);
    sub_80928C0(gFormatBuffer_Items[0], move, NULL);
    if (MoveMatchesBideClassStatus(attacker, move)) {
        msg = gUnknown_80FC72C; // mon loosed move
        GetEntInfo(attacker)->unkFF = 0;
        moveUsable = sub_805744C(attacker, move, TRUE);
    }
    else {
        if (itemId == 0) {
            msg = GetMoveUseText(move->id);
        }
        else {
            msg = gUnknown_80F9158;
        }
        moveUsable = CanMonsterUseMove(attacker, move, TRUE);
    }

    if (moveUsable && r6) {
        sub_806ACE8(attacker, move);
    }

    if (GetEntInfo(attacker)->muzzled.muzzled == TRUE && FailsWhileMuzzled(move->id)) {
        SubstitutePlaceholderStringTags(gFormatBuffer_Monsters[0], attacker, 0);
        LogMessageByIdWithPopupCheckUser(attacker, msg);
        sub_803E708(0xA, 0x3F);
        LogMessageByIdWithPopupCheckUser(attacker, gUnknown_80FC710); // is muzzled!
        return FALSE;
    }
    else if (!moveUsable) {
        SetMessageArgument_2(gFormatBuffer_Monsters[0], GetEntInfo(attacker), 0);
        if (itemId == 0) {
            sub_80928C0(gFormatBuffer_Items[0], move, NULL);
            LogMessageByIdWithPopupCheckUser(attacker, msg);
            sub_803E708(0xA, 0x3F);
            LogMessageByIdWithPopupCheckUser(attacker, gUnknown_80FC6D0); // But the move couldn't be used!
        }
        else {
            BufferItemName(gFormatBuffer_Items[0], itemId, NULL);
            LogMessageByIdWithPopupCheckUser(attacker, msg);
            sub_803E708(0xA, 0x3F);
            LogMessageByIdWithPopupCheckUser(attacker, gUnknown_80FC6FC); // But Orbs are prevented from being used!
        }
        return FALSE;
    }

    gUnknown_202F214 = 0;
    gUnknown_202F20C = 0;
    gUnknown_202F210 = 0;
    gUnknown_202F218 = 0;
    gUnknown_202F219 = 0;
    gUnknown_202F21A = 0;
    gUnknown_202F21C = 0;
    gUnknown_202F220 = 0;
    if (isLinkedMove && GetEntInfo(attacker)->unk153 <= 3) {
        GetEntInfo(attacker)->unk153++;
    }

    var_2C = sub_8057070(move);
    for (i = 0; i < var_2C; i++) {
        u8 r4;
        EntityInfo *entInfo;

        var_24 = 1;
        if (gUnknown_202F220 != 0 || gUnknown_202F221 != 0)
            break;
        if (!EntityExists(attacker) || sub_8044B28())
            return TRUE;

        entInfo = GetEntInfo(attacker);
        if (var_30 != 0 || move->id == MOVE_SNORE || move->id == MOVE_SLEEP_TALK) {
            if (!IsSleeping(attacker) && CannotAttack(attacker, TRUE))
                break;
        }
        else {
            if (CannotAttack(attacker, FALSE))
                break;
        }
        entInfo->unk14A = 0;
        if (move->id == MOVE_THRASH) {
            GetEntInfo(attacker)->action.direction = DungeonRandInt(NUM_DIRECTIONS);
            TargetTileInFront(attacker);
            var_24 = 0;
        }
        gUnknown_203B438 = NULL;
        targetsArray[0] = 0;
        if (var_28 == 0 || var_28 == 1) {
            SetTargetsForMove(targetsArray, attacker, move);
            SortTargets(targetsArray, attacker);
            if (i != 0 && var_24 != 0 && targetsArray[0] == NULL)
                break;
        }
        r4 = sub_8056468(attacker, move, msg, targetsArray, itemId, (i == 0), var_28);
        msg = NULL;
        if (gUnknown_203B438 != 0) {
            sub_806A1E8(gUnknown_203B438);
        }

        if (GetEntInfo(attacker)->cringeClassStatus.status != STATUS_CONFUSED && GetEntInfo(attacker)->cringeClassStatus.status != STATUS_COWERING) {
            EntityInfo *entInfo = GetEntInfo(attacker);
            entInfo->targetPos.x = 0;
            entInfo->targetPos.y = 0;
        }

        gUnknown_202F214++;
        if (var_28 != 0) {
            sub_80566F8(attacker, move, var_28, r4, itemId, isLinkedMove);
        }
        else {
            UseMoveAgainstTargets(targetsArray, attacker, move, itemId, isLinkedMove);
        }

        if (!EntityExists(attacker))
            break;

        sub_806CF18(attacker);
        if (GetEntInfo(attacker)->unk14A == 0) {
            GetEntInfo(attacker)->unk14A = 0; // Redundant as it's already 0
            sub_8079764(attacker);
        }
    }


    if (gUnknown_202F21A != 0) {
        EndFrozenClassStatus(attacker, attacker);
        EndLeechSeedClassStatus(attacker, attacker);
    }

    if (gUnknown_202F219 != 0 && EntityExists(attacker)) {
        EntityInfo *entInfo = GetEntInfo(attacker);

        ConfuseStatusTarget(attacker, attacker, FALSE);
        SetExpMultplier(entInfo);
    }
    return TRUE;
}

bool8 sub_8056468(Entity *entity, Move *move, const u8 *str, Entity **unkArray, bool32 itemId, bool8 arg_4, bool32 unused)
{
    s32 i;
    bool8 ret = FALSE;
    bool32 r7 = (sub_8045888(entity) != FALSE);

    if (str != NULL) {
        for (i = 0; i < 65; i++) {
            if (unkArray[i] == NULL) {
                break;
            }
            if (sub_8045888(unkArray[i])) {
                r7 = TRUE;
                break;
            }
        }

        if (r7) {
            SetMessageArgument_2(gFormatBuffer_Monsters[0], GetEntInfo(entity), 0);
            if (itemId == 0) {
                sub_80928C0(gFormatBuffer_Items[0], move, NULL);
            }
            else {
                BufferItemName(gFormatBuffer_Items[0], itemId, NULL);
            }
        }

        if (move->id != MOVE_REGULAR_ATTACK) {
            DisplayDungeonLoggableMessageTrue(entity, str);
        }
        else {
            DisplayDungeonLoggableMessageFalse(entity, str);
        }
    }

    if (r7) {
        if (arg_4) {
            ret = sub_8040BB0(entity, move, TRUE);
        }
        else {
            ret = sub_8040BB0(entity, move, FALSE);
        }
        sub_8040DA0(entity, move);
    }
    else {
        sub_806CE68(entity, GetEntInfo(entity)->action.direction);
    }

    return ret;
}

struct UnkStruct_sub_800E308_1
{
    s16 unk0;
    s16 unk2;
    DungeonPos unk4;
    DungeonPos unk8;
    s32 unkC;
    s32 unk10;
};

// Maybe DungeonPos? Maybe not, sub_800E308 is called only by sub_8056564, so :shrug:
struct UnkStruct_sub_800E308_2
{
    s16 u0;
    s16 u2;
};

extern s32 sub_800E308(struct UnkStruct_sub_800E308_1 *, struct UnkStruct_sub_800E308_2 *);

#ifdef NONMATCHING // https://decomp.me/scratch/fTUsI
s32 sub_8056564(Entity *entity, DungeonPos *pos, Move *move, s32 r4)
{
    struct UnkStruct_sub_800E308_1 unkSp1;
    struct UnkStruct_sub_800E308_2 unkSp2;
    EntityInfo *entInfo = GetEntInfo(entity);

    if (!gDungeon->unk181e8.blinded && (GetBodySize(entInfo->apparentID) < 4 || r4 == 1)) {
        unkStruct_80BDBC4 *unkStruct = sub_800ECB8(sub_80412E0(move->id, GetApparentWeather(entity), 1));
        s32 unk6 = unkStruct->unk6;
        // This part with unkPos doesn't match
        PixelPos unkPos = {pos->x * 0x1800, pos->y * 0x1800};

        unkPos.x += 0x1000;
        unkPos.y += 0xC00;

        unkSp2.u0 = unkPos.x / 256;
        unkSp2.u2 = unkPos.y / 256;

        if (unk6 != 0) {
            s32 someRetVal;

            sub_800EF10(sub_80412E0(move->id, GetApparentWeather(entity), 1));
            sub_803E46C(0x5E);
            someRetVal = sub_800E710(entInfo->apparentID, sub_80412E0(move->id, GetApparentWeather(entity), 1));
            if (someRetVal != -1) {
                sub_800569C(&unkSp1.unk8,
                            &entity->axObj.axdata,
                            someRetVal);
            }
            else {
                unkSp1.unk8 = (DungeonPos) {0};
            }
            unkSp1.unk0 = sub_80412E0(move->id, GetApparentWeather(entity), 1);
            unkSp1.unk2 = entInfo->apparentID;
            unkSp1.unk4.x = entity->pixelPos.x / 256;
            unkSp1.unk4.y = entity->pixelPos.y / 256;
            unkSp1.unkC = entInfo->action.direction;
            unkSp1.unk10 = 0;

            return sub_800E308(&unkSp1, &unkSp2);
        }
    }

    return -1;
}
#else
NAKED s32 sub_8056564(Entity *entity, DungeonPos *pos, Move *move, s32 r4)
{
    asm_unified("push {r4-r7,lr}\n"
	"	mov r7, r9\n"
	"	mov r6, r8\n"
	"	push {r6,r7}\n"
	"	sub sp, 0x18\n"
	"	adds r6, r0, 0\n"
	"	adds r5, r1, 0\n"
	"	adds r7, r2, 0\n"
	"	adds r4, r3, 0\n"
	"	ldr r0, [r6, 0x70]\n"
	"	mov r8, r0\n"
	"	ldr r0, _08056680\n"
	"	ldr r0, [r0]\n"
	"	ldr r1, _08056684\n"
	"	adds r0, r1\n"
	"	ldrb r0, [r0]\n"
	"	mov r9, r0\n"
	"	cmp r0, 0\n"
	"	beq _0805658C\n"
	"	b _080566E4\n"
	"_0805658C:\n"
	"	mov r2, r8\n"
	"	movs r1, 0x4\n"
	"	ldrsh r0, [r2, r1]\n"
	"	bl GetBodySize\n"
	"	lsls r0, 24\n"
	"	lsrs r0, 24\n"
	"	cmp r0, 0x3\n"
	"	bls _080565A4\n"
	"	cmp r4, 0x1\n"
	"	bne _080565A4\n"
	"	b _080566E4\n"
	"_080565A4:\n"
	"	ldrh r4, [r7, 0x2]\n"
	"	adds r0, r6, 0\n"
	"	bl GetApparentWeather\n"
	"	adds r1, r0, 0\n"
	"	lsls r1, 24\n"
	"	lsrs r1, 24\n"
	"	adds r0, r4, 0\n"
	"	movs r2, 0x1\n"
	"	bl sub_80412E0\n"
	"	lsls r0, 16\n"
	"	lsrs r0, 16\n"
	"	bl sub_800ECB8\n"
	"	movs r2, 0x6\n"
	"	ldrsh r4, [r0, r2]\n"
	"	movs r1, 0\n"
	"	ldrsh r0, [r5, r1]\n"
	"	lsls r1, r0, 1\n"
	"	adds r1, r0\n"
	"	lsls r1, 11\n"
	"	movs r0, 0x2\n"
	"	ldrsh r2, [r5, r0]\n"
	"	lsls r0, r2, 1\n"
	"	adds r0, r2\n"
	"	lsls r0, 11\n"
	"	movs r2, 0x80\n"
	"	lsls r2, 5\n"
	"	adds r3, r0, r2\n"
	"	movs r2, 0xC0\n"
	"	lsls r2, 4\n"
	"	adds r0, r1, r2\n"
	"	cmp r0, 0\n"
	"	bge _080565EC\n"
	"	adds r0, 0xFF\n"
	"_080565EC:\n"
	"	lsls r0, 8\n"
	"	lsrs r0, 16\n"
	"	ldr r1, _08056688\n"
	"	ldr r2, [sp, 0x14]\n"
	"	ands r2, r1\n"
	"	orrs r2, r0\n"
	"	str r2, [sp, 0x14]\n"
	"	adds r0, r3, 0\n"
	"	cmp r0, 0\n"
	"	bge _08056602\n"
	"	adds r0, 0xFF\n"
	"_08056602:\n"
	"	lsls r0, 8\n"
	"	lsrs r0, 16\n"
	"	lsls r0, 16\n"
	"	ldr r1, _0805668C\n"
	"	ands r2, r1\n"
	"	orrs r2, r0\n"
	"	str r2, [sp, 0x14]\n"
	"	cmp r4, 0\n"
	"	beq _080566E4\n"
	"	ldrh r4, [r7, 0x2]\n"
	"	adds r0, r6, 0\n"
	"	bl GetApparentWeather\n"
	"	adds r1, r0, 0\n"
	"	lsls r1, 24\n"
	"	lsrs r1, 24\n"
	"	adds r0, r4, 0\n"
	"	movs r2, 0x1\n"
	"	bl sub_80412E0\n"
	"	lsls r0, 16\n"
	"	lsrs r0, 16\n"
	"	bl sub_800EF10\n"
	"	bl sub_800EF64\n"
	"	movs r0, 0x5E\n"
	"	bl sub_803E46C\n"
	"	mov r0, r8\n"
	"	movs r1, 0x4\n"
	"	ldrsh r5, [r0, r1]\n"
	"	ldrh r4, [r7, 0x2]\n"
	"	adds r0, r6, 0\n"
	"	bl GetApparentWeather\n"
	"	adds r1, r0, 0\n"
	"	lsls r1, 24\n"
	"	lsrs r1, 24\n"
	"	adds r0, r4, 0\n"
	"	movs r2, 0x1\n"
	"	bl sub_80412E0\n"
	"	adds r1, r0, 0\n"
	"	lsls r1, 16\n"
	"	lsrs r1, 16\n"
	"	adds r0, r5, 0\n"
	"	bl sub_800E710\n"
	"	adds r2, r0, 0\n"
	"	movs r0, 0x1\n"
	"	negs r0, r0\n"
	"	cmp r2, r0\n"
	"	beq _08056690\n"
	"	add r0, sp, 0x8\n"
	"	adds r1, r6, 0\n"
	"	adds r1, 0x28\n"
	"	lsls r2, 24\n"
	"	lsrs r2, 24\n"
	"	bl sub_800569C\n"
	"	b _08056694\n"
	"	.align 2, 0\n"
	"_08056680: .4byte gDungeon\n"
	"_08056684: .4byte 0x0001820a\n"
	"_08056688: .4byte 0xffff0000\n"
	"_0805668C: .4byte 0x0000ffff\n"
	"_08056690:\n"
	"	mov r2, r9\n"
	"	str r2, [sp, 0x8]\n"
	"_08056694:\n"
	"	ldrh r4, [r7, 0x2]\n"
	"	adds r0, r6, 0\n"
	"	bl GetApparentWeather\n"
	"	adds r1, r0, 0\n"
	"	lsls r1, 24\n"
	"	lsrs r1, 24\n"
	"	adds r0, r4, 0\n"
	"	movs r2, 0x1\n"
	"	bl sub_80412E0\n"
	"	mov r1, sp\n"
	"	strh r0, [r1]\n"
	"	mov r2, r8\n"
	"	ldrh r0, [r2, 0x4]\n"
	"	strh r0, [r1, 0x2]\n"
	"	ldr r0, [r6, 0xC]\n"
	"	cmp r0, 0\n"
	"	bge _080566BC\n"
	"	adds r0, 0xFF\n"
	"_080566BC:\n"
	"	asrs r0, 8\n"
	"	strh r0, [r1, 0x4]\n"
	"	mov r1, sp\n"
	"	ldr r0, [r6, 0x10]\n"
	"	cmp r0, 0\n"
	"	bge _080566CA\n"
	"	adds r0, 0xFF\n"
	"_080566CA:\n"
	"	asrs r0, 8\n"
	"	strh r0, [r1, 0x6]\n"
	"	mov r0, r8\n"
	"	adds r0, 0x46\n"
	"	ldrb r0, [r0]\n"
	"	str r0, [sp, 0xC]\n"
	"	movs r0, 0\n"
	"	str r0, [sp, 0x10]\n"
	"	add r1, sp, 0x14\n"
	"	mov r0, sp\n"
	"	bl sub_800E308\n"
	"	b _080566E8\n"
	"_080566E4:\n"
	"	movs r0, 0x1\n"
	"	negs r0, r0\n"
	"_080566E8:\n"
	"	add sp, 0x18\n"
	"	pop {r3,r4}\n"
	"	mov r8, r3\n"
	"	mov r9, r4\n"
	"	pop {r4-r7}\n"
	"	pop {r1}\n"
	"	bx r1");
}
#endif // NONMATCHING

// This would signify a new file starts here, but it makes little sense tbh.
UNUSED static const char sPksDirMeme[] = "pksdir0";

static const s32 gUnknown_81069D4[NUM_DIRECTIONS] =
{
    [DIRECTION_SOUTH] = 1,
    [DIRECTION_SOUTHEAST] = 1,
    [DIRECTION_EAST] = 1,
    [DIRECTION_NORTHEAST] = 0,
    [DIRECTION_NORTH] = 0,
    [DIRECTION_NORTHWEST] = 0,
    [DIRECTION_WEST] = 1,
    [DIRECTION_SOUTHWEST] = 1
};

// This function looks important, but what does it do?
void sub_80566F8(Entity *attacker, Move *move, s32 a2, bool8 a3, s32 itemId, s32 isLinkedMove)
{
    DungeonPos var_68;
    DungeonPos var_64;
    Entity *targetsArray[2]; // Only 2 hmm
    s32 var_4C, var_48;
    s32 i, j;
    s32 targetArrId;
    s32 var_3C;
    s32 var_38;
    s32 var_34;
    s32 var_30;
    s32 var_2C;
    s32 var_28, var_24;
    s32 someCount;
    EntityInfo *attackerInfo;
    s32 unkRetVal;
    s32 divResult;
    s32 r9;

    targetArrId = 0;
    someCount = 0;
    attackerInfo = GetEntInfo(attacker);
    unkRetVal = sub_800ED20(move->id);
    var_30 = 2;
    if (unkRetVal != 1) {
        var_30 = 6;
        if (unkRetVal == 2) {
            var_30 = 3;
        }
    }

    var_68.x = attacker->pos.x;
    var_68.y = attacker->pos.y;
    var_4C = gAdjacentTileOffsets[attackerInfo->action.direction].x;
    var_48 = gAdjacentTileOffsets[attackerInfo->action.direction].y;
    for (i = 0; i < a2; i++)
    {
        const Tile *tile;

        if (var_68.x < 0 || var_68.y < 0 || var_68.x > 55 || var_68.y > 31)
            break;

        var_68.x += var_4C;
        var_68.y += var_48;
        someCount++;
        tile = GetTile(var_68.x, var_68.y);
        if (!(tile->terrainType & (TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY)))
            break;
        if (tile->monster != NULL && GetEntityType(tile->monster) == ENTITY_MONSTER)
            break;
    }

    if (MoveRequiresCharging(attacker, move->id) && !MoveMatchesBideClassStatus(attacker, move)) {
        var_34 = -1;
    }
    else {
        var_34 = sub_8056564(attacker, &var_68, move, a2);
    }

    var_68.x = attacker->pos.x;
    var_68.y = attacker->pos.y;
    var_4C = gAdjacentTileOffsets[attackerInfo->action.direction].x;
    var_48 = gAdjacentTileOffsets[attackerInfo->action.direction].y;
    divResult = someCount * (24 / var_30);
    if (a2 > 1) {
        var_3C = divResult + 8;
        if (var_3C >= 64) {
            var_3C = 64;
        }
    }
    else {
        var_3C = 32;
    }

    r9 = 0;
    var_2C = 0x80000 / divResult;
    var_38 = gUnknown_81069D4[attackerInfo->action.direction];
    gDungeon->unk1BDD4.unk1C05E = 1;

    for (i = 0; i < a2; i++)
    {
        DungeonPos var_68Before;
        const Tile *tile;

        if (var_68.x < 0 || var_68.y < 0 || var_68.x > 55 || var_68.y > 31)
            break;

        var_68Before = var_68;
        var_68.x += var_4C;
        var_68.y += var_48;
        if (sub_803F428(&var_68) && !gDungeon->unk181e8.blinded) {
            PixelPos pos32;
            pos32.x = (var_68Before.x * 0x1800) + 0xC00;
            pos32.y = (var_68Before.y * 0x1800) + 0x1000;
            var_28 = var_30 * (var_4C << 8);
            var_24 = var_30 * (var_48 << 8);
            for (j = 0; j < 24 / var_30; j++) {
                if (var_34 >= 0) {
                    s32 r3;
                    s32 r2;

                    if (a3 != 0) {
                        r3 = sin_4096(r9 / 256) * var_3C;
                    }
                    else {
                        r3 = 0;
                    }
                    var_64.x = pos32.x / 256;
                    var_64.y = (pos32.y - r3) / 256;
                    r2 = pos32.y / 256;
                    r2 -= gDungeon->unk181e8.cameraPixelPos.y;
                    r2 /= 2;
                    sub_800E3AC(var_34, &var_64, r2 + var_38);
                }
                sub_803E46C(0x30);
                pos32.x += var_28;
                pos32.y += var_24;
                r9 += var_2C;
            }
        }
        else {
            r9 += (24 / var_30) * var_2C;
        }

        tile = GetTile(var_68.x, var_68.y);
        if (!(tile->terrainType & (TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY)))
            break;
        if (tile->monster != NULL && GetEntityType(tile->monster) == ENTITY_MONSTER && !sub_80571F0(tile->monster, move)) {
            if (targetArrId <= 0) {
                bool8 canHitAnyone = FALSE;
                s32 targetFlags;
                EntityInfo *attackerInfo = GetEntInfo(attacker);
                if (attackerInfo->cringeClassStatus.status == STATUS_CONFUSED
                    || attackerInfo->blinkerClassStatus.status == STATUS_BLINKER
                    || attackerInfo->cringeClassStatus.status == STATUS_COWERING)
                {
                    canHitAnyone = TRUE;
                }
                targetFlags = GetMoveTargetAndRangeForPokemon(attacker, move, FALSE);
                targetArrId = SetNewTarget(targetArrId, targetsArray, targetFlags, attacker, tile->monster, move, canHitAnyone);
            }
            break;
        }
    }

    if (var_34 >= 0) {
        sub_800DC14(var_34);
    }
    sub_804178C(1);
    gDungeon->unk1BDD4.unk1C05E = 0;

    if (targetArrId > 0) {
        targetsArray[targetArrId] = NULL;
        UseMoveAgainstTargets(targetsArray, attacker, move, itemId, isLinkedMove);
    }
    else if (a2 == 1 && sub_803F428(&var_68)) {
        sub_803E708(1, 0x4A);
        sub_8041168(attacker, NULL, move, &var_68);
    }
}

static bool8 AccuracyCalc(Entity *attacker, Entity *target, Move *move, s32 accuracyType, bool8 selfAlwaysHits)
{
    s32 statStageAccuracy, statStageEvasion;
    s32 statStageMul;
    s32 accuracy = GetMoveAccuracyOrAIChance(move, accuracyType);
    s32 rand = DungeonRandInt(100);
    EntityInfo *attackerInfo = GetEntInfo(attacker);
    EntityInfo *targetInfo = GetEntInfo(target);

    if (selfAlwaysHits && attacker == target)
        return TRUE;
    if (move->id == MOVE_REGULAR_ATTACK && IQSkillIsEnabled(attacker, IQ_SURE_HIT_ATTACKER))
        return TRUE;
    if (attackerInfo->sureShotClassStatus.status == STATUS_SURE_SHOT)
        return TRUE;
    if (attackerInfo->sureShotClassStatus.status == STATUS_WHIFFER)
        return FALSE;
    if (accuracy > 100)
        return TRUE;

    if (HasHeldItem(target, ITEM_DETECT_BAND)) {
        accuracy -= gUnknown_80F519C;
    }
    if (IQSkillIsEnabled(target, IQ_QUICK_DODGER)) {
        accuracy -= gUnknown_80F51A0;
    }

    statStageAccuracy = attackerInfo->hitChanceStages[0];
    if (HasAbility(attacker, ABILITY_COMPOUNDEYES)) {
        statStageAccuracy += 2;
    }
    if (move->id == MOVE_THUNDER) {
        s32 weather = GetApparentWeather(attacker);
        if (weather == WEATHER_RAIN) {
            return TRUE;
        }
        else if (weather == WEATHER_SUNNY) {
            statStageAccuracy -= 2;
        }
    }

    if (statStageAccuracy < 0) statStageAccuracy = 0;
    if (statStageAccuracy > 20) statStageAccuracy = 20;

    statStageMul = gUnknown_80F50F4[0][statStageAccuracy];
    if (statStageMul < 0) statStageMul = 0;
    if (statStageMul > (256 * 100)) statStageMul = (256 * 100);

    accuracy *= statStageMul;
    accuracy /= 256;

    statStageEvasion = targetInfo->hitChanceStages[1];
    if (targetInfo->exposed) {
        statStageEvasion = 10;
    }
    if (GetApparentWeather(target) == WEATHER_SANDSTORM && HasAbility(target, ABILITY_SAND_VEIL)) {
        statStageEvasion += 2;
    }
    if (HasAbility(attacker, ABILITY_HUSTLE)) {
        bool32 specialMove = (IsTypePhysical(GetMoveType(move)) == FALSE);
        if (!specialMove) {
            statStageEvasion += 2;
        }
    }

    if (statStageEvasion < 0) statStageEvasion = 0;
    if (statStageEvasion > 20) statStageEvasion = 20;

    statStageMul = gUnknown_80F50F4[1][statStageEvasion];
    if (statStageMul < 0) statStageMul = 0;
    if (statStageMul > (256 * 100)) statStageMul = (256 * 100);

    accuracy *= statStageMul;
    accuracy /= 256;
    if (rand < accuracy)
        return TRUE;
    else
        return FALSE;
}

static void SetTargetsForMove(Entity **targetsArray, Entity *attacker, Move *move)
{
    s32 targetFlags;
    s32 targetFlagsAnd;
    s32 arrId = 0;
    bool8 canHitPartner = (GetEntInfo(attacker)->cringeClassStatus.status == STATUS_CONFUSED
                    || GetEntInfo(attacker)->blinkerClassStatus.status == STATUS_BLINKER
                    || GetEntInfo(attacker)->cringeClassStatus.status == STATUS_COWERING);
    bool8 canHitSelf = (GetEntInfo(attacker)->cringeClassStatus.status == STATUS_CONFUSED || GetEntInfo(attacker)->cringeClassStatus.status == STATUS_COWERING);

    if (IQSkillIsEnabled(attacker, IQ_NONTRAITOR)) {
        canHitSelf = FALSE;
        canHitPartner = FALSE;
    }
    targetFlags = GetMoveTargetAndRangeForPokemon(attacker, move, FALSE);
    if ((targetFlags & 0xF) == 4) {
        bool32 usable = MoveMatchesBideClassStatus(attacker, move);
        if (move->id == MOVE_SOLARBEAM && GetApparentWeather(attacker) == WEATHER_SUNNY) {
            usable = TRUE;
        }
        if (usable)
            targetFlags = 0;
        else
            targetFlags = 0x73;
    }

    targetFlagsAnd = targetFlags & 0xF0;
    if (targetFlagsAnd == 0) {
        Entity *targetEntity = sub_80696A8(attacker);
        if (targetEntity != NULL) {
            arrId = SetNewTarget(arrId, targetsArray, targetFlags, attacker, targetEntity, move, canHitPartner);
        }
    }
    else if (targetFlagsAnd == 0x10 || targetFlagsAnd == 0x20) {
        s32 i;
        s32 direction, to;
        EntityInfo *entInfo = GetEntInfo(attacker);
        if (targetFlagsAnd == 0x20) {
            direction = entInfo->action.direction;
            to = 8;
        }
        else {
            direction = entInfo->action.direction - 1;
            to = 3;
        }
        for (i = 0; i < to; i++, direction++) {
            Entity *targetEntity;
            DungeonPos unkPositon;

            direction &= DIRECTION_MASK;
            unkPositon.x = attacker->pos.x + gAdjacentTileOffsets[direction].x ;
            unkPositon.y = attacker->pos.y + gAdjacentTileOffsets[direction].y;
            targetEntity = GetMonsterAtPos(&unkPositon);
            if (targetEntity != NULL) {
                arrId = SetNewTarget(arrId, targetsArray, targetFlags, attacker, targetEntity, move, canHitPartner);
            }
        }
    }
    else if (targetFlagsAnd == 0x30) {
        s32 i;
        for (i = 0; i < DUNGEON_MAX_POKEMON; i++) {
            Entity *dungeonMon = gDungeon->activePokemon[i];
            if (EntityExists(dungeonMon) && sub_8045A70(attacker, dungeonMon)) {
                if (dungeonMon == attacker) {
                    arrId = SetNewTarget(arrId, targetsArray, targetFlags, attacker, attacker, move, canHitSelf);
                }
                else {
                    arrId = SetNewTarget(arrId, targetsArray, targetFlags, attacker, dungeonMon, move, canHitPartner);
                }
            }
        }
    }
    else if (targetFlagsAnd == 0x40) {
        bool32 r4 = FALSE;
        Entity *targetEntity = sub_80696FC(attacker);
        if (targetEntity != NULL) {
            s32 arrIdBefore = arrId;
            arrId = SetNewTarget(arrId, targetsArray, targetFlags, attacker, targetEntity, move, canHitPartner);
            r4 = (arrId != arrIdBefore);
        }
        if (!r4) {
            targetEntity = sub_806977C(attacker);
            if (targetEntity != NULL) {
                arrId = SetNewTarget(arrId, targetsArray, targetFlags, attacker, targetEntity, move, canHitPartner);
            }
        }
    }
    else if (targetFlagsAnd == 0x50) {
        // Nothing happens here
    }
    else if (targetFlagsAnd == 0x80) {
        Entity *targetEntity = sub_80696FC(attacker);
        if (targetEntity != NULL) {
            arrId = SetNewTarget(arrId, targetsArray, targetFlags, attacker, targetEntity, move, canHitPartner);
        }
    }
    else if (targetFlagsAnd == 0x60) {
        s32 i;
        for (i = 0; i < DUNGEON_MAX_POKEMON; i++) {
            Entity *dungeonMon = gDungeon->activePokemon[i];
            if (EntityExists(dungeonMon)) {
                arrId = SetNewTarget(arrId, targetsArray, targetFlags, attacker, dungeonMon, move, canHitPartner);
            }
        }
    }
    else if (targetFlagsAnd == 0x70) {
        arrId = SetNewTarget(arrId, targetsArray, targetFlags, attacker, attacker, move, canHitPartner);
    }

    targetsArray[arrId] = NULL;
}

static s32 SetNewTarget(s32 targetArrId, Entity **targetsArray, s32 targetFlags_, Entity *attacker, Entity *target, Move *move, bool32 canHitAnyone_)
{
    bool32 canHitTarget;
    EntityInfo *targetInfo;

    // It's happening again, all over the codebase there are problems with s16 arguments, where the lsl/asr asm can't be matched. What is going on with that?
    s32 targetFlags = (s16)targetFlags_;
    bool8 canHitAnyone = canHitAnyone_;
    canHitTarget = FALSE;
    targetInfo = GetEntInfo(target);

    if (move->id == MOVE_BATON_PASS && attacker == target)
        return targetArrId;
    if (targetInfo->shopkeeper == SHOPKEEPER_MODE_SHOPKEEPER)
        return targetArrId;
    if (targetInfo->monsterBehavior == BEHAVIOR_DIGLETT || targetInfo->monsterBehavior == BEHAVIOR_RESCUE_TARGET)
        return targetArrId;

    if (canHitAnyone) {
        canHitTarget = TRUE;
    }
    else {
        s32 targetFlagsAnd = targetFlags & 0xF;
        if (targetFlagsAnd == 0 || targetFlagsAnd == 4) {
            if (GetTreatmentBetweenMonsters(attacker, target, TRUE, FALSE) == 1) {
                canHitTarget = TRUE;
            }
        }
        else if (targetFlagsAnd == 1) {
            if (GetTreatmentBetweenMonsters(attacker, target, TRUE, FALSE) == 0) {
                canHitTarget = TRUE;
            }
        }
        else if (targetFlagsAnd == 2) {
            canHitTarget = TRUE;
        }
        else if (targetFlagsAnd == 5) {
            if (attacker != target) {
                canHitTarget = TRUE;
            }
        }
        else if (targetFlagsAnd == 6) {
            if (GetTreatmentBetweenMonsters(attacker, target, TRUE, FALSE) == 0 && attacker != target) {
                canHitTarget = TRUE;
            }
        }
        else if (targetFlagsAnd == 3) {
            canHitTarget = TRUE;
        }
    }

    if (sub_80571F0(target, move)) {
        canHitTarget = FALSE;
    }

    if (canHitTarget && targetArrId < MAX_MOVE_TARGETS) {
        targetsArray[targetArrId] = target;
        if (!GetEntInfo(target)->isNotTeamMember && gUnknown_203B438 == NULL) {
            gUnknown_203B438 = target;
        }
        targetArrId++;
    }

    return targetArrId;
}

struct MultiTurnChargeMove
{
    u16 moveID;
    u8 status;
};

const struct MultiTurnChargeMove gMultiTurnChargeMoves[10] = {
    {MOVE_SOLARBEAM, STATUS_SOLARBEAM},
    {MOVE_SKY_ATTACK, STATUS_SKY_ATTACK},
    {MOVE_RAZOR_WIND, STATUS_RAZOR_WIND},
    {MOVE_FOCUS_PUNCH, STATUS_FOCUS_PUNCH},
    {MOVE_SKULL_BASH, STATUS_SKULL_BASH},
    {MOVE_FLY, STATUS_FLYING},
    {MOVE_BOUNCE, STATUS_BOUNCING},
    {MOVE_DIVE, STATUS_DIVING},
    {MOVE_DIG, STATUS_DIGGING},
    {MOVE_NOTHING, STATUS_NONE}
};

const u32 gMultiTurnBideClassStatuses[10] = {
    STATUS_SOLARBEAM,
    STATUS_SKY_ATTACK,
    STATUS_RAZOR_WIND,
    STATUS_FOCUS_PUNCH,
    STATUS_SKULL_BASH,
    STATUS_FLYING,
    STATUS_BOUNCING,
    STATUS_DIVING,
    STATUS_DIGGING,
    STATUS_NONE
};

s32 sub_8057070(Move *move)
{
    s32 numberOfChainedHits = GetMoveNumberOfChainedHits(move);
    if (numberOfChainedHits == 0)
        return DungeonRandRange(2, 6);
    else
        return numberOfChainedHits;
}

bool8 MoveCausesPaused(Move *move)
{
    if(move->id == MOVE_FRENZY_PLANT) return TRUE;
    if(move->id == MOVE_HYDRO_CANNON) return TRUE;
    if(move->id == MOVE_HYPER_BEAM) return TRUE;
    if(move->id == MOVE_BLAST_BURN) return TRUE;

    return FALSE;
}

bool8 MoveMatchesBideClassStatus(Entity *pokemon, Move *move)
{
    if (!EntityExists(pokemon))
    {
        return FALSE;
    }
    else
    {
        EntityInfo *pokemonInfo = GetEntInfo(pokemon);
        s32 i;
        for (i = 0; i < 100; i++)
        {
            if (gMultiTurnChargeMoves[i].moveID == MOVE_NOTHING)
            {
                return FALSE;
            }
            if (move->id == gMultiTurnChargeMoves[i].moveID &&
                pokemonInfo->bideClassStatus.status == gMultiTurnChargeMoves[i].status)
            {
                return TRUE;
            }
        }
        return FALSE;
    }
}

bool8 IsChargingAnyTwoTurnMove(Entity *pokemon, bool8 checkCharge)
{
    if (!EntityExists(pokemon))
    {
        return FALSE;
    }
    else
    {
        EntityInfo *pokemonInfo = GetEntInfo(pokemon);
        int i = 0;
        u8 *bideClassStatusPointer = &pokemonInfo->bideClassStatus.status;
        u8 *bideClassStatusPointer2;
        u8 chargeStatus = STATUS_CHARGING;
        for (; i < 100; i++)
        {
            u8 currentStatus = gMultiTurnBideClassStatuses[i];
            u8 bideClassStatus;
            if (currentStatus == STATUS_NONE)
            {
                return FALSE;
            }
            bideClassStatus = *bideClassStatusPointer;
            bideClassStatusPointer2 = &pokemonInfo->bideClassStatus.status;
            if (bideClassStatus == currentStatus)
            {
                return TRUE;
            }
        }
        // BUG: This condition is never reached because the for loop terminates by returning FALSE at the end of the gMultiTurnBideClassStatuses array.
        if (checkCharge && *bideClassStatusPointer2 == chargeStatus)
        {
            return TRUE;
        }
        return FALSE;
    }
}

u32 sub_8057144(Entity * pokemon)
{
    Move *moveStack[80];
    int i, j, nMoves;

    nMoves = 0;
    for (i = 0; i < DUNGEON_MAX_POKEMON; i++)
    {
        Entity *dungeonMon = gDungeon->activePokemon[i];
        if (EntityExists(dungeonMon)) {
            Move *moves = GetEntInfo(dungeonMon)->moves.moves;
            for (j = 0; j < MAX_MON_MOVES; j++)
            {
                if (moves[j].moveFlags & MOVE_FLAG_EXISTS
                    && !MoveRequiresCharging(pokemon, moves[j].id)
                    && moves[j].id != MOVE_SKETCH
                    && nMoves < 80) {
                    moveStack[nMoves++] = &moves[j];
                }
            }
        }
    }

    if (nMoves == 0) {
        return MOVE_REGULAR_ATTACK;
    }
    else {
        return moveStack[DungeonRandInt(nMoves)]->id;
    }
}

bool8 sub_80571F0(Entity * pokemon, Move *move)
{
    u16 moveID;
    s32 tileset;
    EntityInfo *entityInfo;

    entityInfo = GetEntInfo(pokemon);

    if (entityInfo->unkFF == 1) {
        moveID = move->id;
        if ((moveID == MOVE_SKY_UPPERCUT) || (moveID == MOVE_TWISTER) || (moveID == MOVE_GUST) || (moveID == MOVE_THUNDER))
            return FALSE;
        else
            return TRUE;
    }
    else if (entityInfo->unkFF == 2) {
        if (entityInfo->bideClassStatus.status == STATUS_DIVING) {
            if (move->id == MOVE_WHIRLPOOL || move->id == MOVE_SURF) return FALSE;
        }
        else if (entityInfo->bideClassStatus.status == STATUS_DIGGING) {
            moveID = move->id;
            if (moveID == MOVE_EARTHQUAKE || moveID == MOVE_MAGNITUDE) return FALSE;
            if (moveID == MOVE_NATURE_POWER) {
                tileset = gDungeon->tileset;
                if (tileset < 0) {
                    tileset = 0;
                }
                if (0x4a < tileset) {
                    tileset = 0x4a;
                }
                if (gNaturePowerCalledMoves[tileset].moveID == MOVE_EARTHQUAKE) return FALSE;
            }
        }
        return TRUE;
    }
    return FALSE;
}

bool8 sub_805727C(Entity * pokemon, Entity * target, s32 chance)
{
    bool8 uVar2;
    if (sub_8044B28())
        return FALSE;
    if (!EntityExists(pokemon) || !EntityExists(target))
        return FALSE;
    if (GetEntInfo(target)->unk158 == 0 || GetEntInfo(target)->HP == 0)
        return FALSE;

    if (chance != 0) {
        if (HasAbility(pokemon, ABILITY_SERENE_GRACE)) {
            uVar2 = DungeonRandOutcome_2(chance * 2);
        }
        else
        {
            uVar2 = DungeonRandOutcome_2(chance);
        }
    }
    else
    {
        uVar2 = TRUE;
    }

    if (uVar2 && (pokemon != target) && HasAbility(target, ABILITY_SHIELD_DUST))
    {
        sub_80429C8(target);
        return FALSE;
    }

    return uVar2;
}

bool8 RollSecondaryEffect(Entity *pokemon, s32 chance)
{
    if(!EntityExists(pokemon))
        return FALSE;
    if(chance == 0)
        return TRUE;
    if(HasAbility(pokemon, ABILITY_SERENE_GRACE))
        return DungeonRandOutcome_2(chance * 2);
    else
        return DungeonRandOutcome_2(chance);
}

bool8 CanAIUseMove(Entity *pokemon, s32 moveIndex, bool8 hasPPChecker)
{
    s32 i;
    EntityInfo *pokemonInfo = GetEntInfo(pokemon);
    Move *move = &pokemonInfo->moves.moves[moveIndex];
    if (!MoveFlagExists(move))
        return FALSE;
    if (MoveFlagLinkChain(move) || MoveFlagDisabled(move) || MoveFlagSealed(move))
        return FALSE;

    for (i = 0; i < MAX_MON_MOVES; i++) {
        if (CanMonsterUseMove(pokemon, move, hasPPChecker))
            return TRUE;
        move++;
        if (move >= &pokemonInfo->moves.moves[MAX_MON_MOVES])
            break;
        if (!(move->moveFlags & MOVE_FLAG_SUBSEQUENT_IN_LINK_CHAIN))
            break;
    }

    return FALSE;
}

bool8 CanMonsterUseMove(Entity *pokemon, Move *move, bool8 hasPPChecker)
{
    EntityInfo *pokemonInfo = GetEntInfo(pokemon);
    if (move->id == MOVE_REGULAR_ATTACK)
    {
        return TRUE;
    }
    if (move->moveFlags & MOVE_FLAG_DISABLED || move->moveFlags2 & MOVE_FLAG_SEALED)
    {
        return FALSE;
    }
    if (hasPPChecker)
    {
        if (move->PP == 0)
        {
            return FALSE;
        }
        if (pokemonInfo->cringeClassStatus.status == STATUS_TAUNTED && !MoveIgnoresTaunted(move))
        {
            return FALSE;
        }
        if (pokemonInfo->cringeClassStatus.status == STATUS_ENCORE)
        {
            if (move->id == MOVE_STRUGGLE)
            {
                if (!(pokemonInfo->moves.struggleMoveFlags & MOVE_FLAG_LAST_USED))
                {
                    return FALSE;
                }
            }
            else if (!(move->moveFlags & MOVE_FLAG_LAST_USED))
            {
                return FALSE;
            }
        }
    }
    return TRUE;
}

bool8 sub_805744C(Entity * pokemon, Move *move, bool8 param_3)
{
  EntityInfo *entityInfo;

  entityInfo = GetEntInfo(pokemon);
  if (move->id != MOVE_REGULAR_ATTACK) {
    if (((move->moveFlags & MOVE_FLAG_DISABLED)) || ((move->moveFlags2 & MOVE_FLAG_EXISTS))) {
        return FALSE;
    }
    if (param_3 != 0) {
      if ((entityInfo->cringeClassStatus.status == STATUS_TAUNTED) && (!MoveIgnoresTaunted(move))) return FALSE;
      if (entityInfo->cringeClassStatus.status == STATUS_ENCORE) {
        if (move->id == MOVE_STRUGGLE) {
          if((entityInfo->moves.struggleMoveFlags & MOVE_FLAG_LAST_USED) == 0) return FALSE;
        }
        else {
          if((move->moveFlags & MOVE_FLAG_LAST_USED) == 0) return FALSE;
        }
      }
    }
  }
  return TRUE;
}

// Attacker always goes last
static void SortTargets(Entity **targetsArray, Entity *attacker)
{
    Entity *localArray[MAX_MOVE_TARGETS + 1];
    s32 i;
    s32 count = 0;

    for (i = 0; i < MAX_MOVE_TARGETS + 1; i++) {
        if (targetsArray[i] == NULL)
            break;
        if (targetsArray[i] == attacker)
            continue;
        if (count >= MAX_MOVE_TARGETS)
            break;
        localArray[count++] = targetsArray[i];
    }

    for (i = 0; i < MAX_MOVE_TARGETS + 1; i++) {
        if (targetsArray[i] == NULL)
            break;
        if (targetsArray[i] != attacker)
            continue;
        if (count >= MAX_MOVE_TARGETS)
            break;
        localArray[count++] = targetsArray[i];
    }

    for (; count < MAX_MOVE_TARGETS + 1; count++) {
        localArray[count] = NULL;
    }

    for (i = 0; i < MAX_MOVE_TARGETS + 1; i++) {
        targetsArray[i] = localArray[i];
    }
}

// TODO: This file could(should?) be merged with move_actions.c, status_actions.c and move_checks.c into one.
