diff --git a/include/dungeon_ai_attack.h b/include/dungeon_ai_attack.h index 70781a844..99e9d5ac4 100644 --- a/include/dungeon_ai_attack.h +++ b/include/dungeon_ai_attack.h @@ -15,11 +15,6 @@ struct AIPossibleMove void ChooseAIMove(Entity *pokemon); s32 AIConsiderMove(struct AIPossibleMove *aiPossibleMove, Entity *pokemon, Move *move); -bool8 IsTargetInLineRange(Entity *user, Entity *target, s32 range); -s32 TryAddTargetToAITargetList(s32 numPotentialTargets, s32 targetingFlags, Entity *user, Entity *target, Move *move, u32 hasStatusChecker); -bool8 IsAITargetEligible(s32 targetingFlags, Entity *user, Entity *target, Move *move, bool32 hasStatusChecker); -s32 WeightMove(Entity *user, s32 targetingFlags, Entity *target, u32 moveType); -bool8 TargetRegularAttack(Entity *pokemon, u32 *targetDir, bool8 checkPetrified); bool8 IsTargetInRange(Entity *pokemon, Entity *targetPokemon, s32 direction, s32 maxRange); void HandleUseMoveAIAction(Entity *target); void HandleUseOrbAction(Entity *pokemon); diff --git a/include/dungeon_range.h b/include/dungeon_range.h index cf726f30b..66c28756a 100644 --- a/include/dungeon_range.h +++ b/include/dungeon_range.h @@ -4,10 +4,10 @@ #include "structs/str_position.h" #include "structs/dungeon_entity.h" -bool8 IsPositionActuallyInSight(DungeonPos *pos1, DungeonPos *pos2); -bool8 IsPositionInSight(DungeonPos *pos1, DungeonPos *pos2); +bool8 IsPositionActuallyInSight(DungeonPos *origin, DungeonPos *target); +bool8 IsPositionInSight(DungeonPos *origin, DungeonPos *target); void sub_80833E8(DungeonPos *param_1, s32 *param_2); -bool8 IsTargetTwoTilesAway(DungeonPos *pos1, DungeonPos *pos2); +bool8 IsPositionWithinTwoTiles(DungeonPos *pos1, DungeonPos *pos2); bool8 sub_8083568(s32 inX, s32 inY, u8 index); Entity* GetLeader(void); EntityInfo* GetLeaderInfo(void); diff --git a/src/dungeon_ai_attack.c b/src/dungeon_ai_attack.c index 0b48ce4c1..f0f0c3330 100644 --- a/src/dungeon_ai_attack.c +++ b/src/dungeon_ai_attack.c @@ -44,6 +44,12 @@ EWRAM_DATA u8 gPotentialAttackTargetDirections[NUM_DIRECTIONS] = {0}; EWRAM_DATA s32 gPotentialAttackTargetWeights[NUM_DIRECTIONS] = {0}; EWRAM_DATA Entity *gPotentialTargets[NUM_DIRECTIONS] = {0}; +static bool8 IsTargetInLineRange(Entity *user, Entity *target, s32 range); +static s32 TryAddTargetToAITargetList(s32 numPotentialTargets, s32 targetingFlags, Entity *user, Entity *target, Move *move, bool32 hasStatusChecker); +static bool8 IsAITargetEligible(s32 targetingFlags, Entity *user, Entity *target, Move *move, bool32 hasStatusChecker); +static s32 WeightMove(Entity *user, s32 targetingFlags, Entity *target, u32 moveType); +static bool8 TargetRegularAttack(Entity *pokemon, u32 *targetDir, bool8 checkPetrified); + void ChooseAIMove(Entity *pokemon) { EntityInfo *pokemonInfo = GetEntInfo(pokemon); @@ -526,59 +532,51 @@ s32 AIConsiderMove(struct AIPossibleMove *aiPossibleMove, Entity *pokemon, Move return moveWeight; } -bool8 IsTargetInLineRange(Entity *user, Entity *target, s32 range) +static bool8 IsTargetInLineRange(Entity *user, Entity *target, s32 range) { s32 direction; s32 distanceX = abs(user->pos.x - target->pos.x); s32 distanceY = abs(user->pos.y - target->pos.y); s32 distance = max(distanceX, distanceY); - if (distance > RANGED_ATTACK_RANGE || distance > range) - { + if (distance > RANGED_ATTACK_RANGE || distance > range) { return FALSE; } direction = -1; - if (distanceX == distanceY) - { - if (user->pos.x < target->pos.x && - (user->pos.y < target->pos.y || user->pos.y > target->pos.y)) - { - returnTrue: - return TRUE; + if (distanceX == distanceY) { + if (user->pos.x < target->pos.x && user->pos.y < target->pos.y) { + direction = DIRECTION_SOUTH; } - if (user->pos.x > target->pos.x); // Fixes register loading order. - direction = DIRECTION_SOUTHWEST; - if (user->pos.x <= target->pos.x || user->pos.y <= target->pos.y) - { - goto checkDirectionSet; + else if (user->pos.x < target->pos.x && user->pos.y > target->pos.y) { + direction = DIRECTION_EAST; + } + else if (user->pos.x > target->pos.x && user->pos.y > target->pos.y) { + direction = DIRECTION_NORTH; + } + else { + direction = DIRECTION_SOUTHWEST; } - goto returnTrue; } - else if (user->pos.x == target->pos.x && user->pos.y < target->pos.y) - { - return TRUE; + else if (user->pos.x == target->pos.x && user->pos.y < target->pos.y) { + direction = DIRECTION_SOUTH; } - else if (user->pos.x < target->pos.x && user->pos.y == target->pos.y) - { - return TRUE; + else if (user->pos.x < target->pos.x && user->pos.y == target->pos.y) { + direction = DIRECTION_SOUTHEAST; } - else if (user->pos.x == target->pos.x && user->pos.y > target->pos.y) - { - return TRUE; + else if (user->pos.x == target->pos.x && user->pos.y > target->pos.y) { + direction = DIRECTION_NORTHEAST; } - else if (user->pos.x > target->pos.x && user->pos.y == target->pos.y) - { + else if (user->pos.x > target->pos.x && user->pos.y == target->pos.y) { direction = DIRECTION_WEST; } - checkDirectionSet: - if (direction < 0) - { - return FALSE; + + if (direction >= 0) { + return TRUE; } - return TRUE; + return FALSE; } -s32 TryAddTargetToAITargetList(s32 numPotentialTargets, s32 targetingFlags, Entity *user, Entity *target, Move *move, bool32 hasStatusChecker) +static s32 TryAddTargetToAITargetList(s32 numPotentialTargets, s32 targetingFlags, Entity *user, Entity *target, Move *move, bool32 hasStatusChecker) { s32 direction; s32 targetingFlags2 = (s16) targetingFlags; @@ -607,7 +605,7 @@ s32 TryAddTargetToAITargetList(s32 numPotentialTargets, s32 targetingFlags, Enti return numPotentialTargets; } -bool8 IsAITargetEligible(s32 targetingFlags, Entity *user, Entity *target, Move *move, bool32 hasStatusChecker) +static bool8 IsAITargetEligible(s32 targetingFlags, Entity *user, Entity *target, Move *move, bool32 hasStatusChecker) { EntityInfo *targetData; s32 targetingFlags2 = (s16) targetingFlags; @@ -733,7 +731,7 @@ bool8 IsAITargetEligible(s32 targetingFlags, Entity *user, Entity *target, Move return hasTarget; } -s32 WeightMove(Entity *user, s32 targetingFlags, Entity *target, u32 moveType) +static s32 WeightMove(Entity *user, s32 targetingFlags, Entity *target, u32 moveType) { EntityInfo *targetData; s32 targetingFlags2 = (s16) targetingFlags; @@ -767,7 +765,7 @@ s32 WeightMove(Entity *user, s32 targetingFlags, Entity *target, u32 moveType) return weight; } -bool8 TargetRegularAttack(Entity *pokemon, u32 *targetDir, bool8 checkPetrified) +static bool8 TargetRegularAttack(Entity *pokemon, u32 *targetDir, bool8 checkPetrified) { EntityInfo *pokemonInfo = GetEntInfo(pokemon); s32 numPotentialTargets = 0; diff --git a/src/dungeon_ai_movement.c b/src/dungeon_ai_movement.c index 996117772..2dd6cf2d2 100644 --- a/src/dungeon_ai_movement.c +++ b/src/dungeon_ai_movement.c @@ -369,7 +369,7 @@ void DecideMovement(Entity *pokemon, bool8 showRunAwayEffect) if (ShouldAvoidFirstHit(pokemon, pokemonInfo->aiTarget.aiTargetingEnemy)) { if (pokemonInfo->aiTarget.aiObjective == AI_CHASE_TARGET && - IsTargetTwoTilesAway(&pokemon->pos, &pokemonInfo->aiTarget.aiTargetPos)) + IsPositionWithinTwoTiles(&pokemon->pos, &pokemonInfo->aiTarget.aiTargetPos)) { s32 distance = GetDistance(&pokemon->pos, &pokemonInfo->aiTarget.aiTargetPos); if (distance == 2) diff --git a/src/dungeon_range.c b/src/dungeon_range.c index 02b49c5ec..5434ad716 100644 --- a/src/dungeon_range.c +++ b/src/dungeon_range.c @@ -13,96 +13,70 @@ EWRAM_INIT Entity *gLeaderPointer = NULL; -bool8 IsPositionActuallyInSight(DungeonPos *pos1, DungeonPos *pos2) +// Actual function in Sky. TODO: Find other uses of it and sync with Sky. +static inline s32 GetVisibilityRange(void) { - u8 pos1Room; - u8 visibility = gDungeon->unk181e8.visibilityRange; - const Tile *tile1; - if (visibility == 0) - { - visibility = 2; - } - tile1 = GetTile(pos1->x, pos1->y); - pos1Room = tile1->room; - if (pos1Room == CORRIDOR_ROOM) - { - s32 xDiff = pos1->x - pos2->x; - s32 yDiff; - xDiff = xDiff < 0 ? -xDiff : xDiff; - if (xDiff > visibility) - { - return FALSE; - } + s32 visibilityRange = gDungeon->unk181e8.visibilityRange; + if (visibilityRange == 0) + return 2; - yDiff = pos1->y - pos2->y; - yDiff = yDiff < 0 ? -yDiff : yDiff; - if (yDiff > visibility) - { - return FALSE; - } - returnTrue: - return TRUE; - } - else - { - struct RoomData *pos1RoomData = &gDungeon->roomData[pos1Room]; - if (pos1RoomData->bottomRightCornerX - 1 > pos2->x || pos1RoomData->bottomRightCornerY - 1 > pos2->y || - pos1RoomData->topLeftCornerX + 1 <= pos2->x || pos1RoomData->topLeftCornerY + 1 <= pos2->y) - { - return FALSE; - } - goto returnTrue; - } + return visibilityRange; } -bool8 IsPositionInSight(DungeonPos *pos1, DungeonPos *pos2) +bool8 IsPositionActuallyInSight(DungeonPos *origin, DungeonPos *target) { - const Tile *tile; - u8 pos1Room; - s32 xDiff; - s32 yDiff; - s32 x1; - s32 x2; - s32 y1; - s32 y2; - - tile = GetTile(pos1->x,pos1->y); - pos1Room = tile->room; - if (pos1Room != CORRIDOR_ROOM) { - struct RoomData *pos1RoomData = &gDungeon->roomData[pos1Room]; - if (pos1RoomData->bottomRightCornerX - 1 > pos2->x || pos1RoomData->bottomRightCornerY - 1 > pos2->y || - pos1RoomData->topLeftCornerX + 1 <= pos2->x || pos1RoomData->topLeftCornerY + 1 <= pos2->y) - { - goto _08083394; - } - } - else - { -_08083394: - - x1 = pos1->x; - x2 = pos2->x; - - y1 = pos1->y; - y2 = pos2->y; - - yDiff = y1 - y2; - xDiff = x1 - x2; - - xDiff = xDiff < 0 ? -xDiff : xDiff; - yDiff = yDiff < 0 ? -yDiff : yDiff; - - if (yDiff < xDiff) { - yDiff = xDiff; + s32 visibility = GetVisibilityRange(); + const Tile *tile1 = GetTile(origin->x, origin->y); + u8 originRoom = tile1->room; + if (originRoom == CORRIDOR_ROOM) { + if (abs(origin->x - target->x) <= visibility && abs(origin->y - target->y) <= visibility) + return TRUE; } - if ((2 < yDiff)) -returnFalse: + else { + struct RoomData *originRoomData = &gDungeon->roomData[originRoom]; + if (originRoomData->bottomRightCornerX - 1 <= target->x && + originRoomData->bottomRightCornerY - 1 <= target->y && + originRoomData->topLeftCornerX + 1 > target->x && + originRoomData->topLeftCornerY + 1 > target->y) + return TRUE; + } + + return FALSE; +} + +bool8 IsPositionInSight(DungeonPos *origin, DungeonPos *target) +{ + s32 diff; + const Tile *tile = GetTile(origin->x,origin->y); + u8 originRoom = tile->room; + if (originRoom != CORRIDOR_ROOM) { + struct RoomData *originRoomData = &gDungeon->roomData[originRoom]; + if (originRoomData->bottomRightCornerX - 1 <= target->x && + originRoomData->bottomRightCornerY - 1 <= target->y && + originRoomData->topLeftCornerX + 1 > target->x && + originRoomData->topLeftCornerY + 1 > target->y) + return TRUE; + } + + // This looks like a static inline / macro, but I can't get it right for both Red/Sky. See also HandleCurvedProjectileThrow + { + s32 x = origin->x - target->x; + s32 y = origin->y - target->y; + s32 absX = abs(x); + s32 absY = abs(y); + diff = max(absX, absY); + } + + if (diff > 2) return FALSE; - else if((yDiff == 2) && (!IsTargetTwoTilesAway(pos1,pos2))) { - goto returnFalse; + else if (diff == 2) { + if (IsPositionWithinTwoTiles(origin, target)) + return TRUE; + else + return FALSE; } - } - return TRUE; + + return TRUE; } void sub_80833E8(DungeonPos *param_1, s32 *param_2) @@ -133,7 +107,7 @@ void sub_80833E8(DungeonPos *param_1, s32 *param_2) } } -bool8 IsTargetTwoTilesAway(DungeonPos *pos1, DungeonPos *pos2) +bool8 IsPositionWithinTwoTiles(DungeonPos *pos1, DungeonPos *pos2) { s32 i; const Tile *tile;