Merge pull request #91 from AnonymousRandomPerson/master

More item AI decomp
This commit is contained in:
Seth Barberee
2021-12-28 23:00:59 -06:00
committed by GitHub
17 changed files with 13052 additions and 13177 deletions

View File

@@ -1,211 +1,10 @@
#include "asm/constants/gba_constants.inc"
#include "asm/macros.inc"
#include "asm/macros.inc"
.syntax unified
.text
thumb_func_start TargetThrownItem
TargetThrownItem:
push {r4-r7,lr}
mov r7, r10
mov r6, r9
mov r5, r8
push {r5-r7}
adds r4, r0, 0
adds r5, r1, 0
mov r9, r2
mov r10, r3
ldr r0, [sp, 0x20]
lsls r0, 24
lsrs r0, 24
mov r8, r0
movs r0, 0x4
ldrsh r1, [r4, r0]
movs r2, 0x4
ldrsh r0, [r5, r2]
subs r2, r1, r0
cmp r2, 0
bge _08073BA2
negs r2, r2
_08073BA2:
movs r3, 0x6
ldrsh r1, [r4, r3]
movs r6, 0x6
ldrsh r0, [r5, r6]
subs r1, r0
cmp r1, 0
bge _08073BB2
negs r1, r1
_08073BB2:
ldr r0, [r4, 0x70]
adds r0, 0xE0
ldrb r0, [r0]
cmp r0, 0
bne _08073BCA
adds r0, r1, 0
cmp r1, r2
bge _08073BC4
adds r0, r2, 0
_08073BC4:
cmp r0, 0xA
ble _08073BCA
b _08073CDC
_08073BCA:
movs r6, 0x1
negs r6, r6
cmp r2, r1
bne _08073C14
movs r7, 0x4
ldrsh r1, [r4, r7]
movs r2, 0x4
ldrsh r0, [r5, r2]
ldrh r2, [r4, 0x4]
ldrh r3, [r5, 0x4]
cmp r1, r0
bge _08073BFA
movs r6, 0x6
ldrsh r1, [r4, r6]
movs r7, 0x6
ldrsh r0, [r5, r7]
cmp r1, r0
bge _08073BF2
movs r6, 0x1
b _08073C7E
_08073BF2:
cmp r1, r0
ble _08073BFA
movs r6, 0x3
b _08073C7E
_08073BFA:
lsls r1, r2, 16
lsls r0, r3, 16
movs r6, 0x7
cmp r1, r0
ble _08073C7A
movs r0, 0x6
ldrsh r1, [r4, r0]
movs r2, 0x6
ldrsh r0, [r5, r2]
cmp r1, r0
ble _08073C7A
movs r6, 0x5
b _08073C7E
_08073C14:
movs r3, 0x4
ldrsh r1, [r4, r3]
movs r7, 0x4
ldrsh r0, [r5, r7]
ldrh r2, [r4, 0x4]
ldrh r3, [r5, 0x4]
cmp r1, r0
bne _08073C34
movs r0, 0x6
ldrsh r1, [r4, r0]
movs r7, 0x6
ldrsh r0, [r5, r7]
cmp r1, r0
bge _08073C34
movs r6, 0
b _08073C7E
_08073C34:
lsls r1, r2, 16
lsls r0, r3, 16
cmp r1, r0
bge _08073C4C
movs r0, 0x6
ldrsh r1, [r4, r0]
movs r7, 0x6
ldrsh r0, [r5, r7]
cmp r1, r0
bne _08073C4C
movs r6, 0x2
b _08073C7E
_08073C4C:
lsls r1, r2, 16
lsls r0, r3, 16
cmp r1, r0
bne _08073C64
movs r0, 0x6
ldrsh r1, [r4, r0]
movs r7, 0x6
ldrsh r0, [r5, r7]
cmp r1, r0
ble _08073C64
movs r6, 0x4
b _08073C7E
_08073C64:
lsls r1, r2, 16
lsls r0, r3, 16
cmp r1, r0
ble _08073C7A
movs r0, 0x6
ldrsh r1, [r4, r0]
movs r2, 0x6
ldrsh r0, [r5, r2]
cmp r1, r0
bne _08073C7A
movs r6, 0x6
_08073C7A:
cmp r6, 0
blt _08073CDC
_08073C7E:
ldr r0, _08073CC0
adds r7, r6, r0
ldrb r0, [r7]
cmp r0, 0
bne _08073CDC
adds r0, r4, 0
adds r1, r5, 0
adds r2, r6, 0
movs r3, 0xA
bl IsTargetStraightAhead
lsls r0, 24
cmp r0, 0
beq _08073CDC
movs r0, 0x1
strb r0, [r7]
ldr r1, _08073CC4
ldr r0, _08073CC8
ldr r0, [r0]
lsls r0, 2
adds r1, r0, r1
str r6, [r1]
ldr r1, _08073CCC
adds r4, r0, r1
mov r3, r8
cmp r3, 0
bne _08073CD0
adds r0, r5, 0
mov r1, r9
mov r2, r10
bl EvaluateItem
b _08073CD2
.align 2, 0
_08073CC0: .4byte gTargetAhead
_08073CC4: .4byte gPotentialTargetDirections
_08073CC8: .4byte gNumPotentialTargets
_08073CCC: .4byte gPotentialTargetWeights
_08073CD0:
movs r0, 0x64
_08073CD2:
str r0, [r4]
ldr r1, _08073CEC
ldr r0, [r1]
adds r0, 0x1
str r0, [r1]
_08073CDC:
pop {r3-r5}
mov r8, r3
mov r9, r4
mov r10, r5
pop {r4-r7}
pop {r0}
bx r0
.align 2, 0
_08073CEC: .4byte gNumPotentialTargets
thumb_func_end TargetThrownItem
thumb_func_start sub_8073CF0
sub_8073CF0:
push {lr}

File diff suppressed because it is too large Load Diff

12846
asm/code_807CABC.s Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -34,7 +34,14 @@ gUnknown_80F4426: @ 80F4426
.global gAdjacentTileOffsets
gAdjacentTileOffsets: @ 80F4448
@ replacing .incbin "baserom.gba", 0x000f4448, 0x20
.byte 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00
.2byte 0, 1
.2byte 1, 1
.2byte 1, 0
.2byte 1, -1
.2byte 0, -1
.2byte -1, -1
.2byte -1, 0
.2byte -1, 1
.global gUnknown_80F4468
gUnknown_80F4468: @ 80F4468

View File

@@ -0,0 +1,9 @@
#ifndef GUARD_DUNGEON_AI_ATTACK_H
#define GUARD_DUNGEON_AI_ATTACK_H
#include "dungeon_entity.h"
// 0x7C9F8
bool8 IsTargetStraightAhead(struct DungeonEntity *pokemon, struct DungeonEntity *targetPokemon, s32 facingDir, s32 maxRange);
#endif

View File

@@ -10,5 +10,7 @@ void DecideUseItem(struct DungeonEntity *pokemon);
void FindStraightThrowableTargets(struct DungeonEntity *pokemon, s32 thrownAIFlag, struct ItemSlot *item, bool8 ignoreRollChance);
// 0x73AA0
void FindRockItemTargets(struct DungeonEntity *pokemon, struct ItemSlot *item, struct Position potentialTargets[], bool8 ignoreRollChance);
// 0x73B78
void TargetThrownItem(struct DungeonEntity *pokemon, struct DungeonEntity *targetPokemon, struct ItemSlot *item, s32 targetingFlags, bool8 ignoreRollChance);
#endif

View File

@@ -1,6 +1,7 @@
#ifndef GUARD_DUNGEON_ENTITY_H
#define GUARD_DUNGEON_ENTITY_H
#include "constants/global.h"
#include "constants/move.h"
#include "item.h"
#include "position.h"

View File

@@ -42,8 +42,8 @@ struct MapRoom
enum TileType
{
TILE_TYPE_FLOOR = 1 << 0,
TILE_TYPE_UNK_1 = 1 << 1,
TILE_TYPE_LIQUID = 1 << 2, // Water or lava depending on the dungeon.
TILE_TYPE_LIQUID = 1 << 1, // Water or lava depending on the dungeon.
TILE_TYPE_UNK_2 = 1 << 2,
TILE_TYPE_ROOM_EXIT = 1 << 3,
TILE_TYPE_MAP_EDGE = 1 << 4,
TILE_TYPE_SHOP = 1 << 5,

6
include/pokemon_3.h Normal file
View File

@@ -0,0 +1,6 @@
#ifndef GUARD_POKEMON_3_H
#define GUARD_POKEMON_3_H
bool8 IsIQSkillSet(u8 *IQSkillsEnabled, u32 IQSkill);
#endif

View File

@@ -218,9 +218,11 @@ SECTIONS {
src/dungeon_pokemon_attributes_1.o(.text);
asm/code_80718D8.o(.text);
src/dungeon_ai_items.o(.text);
asm/code_8073B78.o(.text);
asm/code_8073CF0.o(.text);
src/dungeon_movement.o(.text);
asm/code_8075BA4.o(.text);
src/dungeon_ai_attack.o(.text);
asm/code_807CABC.o(.text);
src/dungeon_range.o(.text);
asm/code_808333C.o(.text);
src/dungeon_random.o(.text);

View File

@@ -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;

View File

@@ -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)

77
src/dungeon_ai_attack.c Normal file
View File

@@ -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;
}

View File

@@ -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++;
}
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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;
}
}