summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSeth Barberee <seth.barberee@gmail.com>2021-12-28 23:00:59 -0600
committerGitHub <noreply@github.com>2021-12-28 23:00:59 -0600
commitedf909be4da55a435bf81f96ffcbd156b2120562 (patch)
tree7bbce0d40ce8c714e793ef22f3a7c125f9ff3fbd /src
parent6512ebff67e163a5a6c0f5e19847e2a4dda19ad1 (diff)
parentea10f7b7bd6957312b9b0dfa371761c5936bc80a (diff)
Merge pull request #91 from AnonymousRandomPerson/master
More item AI decomp
Diffstat (limited to 'src')
-rw-r--r--src/code_80521D0_1.c4
-rw-r--r--src/dungeon_ai_1.c2
-rw-r--r--src/dungeon_ai_attack.c77
-rw-r--r--src/dungeon_ai_items.c77
-rw-r--r--src/dungeon_movement.c4
-rw-r--r--src/dungeon_pokemon_attributes_1.c17
-rw-r--r--src/pokemon_3.c17
7 files changed, 174 insertions, 24 deletions
diff --git a/src/code_80521D0_1.c b/src/code_80521D0_1.c
index ac9ebef..2b23a14 100644
--- a/src/code_80521D0_1.c
+++ b/src/code_80521D0_1.c
@@ -208,7 +208,7 @@ void sub_808BCE4(void)
struct MapTile *puVar1;
puVar1 = GetMapEntity(gDungeonGlobalData->unkE23C, gDungeonGlobalData->unkE23E);
- puVar1->tileType &= ~(TILE_TYPE_FLOOR | TILE_TYPE_UNK_1);
+ puVar1->tileType &= ~(TILE_TYPE_FLOOR | TILE_TYPE_LIQUID);
puVar1->tileType |= TILE_TYPE_MAP_EDGE;
puVar1->tileType &= ~TILE_TYPE_STAIRS;
sub_8049884();
@@ -222,7 +222,7 @@ void sub_808BD38(void)
struct MapTile *puVar1;
puVar1 = GetMapEntity(gDungeonGlobalData->unkE23C, gDungeonGlobalData->unkE23E);
- puVar1->tileType &= ~(TILE_TYPE_FLOOR | TILE_TYPE_UNK_1);
+ puVar1->tileType &= ~(TILE_TYPE_FLOOR | TILE_TYPE_LIQUID);
puVar1->tileType |= TILE_TYPE_FLOOR;
puVar1->tileType &= ~TILE_TYPE_MAP_EDGE;
puVar1->tileType |= TILE_TYPE_STAIRS;
diff --git a/src/dungeon_ai_1.c b/src/dungeon_ai_1.c
index 7d45909..1d177c7 100644
--- a/src/dungeon_ai_1.c
+++ b/src/dungeon_ai_1.c
@@ -3,8 +3,8 @@
#include "constants/status.h"
#include "constants/targeting.h"
+#include "dungeon_pokemon_attributes_1.h"
-extern bool8 CanSeeInvisible(struct DungeonEntity*);
extern bool8 gTargetingData[3][2][2][2];
u8 CanTarget(struct DungeonEntity *pokemon, struct DungeonEntity *targetPokemon, bool8 ignoreInvisible, bool8 checkPetrified)
diff --git a/src/dungeon_ai_attack.c b/src/dungeon_ai_attack.c
new file mode 100644
index 0000000..48ccdfe
--- /dev/null
+++ b/src/dungeon_ai_attack.c
@@ -0,0 +1,77 @@
+#include "global.h"
+#include "dungeon_ai_attack.h"
+
+#include "constants/iq_skill.h"
+#include "dungeon_global_data.h"
+#include "dungeon_map_access.h"
+#include "dungeon_pokemon_attributes_1.h"
+
+extern struct Position gAdjacentTileOffsets[8];
+
+bool8 IsTargetStraightAhead(struct DungeonEntity *pokemon, struct DungeonEntity *targetPokemon, s32 facingDir, s32 maxRange)
+{
+ s32 posDiffX = pokemon->posWorld.x - targetPokemon->posWorld.x;
+ s32 effectiveMaxRange;
+ if (posDiffX < 0)
+ {
+ posDiffX = -posDiffX;
+ }
+ effectiveMaxRange = pokemon->posWorld.y - targetPokemon->posWorld.y;
+ if (effectiveMaxRange < 0)
+ {
+ effectiveMaxRange = -effectiveMaxRange;
+ }
+ if (effectiveMaxRange < posDiffX)
+ {
+ effectiveMaxRange = posDiffX;
+ }
+ if (effectiveMaxRange > maxRange)
+ {
+ effectiveMaxRange = maxRange;
+ }
+ if (!HasIQSkill(pokemon, IQ_SKILL_COURSE_CHECKER))
+ {
+ // 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)
+ {
+ return TRUE;
+ }
+ }
+ else
+ {
+ 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++)
+ {
+ struct MapTile *mapTile;
+ currentPosX += adjacentTileOffsetX;
+ currentPosY += adjacentTileOffsetY;
+ if (currentPosX <= 0 || currentPosY <= 0 ||
+ currentPosX >= DUNGEON_MAX_SIZE_X - 1 || currentPosY >= DUNGEON_MAX_SIZE_Y - 1)
+ {
+ break;
+ }
+ while (0); // Extra label needed to swap branch locations in ASM.
+ mapTile = GetMapTileAtPosition(currentPosX, currentPosY);
+ if (!(mapTile->tileType & (TILE_TYPE_FLOOR | TILE_TYPE_LIQUID)))
+ {
+ break;
+ }
+ if (mapTile->pokemon == targetPokemon)
+ {
+ return TRUE;
+ }
+ if (mapTile->pokemon != NULL)
+ {
+ break;
+ }
+ }
+ }
+ return FALSE;
+}
diff --git a/src/dungeon_ai_items.c b/src/dungeon_ai_items.c
index 4afc928..56e4447 100644
--- a/src/dungeon_ai_items.c
+++ b/src/dungeon_ai_items.c
@@ -3,9 +3,11 @@
#include "constants/direction.h"
#include "constants/dungeon_action.h"
#include "constants/iq_skill.h"
+#include "constants/status.h"
#include "constants/targeting.h"
#include "dungeon_action.h"
#include "dungeon_ai_1.h"
+#include "dungeon_ai_attack.h"
#include "dungeon_ai_items.h"
#include "dungeon_capabilities.h"
#include "dungeon_capabilities_1.h"
@@ -24,6 +26,7 @@
#define NUM_POTENTIAL_ROCK_TARGETS 20
#define GROUND_ITEM_TOOLBOX_INDEX 0x80
#define HELD_ITEM_TOOLBOX_INDEX 0x81
+#define RANGED_ATTACK_RANGE 10
enum ItemTargetFlag
{
@@ -32,9 +35,8 @@ enum ItemTargetFlag
};
extern s32 CalculateFacingDir(struct Position*, struct Position*);
-extern u32 EvaluateItem(struct DungeonEntity*, struct ItemSlot*, u8);
+extern u32 EvaluateItem(struct DungeonEntity*, struct ItemSlot*, u32);
extern void sub_8077274(struct DungeonEntity *, struct DungeonEntity *);
-extern void TargetThrownItem(struct DungeonEntity*, struct DungeonEntity*, struct ItemSlot*, u8, bool8);
extern s32 gNumPotentialTargets;
extern u32 gPotentialTargetWeights[NUM_DIRECTIONS];
@@ -284,7 +286,7 @@ void FindStraightThrowableTargets(struct DungeonEntity *pokemon, s32 thrownAIFla
struct DungeonEntity* targetPokemon = gDungeonGlobalData->allPokemon[i];
if (EntityExists(targetPokemon) && pokemon != targetPokemon)
{
- u8 targetingFlags;
+ s32 targetingFlags;
if (thrownAIFlag == ITEM_AI_FLAG_TARGET_ALLY)
{
if (CanTarget(pokemon, targetPokemon, FALSE, FALSE) == TARGET_CAPABILITY_CANNOT_ATTACK)
@@ -357,3 +359,72 @@ void FindRockItemTargets(struct DungeonEntity *pokemon, struct ItemSlot *item, s
}
}
}
+
+void TargetThrownItem(struct DungeonEntity *pokemon, struct DungeonEntity *targetPokemon, struct ItemSlot *item, s32 targetingFlags, bool8 ignoreRollChance)
+{
+ s32 posDiffX = pokemon->posWorld.x - targetPokemon->posWorld.x;
+ s32 posDiffY;
+ s32 targetDirection;
+ posDiffX = posDiffX < 0 ? -posDiffX : posDiffX;
+ posDiffY = pokemon->posWorld.y - targetPokemon->posWorld.y;
+ posDiffY = posDiffY < 0 ? -posDiffY : posDiffY;
+ if (pokemon->entityData->itemStatus == ITEM_STATUS_NONE)
+ {
+ s32 maxPosDiff = posDiffY < posDiffX ? posDiffX : posDiffY;
+ if (maxPosDiff > RANGED_ATTACK_RANGE)
+ {
+ return;
+ }
+ }
+ targetDirection = -1;
+ if (posDiffX == posDiffY)
+ {
+ if (pokemon->posWorld.x < targetPokemon->posWorld.x && pokemon->posWorld.y < targetPokemon->posWorld.y)
+ {
+ targetDirection = DIRECTION_SOUTHEAST;
+ }
+ else if (pokemon->posWorld.x < targetPokemon->posWorld.x && pokemon->posWorld.y > targetPokemon->posWorld.y)
+ {
+ targetDirection = DIRECTION_NORTHEAST;
+ }
+ else if (pokemon->posWorld.x > targetPokemon->posWorld.x && pokemon->posWorld.y > targetPokemon->posWorld.y)
+ {
+ targetDirection = DIRECTION_NORTHWEST;
+ }
+ else
+ {
+ targetDirection = DIRECTION_SOUTHWEST;
+ }
+ }
+ else
+ {
+ if (pokemon->posWorld.x == targetPokemon->posWorld.x && pokemon->posWorld.y < targetPokemon->posWorld.y)
+ {
+ targetDirection = DIRECTION_SOUTH;
+ }
+ else if (pokemon->posWorld.x < targetPokemon->posWorld.x && pokemon->posWorld.y == targetPokemon->posWorld.y)
+ {
+ targetDirection = DIRECTION_EAST;
+ }
+ else if (pokemon->posWorld.x == targetPokemon->posWorld.x && pokemon->posWorld.y > targetPokemon->posWorld.y)
+ {
+ targetDirection = DIRECTION_NORTH;
+ }
+ else if (pokemon->posWorld.x > targetPokemon->posWorld.x && pokemon->posWorld.y == targetPokemon->posWorld.y)
+ {
+ targetDirection = DIRECTION_WEST;
+ }
+ }
+
+ if (targetDirection > -1 && !gTargetAhead[targetDirection] && IsTargetStraightAhead(pokemon, targetPokemon, targetDirection, RANGED_ATTACK_RANGE))
+ {
+ u32 itemWeight;
+ u32 *targetWeight;
+ gTargetAhead[targetDirection] = TRUE;
+ gPotentialTargetDirections[gNumPotentialTargets] = targetDirection;
+ targetWeight = &gPotentialTargetWeights[gNumPotentialTargets];
+ itemWeight = !ignoreRollChance ? EvaluateItem(targetPokemon, item, targetingFlags) : 100;
+ *targetWeight = itemWeight;
+ gNumPotentialTargets++;
+ }
+}
diff --git a/src/dungeon_movement.c b/src/dungeon_movement.c
index 1601cff..bcf6163 100644
--- a/src/dungeon_movement.c
+++ b/src/dungeon_movement.c
@@ -51,7 +51,7 @@ u32 sub_8075818(struct DungeonEntity *entity)
{
tile = GetMapEntityForDungeonEntity(entity);
if(HasIQSkill(entity, IQ_SKILL_SUPER_MOBILE))
- if(!(tile->tileType & (TILE_TYPE_FLOOR | TILE_TYPE_UNK_1)))
+ if(!(tile->tileType & (TILE_TYPE_FLOOR | TILE_TYPE_LIQUID)))
return 1;
subEntity = tile->mapObject;
if(subEntity != NULL)
@@ -95,7 +95,7 @@ flag_check:
{
if(!(entityData->heldItem.itemFlags & ITEM_FLAG_EXISTS))
{
- if(!(tile->tileType & (TILE_TYPE_FLOOR | TILE_TYPE_UNK_1)))
+ if(!(tile->tileType & (TILE_TYPE_FLOOR | TILE_TYPE_LIQUID)))
{
if(entityData->isEnemy)
break;
diff --git a/src/dungeon_pokemon_attributes_1.c b/src/dungeon_pokemon_attributes_1.c
index d3b8cab..a5d6acf 100644
--- a/src/dungeon_pokemon_attributes_1.c
+++ b/src/dungeon_pokemon_attributes_1.c
@@ -9,6 +9,7 @@
#include "constants/move_id.h"
#include "constants/status.h"
#include "constants/tactic.h"
+#include "pokemon_3.h"
extern s16 gItemMasterMinWildLevel;
@@ -26,9 +27,9 @@ extern s32 GetMovePower(struct PokemonMove *move);
bool8 CanSeeInvisible(struct DungeonEntity *pokemon)
{
struct DungeonEntityData *pokemonData = pokemon->entityData;
- if(pokemonData->eyesightStatus != EYESIGHT_STATUS_EYEDROPS)
+ if (pokemonData->eyesightStatus != EYESIGHT_STATUS_EYEDROPS)
{
- if(!HasItem(pokemon, ITEM_ID_GOGGLE_SPECS))
+ if (!HasItem(pokemon, ITEM_ID_GOGGLE_SPECS))
return FALSE;
else
return TRUE;
@@ -63,7 +64,7 @@ void LoadIQSkills(struct DungeonEntity *pokemon)
u8 *iVar2;
s32 IQSkill;
struct DungeonEntityData *pokemonData;
-
+
pokemonData = pokemon->entityData;
if (pokemonData->isEnemy) {
iVar2 = pokemonData->IQSkillsEnabled;
@@ -82,8 +83,8 @@ void LoadIQSkills(struct DungeonEntity *pokemon)
pokemonData->IQSkillsEnabled[2] = 0;
for(IQSkill = IQ_SKILL_TYPE_ADVANTAGE_MASTER; IQSkill < NUM_IQ_SKILLS; IQSkill++)
{
- if (HasIQForSkill(pokemonData->IQ,IQSkill) &&
- IsIQSkillSet(pokemonData->IQSkillsSelected, 1 << IQSkill))
+ if (HasIQForSkill(pokemonData->IQ,IQSkill) &&
+ IsIQSkillSet(pokemonData->IQSkillsSelected, 1 << IQSkill))
{
SetIQSkill(pokemonData->IQSkillsEnabled,IQSkill);
}
@@ -95,7 +96,7 @@ bool8 CanSeeTeammate(struct DungeonEntity * pokemon)
{
struct DungeonEntity *teamMember;
s32 memberIdx;
-
+
if (pokemon->entityData->isEnemy) {
return FALSE;
}
@@ -132,13 +133,13 @@ s32 CalculateMovePower(struct DungeonEntity *pokemon, struct PokemonMove *pokeMo
bool8 ToolboxEnabled(struct DungeonEntityData *pokemon)
{
if(!IsToolboxEnabled(pokemon->entityID))
- return FALSE;
+ return FALSE;
return TRUE;
}
static inline bool8 sub_8071A8C_sub(struct DungeonEntityData *pokemonData)
{
- if(pokemonData->joinLocation == DUNGEON_JOIN_LOCATION_CLIENT_POKEMON ||
+ if(pokemonData->joinLocation == DUNGEON_JOIN_LOCATION_CLIENT_POKEMON ||
pokemonData->joinLocation == DUNGEON_RESCUE_TEAM_BASE)
return TRUE;
else
diff --git a/src/pokemon_3.c b/src/pokemon_3.c
index 743a9dd..9d28f98 100644
--- a/src/pokemon_3.c
+++ b/src/pokemon_3.c
@@ -1,4 +1,6 @@
#include "global.h"
+#include "pokemon_3.h"
+
#include "pokemon.h"
#include "random.h"
#include "constants/iq_skill.h"
@@ -45,7 +47,6 @@ extern s16 gUnknown_810AC66; // 0x8
// 2, 4, 6, 7, 8, 9, 0xA, 0xD, 0xF, 0x11
extern s32 gUnknown_810AC90[10];
-extern bool8 IsIQSkillSet(u8 *, u32);
extern void SetIQSkill(u8 *, u32);
extern void AddSprite(u16 *, u32, u32, u32);
@@ -613,22 +614,22 @@ void SetDefaultIQSkills(u8 *param_1, bool8 enableSelfCurer)
SetIQSkill(param_1, IQ_SKILL_COURSE_CHECKER);
SetIQSkill(param_1, IQ_SKILL_ITEM_MASTER);
- // Flag is usually enabled for Boss fights..
+ // Flag is usually enabled for Boss fights.
if (enableSelfCurer) {
SetIQSkill(param_1, IQ_SKILL_SELF_CURER);
}
}
-bool8 IsIQSkillSet(u8 *param_1, u32 param_2)
+bool8 IsIQSkillSet(u8 *IQSkillsEnabled, u32 IQSkill)
{
-
- if ((((param_1[0] & param_2) == 0) &&
- ((param_1[1] & param_2 >> 8) == 0)) &&
- ((param_1[2] & param_2 >> 0x10) == 0))
+ if (!(IQSkillsEnabled[0] & IQSkill) &&
+ !(IQSkillsEnabled[1] & IQSkill >> 8) &&
+ !(IQSkillsEnabled[2] & IQSkill >> 16))
{
return FALSE;
}
- else {
+ else
+ {
return TRUE;
}
}