diff options
Diffstat (limited to 'src/dungeon_ai_attack_1.c')
-rw-r--r-- | src/dungeon_ai_attack_1.c | 224 |
1 files changed, 43 insertions, 181 deletions
diff --git a/src/dungeon_ai_attack_1.c b/src/dungeon_ai_attack_1.c index cef0aac..641bc8c 100644 --- a/src/dungeon_ai_attack_1.c +++ b/src/dungeon_ai_attack_1.c @@ -1,214 +1,76 @@ #include "global.h" #include "dungeon_ai_attack_1.h" -#include "constants/direction.h" #include "constants/iq_skill.h" -#include "constants/targeting.h" -#include "constants/type.h" -#include "dungeon_ai_targeting_2.h" #include "dungeon_global_data.h" +#include "dungeon_map_access.h" #include "dungeon_pokemon_attributes.h" -#include "dungeon_random.h" -#include "moves.h" -#include "position_util.h" -#include "status_checker.h" -#include "status_checks_1.h" -#include "type_effectiveness.h" +#include "dungeon_util.h" -extern bool8 gCanAttackInDirection[NUM_DIRECTIONS]; -extern s32 gPotentialAttackTargetWeights[NUM_DIRECTIONS]; -extern u8 gPotentialAttackTargetDirections[NUM_DIRECTIONS]; -extern struct DungeonEntity *gPotentialTargets[NUM_DIRECTIONS]; - -s32 WeightMoveIfUsable(s32 numPotentialTargets, s32 targetingFlags, struct DungeonEntity *user, struct DungeonEntity *target, struct PokemonMove *move, bool32 hasStatusChecker) +bool8 IsTargetStraightAhead(struct DungeonEntity *pokemon, struct DungeonEntity *targetPokemon, s32 facingDir, s32 maxRange) { - s32 facingDir; - s32 targetingFlags2 = (s16) targetingFlags; - bool8 hasStatusChecker2 = hasStatusChecker; - struct DungeonEntityData *userData = user->entityData; - if ((user->posWorld.x == target->posWorld.x && user->posWorld.y == target->posWorld.y) || - (targetingFlags2 & 0xF0) == TARGETING_FLAG_TARGET_ROOM || - (targetingFlags2 & 0xF0) == TARGETING_FLAG_TARGET_FLOOR || - (targetingFlags2 & 0xF0) == TARGETING_FLAG_TARGET_SELF) - { - facingDir = userData->action.facingDir; - } - else - { - facingDir = CalculateFacingDir(&user->posWorld, &target->posWorld); - } - if (!gCanAttackInDirection[facingDir] && - CanUseStatusMove(targetingFlags2, user, target, move, hasStatusChecker2)) + s32 posDiffX = pokemon->posWorld.x - targetPokemon->posWorld.x; + s32 effectiveMaxRange; + if (posDiffX < 0) { - gCanAttackInDirection[facingDir] = TRUE; - do { gPotentialAttackTargetDirections[numPotentialTargets] = facingDir; } while (0); - gPotentialAttackTargetWeights[numPotentialTargets] = WeightMove(user, targetingFlags2, target, GetMoveTypeForPokemon(user, move)); - gPotentialTargets[numPotentialTargets] = target; - numPotentialTargets++; + posDiffX = -posDiffX; } - return numPotentialTargets; -} - -bool8 CanUseStatusMove(s32 targetingFlags, struct DungeonEntity *user, struct DungeonEntity *target, struct PokemonMove *move, bool32 hasStatusChecker) -{ - struct DungeonEntityData *targetData; - s32 targetingFlags2 = (s16) targetingFlags; - bool8 hasStatusChecker2 = hasStatusChecker; - bool8 hasTarget = FALSE; - u32 categoryTargetingFlags = targetingFlags2 & 0xF; - u32 *categoryTargetingFlags2 = &categoryTargetingFlags; // Fixes a regswap. - if (*categoryTargetingFlags2 == TARGETING_FLAG_TARGET_OTHER) + effectiveMaxRange = pokemon->posWorld.y - targetPokemon->posWorld.y; + if (effectiveMaxRange < 0) { - if (CanTarget(user, target, FALSE, TRUE) == TARGET_CAPABILITY_CAN_TARGET) - { - hasTarget = TRUE; - } + effectiveMaxRange = -effectiveMaxRange; } - else if (categoryTargetingFlags == TARGETING_FLAG_HEAL_TEAM) + if (effectiveMaxRange < posDiffX) { - goto checkCanTarget; + effectiveMaxRange = posDiffX; } - else if (categoryTargetingFlags == TARGETING_FLAG_LONG_RANGE) + if (effectiveMaxRange > maxRange) { - targetData = target->entityData; - goto checkThirdParty; + effectiveMaxRange = maxRange; } - else if (categoryTargetingFlags == TARGETING_FLAG_ATTACK_ALL) + if (!HasIQSkill(pokemon, IQ_SKILL_COURSE_CHECKER)) { - targetData = target->entityData; - if (user == target) + // BUG: effectiveMaxRange is already capped at maxRange, so this condition always evaluates to TRUE. + // The AI also has range checks elsewhere, so this doesn't become an issue in most cases. + // If the AI has the Long Toss or Pierce statuses and Course Checker is disabled, + // this incorrect check causes the AI to throw items at targets further than 10 tiles away. + if (effectiveMaxRange <= maxRange) { - goto returnFalse; - } - checkThirdParty: - hasTarget = TRUE; - if (targetData->shopkeeperMode == SHOPKEEPER_FRIENDLY || - targetData->clientType == CLIENT_TYPE_DONT_MOVE || - targetData->clientType == CLIENT_TYPE_CLIENT) - { - returnFalse: - return FALSE; + return TRUE; } } - else if (categoryTargetingFlags == TARGETING_FLAG_BOOST_TEAM) - { - if (user == target) - { - goto returnFalse; - } - checkCanTarget: - if (CanTarget(user, target, FALSE, TRUE) == TARGET_CAPABILITY_CANNOT_ATTACK) - { - hasTarget = TRUE; - } - } - else if ((u16) (categoryTargetingFlags - 3) <= 1) // categoryTargetingFlags == TARGETING_FLAG_ITEM - { - hasTarget = TRUE; - } - - if (hasTarget) + else { - if (hasStatusChecker2) + s32 currentPosX = pokemon->posWorld.x; + s32 currentPosY = pokemon->posWorld.y; + s32 adjacentTileOffsetX = gAdjacentTileOffsets[facingDir].x; + s32 adjacentTileOffsetY = gAdjacentTileOffsets[facingDir].y; + s32 i; + for (i = 0; i <= effectiveMaxRange; i++) { - if (!CanUseOnTargetWithStatusChecker(user, target, move)) + struct MapTile *mapTile; + currentPosX += adjacentTileOffsetX; + currentPosY += adjacentTileOffsetY; + if (currentPosX <= 0 || currentPosY <= 0 || + currentPosX >= DUNGEON_MAX_SIZE_X - 1 || currentPosY >= DUNGEON_MAX_SIZE_Y - 1) { - goto returnFalse; + break; } - if ((targetingFlags2 & 0xF00) == TARGETING_FLAG_SET_TRAP) + while (0); // Extra label needed to swap branch locations in ASM. + mapTile = GetMapTile_1(currentPosX, currentPosY); + if (!(mapTile->tileType & (TILE_TYPE_FLOOR | TILE_TYPE_LIQUID))) { - goto rollMoveUseChance; + break; } - else if ((targetingFlags2 & 0xF00) == TARGETING_FLAG_HEAL_HP) + if (mapTile->pokemon == targetPokemon) { - if (!HasQuarterHPOrLess(target)) - { - if (*categoryTargetingFlags2); - goto returnFalse; - } + return TRUE; } - else if ((targetingFlags2 & 0xF00) == TARGETING_FLAG_HEAL_STATUS) + if (mapTile->pokemon != NULL) { - if (!HasNegativeStatus(target)) - { - if (*categoryTargetingFlags2); // Flips the conditional. - goto returnFalse; - } - } - else if ((targetingFlags2 & 0xF00) == TARGETING_FLAG_DREAM_EATER) - { - if (!IsSleeping(target)) - { - if (*categoryTargetingFlags2); // Flips the conditional. - goto returnFalse; - } - } - else if ((targetingFlags2 & 0xF00) == TARGETING_FLAG_EXPOSE) - { - targetData = target->entityData; - if ((targetData->types[0] != TYPE_GHOST && targetData->types[1] != TYPE_GHOST) || targetData->exposedStatus) - { - if (*categoryTargetingFlags2); // Flips the conditional. - goto returnFalse; - } - } - else if ((targetingFlags2 & 0xF00) == TARGETING_FLAG_HEAL_ALL) - { - if (!HasNegativeStatus(target) && !HasQuarterHPOrLess(target)) - { - if (*categoryTargetingFlags2); // Flips the conditional. - goto returnFalse; - } + break; } } - else if ((targetingFlags2 & 0xF00) == TARGETING_FLAG_SET_TRAP) - { - s32 useChance; - rollMoveUseChance: - useChance = GetMoveAccuracy(move, ACCURACY_TYPE_USE_CHANCE); - if (DungeonRandomCapped(100) >= useChance) - { - goto returnFalse; - } - } - } - return hasTarget; -} - -s32 WeightMove(struct DungeonEntity *user, s32 targetingFlags, struct DungeonEntity *target, u32 moveType) -{ -#ifndef NONMATCHING - register struct DungeonEntityData *targetData asm("r4"); -#else - struct DungeonEntityData *targetData; -#endif - s32 targetingFlags2 = (s16) targetingFlags; - u8 moveType2 = moveType; - u8 weight = 1; - struct DungeonEntityData *targetData2; - targetData2 = targetData = target->entityData; - if (!targetData->isEnemy || (targetingFlags2 & 0xF) != TARGETING_FLAG_TARGET_OTHER) - { - return 1; - } - else if (HasIQSkill(user, IQ_SKILL_EXP_GO_GETTER)) - { - // BUG: expYieldRankings has lower values as the Pokémon's experience yield increases. - // This causes Exp. Go-Getter to prioritizes Pokémon worth less experience - // instead of Pokémon worth more experience. - weight = gDungeonGlobalData->expYieldRankings[targetData->entityID]; - } - else if (HasIQSkill(user, IQ_SKILL_EFFICIENCY_EXPERT)) - { - weight = -12 - targetData2->HP; - if (weight == 0) - { - weight = 1; - } - } - else if (HasIQSkill(user, IQ_SKILL_WEAK_TYPE_PICKER)) - { - weight = WeightWeakTypePicker(user, target, moveType2) + 1; } - return weight; + return FALSE; } |