From f728e7e90ebd50521dbc32f7f2b2be5858d91477 Mon Sep 17 00:00:00 2001 From: AnonymousRandomPerson Date: Fri, 4 Feb 2022 23:13:01 -0500 Subject: Decomped DecideAttack() --- src/dungeon_ai_attack.c | 332 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 289 insertions(+), 43 deletions(-) (limited to 'src/dungeon_ai_attack.c') diff --git a/src/dungeon_ai_attack.c b/src/dungeon_ai_attack.c index 5794038..e695422 100644 --- a/src/dungeon_ai_attack.c +++ b/src/dungeon_ai_attack.c @@ -1,76 +1,322 @@ #include "global.h" #include "dungeon_ai_attack.h" +#include "constants/direction.h" +#include "constants/dungeon_action.h" #include "constants/iq_skill.h" -#include "dungeon_global_data.h" -#include "dungeon_map_access.h" +#include "constants/move_id.h" +#include "constants/status.h" +#include "constants/tactic.h" +#include "constants/type.h" +#include "dungeon_action.h" +#include "dungeon_ai.h" +#include "dungeon_capabilities_1.h" +#include "dungeon_pokemon_attributes.h" #include "dungeon_pokemon_attributes_1.h" -#include "dungeon_util.h" +#include "dungeon_random.h" +#include "dungeon_random_1.h" +#include "moves.h" +#include "status_checks.h" -bool8 IsTargetStraightAhead(struct DungeonEntity *pokemon, struct DungeonEntity *targetPokemon, s32 facingDir, s32 maxRange) +#define REGULAR_ATTACK_INDEX 4 + +const s16 gRegularAttackWeights[] = {100, 20, 30, 40, 50}; + +struct MoveTargetResults +{ + bool8 moveUsable; + u8 targetDir; + s32 moveWeight; +}; + +extern bool8 IsChargeMove(struct DungeonEntity*, struct PokemonMove*); +extern void TargetTileInFront(struct DungeonEntity*); +extern s32 FindMoveTarget(struct MoveTargetResults*, struct DungeonEntity*, struct PokemonMove*); +extern bool8 IsMoveUsable(struct DungeonEntity*, s32, bool8); +extern bool8 TargetRegularAttack(struct DungeonEntity*, u32*, bool8); + +void DecideAttack(struct DungeonEntity *pokemon) { - s32 posDiffX = pokemon->posWorld.x - targetPokemon->posWorld.x; - s32 effectiveMaxRange; - if (posDiffX < 0) + struct DungeonEntityData *pokemonData = pokemon->entityData; + s32 i; + s32 chargeStatus = CHARGING_STATUS_CHARGE; + struct MoveTargetResults moveTargetResults[MAX_MON_MOVES + 1]; + bool8 willNotUnlinkMove[MAX_MON_MOVES]; + s32 randomWeight; + bool8 hasPPChecker; + s32 numUsableMoves; + s32 total; + s32 weightCounter; + bool8 hasWeakTypePicker; + s32 regularAttackTargetDir; + bool8 canTargetRegularAttack; + s32 maxWeight; + if (CannotAttack(pokemon, FALSE) || + ShouldAvoidEnemiesAndShowEffect(pokemon, TRUE) || + HasTactic(pokemon, TACTIC_KEEP_YOUR_DISTANCE) || + (pokemonData->volatileStatus == VOLATILE_STATUS_CONFUSED && RollPercentChance(gConfusedAttackChance))) { - posDiffX = -posDiffX; + return; } - effectiveMaxRange = pokemon->posWorld.y - targetPokemon->posWorld.y; - if (effectiveMaxRange < 0) + if (pokemonData->chargingStatus != CHARGING_STATUS_NONE) { - effectiveMaxRange = -effectiveMaxRange; + for (i = 0; i < MAX_MON_MOVES; i++) + { + if (pokemonData->moves[i].moveFlags & MOVE_FLAG_EXISTS && + IsChargeMove(pokemon, &pokemonData->moves[i]) && + pokemonData->chargingStatusMoveIndex == i) + { + s32 chosenMoveIndex; + SetAction(&pokemonData->action, DUNGEON_ACTION_USE_MOVE_AI); + chosenMoveIndex = i; + if (i > 0 && pokemonData->moves[i].moveFlags & MOVE_FLAG_LINKED) + { + while (--chosenMoveIndex > 0) + { + if (!(pokemonData->moves[chosenMoveIndex].moveFlags & MOVE_FLAG_LINKED)) + { + break; + } + } + } + pokemonData->action.actionUseIndex = chosenMoveIndex; + TargetTileInFront(pokemon); + return; + } + } } - if (effectiveMaxRange < posDiffX) + total = 0; + numUsableMoves = 0; + for (i = 0; i < MAX_MON_MOVES; i++) { - effectiveMaxRange = posDiffX; + struct PokemonMove *move = &pokemonData->moves[i]; + if (pokemonData->moves[i].moveFlags & MOVE_FLAG_EXISTS) + { + if (pokemonData->moves[i].moveFlags & MOVE_FLAG_ENABLED) + { + numUsableMoves++; + } + total += move->PP; + } + } + if (total == 0) + { + struct PokemonMove struggle; + InitPokemonMove(&struggle, MOVE_STRUGGLE); + FindMoveTarget(&moveTargetResults[0], pokemon, &struggle); + if (moveTargetResults[0].moveUsable) + { + SetAction(&pokemonData->action, DUNGEON_ACTION_STRUGGLE); + pokemonData->action.facingDir = moveTargetResults[0].targetDir & DIRECTION_MASK; + TargetTileInFront(pokemon); + } + return; } - if (effectiveMaxRange > maxRange) + hasWeakTypePicker = HasIQSkill(pokemon, IQ_SKILL_WEAK_TYPE_PICKER); + hasPPChecker = HasIQSkill(pokemon, IQ_SKILL_PP_CHECKER) != FALSE; + total = 0; + for (i = 0; i < MAX_MON_MOVES; i++) { - effectiveMaxRange = maxRange; + willNotUnlinkMove[i] = TRUE; } - if (!HasIQSkill(pokemon, IQ_SKILL_COURSE_CHECKER)) + if (hasPPChecker) { - // 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) + s32 minPP = 99; + s32 linkedMoveStartIndex = 0; + // Linked moves unlink if any move in the chain runs out of PP. + // With PP Checker, the AI avoids this by not using linked moves if any move in the chain has 1 PP left. + // This requires a separate check from the 0-PP check used for unlinked moves. + for (i = 0; i < MAX_MON_MOVES; i++) { - return TRUE; + struct PokemonMove *move = &pokemonData->moves[i]; + if (!(move->moveFlags & MOVE_FLAG_EXISTS)) + { + break; + } + if (i != 0 && !(move->moveFlags & MOVE_FLAG_LINKED)) + { + if (linkedMoveStartIndex + 1 < i && minPP <= 1 && linkedMoveStartIndex + 1 <= i) + { + s32 j; + for (j = linkedMoveStartIndex; j < i; j++) + { + willNotUnlinkMove[j] = FALSE; + } + } + minPP = move->PP; + linkedMoveStartIndex = i; + } + else + { + s32 newMinPP = move->PP; + if (newMinPP > minPP) + { + newMinPP = minPP; + } + minPP = newMinPP; + } + } + if (linkedMoveStartIndex + 1 < i && minPP <= 1 && linkedMoveStartIndex + 1 <= i) + { + s32 j; + for (j = linkedMoveStartIndex; j < i; j++) + { + willNotUnlinkMove[j] = FALSE; + } } } - else + for (i = 0; i < MAX_MON_MOVES; i++) + { + struct PokemonMove *move; + moveTargetResults[i].moveUsable = FALSE; + move = &pokemonData->moves[i]; + if (move->moveFlags & MOVE_FLAG_EXISTS && + willNotUnlinkMove[i] && + IsMoveUsable(pokemon, i, hasPPChecker) && + move->moveFlags & MOVE_FLAG_ENABLED) + { + moveTargetResults[i].moveUsable = TRUE; + if (pokemonData->chargingStatus == chargeStatus) + { + if (move->moveID == MOVE_CHARGE) + { + moveTargetResults[i].moveWeight = 0; + continue; + } + else if (GetMoveTypeForPokemon(pokemon, move) == TYPE_ELECTRIC) + { + moveTargetResults[i].moveWeight = GetMoveWeight(move); + } + else + { + moveTargetResults[i].moveWeight = 1; + } + } + else if (hasWeakTypePicker) + { + struct MoveTargetResults *results = &moveTargetResults[i]; + results->moveWeight = FindMoveTarget(results, pokemon, move); + } + else + { + moveTargetResults[i].moveWeight = GetMoveWeight(move); + } + total += moveTargetResults[i].moveWeight; + } + } + moveTargetResults[REGULAR_ATTACK_INDEX].moveWeight = 0; + if (!HasIQSkill(pokemon, IQ_SKILL_EXCLUSIVE_MOVE_USER) && pokemonData->chargingStatus != chargeStatus) + { + moveTargetResults[REGULAR_ATTACK_INDEX].moveUsable = TRUE; + if (pokemonData->chargingStatus == chargeStatus) + { + // Never reached? Charge already skips the regular attack in the outer block. + moveTargetResults[REGULAR_ATTACK_INDEX].moveWeight = 1; + } + else if (hasWeakTypePicker) + { + moveTargetResults[REGULAR_ATTACK_INDEX].moveWeight = 2; + } + else + { + moveTargetResults[REGULAR_ATTACK_INDEX].moveWeight = gRegularAttackWeights[numUsableMoves]; + } + total += moveTargetResults[REGULAR_ATTACK_INDEX].moveWeight; + } + if (hasWeakTypePicker) { - 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++) + maxWeight = 0; + total = 0; + for (i = 0; i < MAX_MON_MOVES + 1; i++) { - struct MapTile *mapTile; - currentPosX += adjacentTileOffsetX; - currentPosY += adjacentTileOffsetY; - if (currentPosX <= 0 || currentPosY <= 0 || - currentPosX >= DUNGEON_MAX_SIZE_X - 1 || currentPosY >= DUNGEON_MAX_SIZE_Y - 1) + if (!moveTargetResults[i].moveUsable) { - break; + moveTargetResults[i].moveWeight = 0; } - while (0); // Extra label needed to swap branch locations in ASM. - mapTile = GetMapTileAtPosition(currentPosX, currentPosY); - if (!(mapTile->tileType & (TILE_TYPE_FLOOR | TILE_TYPE_LIQUID))) + else if (maxWeight < moveTargetResults[i].moveWeight) { - break; + maxWeight = moveTargetResults[i].moveWeight; } - if (mapTile->pokemon == targetPokemon) + } + for (i = 0; i < MAX_MON_MOVES + 1; i++) + { + if (moveTargetResults[i].moveUsable) { - return TRUE; + if (maxWeight != moveTargetResults[i].moveWeight) + { + moveTargetResults[i].moveWeight = 0; + } + total += moveTargetResults[i].moveWeight; } - if (mapTile->pokemon != NULL) + } + } + if (total == 0) + { + return; + } + randomWeight = DungeonRandomCapped(total); + weightCounter = 0; + if (!HasIQSkill(pokemon, IQ_SKILL_EXCLUSIVE_MOVE_USER)) + { + canTargetRegularAttack = TargetRegularAttack(pokemon, ®ularAttackTargetDir, TRUE); + } + else + { + canTargetRegularAttack = FALSE; + regularAttackTargetDir = DIRECTION_SOUTH; + } + for (i = 0; i <= REGULAR_ATTACK_INDEX; i++) + { + if (moveTargetResults[i].moveUsable && moveTargetResults[i].moveWeight != 0) + { + weightCounter += moveTargetResults[i].moveWeight; + if (weightCounter >= randomWeight) { - break; + if (i == REGULAR_ATTACK_INDEX) + { + if (canTargetRegularAttack) + { + SetAction(&pokemonData->action, DUNGEON_ACTION_REGULAR_ATTACK); + pokemonData->action.facingDir = regularAttackTargetDir & DIRECTION_MASK; + TargetTileInFront(pokemon); + } + } + else + { + FindMoveTarget(&moveTargetResults[i], pokemon, &pokemonData->moves[i]); + if (moveTargetResults[i].moveUsable) + { + s32 chosenMoveIndex; + SetAction(&pokemonData->action, DUNGEON_ACTION_USE_MOVE_AI); + chosenMoveIndex = i; + if (i > 0 && pokemonData->moves[i].moveFlags & MOVE_FLAG_LINKED) + { + while (--chosenMoveIndex > 0) + { + if (!(pokemonData->moves[chosenMoveIndex].moveFlags & MOVE_FLAG_LINKED)) + { + break; + } + } + } + pokemonData->action.facingDir = moveTargetResults[i].targetDir & DIRECTION_MASK; + pokemonData->action.actionUseIndex = chosenMoveIndex; + TargetTileInFront(pokemon); + } + else + { + break; + } + } + return; } } } - return FALSE; + if (canTargetRegularAttack) + { + SetAction(&pokemonData->action, DUNGEON_ACTION_REGULAR_ATTACK); + pokemonData->action.facingDir = regularAttackTargetDir & DIRECTION_MASK; + TargetTileInFront(pokemon); + } } -- cgit v1.2.3 From a9b5977d4ca6c0aeedea966a0165b625a4c2dbab Mon Sep 17 00:00:00 2001 From: AnonymousRandomPerson Date: Sat, 5 Feb 2022 20:23:01 -0500 Subject: Decomped MoveMatchesChargingStatus --- src/dungeon_ai_attack.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/dungeon_ai_attack.c') diff --git a/src/dungeon_ai_attack.c b/src/dungeon_ai_attack.c index e695422..0c48f24 100644 --- a/src/dungeon_ai_attack.c +++ b/src/dungeon_ai_attack.c @@ -8,6 +8,7 @@ #include "constants/status.h" #include "constants/tactic.h" #include "constants/type.h" +#include "charge_move.h" #include "dungeon_action.h" #include "dungeon_ai.h" #include "dungeon_capabilities_1.h" @@ -29,7 +30,6 @@ struct MoveTargetResults s32 moveWeight; }; -extern bool8 IsChargeMove(struct DungeonEntity*, struct PokemonMove*); extern void TargetTileInFront(struct DungeonEntity*); extern s32 FindMoveTarget(struct MoveTargetResults*, struct DungeonEntity*, struct PokemonMove*); extern bool8 IsMoveUsable(struct DungeonEntity*, s32, bool8); @@ -63,7 +63,7 @@ void DecideAttack(struct DungeonEntity *pokemon) for (i = 0; i < MAX_MON_MOVES; i++) { if (pokemonData->moves[i].moveFlags & MOVE_FLAG_EXISTS && - IsChargeMove(pokemon, &pokemonData->moves[i]) && + MoveMatchesChargingStatus(pokemon, &pokemonData->moves[i]) && pokemonData->chargingStatusMoveIndex == i) { s32 chosenMoveIndex; -- cgit v1.2.3 From 9939c543ce7a8cbf7abb85d3125b5e6d95204433 Mon Sep 17 00:00:00 2001 From: AnonymousRandomPerson Date: Sat, 5 Feb 2022 22:02:03 -0500 Subject: Decomped TargetTileInFront() --- src/dungeon_ai_attack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/dungeon_ai_attack.c') diff --git a/src/dungeon_ai_attack.c b/src/dungeon_ai_attack.c index 0c48f24..416d4da 100644 --- a/src/dungeon_ai_attack.c +++ b/src/dungeon_ai_attack.c @@ -18,6 +18,7 @@ #include "dungeon_random_1.h" #include "moves.h" #include "status_checks.h" +#include "targeting.h" #define REGULAR_ATTACK_INDEX 4 @@ -30,7 +31,6 @@ struct MoveTargetResults s32 moveWeight; }; -extern void TargetTileInFront(struct DungeonEntity*); extern s32 FindMoveTarget(struct MoveTargetResults*, struct DungeonEntity*, struct PokemonMove*); extern bool8 IsMoveUsable(struct DungeonEntity*, s32, bool8); extern bool8 TargetRegularAttack(struct DungeonEntity*, u32*, bool8); -- cgit v1.2.3 From a02346be01efa13b6d969a89be642e3450f7ca35 Mon Sep 17 00:00:00 2001 From: AnonymousRandomPerson Date: Sun, 13 Feb 2022 22:02:17 -0500 Subject: Decomped FindMoveTarget() --- src/dungeon_ai_attack.c | 219 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 212 insertions(+), 7 deletions(-) (limited to 'src/dungeon_ai_attack.c') diff --git a/src/dungeon_ai_attack.c b/src/dungeon_ai_attack.c index 416d4da..5667d75 100644 --- a/src/dungeon_ai_attack.c +++ b/src/dungeon_ai_attack.c @@ -11,12 +11,18 @@ #include "charge_move.h" #include "dungeon_action.h" #include "dungeon_ai.h" +#include "dungeon_ai_attack_1.h" #include "dungeon_capabilities_1.h" +#include "dungeon_global_data.h" +#include "dungeon_map_access.h" #include "dungeon_pokemon_attributes.h" #include "dungeon_pokemon_attributes_1.h" #include "dungeon_random.h" #include "dungeon_random_1.h" +#include "dungeon_util.h" +#include "dungeon_visibility.h" #include "moves.h" +#include "position_util.h" #include "status_checks.h" #include "targeting.h" @@ -24,16 +30,21 @@ const s16 gRegularAttackWeights[] = {100, 20, 30, 40, 50}; -struct MoveTargetResults -{ - bool8 moveUsable; - u8 targetDir; - s32 moveWeight; -}; +extern bool8 gCanAttackInDirection[NUM_DIRECTIONS]; +extern s32 gNumPotentialTargets; +extern s32 gPotentialTargetWeights_2[NUM_DIRECTIONS]; +extern u8 gPotentialAttackTargetDirections[NUM_DIRECTIONS]; +extern struct DungeonEntity *gPotentialTargets[NUM_DIRECTIONS]; -extern s32 FindMoveTarget(struct MoveTargetResults*, struct DungeonEntity*, struct PokemonMove*); extern bool8 IsMoveUsable(struct DungeonEntity*, s32, bool8); extern bool8 TargetRegularAttack(struct DungeonEntity*, u32*, bool8); +extern s16 GetTargetingFlags(struct DungeonEntity*, struct PokemonMove*, bool8); +extern bool8 CanUseWithStatusChecker(struct DungeonEntity*, struct PokemonMove*); +extern bool8 CanAttackInFront(struct DungeonEntity*, s32); +extern s32 WeightMoveIfUsable(s32, s32, struct DungeonEntity*, struct DungeonEntity*, struct PokemonMove*, bool8); +extern bool8 IsTargetInLineRange(struct DungeonEntity*, struct DungeonEntity*, s32); +extern bool8 CanUseStatusMove(s32, struct DungeonEntity*, struct DungeonEntity*, struct PokemonMove*, bool8); +extern s32 WeightMove(struct DungeonEntity*, s32, struct DungeonEntity*, u8); void DecideAttack(struct DungeonEntity *pokemon) { @@ -320,3 +331,197 @@ void DecideAttack(struct DungeonEntity *pokemon) TargetTileInFront(pokemon); } } + +s32 FindMoveTarget(struct MoveTargetResults *moveTargetResults, struct DungeonEntity *pokemon, struct PokemonMove *move) +{ + s32 targetingFlags; + s32 moveWeight = 1; + struct DungeonEntityData *pokemonData = pokemon->entityData; + s32 numPotentialTargets = 0; + s32 i; + bool8 hasStatusChecker; + s32 rangeTargetingFlags; + s32 rangeTargetingFlags2; + for (i = 0; i < NUM_DIRECTIONS; i++) + { + gCanAttackInDirection[i] = FALSE; + } + targetingFlags = GetTargetingFlags(pokemon, move, TRUE); + hasStatusChecker = HasIQSkill(pokemon, IQ_SKILL_STATUS_CHECKER); + moveTargetResults->moveUsable = FALSE; + if ((pokemonData->volatileStatus == VOLATILE_STATUS_TAUNTED && !GetMoveDealsDirectDamage(move)) || + (hasStatusChecker && !CanUseWithStatusChecker(pokemon, move))) + { + return 1; + } + rangeTargetingFlags = targetingFlags & 0xF0; + if (rangeTargetingFlags == TARGETING_FLAG_TARGET_OTHER || + rangeTargetingFlags == TARGETING_FLAG_TARGET_FRONTAL_CONE || + rangeTargetingFlags == TARGETING_FLAG_TARGET_AROUND) + { + if (pokemonData->eyesightStatus == EYESIGHT_STATUS_BLINKER) + { + u8 facingDir = pokemonData->action.facingDir; + i = facingDir; // Fixes a regswap. + if (!gCanAttackInDirection[i]) + { + gCanAttackInDirection[i] = TRUE; + gPotentialAttackTargetDirections[numPotentialTargets] = i; + gPotentialTargetWeights_2[numPotentialTargets] = 99; + gPotentialTargets[numPotentialTargets] = NULL; + numPotentialTargets++; + } + } + else + { + for (i = 0; i < NUM_DIRECTIONS; i++) + { + // Double assignment to fix a regswap. + s16 rangeTargetingFlags = rangeTargetingFlags2 = targetingFlags & 0xF0; + struct MapTile *adjacentTile = GetMapTileAtPosition(pokemon->posWorld.x + gAdjacentTileOffsets[i].x, + pokemon->posWorld.y + gAdjacentTileOffsets[i].y); + struct DungeonEntity *adjacentPokemon = adjacentTile->pokemon; + if (adjacentPokemon != NULL && GetEntityType(adjacentPokemon) == ENTITY_POKEMON) + { + if (rangeTargetingFlags != TARGETING_FLAG_TARGET_FRONTAL_CONE && + rangeTargetingFlags != TARGETING_FLAG_TARGET_AROUND) + { + if (!CanAttackInFront(pokemon, i)) + { + continue; + } + } + numPotentialTargets = WeightMoveIfUsable(numPotentialTargets, targetingFlags, pokemon, adjacentPokemon, move, hasStatusChecker); + } + } + } + } + else if (rangeTargetingFlags == TARGETING_FLAG_TARGET_ROOM) + { + s32 i; + for (i = 0; i < DUNGEON_MAX_POKEMON; i++) + { + struct DungeonEntity *target = gDungeonGlobalData->allPokemon[i]; + if (EntityExists(target) && CanSee(pokemon, target)) + { + numPotentialTargets = WeightMoveIfUsable(numPotentialTargets, targetingFlags, pokemon, target, move, hasStatusChecker); + } + } + } + else if (rangeTargetingFlags == TARGETING_FLAG_TARGET_2_TILES_AHEAD) + { + for (i = 0; i < NUM_DIRECTIONS; i++) + { + struct MapTile *targetTile = GetMapTileAtPosition(pokemon->posWorld.x + gAdjacentTileOffsets[i].x, + pokemon->posWorld.y + gAdjacentTileOffsets[i].y); + if (CanAttackInFront(pokemon, i)) + { + struct DungeonEntity *targetPokemon = targetTile->pokemon; + if (targetPokemon != NULL && GetEntityType(targetPokemon) == ENTITY_POKEMON) + { + s32 prevNumPotentialTargets = numPotentialTargets; + numPotentialTargets = WeightMoveIfUsable(numPotentialTargets, targetingFlags, pokemon, targetPokemon, move, hasStatusChecker); + if (prevNumPotentialTargets != numPotentialTargets) + { + continue; + } + } + targetTile = GetMapTileAtPosition(pokemon->posWorld.x + gAdjacentTileOffsets[i].x * 2, + pokemon->posWorld.y + gAdjacentTileOffsets[i].y * 2); + targetPokemon = targetTile->pokemon; + if (targetPokemon != NULL && GetEntityType(targetPokemon) == ENTITY_POKEMON) + { + numPotentialTargets = WeightMoveIfUsable(numPotentialTargets, targetingFlags, pokemon, targetPokemon, move, hasStatusChecker); + } + } + } + } + else if (rangeTargetingFlags == TARGETING_FLAG_TARGET_LINE || rangeTargetingFlags == TARGETING_FLAG_CUT_CORNERS) + { + s32 maxRange = 1; + s32 i; + if (rangeTargetingFlags == TARGETING_FLAG_TARGET_LINE) + { + maxRange = 10; + } + for (i = 0; i < DUNGEON_MAX_POKEMON; i++) + { + struct DungeonEntity *target = gDungeonGlobalData->allPokemon[i]; + if (EntityExists(target) && pokemon != target) + { + s32 facingDir = CalculateFacingDir(&pokemon->posWorld, &target->posWorld); + if (!gCanAttackInDirection[facingDir] && + CanSee(pokemon, target) && + IsTargetInLineRange(pokemon, target, maxRange) && + CanUseStatusMove(targetingFlags, pokemon, target, move, hasStatusChecker) && + IsTargetStraightAhead(pokemon, target, facingDir, maxRange)) + { + gCanAttackInDirection[facingDir] = TRUE; + gPotentialAttackTargetDirections[numPotentialTargets] = facingDir; + gPotentialTargetWeights_2[numPotentialTargets] = WeightMove(pokemon, targetingFlags, target, GetMoveTypeForPokemon(pokemon, move)); + gPotentialTargets[numPotentialTargets] = target; + numPotentialTargets++; + } + } + } + } + else if (rangeTargetingFlags == TARGETING_FLAG_TARGET_FLOOR) + { + s32 i; + for (i = 0; i < DUNGEON_MAX_POKEMON; i++) + { + struct DungeonEntity *target = gDungeonGlobalData->allPokemon[i]; + if (EntityExists(target)) + { + numPotentialTargets = WeightMoveIfUsable(numPotentialTargets, targetingFlags, pokemon, target, move, hasStatusChecker); + } + } + } + else if (rangeTargetingFlags == TARGETING_FLAG_SELF_HEAL) + { + numPotentialTargets = WeightMoveIfUsable(numPotentialTargets, targetingFlags, pokemon, pokemon, move, hasStatusChecker); + } + if (numPotentialTargets == 0) + { + moveTargetResults->moveUsable = FALSE; + } + else + { + s32 totalWeight = 0; + s32 maxWeight = 0; + s32 weightCounter; + s32 i; + for (i = 0; i < numPotentialTargets; i++) + { + if (maxWeight < gPotentialTargetWeights_2[i]) + { + maxWeight = gPotentialTargetWeights_2[i]; + } + } + for (i = 0; i < numPotentialTargets; i++) + { + if (maxWeight != gPotentialTargetWeights_2[i]) + { + gPotentialTargetWeights_2[i] = 0; + } + } + moveWeight = maxWeight; + for (i = 0; i < numPotentialTargets; i++) + { + totalWeight += gPotentialTargetWeights_2[i]; + } + weightCounter = DungeonRandomCapped(totalWeight); + for (i = 0; i < numPotentialTargets; i++) + { + weightCounter -= gPotentialTargetWeights_2[i]; + if (weightCounter < 0) + { + break; + } + } + moveTargetResults->moveUsable = TRUE; + moveTargetResults->targetDir = gPotentialAttackTargetDirections[i]; + moveTargetResults->moveWeight = 8; + } + return moveWeight; +} \ No newline at end of file -- cgit v1.2.3 From 3bbb6035e746cdb83b128b1d6153436756cb3be0 Mon Sep 17 00:00:00 2001 From: AnonymousRandomPerson Date: Sun, 13 Feb 2022 22:30:25 -0500 Subject: Decomped GetMoveTargetingFlagsForPokemon() --- src/dungeon_ai_attack.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/dungeon_ai_attack.c') diff --git a/src/dungeon_ai_attack.c b/src/dungeon_ai_attack.c index 5667d75..f0362ed 100644 --- a/src/dungeon_ai_attack.c +++ b/src/dungeon_ai_attack.c @@ -25,6 +25,7 @@ #include "position_util.h" #include "status_checks.h" #include "targeting.h" +#include "targeting_flags.h" #define REGULAR_ATTACK_INDEX 4 @@ -38,7 +39,6 @@ extern struct DungeonEntity *gPotentialTargets[NUM_DIRECTIONS]; extern bool8 IsMoveUsable(struct DungeonEntity*, s32, bool8); extern bool8 TargetRegularAttack(struct DungeonEntity*, u32*, bool8); -extern s16 GetTargetingFlags(struct DungeonEntity*, struct PokemonMove*, bool8); extern bool8 CanUseWithStatusChecker(struct DungeonEntity*, struct PokemonMove*); extern bool8 CanAttackInFront(struct DungeonEntity*, s32); extern s32 WeightMoveIfUsable(s32, s32, struct DungeonEntity*, struct DungeonEntity*, struct PokemonMove*, bool8); @@ -346,7 +346,7 @@ s32 FindMoveTarget(struct MoveTargetResults *moveTargetResults, struct DungeonEn { gCanAttackInDirection[i] = FALSE; } - targetingFlags = GetTargetingFlags(pokemon, move, TRUE); + targetingFlags = GetMoveTargetingFlagsForPokemon(pokemon, move, TRUE); hasStatusChecker = HasIQSkill(pokemon, IQ_SKILL_STATUS_CHECKER); moveTargetResults->moveUsable = FALSE; if ((pokemonData->volatileStatus == VOLATILE_STATUS_TAUNTED && !GetMoveDealsDirectDamage(move)) || @@ -477,7 +477,7 @@ s32 FindMoveTarget(struct MoveTargetResults *moveTargetResults, struct DungeonEn } } } - else if (rangeTargetingFlags == TARGETING_FLAG_SELF_HEAL) + else if (rangeTargetingFlags == TARGETING_FLAG_TARGET_SELF) { numPotentialTargets = WeightMoveIfUsable(numPotentialTargets, targetingFlags, pokemon, pokemon, move, hasStatusChecker); } -- cgit v1.2.3 From 2a2a0805b481b8425b4d1047d868fb1159993e6c Mon Sep 17 00:00:00 2001 From: AnonymousRandomPerson Date: Sun, 13 Feb 2022 23:13:47 -0500 Subject: Decomped HasType() --- src/dungeon_ai_attack.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src/dungeon_ai_attack.c') diff --git a/src/dungeon_ai_attack.c b/src/dungeon_ai_attack.c index f0362ed..6e202b5 100644 --- a/src/dungeon_ai_attack.c +++ b/src/dungeon_ai_attack.c @@ -16,7 +16,6 @@ #include "dungeon_global_data.h" #include "dungeon_map_access.h" #include "dungeon_pokemon_attributes.h" -#include "dungeon_pokemon_attributes_1.h" #include "dungeon_random.h" #include "dungeon_random_1.h" #include "dungeon_util.h" -- cgit v1.2.3 From ece475a4804a64790cfa86dfa0ba577a732adee8 Mon Sep 17 00:00:00 2001 From: AnonymousRandomPerson Date: Sun, 13 Feb 2022 23:17:46 -0500 Subject: Renamed some boolean move functions --- src/dungeon_ai_attack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/dungeon_ai_attack.c') diff --git a/src/dungeon_ai_attack.c b/src/dungeon_ai_attack.c index 6e202b5..30e5d3a 100644 --- a/src/dungeon_ai_attack.c +++ b/src/dungeon_ai_attack.c @@ -348,7 +348,7 @@ s32 FindMoveTarget(struct MoveTargetResults *moveTargetResults, struct DungeonEn targetingFlags = GetMoveTargetingFlagsForPokemon(pokemon, move, TRUE); hasStatusChecker = HasIQSkill(pokemon, IQ_SKILL_STATUS_CHECKER); moveTargetResults->moveUsable = FALSE; - if ((pokemonData->volatileStatus == VOLATILE_STATUS_TAUNTED && !GetMoveDealsDirectDamage(move)) || + if ((pokemonData->volatileStatus == VOLATILE_STATUS_TAUNTED && !MoveDealsDirectDamage(move)) || (hasStatusChecker && !CanUseWithStatusChecker(pokemon, move))) { return 1; -- cgit v1.2.3