pmd-red/src/dungeon_move_util.c

1413 lines
45 KiB
C

#include "global.h"
#include "globaldata.h"
#include "dungeon_move_util.h"
#include "constants/ability.h"
#include "constants/iq_skill.h"
#include "constants/status.h"
#include "constants/weather.h"
#include "dungeon_move_util.h"
#include "effect_main.h"
#include "effect_data.h"
#include "effect_sub_1.h"
#include "dungeon_vram.h"
#include "dungeon_tilemap.h"
#include "code_8041AD0.h"
#include "code_806CD90.h"
#include "code_8077274_1.h"
#include "dungeon_random.h"
#include "dungeon_logic.h"
#include "dungeon_config.h"
#include "run_dungeon.h"
#include "dungeon_items.h"
#include "dungeon_map_access.h"
#include "dungeon_message.h"
#include "dungeon_misc.h"
#include "dungeon_move.h"
#include "dungeon_random.h"
#include "dungeon_strings.h"
#include "dungeon_util.h"
#include "math.h"
#include "move_effects_target.h"
#include "move_util.h"
#include "moves.h"
#include "position_util.h"
#include "sprite.h"
#include "status.h"
#include "move_orb_actions_4.h"
#include "weather.h"
#include "targeting_flags.h"
#include "pokemon_types.h"
#include "dungeon_run_end.h"
#include "dungeon_pos_data.h"
#include "dungeon_engine.h"
#include "dungeon_damage.h"
#include "dungeon_leveling.h"
extern void sub_80429C8(Entity *r0);
extern void sub_806A1E8(Entity *pokemon);
extern void sub_804178C(u32);
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_800EF10(u16 r0);
extern void sub_800E3AC(s32 a0, DungeonPos *pos, s32 a2);
extern void sub_8041168(Entity *entity, Entity *entity2, Move *,DungeonPos *);
static u8 ToItemID(u32 itemID);
static EWRAM_INIT Entity *gUnknown_203B438 = NULL;
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 (!EntityIsValid(attacker) || IsFloorOver())
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) {
BufferMoveName(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);
BufferMoveName(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 (!EntityIsValid(attacker) || IsFloorOver())
break;
if (++moveId >= MAX_MON_MOVES)
break;
if (!MOVE_FLAG_LINK_CHAIN(&attackerInfo->moves.moves[moveId]))
break;
}
if (EntityIsValid(attacker)) {
for (i = 0; i < MAX_MON_MOVES; i++) {
if (attackerInfo->mimicMoveIDs[i] != 0) {
Move mimicMove, assistMove;
Move *movePtr;
movePtr = &mimicMove;
InitPokemonMoveOrNullObject(&mimicMove, attackerInfo->mimicMoveIDs[i]);
if (MoveFlagExists(&mimicMove)) {
if (mimicMove.id == MOVE_ASSIST) {
assistMove = mimicMove;
assistMove.id = sub_8057144(attacker);
movePtr = &assistMove;
BufferMoveName(gFormatBuffer_Items[0], &assistMove, NULL);
LogMessageByIdWithPopupCheckUser(attacker, gUnknown_80FD2DC); // Assist:
}
TryUseChosenMove(attacker, 0, itemId, arg_0, isLinkedMove, movePtr);
}
sub_804178C(1);
}
}
}
if (EntityIsValid(attacker)) {
EnemyEvolution(attacker);
if (EntityIsValid(attacker) && gUnknown_202F222 != 0) {
gUnknown_202F222 = 0;
if (EntityIsValid(attacker)) {
EntityInfo *attackerInfo = GetEntInfo(attacker);
s32 statusTurns = CalculateStatusTurns(attacker, gPauseTurnRange, TRUE);
PausedStatusTarget(attacker, attacker, 1, statusTurns, FALSE);
SetExpMultplier(attackerInfo);
}
}
}
return TRUE;
}
void TriggerTargetAbilityEffect(Entity *attacker)
{
if (EntityIsValid(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!
SleepStatusTarget(attacker, attacker, CalculateStatusTurns(attacker, gSleepTurnRange, 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 = gStenchTerrifiedTurnsNo;
}
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);
BufferMoveName(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) {
MarkLastUsedMonMove(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) {
BufferMoveName(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)->usedLinkedMovesCounter < MAX_MON_MOVES) {
GetEntInfo(attacker)->usedLinkedMovesCounter++;
}
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 (!EntityIsValid(attacker) || IsFloorOver())
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 (!EntityIsValid(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 && EntityIsValid(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 = (ShouldDisplayEntity(entity) != FALSE);
if (str != NULL) {
for (i = 0; i < 65; i++) {
if (unkArray[i] == NULL) {
break;
}
if (ShouldDisplayEntity(unkArray[i])) {
r7 = TRUE;
break;
}
}
if (r7) {
SetMessageArgument_2(gFormatBuffer_Monsters[0], GetEntInfo(entity), 0);
if (itemId == 0) {
BufferMoveName(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;
}
s32 sub_8056564(Entity *entity, DungeonPos *pos, Move *move, s32 r4)
{
struct UnkStruct_8040094 unkSp1;
DungeonPos unkSp2;
EntityInfo *entInfo = GetEntInfo(entity);
if (!gDungeon->unk181e8.blinded && (GetBodySize(entInfo->apparentID) < 4 || r4 != 1)) {
s32 unk6 = sub_800ECB8(sub_80412E0(move->id, GetApparentWeather(entity), 1))->unk6;
s32 pixelPosX = X_POS_TO_PIXELPOS(pos->x);
s32 pixelPosY = Y_POS_TO_PIXELPOS(pos->y);
unkSp2.x = pixelPosX / 256;
unkSp2.y = pixelPosY / 256;
if (unk6 != 0) {
s32 someRetVal;
sub_800EF10(sub_80412E0(move->id, GetApparentWeather(entity), 1));
sub_800EF64();
DungeonRunFrameActions(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;
}
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->terrainFlags & (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 = X_POS_TO_PIXELPOS(var_68Before.x);
pos32.y = Y_POS_TO_PIXELPOS(var_68Before.y);
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);
}
DungeonRunFrameActions(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->terrainFlags & (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);
}
}
bool8 AccuracyCalc(Entity *attacker, Entity *target, Move *move, s32 accuracyType, bool8 selfAlwaysHits)
{
s32 statStageAccuracy, statStageEvasion;
s24_8 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 -= gDetectBandAccuracyDebuffValue;
}
if (IQSkillIsEnabled(target, IQ_QUICK_DODGER)) {
accuracy -= gIqQuickDodgerAccuracyDebuffValue;
}
statStageAccuracy = attackerInfo->hitChanceStages[0];
if (AbilityIsActive(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 = gAccEvsStatStageMultipliers[0][statStageAccuracy];
if (statStageMul.raw < 0) statStageMul.raw = 0;
if (statStageMul.raw > IntToF248_2(100).raw) statStageMul = IntToF248_2(100);
accuracy *= statStageMul.raw;
accuracy /= 256;
statStageEvasion = targetInfo->hitChanceStages[1];
if (targetInfo->exposed) {
statStageEvasion = 10;
}
if (GetApparentWeather(target) == WEATHER_SANDSTORM && AbilityIsActive(target, ABILITY_SAND_VEIL)) {
statStageEvasion += 2;
}
if (AbilityIsActive(attacker, ABILITY_HUSTLE)) {
bool32 specialMove = (IsTypePhysical(GetMoveType(move)) == FALSE);
if (!specialMove) {
statStageEvasion += 2;
}
}
if (statStageEvasion < 0) statStageEvasion = 0;
if (statStageEvasion > 20) statStageEvasion = 20;
statStageMul = gAccEvsStatStageMultipliers[1][statStageEvasion];
if (statStageMul.raw < 0) statStageMul.raw = 0;
if (statStageMul.raw > IntToF248_2(100).raw) statStageMul = IntToF248_2(100);
accuracy *= statStageMul.raw;
accuracy /= 256;
if (rand < accuracy)
return TRUE;
else
return FALSE;
}
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 (EntityIsValid(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 (EntityIsValid(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;
}
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 (!EntityIsValid(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 (!EntityIsValid(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 (EntityIsValid(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 (IsFloorOver())
return FALSE;
if (!EntityIsValid(pokemon) || !EntityIsValid(target))
return FALSE;
if (GetEntInfo(target)->unk158 == 0 || GetEntInfo(target)->HP == 0)
return FALSE;
if (chance != 0) {
if (AbilityIsActive(pokemon, ABILITY_SERENE_GRACE)) {
uVar2 = DungeonRandOutcome_2(chance * 2);
}
else
{
uVar2 = DungeonRandOutcome_2(chance);
}
}
else
{
uVar2 = TRUE;
}
if (uVar2 && (pokemon != target) && AbilityIsActive(target, ABILITY_SHIELD_DUST))
{
sub_80429C8(target);
return FALSE;
}
return uVar2;
}
bool8 RollSecondaryEffect(Entity *pokemon, s32 chance)
{
if(!EntityIsValid(pokemon))
return FALSE;
if(chance == 0)
return TRUE;
if(AbilityIsActive(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 (MOVE_FLAG_LINK_CHAIN(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_FLAG_LINK_CHAIN(move))
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
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];
}
}
bool8 MoveRequiresCharging(Entity* pokemon, u16 moveID)
{
if ((moveID == MOVE_SOLARBEAM) && (GetApparentWeather(pokemon) == WEATHER_SUNNY)) {
return FALSE;
}
else {
return DoesMoveCharge(moveID);
}
}
void sub_8057588(Entity * pokemon, u8 param_2)
{
Move *move;
s32 index;
s32 PPtoRemove;
s32 PPCounter;
EntityInfo *entityInfo;
if (EntityIsValid(pokemon)) {
entityInfo = GetEntInfo(pokemon);
for(index = 0; index < MAX_MON_MOVES; index++)
{
move = &entityInfo->moves.moves[index];
if ((move->moveFlags & MOVE_FLAG_EXISTS)) {
PPtoRemove = 1;
if ((move->moveFlags2 & MOVE_FLAG_LAST_USED)) {
move->moveFlags2 &= ~(MOVE_FLAG_LAST_USED);
PPtoRemove = 2;
}
if (((move->moveFlags2 & MOVE_FLAG_SET)) && (move->moveFlags2 &= ~(MOVE_FLAG_SET), param_2 != 0))
{
if(PPtoRemove != 0)
{
PPCounter = PPtoRemove;
for (; PPCounter != 0; PPCounter--) {
if (move->PP != 0) {
move->PP--;
}
}
}
}
}
}
}
}
s16 GetDungeonExitReasonFromMoveOrItem(Move *move, s32 itemID)
{
return GetDungeonExitReasonFromMoveOrItemID(move->id, ToItemID(itemID));
}
static u8 ToItemID(u32 itemID)
{
if(itemID == ITEM_NOTHING)
return ITEM_NOTHING;
else
return itemID;
}