From 12e467d633cf36cadeccaebdfd680d7ceaf790b5 Mon Sep 17 00:00:00 2001 From: AnonymousRandomPerson Date: Sat, 15 Nov 2025 22:36:13 -0500 Subject: [PATCH 1/6] Decomped GetTurnLimit --- asm/include/main_02051098.inc | 9 ++-- asm/include/main_020512C8.inc | 4 ++ asm/main_02051098.s | 93 ----------------------------------- asm/main_020512C8.s | 86 ++++++++++++++++++++++++++++++++ asm/main_rodata_020908D4.s | 2 - include/dungeon.h | 25 +++++++--- include/main_020512B0.h | 9 ++++ main.lsf | 2 + src/dungeon_logic_7.c | 3 +- src/dungeon_recruitment_2.c | 2 +- src/main_020512B0.c | 9 ++++ 11 files changed, 134 insertions(+), 110 deletions(-) create mode 100644 asm/include/main_020512C8.inc create mode 100644 asm/main_020512C8.s create mode 100644 include/main_020512B0.h create mode 100644 src/main_020512B0.c diff --git a/asm/include/main_02051098.inc b/asm/include/main_02051098.inc index 1714f2c8..0f056522 100644 --- a/asm/include/main_02051098.inc +++ b/asm/include/main_02051098.inc @@ -1,10 +1,7 @@ #pragma once -.public _020A0C68 -.public _020A0C69 -.public _020A0C6C -.public _020AFF7C -.public _020AFF80 -.public _020AFF88 .public CopyBitsFrom .public CopyBitsTo .public DUNGEON_RESTRICTIONS +.public _020AFF7C +.public _020AFF80 +.public _020AFF88 diff --git a/asm/include/main_020512C8.inc b/asm/include/main_020512C8.inc new file mode 100644 index 00000000..ac3c8096 --- /dev/null +++ b/asm/include/main_020512C8.inc @@ -0,0 +1,4 @@ +#pragma once +.public DUNGEON_RESTRICTIONS +.public _020A0C68 +.public _020A0C69 diff --git a/asm/main_02051098.s b/asm/main_02051098.s index bac1c586..9a3e7e53 100644 --- a/asm/main_02051098.s +++ b/asm/main_02051098.s @@ -166,96 +166,3 @@ DungeonGoesUp: ; 0x02051288 .align 2, 0 _020512AC: .word DUNGEON_RESTRICTIONS arm_func_end DungeonGoesUp - - arm_func_start GetTurnLimit -GetTurnLimit: ; 0x020512B0 - mov r1, #0xc - mul r1, r0, r1 - ldr r0, _020512C4 ; =_020A0C6C - ldrsh r0, [r0, r1] - bx lr - .align 2, 0 -_020512C4: .word _020A0C6C - arm_func_end GetTurnLimit - - arm_func_start DoesNotSaveWhenEntering -DoesNotSaveWhenEntering: ; 0x020512C8 - mov r1, #0xc - mul r1, r0, r1 - ldr r0, _020512EC ; =DUNGEON_RESTRICTIONS - ldr r0, [r0, r1] - tst r0, #0x80 - movne r0, #1 - moveq r0, #0 - and r0, r0, #0xff - bx lr - .align 2, 0 -_020512EC: .word DUNGEON_RESTRICTIONS - arm_func_end DoesNotSaveWhenEntering - - arm_func_start TreasureBoxDropsEnabled -TreasureBoxDropsEnabled: ; 0x020512F0 - mov r1, #0xc - mul r1, r0, r1 - ldr r0, _02051314 ; =DUNGEON_RESTRICTIONS - ldr r0, [r0, r1] - tst r0, #0x400 - movne r0, #1 - moveq r0, #0 - and r0, r0, #0xff - bx lr - .align 2, 0 -_02051314: .word DUNGEON_RESTRICTIONS - arm_func_end TreasureBoxDropsEnabled - - arm_func_start IsLevelResetDungeon -IsLevelResetDungeon: ; 0x02051318 - mov r1, #0xc - mul r1, r0, r1 - ldr r0, _0205133C ; =DUNGEON_RESTRICTIONS - ldr r0, [r0, r1] - tst r0, #0x10 - movne r0, #1 - moveq r0, #0 - and r0, r0, #0xff - bx lr - .align 2, 0 -_0205133C: .word DUNGEON_RESTRICTIONS - arm_func_end IsLevelResetDungeon - - arm_func_start GetMaxItemsAllowed -GetMaxItemsAllowed: ; 0x02051340 - mov r1, #0xc - mul r1, r0, r1 - ldr r0, _02051354 ; =_020A0C69 - ldrb r0, [r0, r1] - bx lr - .align 2, 0 -_02051354: .word _020A0C69 - arm_func_end GetMaxItemsAllowed - - arm_func_start IsMoneyAllowed -IsMoneyAllowed: ; 0x02051358 - mov r1, #0xc - mul r1, r0, r1 - ldr r0, _0205137C ; =DUNGEON_RESTRICTIONS - ldr r0, [r0, r1] - tst r0, #0x20 - movne r0, #1 - moveq r0, #0 - and r0, r0, #0xff - bx lr - .align 2, 0 -_0205137C: .word DUNGEON_RESTRICTIONS - arm_func_end IsMoneyAllowed - - arm_func_start GetMaxRescueAttempts -GetMaxRescueAttempts: ; 0x02051380 - mov r1, #0xc - mul r1, r0, r1 - ldr r0, _02051394 ; =_020A0C68 - ldrsb r0, [r0, r1] - bx lr - .align 2, 0 -_02051394: .word _020A0C68 - arm_func_end GetMaxRescueAttempts diff --git a/asm/main_020512C8.s b/asm/main_020512C8.s new file mode 100644 index 00000000..bd9aad70 --- /dev/null +++ b/asm/main_020512C8.s @@ -0,0 +1,86 @@ + .include "asm/macros.inc" + .include "main_020512C8.inc" + + .text + + arm_func_start DoesNotSaveWhenEntering +DoesNotSaveWhenEntering: ; 0x020512C8 + mov r1, #0xc + mul r1, r0, r1 + ldr r0, _020512EC ; =DUNGEON_RESTRICTIONS + ldr r0, [r0, r1] + tst r0, #0x80 + movne r0, #1 + moveq r0, #0 + and r0, r0, #0xff + bx lr + .align 2, 0 +_020512EC: .word DUNGEON_RESTRICTIONS + arm_func_end DoesNotSaveWhenEntering + + arm_func_start TreasureBoxDropsEnabled +TreasureBoxDropsEnabled: ; 0x020512F0 + mov r1, #0xc + mul r1, r0, r1 + ldr r0, _02051314 ; =DUNGEON_RESTRICTIONS + ldr r0, [r0, r1] + tst r0, #0x400 + movne r0, #1 + moveq r0, #0 + and r0, r0, #0xff + bx lr + .align 2, 0 +_02051314: .word DUNGEON_RESTRICTIONS + arm_func_end TreasureBoxDropsEnabled + + arm_func_start IsLevelResetDungeon +IsLevelResetDungeon: ; 0x02051318 + mov r1, #0xc + mul r1, r0, r1 + ldr r0, _0205133C ; =DUNGEON_RESTRICTIONS + ldr r0, [r0, r1] + tst r0, #0x10 + movne r0, #1 + moveq r0, #0 + and r0, r0, #0xff + bx lr + .align 2, 0 +_0205133C: .word DUNGEON_RESTRICTIONS + arm_func_end IsLevelResetDungeon + + arm_func_start GetMaxItemsAllowed +GetMaxItemsAllowed: ; 0x02051340 + mov r1, #0xc + mul r1, r0, r1 + ldr r0, _02051354 ; =_020A0C69 + ldrb r0, [r0, r1] + bx lr + .align 2, 0 +_02051354: .word _020A0C69 + arm_func_end GetMaxItemsAllowed + + arm_func_start IsMoneyAllowed +IsMoneyAllowed: ; 0x02051358 + mov r1, #0xc + mul r1, r0, r1 + ldr r0, _0205137C ; =DUNGEON_RESTRICTIONS + ldr r0, [r0, r1] + tst r0, #0x20 + movne r0, #1 + moveq r0, #0 + and r0, r0, #0xff + bx lr + .align 2, 0 +_0205137C: .word DUNGEON_RESTRICTIONS + arm_func_end IsMoneyAllowed + + arm_func_start GetMaxRescueAttempts +GetMaxRescueAttempts: ; 0x02051380 + mov r1, #0xc + mul r1, r0, r1 + ldr r0, _02051394 ; =_020A0C68 + ldrsb r0, [r0, r1] + bx lr + .align 2, 0 +_02051394: .word _020A0C68 + arm_func_end GetMaxRescueAttempts diff --git a/asm/main_rodata_020908D4.s b/asm/main_rodata_020908D4.s index 0fc0af95..450ab3f7 100644 --- a/asm/main_rodata_020908D4.s +++ b/asm/main_rodata_020908D4.s @@ -10402,8 +10402,6 @@ _020A0C69: .global _020A0C6A _020A0C6A: .byte 0x04, 0x00 - .global _020A0C6C -_020A0C6C: .byte 0xE8, 0x03 .global _020A0C6E _020A0C6E: diff --git a/include/dungeon.h b/include/dungeon.h index 5150752d..b21da84b 100644 --- a/include/dungeon.h +++ b/include/dungeon.h @@ -1823,14 +1823,27 @@ struct dungeon { u8 field_0x2cb13; }; +// Entry for a single dungeon in the dungeon restriction list struct dungeon_restriction { + // 0x0: flags: 2-byte bitfield u32 flags; - u8 max_rescue_attempts; - u8 max_items_allowed; - u8 max_party_size; - u8 pad; - u16 turn_limit_per_floor; - u16 random_movement_chance; + // bool8 f_dungeon_goes_up : 1; // Dungeon goes up (stairs ascend, floors are labeled 1F, 2F, ...) + // bool8 f_enemies_evolve : 1; // Enemies evolve after they defeat another monster + // bool8 f_enemies_give_exp : 1; // Enemies give experience + // bool8 f_recruitment_allowed : 1; // Recruitment is allowed + // bool8 f_reset_to_level_1 : 1; // Team members are reset to level 1 for the dungeon + // bool8 f_money_allowed : 1; // Money is allowed to be brought into the dungeon + // bool8 f_leader_change_enabled : 1; // The team leader can be changed within the dungeon + // bool8 f_enter_without_saving : 1; // If false, the game will be saved upon entering + // bool8 f_disable_iq_skills : 1; // IQ skills won't work in the dungeon + // bool8 f_no_trap_uncovering : 1; // Traps cannot be revealed by attacking or throwing items + // bool8 f_treasure_box_drops : 1; // Enemies can drop Treasure Boxes + u8 max_rescue_attempts; // 0x4: 0xFF means no rescues allowed + u8 max_items_allowed; // 0x5: Maximum number of items that can be brought into the dungeon + u8 max_party_size; // 0x6: Maximum number of team members that can enter the dungeon + s16 turn_limit_per_floor; // 0x8: Number of turns per floor before the wind blows you out + // 0xA: Chance of setting the monster::random_movement field to 1 when spawning an enemy + s16 random_movement_chance; }; #endif // PMDSKY_DUNGEON_H diff --git a/include/main_020512B0.h b/include/main_020512B0.h new file mode 100644 index 00000000..bec3477d --- /dev/null +++ b/include/main_020512B0.h @@ -0,0 +1,9 @@ +#ifndef PMDSKY_MAIN_020512B0_H +#define PMDSKY_MAIN_020512B0_H + +#include "enums.h" +#include "util.h" + +s32 GetTurnLimit(enum dungeon_id dungeon_id); + +#endif //PMDSKY_MAIN_020512B0_H diff --git a/main.lsf b/main.lsf index 10fda222..1ff17fe6 100644 --- a/main.lsf +++ b/main.lsf @@ -94,6 +94,8 @@ Static main Object asm/main_0204DE7C.o Object src/number_util.o Object asm/main_02051098.o + Object src/main_020512B0.o + Object asm/main_020512C8.o Object src/dungeon_recruitment_2.o Object asm/main_020513C0.o Object src/main_020514CC.o diff --git a/src/dungeon_logic_7.c b/src/dungeon_logic_7.c index 152f7c8a..e8277238 100644 --- a/src/dungeon_logic_7.c +++ b/src/dungeon_logic_7.c @@ -3,10 +3,9 @@ #include "dungeon_mode.h" #include "dungeon_util_static.h" #include "fixed_room_data_1.h" +#include "main_020512B0.h" #include "util.h" -extern s32 GetTurnLimit(enum dungeon_id dungeon_id); - bool8 IsMonsterLoneOutlaw(struct monster* monster_info) { return IsBehaviorLoneOutlaw(monster_info->monster_behavior); diff --git a/src/dungeon_recruitment_2.c b/src/dungeon_recruitment_2.c index f6b48752..7eadff2b 100644 --- a/src/dungeon_recruitment_2.c +++ b/src/dungeon_recruitment_2.c @@ -4,7 +4,7 @@ #include "enums.h" #include "util.h" -extern struct dungeon_restriction DUNGEON_RESTRICTIONS[]; +extern struct dungeon_restriction DUNGEON_RESTRICTIONS[256]; bool8 IsRecruitingAllowed(enum dungeon_id dungeon_id) { diff --git a/src/main_020512B0.c b/src/main_020512B0.c new file mode 100644 index 00000000..2c12582e --- /dev/null +++ b/src/main_020512B0.c @@ -0,0 +1,9 @@ +#include "main_020512B0.h" +#include "dungeon.h" + +extern struct dungeon_restriction DUNGEON_RESTRICTIONS[256]; + +s32 GetTurnLimit(enum dungeon_id dungeon_id) +{ + return DUNGEON_RESTRICTIONS[dungeon_id].turn_limit_per_floor; +} From 045b081c4881d1d1e75838dfafa6bbd7e5efc697 Mon Sep 17 00:00:00 2001 From: AnonymousRandomPerson Date: Sat, 15 Nov 2025 22:45:04 -0500 Subject: [PATCH 2/6] Decomped CanSeeTeammate --- asm/include/overlay_29_02301FBC.inc | 3 -- asm/overlay_29_02301FBC.s | 43 ----------------------------- include/dungeon_logic_5.h | 2 ++ src/dungeon_ai_movement.c | 2 +- src/dungeon_logic_5.c | 15 ++++++++++ 5 files changed, 18 insertions(+), 47 deletions(-) diff --git a/asm/include/overlay_29_02301FBC.inc b/asm/include/overlay_29_02301FBC.inc index 2e0a096b..e0cc2e49 100644 --- a/asm/include/overlay_29_02301FBC.inc +++ b/asm/include/overlay_29_02301FBC.inc @@ -1,10 +1,7 @@ #pragma once .public CanLearnIqSkill -.public CanSeeTarget .public DisableIqSkill -.public DUNGEON_PTR .public EnableIqSkill -.public EntityIsValid__023000E4 .public GetPerformanceFlagWithChecks .public GetSpeciesIqSkill .public IqSkillFlagTest diff --git a/asm/overlay_29_02301FBC.s b/asm/overlay_29_02301FBC.s index e1e7d47c..c25027ac 100644 --- a/asm/overlay_29_02301FBC.s +++ b/asm/overlay_29_02301FBC.s @@ -174,46 +174,3 @@ ov29_023021F0: ; 0x023021F0 .align 2, 0 _023021FC: .word UpdateIqSkills arm_func_end ov29_023021F0 - - arm_func_start CanSeeTeammate -CanSeeTeammate: ; 0x02302200 - stmdb sp!, {r3, r4, r5, r6, r7, lr} - mov r4, r0 - ldr r0, [r4, #0xb4] - ldrb r0, [r0, #6] - cmp r0, #0 - movne r0, #0 - ldmneia sp!, {r3, r4, r5, r6, r7, pc} - mov r6, #0 - ldr r5, _02302278 ; =DUNGEON_PTR - b _02302268 -_02302228: - ldr r1, [r5] - mov r0, r4 - add r1, r1, r6, lsl #2 - add r1, r1, #0x12000 -#ifdef JAPAN - ldr r7, [r1, #0xa84] -#else - ldr r7, [r1, #0xb28] -#endif - bl EntityIsValid__023000E4 - cmp r0, #0 - cmpne r4, r7 - beq _02302264 - mov r0, r4 - mov r1, r7 - bl CanSeeTarget - cmp r0, #0 - movne r0, #1 - ldmneia sp!, {r3, r4, r5, r6, r7, pc} -_02302264: - add r6, r6, #1 -_02302268: - cmp r6, #4 - blt _02302228 - mov r0, #0 - ldmia sp!, {r3, r4, r5, r6, r7, pc} - .align 2, 0 -_02302278: .word DUNGEON_PTR - arm_func_end CanSeeTeammate diff --git a/include/dungeon_logic_5.h b/include/dungeon_logic_5.h index f8242b63..55c8130d 100644 --- a/include/dungeon_logic_5.h +++ b/include/dungeon_logic_5.h @@ -3,6 +3,8 @@ #include "dungeon_mode.h" +// Checks if an allied monster can see any other teammate (via CanSeeTarget). Always returns false for enemy monsters. +bool8 CanSeeTeammate(struct entity *monster); // Check the type of a move when used by a certain monster. Accounts for special cases such as Hidden Power, Weather Ball, the regular attack... enum type_id GetMoveTypeForMonster(struct entity *entity, struct move *move); diff --git a/src/dungeon_ai_movement.c b/src/dungeon_ai_movement.c index 9559354e..84c30b7d 100644 --- a/src/dungeon_ai_movement.c +++ b/src/dungeon_ai_movement.c @@ -7,6 +7,7 @@ #include "dungeon_ai_targeting_1.h" #include "dungeon_capabilities_1.h" #include "dungeon_capabilities_4.h" +#include "dungeon_logic_5.h" #include "dungeon_logic_7.h" #include "dungeon_logic_8.h" #include "dungeon_map_access.h" @@ -50,7 +51,6 @@ struct can_move_in_direction_info const s32 FACING_DIRECTION_INCREMENTS[] = {0, 1, -1, 2, -2, 3, -3, 4}; extern bool8 ShouldAvoidFirstHit(struct entity *monster, bool8 force_avoid); -extern bool8 CanSeeTeammate(struct entity *monster); extern struct entity* GetLeaderIfVisible(struct entity *monster); extern bool8 IsAtJunction(struct entity *monster); diff --git a/src/dungeon_logic_5.c b/src/dungeon_logic_5.c index 0cd0b12d..946e2feb 100644 --- a/src/dungeon_logic_5.c +++ b/src/dungeon_logic_5.c @@ -1,12 +1,27 @@ #include "dungeon_logic_5.h" #include "dungeon_pokemon_attributes.h" #include "dungeon_util_static.h" +#include "dungeon_visibility.h" #include "main_02014CEC.h" #include "moves_2.h" #include "natural_gift_data.h" #include "overlay_29_023000E4.h" #include "special_move_types.h" +bool8 CanSeeTeammate(struct entity *monster) +{ + if (GetEntInfo(monster)->is_not_team_member) + return FALSE; + + for (s32 member_idx = 0; member_idx < MAX_TEAM_MEMBERS; member_idx++) + { + struct entity *team_member = DUNGEON_PTR[0]->monster_slots.party_members[member_idx]; + if (EntityIsValid__023000E4(monster) && monster != team_member && CanSeeTarget(monster, team_member)) + return TRUE; + } + return FALSE; +} + enum type_id GetMoveTypeForMonster(struct entity *entity, struct move *move) { if (!IsRegularAttackOrProjectile(move->id) && EntityIsValid__023000E4(entity) && AbilityIsActive(entity, ABILITY_NORMALIZE)) From b74b0f2b7e751528c9b75a9bce96629d7856e7d8 Mon Sep 17 00:00:00 2001 From: AnonymousRandomPerson Date: Sat, 15 Nov 2025 22:54:56 -0500 Subject: [PATCH 3/6] Decomped GetLeaderIfVisible --- asm/include/overlay_29_023082C4.inc | 4 --- asm/overlay_29_023082C4.s | 40 ----------------------------- include/dungeon_ai_leader.h | 2 ++ main.lsf | 1 - src/dungeon_ai_leader.c | 25 ++++++++++++++++++ src/dungeon_ai_movement.c | 1 - 6 files changed, 27 insertions(+), 46 deletions(-) delete mode 100644 asm/include/overlay_29_023082C4.inc delete mode 100644 asm/overlay_29_023082C4.s diff --git a/asm/include/overlay_29_023082C4.inc b/asm/include/overlay_29_023082C4.inc deleted file mode 100644 index c40ba39b..00000000 --- a/asm/include/overlay_29_023082C4.inc +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -.public CanTargetEntity -.public GetLeader -.public GetTreatmentBetweenMonsters diff --git a/asm/overlay_29_023082C4.s b/asm/overlay_29_023082C4.s deleted file mode 100644 index ffd3caaf..00000000 --- a/asm/overlay_29_023082C4.s +++ /dev/null @@ -1,40 +0,0 @@ - .include "asm/macros.inc" - .include "overlay_29_023082C4.inc" - - .text - - arm_func_start GetLeaderIfVisible -GetLeaderIfVisible: ; 0x023082C4 - stmdb sp!, {r3, r4, r5, lr} - mov r5, r0 - ldr r0, [r5, #0xb4] - ldrb r0, [r0, #6] - cmp r0, #0 - movne r0, #0 - ldmneia sp!, {r3, r4, r5, pc} - bl GetLeader - movs r4, r0 - beq _02308338 - ldr r0, [r4, #0xb4] - ldrb r0, [r0, #0xd8] - cmp r0, #2 - moveq r0, #0 - ldmeqia sp!, {r3, r4, r5, pc} - mov r2, #0 - mov r0, r5 - mov r1, r4 - mov r3, r2 - bl GetTreatmentBetweenMonsters - cmp r0, #0 - movne r0, #0 - ldmneia sp!, {r3, r4, r5, pc} - mov r0, r5 - mov r1, r4 - bl CanTargetEntity - cmp r0, #0 - movne r0, r4 - ldmneia sp!, {r3, r4, r5, pc} -_02308338: - mov r0, #0 - ldmia sp!, {r3, r4, r5, pc} - arm_func_end GetLeaderIfVisible diff --git a/include/dungeon_ai_leader.h b/include/dungeon_ai_leader.h index d0439509..bdf0262c 100644 --- a/include/dungeon_ai_leader.h +++ b/include/dungeon_ai_leader.h @@ -8,5 +8,7 @@ bool8 EntityIsValid__0230827C(struct entity *entity); // Checks if the monster should follow the leader. Always returns false for enemy monsters. // This function may actually be should monster target leader position. bool8 ShouldMonsterFollowLeader(struct entity *monster); +// For allied monsters, gets the leader monster if they are visible to the ally. Always returns null for enemy monsters. +struct entity* GetLeaderIfVisible(struct entity *monster); #endif //PMDSKY_DUNGEON_AI_LEADER_H diff --git a/main.lsf b/main.lsf index 1ff17fe6..5da3bba2 100644 --- a/main.lsf +++ b/main.lsf @@ -512,7 +512,6 @@ Overlay OVY_29 Object src/overlay_29_02307EF8.o Object asm/overlay_29_02307F4C.o Object src/dungeon_ai_leader.o - Object asm/overlay_29_023082C4.o Object src/dungeon_ai.o Object asm/overlay_29_023085DC.o Object src/overlay_29_02308FBC.o diff --git a/src/dungeon_ai_leader.c b/src/dungeon_ai_leader.c index 3150a95f..0017f079 100644 --- a/src/dungeon_ai_leader.c +++ b/src/dungeon_ai_leader.c @@ -1,7 +1,11 @@ #include "dungeon_ai_leader.h" +#include "dungeon_ai_targeting_1.h" #include "dungeon_util_static.h" +#include "dungeon_visibility.h" #include "main_02058C3C.h" +extern struct entity* GetLeader(void); + bool8 EntityIsValid__0230827C(struct entity *entity) { if (entity == NULL) @@ -17,3 +21,24 @@ bool8 ShouldMonsterFollowLeader(struct entity *monster) return DoesTacticFollowLeader(GetEntInfo(monster)->tactic); } + +struct entity* GetLeaderIfVisible(struct entity *monster) +{ + if (GetEntInfo(monster)->is_not_team_member) + return NULL; + + struct entity *leader = GetLeader(); + if (leader != NULL) + { + if (GetEntInfo(leader)->curse_class_status.curse == STATUS_CURSE_DECOY) + return NULL; + + if (GetTreatmentBetweenMonsters(monster, leader, FALSE, FALSE) != TREATMENT_TREAT_AS_ALLY) + return NULL; + + if (CanTargetEntity(monster, leader)) + return leader; + } + + return NULL; +} diff --git a/src/dungeon_ai_movement.c b/src/dungeon_ai_movement.c index 84c30b7d..da31d7ce 100644 --- a/src/dungeon_ai_movement.c +++ b/src/dungeon_ai_movement.c @@ -51,7 +51,6 @@ struct can_move_in_direction_info const s32 FACING_DIRECTION_INCREMENTS[] = {0, 1, -1, 2, -2, 3, -3, 4}; extern bool8 ShouldAvoidFirstHit(struct entity *monster, bool8 force_avoid); -extern struct entity* GetLeaderIfVisible(struct entity *monster); extern bool8 IsAtJunction(struct entity *monster); bool8 ShouldMonsterRunAwayAndShowEffectOutlawCheck(struct entity *monster, bool8 show_run_away_effect) From 6ddd6ad9b93401d7b7e37e07cfa039011a505366 Mon Sep 17 00:00:00 2001 From: AnonymousRandomPerson Date: Sat, 15 Nov 2025 23:11:18 -0500 Subject: [PATCH 4/6] Decomped GetLeader --- asm/include/overlay_29_022E9488.inc | 4 +-- asm/overlay_29_022E9488.s | 40 ----------------------------- include/dg_uty.h | 2 ++ src/dg_uty.c | 22 ++++++++++++++++ src/dungeon_ai_leader.c | 3 +-- src/overlay_31_02382820.c | 2 +- 6 files changed, 27 insertions(+), 46 deletions(-) diff --git a/asm/include/overlay_29_022E9488.inc b/asm/include/overlay_29_022E9488.inc index 4a63334c..d0a71e4b 100644 --- a/asm/include/overlay_29_022E9488.inc +++ b/asm/include/overlay_29_022E9488.inc @@ -1,8 +1,6 @@ #pragma once -.public _020AFC4C .public DUNGEON_PTR -.public EntityIsValid__022E95F4 -.public LEADER_PTR +.public _020AFC4C .public ov29_0237C888 .public ov29_0237C88A .public ov29_0237C88E diff --git a/asm/overlay_29_022E9488.s b/asm/overlay_29_022E9488.s index 764af856..b283bf63 100644 --- a/asm/overlay_29_022E9488.s +++ b/asm/overlay_29_022E9488.s @@ -74,43 +74,3 @@ _022E9574: .word 0xFFFF000F _022E9578: .word _020AFC4C _022E957C: .word ov29_0237C888 arm_func_end ov29_022E9488 - - arm_func_start GetLeader -GetLeader: ; 0x022E9580 - stmdb sp!, {r4, r5, r6, lr} - ldr r0, _022E95EC ; =LEADER_PTR - ldr r0, [r0] - cmp r0, #0 - ldmneia sp!, {r4, r5, r6, pc} - mov r5, #0 - ldr r4, _022E95F0 ; =DUNGEON_PTR - b _022E95DC -_022E95A0: - ldr r0, [r4] - add r0, r0, r5, lsl #2 - add r0, r0, #0x12000 -#ifdef JAPAN - ldr r6, [r0, #0xa84] -#else - ldr r6, [r0, #0xb28] -#endif - mov r0, r6 - bl EntityIsValid__022E95F4 - cmp r0, #0 - ldrne r0, [r6, #0xb4] - ldrneb r0, [r0, #7] - cmpne r0, #0 - ldrne r1, _022E95EC ; =LEADER_PTR - movne r0, r6 - strne r6, [r1] - ldmneia sp!, {r4, r5, r6, pc} - add r5, r5, #1 -_022E95DC: - cmp r5, #4 - blt _022E95A0 - mov r0, #0 - ldmia sp!, {r4, r5, r6, pc} - .align 2, 0 -_022E95EC: .word LEADER_PTR -_022E95F0: .word DUNGEON_PTR - arm_func_end GetLeader diff --git a/include/dg_uty.h b/include/dg_uty.h index 2ac6d78e..26586b41 100644 --- a/include/dg_uty.h +++ b/include/dg_uty.h @@ -3,6 +3,8 @@ #include "dungeon_mode.h" +// Gets the pointer to the entity that is currently leading the team, or null if none of the first 4 entities is a valid monster with its is_team_leader flag set. It also sets LEADER_PTR to the result before returning it. +struct entity* GetLeader(); // Checks if an entity pointer points to a valid entity (not entity type 0, which represents no entity). bool8 EntityIsValid__022E95F4(struct entity *entity); diff --git a/src/dg_uty.c b/src/dg_uty.c index 2ffff0c7..a0a5aa8a 100644 --- a/src/dg_uty.c +++ b/src/dg_uty.c @@ -1,8 +1,30 @@ #include "dg_uty.h" +#include "dungeon.h" #include "dungeon_util_static.h" // file starts at 0x022e9020 +extern struct entity *LEADER_PTR; + +struct entity* GetLeader() +{ + struct entity *leader = LEADER_PTR; + if (leader == NULL) + { + for (s32 i = 0; i < MAX_TEAM_MEMBERS; i++) + { + struct entity *current_pokemon = DUNGEON_PTR[0]->monster_slots.party_members[i]; + if (EntityIsValid__022E95F4(current_pokemon) && GetEntInfo(current_pokemon)->is_team_leader) + { + LEADER_PTR = current_pokemon; + return current_pokemon; + } + } + return NULL; + } + return leader; +} + bool8 EntityIsValid__022E95F4(struct entity *entity) { if (entity == NULL) diff --git a/src/dungeon_ai_leader.c b/src/dungeon_ai_leader.c index 0017f079..bfde196a 100644 --- a/src/dungeon_ai_leader.c +++ b/src/dungeon_ai_leader.c @@ -1,11 +1,10 @@ #include "dungeon_ai_leader.h" +#include "dg_uty.h" #include "dungeon_ai_targeting_1.h" #include "dungeon_util_static.h" #include "dungeon_visibility.h" #include "main_02058C3C.h" -extern struct entity* GetLeader(void); - bool8 EntityIsValid__0230827C(struct entity *entity) { if (entity == NULL) diff --git a/src/overlay_31_02382820.c b/src/overlay_31_02382820.c index 1b051f43..6112d055 100644 --- a/src/overlay_31_02382820.c +++ b/src/overlay_31_02382820.c @@ -1,4 +1,5 @@ #include "overlay_31_02382820.h" +#include "dg_uty.h" #include "dungeon_ai_targeting.h" #include "dungeon_util_static.h" #include "number_util.h" @@ -23,7 +24,6 @@ extern u16 ov31_02389E22[]; extern void* MemAlloc(u32 size, u32 nmemb); -extern struct entity* GetLeader(void); extern u32 GetMoneyCarried(void); extern u32 sub_0204F9E0(void); extern void ov29_022E2A78(u8*, void*, u32); // The third argument isn't actually used in the From a5882c3d58d7101cde0e6b665b41acc422ffc071 Mon Sep 17 00:00:00 2001 From: AnonymousRandomPerson Date: Sat, 15 Nov 2025 23:19:43 -0500 Subject: [PATCH 5/6] Decomped ShouldAvoidFirstHit --- asm/include/overlay_29_02301498.inc | 1 - asm/overlay_29_02301498.s | 13 ------------- include/dungeon_ai_targeting.h | 5 +++++ src/dungeon_ai_movement.c | 1 - src/dungeon_ai_targeting.c | 8 ++++++++ 5 files changed, 13 insertions(+), 15 deletions(-) diff --git a/asm/include/overlay_29_02301498.inc b/asm/include/overlay_29_02301498.inc index f29c18ec..2fb0d89d 100644 --- a/asm/include/overlay_29_02301498.inc +++ b/asm/include/overlay_29_02301498.inc @@ -6,6 +6,5 @@ .public GetTile .public IqSkillIsEnabled .public IsCurrentTilesetBackground -.public IsTacticSet .public ItemIsActive__022FF898 .public SECONDARY_TERRAIN_TYPES diff --git a/asm/overlay_29_02301498.s b/asm/overlay_29_02301498.s index 6be18276..5bc6d95b 100644 --- a/asm/overlay_29_02301498.s +++ b/asm/overlay_29_02301498.s @@ -111,16 +111,3 @@ _02301534: _0230158C: .word DUNGEON_PTR _02301590: .word SECONDARY_TERRAIN_TYPES arm_func_end IsAtJunction - - arm_func_start ShouldAvoidFirstHit -ShouldAvoidFirstHit: ; 0x02301594 - stmdb sp!, {r4, lr} - mov r4, r1 - mov r1, #3 - bl IsTacticSet - cmp r0, #0 - cmpne r4, #0 - movne r0, #1 - moveq r0, #0 - ldmia sp!, {r4, pc} - arm_func_end ShouldAvoidFirstHit diff --git a/include/dungeon_ai_targeting.h b/include/dungeon_ai_targeting.h index 4018a351..44827f9f 100644 --- a/include/dungeon_ai_targeting.h +++ b/include/dungeon_ai_targeting.h @@ -3,6 +3,11 @@ #include "dungeon_mode.h" +// Checks whether an AI-controlled monster should try to avoid the first hit in battle. +// monster: Entity pointer +// should_avoid: If true, this function always returns true. +// return: True if the monster should try to avoid the first hit in battle. +bool8 ShouldAvoidFirstHit(struct entity *monster, bool8 should_avoid); // Checks if a monster should run away from other monsters // return: True if the monster should run away, false otherwise bool8 ShouldMonsterRunAway(struct entity *monster); diff --git a/src/dungeon_ai_movement.c b/src/dungeon_ai_movement.c index da31d7ce..a9e8cb4c 100644 --- a/src/dungeon_ai_movement.c +++ b/src/dungeon_ai_movement.c @@ -50,7 +50,6 @@ struct can_move_in_direction_info const s32 FACING_DIRECTION_INCREMENTS[] = {0, 1, -1, 2, -2, 3, -3, 4}; -extern bool8 ShouldAvoidFirstHit(struct entity *monster, bool8 force_avoid); extern bool8 IsAtJunction(struct entity *monster); bool8 ShouldMonsterRunAwayAndShowEffectOutlawCheck(struct entity *monster, bool8 show_run_away_effect) diff --git a/src/dungeon_ai_targeting.c b/src/dungeon_ai_targeting.c index 1b6e8215..2322a35c 100644 --- a/src/dungeon_ai_targeting.c +++ b/src/dungeon_ai_targeting.c @@ -4,6 +4,14 @@ #include "dungeon_util_static.h" #include "overlay_29_023000E4.h" +bool8 ShouldAvoidFirstHit(struct entity *monster, bool8 should_avoid) +{ + if (IsTacticSet(monster, TACTIC_AVOID_THE_FIRST_HIT) && should_avoid) + return TRUE; + + return FALSE; +} + extern void DisplayRunAwayIfTriggered(struct entity *monster, bool8 show_run_away_effect); bool8 ShouldMonsterRunAway(struct entity *monster) From a47a2cad7eedab28055f6e05adb6de4c52fd6ed6 Mon Sep 17 00:00:00 2001 From: AnonymousRandomPerson Date: Sat, 15 Nov 2025 23:58:55 -0500 Subject: [PATCH 6/6] Decomped IsAtJunction --- asm/include/overlay_29_02301498.inc | 10 --- asm/overlay_29_02301498.s | 113 ---------------------------- include/dungeon_capabilities_4.h | 2 + include/dungeon_mode.h | 4 +- main.lsf | 1 - src/dungeon_ai.c | 2 +- src/dungeon_ai_movement.c | 2 - src/dungeon_capabilities_4.c | 66 ++++++++++++++++ 8 files changed, 71 insertions(+), 129 deletions(-) delete mode 100644 asm/include/overlay_29_02301498.inc delete mode 100644 asm/overlay_29_02301498.s diff --git a/asm/include/overlay_29_02301498.inc b/asm/include/overlay_29_02301498.inc deleted file mode 100644 index 2fb0d89d..00000000 --- a/asm/include/overlay_29_02301498.inc +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once -.public DUNGEON_PTR -.public DungeonRandInt -.public GetDirectionalMobilityType -.public GetMobilityTypeCheckSlipAndFloating -.public GetTile -.public IqSkillIsEnabled -.public IsCurrentTilesetBackground -.public ItemIsActive__022FF898 -.public SECONDARY_TERRAIN_TYPES diff --git a/asm/overlay_29_02301498.s b/asm/overlay_29_02301498.s deleted file mode 100644 index 5bc6d95b..00000000 --- a/asm/overlay_29_02301498.s +++ /dev/null @@ -1,113 +0,0 @@ - .include "asm/macros.inc" - .include "overlay_29_02301498.inc" - - .text - - arm_func_start IsAtJunction -IsAtJunction: ; 0x02301498 -#ifdef JAPAN -#define OV29_02301498_OFFSET -4 -#else -#define OV29_02301498_OFFSET 0 -#endif - stmdb sp!, {r3, r4, r5, lr} - mov r5, r0 - ldr r1, [r5, #0xb4] - ldrsh r1, [r1, #2] - bl GetMobilityTypeCheckSlipAndFloating -#ifdef JAPAN - mov r4, r0 - bl IsCurrentTilesetBackground - cmp r0, #0 - bne _02302A30_JP - ldr r0, [r5, #0xb4] - ldrb r0, [r0, #0xef] - cmp r0, #3 - moveq r4, #3 - beq _02302A30_JP - mov r0, r5 - mov r1, #0x10 - bl ItemIsActive__022FF898 - cmp r0, #0 - movne r4, #3 - bne _02302A30_JP - mov r0, r5 - mov r1, #0xc - bl IqSkillIsEnabled - cmp r0, #0 - movne r4, #2 - bne _02302A30_JP - mov r0, r5 - mov r1, #0xd - bl IqSkillIsEnabled - cmp r0, #0 - movne r4, #3 -_02302A30_JP: -#else - mov r1, r0 - mov r0, r5 - mov r2, #0xff - bl GetDirectionalMobilityType - mov r4, r0 -#endif - cmp r4, #3 - bne _023014FC - ldr r4, [r5, #0xb4] - mov r0, #0x64 - bl DungeonRandInt - add r1, r4, #0x200 - ldrsh r2, [r1, #0x12 + OV29_02301498_OFFSET] - add r0, r2, r0 - strh r0, [r1, #0x12 + OV29_02301498_OFFSET] - ldrsh r0, [r1, #0x12 + OV29_02301498_OFFSET] - cmp r0, #0xc8 - mov r0, #0 - strgeh r0, [r1, #0x12 + OV29_02301498_OFFSET] - movge r0, #1 - ldmia sp!, {r3, r4, r5, pc} -_023014FC: - ldr r0, _0230158C ; =DUNGEON_PTR - ldr r1, _02301590 ; =SECONDARY_TERRAIN_TYPES - ldr r0, [r0] - add r0, r0, #0x4000 -#ifdef JAPAN - ldrsh r0, [r0, #0x30] -#else - ldrsh r0, [r0, #0xd4] -#endif - ldrb r0, [r1, r0] - cmp r0, #1 - cmpeq r4, #1 - bne _02301534 - mov r0, r5 - mov r1, #0x14 - bl IqSkillIsEnabled - cmp r0, #0 - movne r4, #0 -_02301534: - ldrsh r0, [r5, #4] - ldrsh r1, [r5, #6] - bl GetTile - add r0, r0, r4 - ldrb r0, [r0, #8] - cmp r0, #0x54 - moveq r0, #1 - ldmeqia sp!, {r3, r4, r5, pc} - cmp r0, #0x51 - moveq r0, #1 - ldmeqia sp!, {r3, r4, r5, pc} - cmp r0, #0x45 - moveq r0, #1 - ldmeqia sp!, {r3, r4, r5, pc} - cmp r0, #0x15 - moveq r0, #1 - ldmeqia sp!, {r3, r4, r5, pc} - cmp r0, #0x55 - moveq r0, #1 - movne r0, #0 - and r0, r0, #0xff - ldmia sp!, {r3, r4, r5, pc} - .align 2, 0 -_0230158C: .word DUNGEON_PTR -_02301590: .word SECONDARY_TERRAIN_TYPES - arm_func_end IsAtJunction diff --git a/include/dungeon_capabilities_4.h b/include/dungeon_capabilities_4.h index 531375c4..013cd5bf 100644 --- a/include/dungeon_capabilities_4.h +++ b/include/dungeon_capabilities_4.h @@ -18,5 +18,7 @@ bool8 CanAttackInDirection(struct entity *monster, s32 direction); // out_monster_in_target_position: [output] True if movement was not possible because there was another monster on the target tile, false otherwise. // return: True if the monster can move in the specified direction, false otherwise. bool8 CanAiMonsterMoveInDirection(struct entity *monster, s32 direction, bool8 *out_monster_in_target_position); +// Checks if the tile the given monster is on is considered a junction for the purposes of AI movement. This is affected by what types of terrain the monster can cross. +bool8 IsAtJunction(struct entity *monster); #endif //PMDSKY_DUNGEON_CAPABILITIES_4_H diff --git a/include/dungeon_mode.h b/include/dungeon_mode.h index 55965651..0cd29012 100644 --- a/include/dungeon_mode.h +++ b/include/dungeon_mode.h @@ -649,8 +649,8 @@ struct monster { u8 field_0x20f; u8 hp_fractional; // 0x210: 200 * fractional_part(HP) u8 field_0x211; - u8 field_0x212; - u8 field_0x213; + // 0x212: When a Pokémon can pass through walls in a hallway, this counts up to 200 before the Pokémon turns in a random direction. + s16 mobile_turn_timer; // 0x214: Somehow related to gaining exp through a joy ribbon. Set to 0 after // gaining or losing a level. Also checked and set to 0 when an enemy evolves. // Maybe for a specific scenario of leveling up with exp from a joy ribbon? diff --git a/main.lsf b/main.lsf index 5da3bba2..c83bfbc5 100644 --- a/main.lsf +++ b/main.lsf @@ -480,7 +480,6 @@ Overlay OVY_29 Object src/dungeon_capabilities_3.o Object asm/overlay_29_02300FCC.o Object src/dungeon_capabilities_4.o - Object asm/overlay_29_02301498.o Object src/dungeon_ai_targeting.o Object asm/overlay_29_023016D8.o Object src/dungeon_ai_targeting_1.o diff --git a/src/dungeon_ai.c b/src/dungeon_ai.c index 9ea9b54f..e2edaa92 100644 --- a/src/dungeon_ai.c +++ b/src/dungeon_ai.c @@ -4,6 +4,7 @@ #include "dungeon_action.h" #include "dungeon_ai_itcm.h" #include "dungeon_ai_items.h" +#include "dungeon_ai_movement.h" #include "dungeon_capabilities_1.h" #include "dungeon_pokemon_attributes.h" #include "dungeon_pokemon_attributes_1.h" @@ -26,7 +27,6 @@ extern void EndFrozenClassStatus(struct entity *user, struct entity *target, bool8 log); extern void SubstitutePlaceholderStringTags(u8 *string_id, struct entity *entity, u32 param_3); extern void LogMessageByIdWithPopupCheckUser(struct entity *user, u32 message_id); -extern void AiMovement(struct entity *monster, bool8 show_run_away_effect); void RunMonsterAi(struct entity *monster, u32 unused) { diff --git a/src/dungeon_ai_movement.c b/src/dungeon_ai_movement.c index a9e8cb4c..c7a4d5da 100644 --- a/src/dungeon_ai_movement.c +++ b/src/dungeon_ai_movement.c @@ -50,8 +50,6 @@ struct can_move_in_direction_info const s32 FACING_DIRECTION_INCREMENTS[] = {0, 1, -1, 2, -2, 3, -3, 4}; -extern bool8 IsAtJunction(struct entity *monster); - bool8 ShouldMonsterRunAwayAndShowEffectOutlawCheck(struct entity *monster, bool8 show_run_away_effect) { bool8 should_run_away = FALSE; diff --git a/src/dungeon_capabilities_4.c b/src/dungeon_capabilities_4.c index f4261592..8f61b2cd 100644 --- a/src/dungeon_capabilities_4.c +++ b/src/dungeon_capabilities_4.c @@ -1,4 +1,5 @@ #include "dungeon_capabilities_4.h" +#include "dg_random.h" #include "direction.h" #include "directional_bit_masks.h" #include "dungeon.h" @@ -173,3 +174,68 @@ bool8 CanAiMonsterMoveInDirection(struct entity *monster, s32 direction, bool8 * *out_monster_in_target_position = TRUE; return FALSE; } + +bool8 IsAtJunction(struct entity *monster) +{ + enum mobility_type mobility = GetMobilityTypeCheckSlipAndFloating(monster, GetEntInfo(monster)->id); + + #ifdef JAPAN + if (!IsCurrentTilesetBackground()) + { + if (GetEntInfo(monster)->invisible_class_status.status == STATUS_INVISIBLE_MOBILE) + mobility = MOBILITY_INTANGIBLE; + else if (ItemIsActive__022FF898(monster, ITEM_MOBILE_SCARF)) + mobility = MOBILITY_INTANGIBLE; + else if (IqSkillIsEnabled(monster, IQ_ALL_TERRAIN_HIKER)) + // BUG: If a Pokémon can normally move through walls, All-Terrain Hiker will block them from moving through walls. + // This bug is fixed in the NA/EU versions. + mobility = MOBILITY_HOVERING; + else if (IqSkillIsEnabled(monster, IQ_ABSOLUTE_MOVER)) { + mobility = MOBILITY_INTANGIBLE; + } + } + #else + mobility = GetDirectionalMobilityType(monster, mobility, DIR_NONE_UNSIGNED); + #endif + + if (mobility == MOBILITY_INTANGIBLE) + { + struct monster *pokemon_info = GetEntInfo(monster); + pokemon_info->mobile_turn_timer += DungeonRandInt(100); + if (pokemon_info->mobile_turn_timer < 200) + return FALSE; + + pokemon_info->mobile_turn_timer = 0; + return TRUE; + } + + const struct tile *map_tile; + if (SECONDARY_TERRAIN_TYPES[DUNGEON_PTR[0]->gen_info.tileset_id] == SECONDARY_TERRAIN_LAVA && + mobility == MOBILITY_SECONDARY && + IqSkillIsEnabled(monster, IQ_LAVA_EVADER)) + mobility = MOBILITY_NORMAL; + + map_tile = GetTile(monster->pos.x, monster->pos.y); + u8 walkable_neighbor_flags = map_tile->walkable_neighbor_flags[mobility]; + /* + Check for configurations of open tiles that are considered junctions; i.e., shaped like a 'T' or '+'. + X=Wall, O=Open + + 0x54 0x51 0x45 0x15 0x55 + XOX XOX XXX XOX XOX + OOO OOX OOO XOO OOO + XXX XOX XOX XOX XOX + */ + if (walkable_neighbor_flags == 0x54) + return TRUE; + if (walkable_neighbor_flags == 0x51) + return TRUE; + if (walkable_neighbor_flags == 0x45) + return TRUE; + if (walkable_neighbor_flags == 0x15) + return TRUE; + if (walkable_neighbor_flags == 0x55) + return TRUE; + + return FALSE; +}