Decomped CalculateAiTargetPos

Matched by @taxicat1
This commit is contained in:
AnonymousRandomPerson 2025-10-03 20:05:37 -04:00
parent 0dbd134215
commit 5bedbc4753
8 changed files with 160 additions and 291 deletions

View File

@ -1,8 +0,0 @@
#pragma once
.public CanAiMonsterMoveInDirection
.public DIRECTIONS_XY
.public DUNGEON_PTR
.public DungeonRandInt
.public FACING_DIRECTION_INCREMENTS
.public GetTile
.public IsAtJunction

View File

@ -0,0 +1 @@
#pragma once

View File

@ -1,280 +0,0 @@
.include "asm/macros.inc"
.include "itcm_01FFB2C8.inc"
.section .itcm,4,1,4
arm_func_start CalculateAiTargetPos
CalculateAiTargetPos: ; 0x01FFB2C8
stmdb sp!, {r3, r4, r5, r6, r7, r8, sb, sl, fp, lr}
ldr r1, _01FFB61C ; =DUNGEON_PTR
mov sl, r0
ldr r0, [r1]
ldr sb, [sl, #0xb4]
add r0, r0, #0x4000
#ifdef JAPAN
ldrb r0, [r0, #0x36]
#else
ldrb r0, [r0, #0xda]
#endif
ldrb r4, [sl, #0x25]
mov r5, #0
cmp r0, #0xa5
beq _01FFB304
cmp r0, #0xaa
blo _01FFB31C
cmp r0, #0xdc
bhs _01FFB31C
_01FFB304:
ldrsh r0, [sl, #4]
ldrsh r1, [sl, #6]
bl GetTile
ldrh r0, [r0]
tst r0, #0x100
movne r5, #1
_01FFB31C:
cmp r5, #0
bne _01FFB32C
cmp r4, #0xff
bne _01FFB3F0
_01FFB32C:
ldrb r1, [sb, #0x4c]
mov r0, sl
mov r7, #0
add r1, r1, #4
and r6, r1, #7
bl IsAtJunction
cmp r0, #0
beq _01FFB35C
mov r0, #8
bl DungeonRandInt
strb r0, [sb, #0x4c]
mov r7, #1
_01FFB35C:
mov r5, #0
ldr r4, _01FFB620 ; =FACING_DIRECTION_INCREMENTS
add fp, sp, #1
b _01FFB3E4
_01FFB36C:
ldrb r1, [sb, #0x4c]
ldr r0, [r4, r5, lsl #2]
cmp r7, #0
add r0, r1, r0
and r8, r0, #7
beq _01FFB38C
cmp r8, r6
beq _01FFB3E0
_01FFB38C:
mov r0, sl
mov r1, r8
mov r2, fp
bl CanAiMonsterMoveInDirection
cmp r0, #0
beq _01FFB3E0
mov r0, #3
strb r0, [sb, #0x7c]
ldr r0, _01FFB624 ; =DIRECTIONS_XY
mov r3, r8, lsl #2
ldrsh r2, [r0, r3]
ldrsh r4, [sl, #4]
ldr r1, _01FFB628 ; =DIRECTIONS_XY + 2
mov r0, #1
add r2, r4, r2
strh r2, [sb, #0x8c]
ldrsh r2, [sl, #6]
ldrsh r1, [r1, r3]
add r1, r2, r1
strh r1, [sb, #0x8e]
ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, sl, fp, pc}
_01FFB3E0:
add r5, r5, #1
_01FFB3E4:
cmp r5, #8
blt _01FFB36C
b _01FFB5D8
_01FFB3F0:
ldr r0, _01FFB61C ; =DUNGEON_PTR
#ifdef JAPAN
ldr r1, [sb, #0x11c]
ldr r2, [r0]
cmp r1, #0
add r0, r2, r4, lsl #1
add r1, r2, #0x204
add r0, r0, #0xf100
add r1, r1, #0xf000
add r6, r1, r4, lsl #7
ldrsh r5, [r0, #0xc4]
#else
ldr r1, [sb, #0x120]
ldr r2, [r0]
cmp r1, #0
add r0, r2, r4, lsl #1
add r1, r2, #0x2a8
add r0, r0, #0xf200
add r1, r1, #0xf000
add r6, r1, r4, lsl #7
ldrsh r5, [r0, #0x68]
#endif
beq _01FFB460
mov r0, #8
bl DungeonRandInt
mov r1, #6
strb r1, [sb, #0x7c]
mov r3, r0, lsl #2
ldr r0, _01FFB624 ; =DIRECTIONS_XY
ldrsh r4, [sl, #4]
ldrsh r2, [r0, r3]
ldr r1, _01FFB628 ; =DIRECTIONS_XY + 2
mov r0, #1
add r2, r4, r2
strh r2, [sb, #0x8c]
ldrsh r2, [sl, #6]
ldrsh r1, [r1, r3]
add r1, r2, r1
strh r1, [sb, #0x8e]
ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, sl, fp, pc}
_01FFB460:
ldrb r0, [sb, #0x7c]
cmp r0, #4
beq _01FFB520
cmp r5, #0
bne _01FFB4B8
mov r0, #8
bl DungeonRandInt
mov r1, #6
strb r1, [sb, #0x7c]
mov r3, r0, lsl #2
ldr r0, _01FFB624 ; =DIRECTIONS_XY
ldrsh r4, [sl, #4]
ldrsh r2, [r0, r3]
ldr r1, _01FFB628 ; =DIRECTIONS_XY + 2
mov r0, #1
add r2, r4, r2
strh r2, [sb, #0x8c]
ldrsh r2, [sl, #6]
ldrsh r1, [r1, r3]
add r1, r2, r1
strh r1, [sb, #0x8e]
ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, sl, fp, pc}
_01FFB4B8:
mov r4, #0
b _01FFB518
_01FFB4C0:
mov r0, r5
bl DungeonRandInt
mov r2, r0, lsl #2
ldrsh r3, [sl, #4]
ldrsh r1, [r6, r2]
cmp r3, r1
addeq r1, r6, r2
ldreqsh r2, [sl, #6]
ldreqsh r1, [r1, #2]
cmpeq r2, r1
beq _01FFB514
mov r1, #4
strb r1, [sb, #0x7c]
mov r1, r0, lsl #2
ldrsh r2, [r6, r1]
add r1, r6, r0, lsl #2
mov r0, #1
strh r2, [sb, #0x8c]
ldrsh r1, [r1, #2]
strh r1, [sb, #0x8e]
ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, sl, fp, pc}
_01FFB514:
add r4, r4, #1
_01FFB518:
cmp r4, #0xa
blt _01FFB4C0
_01FFB520:
ldrsh r0, [sl, #4]
ldrsh r1, [sl, #6]
bl GetTile
ldrh r0, [r0]
tst r0, #8
beq _01FFB5D0
mov r0, #8
bl DungeonRandInt
mov r8, r0
mov r5, #0
add fp, sp, #0
ldr r4, _01FFB624 ; =DIRECTIONS_XY
b _01FFB5C8
_01FFB554:
and r8, r8, #7
mov r1, r8, lsl #2
add r0, r4, r8, lsl #2
ldrsh r6, [sl, #4]
ldrsh r3, [r4, r1]
ldrsh r2, [sl, #6]
ldrsh r1, [r0, #2]
add r6, r6, r3
mov r0, r6
add r7, r2, r1
mov r1, r7
bl GetTile
ldrb r0, [r0, #7]
cmp r0, #0xff
bne _01FFB5C0
mov r0, sl
mov r1, r8
mov r2, fp
bl CanAiMonsterMoveInDirection
cmp r0, #0
beq _01FFB5C0
mov r0, #3
strb r0, [sb, #0x7c]
strh r6, [sb, #0x8c]
strh r7, [sb, #0x8e]
mov r0, #1
ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, sl, fp, pc}
_01FFB5C0:
add r5, r5, #1
add r8, r8, #1
_01FFB5C8:
cmp r5, #8
blt _01FFB554
_01FFB5D0:
mov r0, #1
ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, sl, fp, pc}
_01FFB5D8:
mov r0, #8
bl DungeonRandInt
mov r1, #6
strb r1, [sb, #0x7c]
mov r3, r0, lsl #2
ldr r0, _01FFB624 ; =DIRECTIONS_XY
ldrsh r4, [sl, #4]
ldrsh r2, [r0, r3]
ldr r1, _01FFB628 ; =DIRECTIONS_XY + 2
mov r0, #1
add r2, r4, r2
strh r2, [sb, #0x8c]
ldrsh r2, [sl, #6]
ldrsh r1, [r1, r3]
add r1, r2, r1
strh r1, [sb, #0x8e]
ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, sl, fp, pc}
.align 2, 0
_01FFB61C: .word DUNGEON_PTR
_01FFB620: .word FACING_DIRECTION_INCREMENTS
_01FFB624: .word DIRECTIONS_XY
_01FFB628: .word DIRECTIONS_XY + 2
arm_func_end CalculateAiTargetPos
arm_func_start sub_01FFB62C
sub_01FFB62C: ; 0x01FFB62C
ldr r3, [r0, #0xb4]
mov r2, #0
strb r2, [r3, #0x7c]
ldrh r1, [r0, #4]
strh r1, [r3, #0x8c]
ldrh r0, [r0, #6]
strh r0, [r3, #0x8e]
str r2, [r3, #0x84]
strh r2, [r3, #0x80]
bx lr
arm_func_end sub_01FFB62C
.global _01FFB654
_01FFB654:
.byte 0x05, 0x03, 0x00, 0x00

22
asm/itcm_01FFB62C.s Normal file
View File

@ -0,0 +1,22 @@
.include "asm/macros.inc"
.include "itcm_01FFB62C.inc"
.section .itcm,4,1,4
arm_func_start sub_01FFB62C
sub_01FFB62C: ; 0x01FFB62C
ldr r3, [r0, #0xb4]
mov r2, #0
strb r2, [r3, #0x7c]
ldrh r1, [r0, #4]
strh r1, [r3, #0x8c]
ldrh r0, [r0, #6]
strh r0, [r3, #0x8e]
str r2, [r3, #0x84]
strh r2, [r3, #0x80]
bx lr
arm_func_end sub_01FFB62C
.global _01FFB654
_01FFB654:
.byte 0x05, 0x03, 0x00, 0x00

View File

@ -3,6 +3,11 @@
#include "dungeon_mode.h"
// Used by the AI to determine the direction in which a monster should move
// monster: Entity pointer
// show_run_away_effect: If the monster becomes terrified, this flag determines whether the "poof" visual effect will show.
void AiMovement(struct entity *monster, bool8 show_run_away_effect);
// Calculates the target position of an AI-controlled monster and stores it in the monster's ai_target_pos field
bool8 CalculateAiTargetPos(struct entity *monster);
#endif //PMDSKY_DUNGEON_AI_MOVEMENT_H

View File

@ -143,7 +143,7 @@ Autoload ITCM
Address 0x01FF8000
Object asm/itcm.o (.itcm)
Object src/dungeon_ai_movement.o (.itcm)
Object asm/itcm_01FFB2C8.o (.itcm)
Object asm/itcm_01FFB62C.o (.itcm)
Object src/dungeon_ai_itcm.o (.itcm)
Object asm/itcm_01FFBD20.o (.itcm)
}

View File

@ -40,7 +40,6 @@ struct can_move_in_direction_info
const s32 FACING_DIRECTION_INCREMENTS[] = {0, 1, -1, 2, -2, 3, -3, 4};
extern bool8 CalculateAiTargetPos(struct entity *monster);
extern bool8 CanAiMonsterMoveInDirection(struct entity *monster, s32 direction, bool8 *out_monster_in_target_position);
extern bool8 CanTargetEntity(struct entity *user, struct entity *target);
extern bool8 CanTargetPosition(struct entity *monster, struct position *position);
@ -57,6 +56,7 @@ extern bool8 ShouldAvoidFirstHit(struct entity *monster, bool8 force_avoid);
extern bool8 CanSeeTeammate(struct entity *monster);
extern struct entity* GetLeaderIfVisible(struct entity *monster);
extern bool8 ov29_02348D00(struct item*);
extern bool8 IsAtJunction(struct entity *monster);
// https://decomp.me/scratch/2QnEr
#ifdef NONMATCHING
@ -1691,3 +1691,124 @@ _01FFB2A4:
ldmia sp!, {r3, r4, r5, r6, r7, r8, r9, r10, r11, pc}
}
#endif
bool8 CalculateAiTargetPos(struct entity *monster)
{
struct monster *pokemon_info = GetEntInfo(monster);
enum fixed_room_id fixed_room_id = DUNGEON_PTR[0]->gen_info.fixed_room_id;
s32 room = monster->room_idx;
bool8 is_sealed_chamber = FALSE;
if (fixed_room_id == FIXED_SEALED_CHAMBER ||
fixed_room_id >= FIXED_CLEAR_SILK_CHAMBER && fixed_room_id < FIXED_LEGENDARY_EXCLUSIVE_CHAMBER_1)
{
if (GetTile(monster->pos.x, monster->pos.y)->terrain_flags & TERRAIN_TYPE_UNBREAKABLE)
is_sealed_chamber = TRUE;
}
if (is_sealed_chamber || room == CORRIDOR_ROOM)
{
s32 i;
s32 opposite_facing_dir = (pokemon_info->action.direction + NUM_DIRECTIONS / 2) & DIRECTION_MASK;
bool8 is_at_junction = FALSE;
s32 target_facing_dir;
if (IsAtJunction(monster))
{
pokemon_info->action.direction = DungeonRandInt(NUM_DIRECTIONS);
is_at_junction = TRUE;
}
for (i = 0; i < NUM_DIRECTIONS; i++)
{
bool8 pokemon_in_front;
target_facing_dir = (pokemon_info->action.direction + FACING_DIRECTION_INCREMENTS[i]) & DIRECTION_MASK;
if (is_at_junction && target_facing_dir == opposite_facing_dir)
{
continue;
}
if (!CanAiMonsterMoveInDirection(monster, target_facing_dir, &pokemon_in_front))
{
continue;
}
pokemon_info->ai_target.ai_objective = AI_ROAM;
pokemon_info->ai_target.ai_target_pos.x = monster->pos.x + DIRECTIONS_XY[target_facing_dir].x;
pokemon_info->ai_target.ai_target_pos.y = monster->pos.y + DIRECTIONS_XY[target_facing_dir].y;
return TRUE;
}
}
else
{
s32 i;
s32 target_facing_dir;
s32 natural_junction_list_counts = DUNGEON_PTR[0]->natural_junction_list_counts[room];
struct position *natural_junction_list = DUNGEON_PTR[0]->natural_junction_list[room];
if (pokemon_info->random_movement)
{
target_facing_dir = DungeonRandInt(NUM_DIRECTIONS);
pokemon_info->ai_target.ai_objective = AI_STAND_STILL;
pokemon_info->ai_target.ai_target_pos.x = monster->pos.x + DIRECTIONS_XY[target_facing_dir].x;
pokemon_info->ai_target.ai_target_pos.y = monster->pos.y + DIRECTIONS_XY[target_facing_dir].y;
return TRUE;
}
else
{
if (pokemon_info->ai_target.ai_objective != AI_LEAVE_ROOM)
{
if (natural_junction_list_counts == 0)
{
target_facing_dir = DungeonRandInt(NUM_DIRECTIONS);
pokemon_info->ai_target.ai_objective = AI_STAND_STILL;
pokemon_info->ai_target.ai_target_pos.x = monster->pos.x + DIRECTIONS_XY[target_facing_dir].x;
pokemon_info->ai_target.ai_target_pos.y = monster->pos.y + DIRECTIONS_XY[target_facing_dir].y;
return TRUE;
}
for (i = 0; i < 10; i++)
{
target_facing_dir = DungeonRandInt(natural_junction_list_counts);
if (monster->pos.x != natural_junction_list[target_facing_dir].x ||
monster->pos.y != natural_junction_list[target_facing_dir].y)
{
pokemon_info->ai_target.ai_objective = AI_LEAVE_ROOM;
pokemon_info->ai_target.ai_target_pos.x = natural_junction_list[target_facing_dir].x;
pokemon_info->ai_target.ai_target_pos.y = natural_junction_list[target_facing_dir].y;
return TRUE;
}
}
// If the AI randomly picks the exit it's standing on 10 times,
// it gives up and exits the way it came.
// This occurs normally for one-exit rooms, but can happen rarely for multi-exit rooms.
}
if (GetTile(monster->pos.x, monster->pos.y)->terrain_flags & TERRAIN_TYPE_NATURAL_JUNCTION)
{
s32 i;
target_facing_dir = DungeonRandInt(NUM_DIRECTIONS);
for (i = 0; i < NUM_DIRECTIONS; i++, target_facing_dir++)
{
bool8 pokemon_in_front;
s32 forward_x, forward_y;
target_facing_dir &= DIRECTION_MASK;
forward_x = monster->pos.x + DIRECTIONS_XY[target_facing_dir].x;
forward_y = monster->pos.y + DIRECTIONS_XY[target_facing_dir].y;
if (GetTile(forward_x, forward_y)->room == CORRIDOR_ROOM &&
CanAiMonsterMoveInDirection(monster, target_facing_dir, &pokemon_in_front))
{
pokemon_info->ai_target.ai_objective = AI_ROAM;
pokemon_info->ai_target.ai_target_pos.x = forward_x;
pokemon_info->ai_target.ai_target_pos.y = forward_y;
return TRUE;
}
}
}
return TRUE;
}
}
s32 target_facing_dir = DungeonRandInt(NUM_DIRECTIONS);
pokemon_info->ai_target.ai_objective = AI_STAND_STILL;
pokemon_info->ai_target.ai_target_pos.x = monster->pos.x + DIRECTIONS_XY[target_facing_dir].x;
pokemon_info->ai_target.ai_target_pos.y = monster->pos.y + DIRECTIONS_XY[target_facing_dir].y;
return TRUE;
}

View File

@ -57,6 +57,8 @@ with open(original_file_path, 'r') as original_file:
if function_location.startswith('main'):
file_prefix = 'main_'
elif function_location.startswith('itcm'):
file_prefix = 'itcm_'
else:
file_prefix = function_location[:len('overlay_00_')]
if file_prefix[-1] != '_':
@ -130,7 +132,7 @@ for i, line in enumerate(lsf_lines):
lsf_lines[i] = ''
prev_line = lsf_lines[i - 1]
if prev_line.startswith(SRC_LSF_PREFIX):
merge_prev_file = prev_line[len(SRC_LSF_PREFIX) : -3]
merge_prev_file = prev_line[len(SRC_LSF_PREFIX):]
if not include_new_asm_file and merge_prev_file is None:
next_line = lsf_lines[i + 1]
if next_line.startswith(SRC_LSF_PREFIX):
@ -141,6 +143,12 @@ for i, line in enumerate(lsf_lines):
lsf_lines[i] += f'\tObject asm/{new_asm_base_name}.o{lsf_suffix}\n'
break
if merge_prev_file is not None:
line_end_index = len('.o\n')
if merge_prev_file.endswith('.o (.itcm)\n'):
line_end_index = len('.o (.itcm)\n')
merge_prev_file = merge_prev_file[:-line_end_index]
print('Updating', LSF_FILE_PATH)
with open(LSF_FILE_PATH, 'w') as lsf_file:
lsf_file.writelines(lsf_lines)