From f5f90cb7a194d658401cd58599b19cbcae9e1e41 Mon Sep 17 00:00:00 2001 From: Seth Barberee Date: Thu, 23 Jul 2026 16:47:54 -0700 Subject: [PATCH] Match LightningRodStormDrainCheck thanks to @taxicat1 and other funcs --- asm/itcm_01FFBD20.s | 237 -------------------------------------- include/dungeon.h | 18 ++- include/dungeon_ai_itcm.h | 5 + main.lsf | 1 - src/dungeon_ai_itcm.c | 113 ++++++++++++++++++ 5 files changed, 125 insertions(+), 249 deletions(-) delete mode 100644 asm/itcm_01FFBD20.s diff --git a/asm/itcm_01FFBD20.s b/asm/itcm_01FFBD20.s deleted file mode 100644 index 717420f6..00000000 --- a/asm/itcm_01FFBD20.s +++ /dev/null @@ -1,237 +0,0 @@ - .include "asm/macros.inc" - .include "itcm_01FFBD20.inc" - - .section .itcm,4,1,4 - - arm_func_start sub_01FFBD20 -sub_01FFBD20: ; 0x01FFBD20 - stmdb sp!, {r3, r4, r5, r6, r7, lr} - mov r6, r1 - mov r7, r0 - mov r0, r6 - bl IsMonster__0231A9D4 - cmp r0, #0 - ldmeqia sp!, {r3, r4, r5, r6, r7, pc} - ldr r5, [r6, #0xb4] - ldrb r0, [r5, #6] - cmp r0, #0 - beq _01FFBD5C - ldrb r0, [r5, #8] - cmp r0, #0 - moveq r3, #1 - beq _01FFBD60 -_01FFBD5C: - mov r3, #0 -_01FFBD60: - ldr r1, _01FFBDF0 ; =DUNGEON_PTR - mov r0, r6 - ldr r2, [r1] - mov r1, #0x32 -#ifdef JAPAN - add r2, r2, #0x1840 - add r2, r2, #0x18000 -#else - add r2, r2, #0xe4 - add r2, r2, #0x19800 -#endif - add r4, r2, r3, lsl #4 - bl AbilityIsActiveVeneer - cmp r0, #0 - beq _01FFBDB0 - ldr r0, [r4] - cmp r0, #0 - bne _01FFBDB0 - mov r0, r7 - mov r1, r6 - bl sub_01FFBF78 - cmp r0, #0 - strne r6, [r4] - ldrne r0, [r5, #0xb0] - strne r0, [r4, #4] -_01FFBDB0: - mov r0, r6 - mov r1, #0x7a - bl AbilityIsActiveVeneer - cmp r0, #0 - ldmeqia sp!, {r3, r4, r5, r6, r7, pc} - ldr r0, [r4, #8] - cmp r0, #0 - ldmneia sp!, {r3, r4, r5, r6, r7, pc} - mov r0, r7 - mov r1, r6 - bl sub_01FFBF78 - cmp r0, #0 - strne r6, [r4, #8] - ldrne r0, [r5, #0xb0] - strne r0, [r4, #0xc] - ldmia sp!, {r3, r4, r5, r6, r7, pc} - .align 2, 0 -_01FFBDF0: .word DUNGEON_PTR - arm_func_end sub_01FFBD20 - - arm_func_start sub_01FFBDF4 -sub_01FFBDF4: ; 0x01FFBDF4 - stmdb sp!, {r3, r4, r5, r6, r7, lr} - mov r7, r0 - bl ov29_0231B008 - mov r0, r7 - bl EntityIsValid__02319F8C - cmp r0, #0 - ldmeqia sp!, {r3, r4, r5, r6, r7, pc} - ldr r4, _01FFBE58 ; =DUNGEON_PTR - mov r5, #0 -_01FFBE18: - ldr r0, [r4] - add r0, r0, r5, lsl #2 - add r0, r0, #0x12000 -#ifdef JAPAN - ldr r6, [r0, #0xad4] -#else - ldr r6, [r0, #0xb78] -#endif - mov r0, r6 - bl EntityIsValid__02319F8C - cmp r0, #0 - cmpne r7, r6 - beq _01FFBE48 - mov r0, r7 - mov r1, r6 - bl sub_01FFBD20 -_01FFBE48: - add r5, r5, #1 - cmp r5, #0x14 - blt _01FFBE18 - ldmia sp!, {r3, r4, r5, r6, r7, pc} - .align 2, 0 -_01FFBE58: .word DUNGEON_PTR - arm_func_end sub_01FFBDF4 - - arm_func_start LightningRodStormDrainCheck -LightningRodStormDrainCheck: ; 0x01FFBE5C - stmdb sp!, {r3, r4, r5, r6, r7, r8, sb, sl, fp, lr} - mov sl, r0 - mov sb, r1 - mov r8, r2 - mov r7, r3 - mov r5, #0 - ldr r4, _01FFBF70 ; =_01FFB654 - ldr fp, _01FFBF74 ; =DUNGEON_PTR - b _01FFBF60 -_01FFBE80: - ldr r1, [fp] - mov r0, sl -#ifdef JAPAN - add r1, r1, #0x1840 - add r1, r1, #0x18000 -#else - add r1, r1, #0xe4 - add r1, r1, #0x19800 -#endif - add r6, r1, r5, lsl #4 - mov r1, #0x53 - bl AbilityIsActiveVeneer - cmp r0, #0 - bne _01FFBF5C - mov r0, sl - mov r1, r8 - bl GetMoveTypeForMonster - ldrb r1, [r4, r7] - cmp r1, r0 - bne _01FFBF5C - mov r0, sl - mov r1, r8 - mov r2, #0 - bl GetEntityMoveTargetAndRange - and r0, r0, #0xf0 - cmp r0, #0x70 - beq _01FFBF5C - ldr r0, [r6, r7, lsl #3] - bl IsMonster__0231A9D4 - cmp r0, #0 - beq _01FFBF4C - ldr r0, [r6, r7, lsl #3] - add r1, r6, r7, lsl #3 - ldr r2, [r1, #4] - ldr r1, [r0, #0xb4] - ldr r1, [r1, #0xb0] - cmp r2, r1 - bne _01FFBF4C - mov r1, sl - mov r2, #1 - mov r3, #0 - bl GetTreatmentBetweenMonsters - cmp r0, #1 - bne _01FFBF4C - ldr r0, [sb, #0xb4] - ldr r2, [r6, r7, lsl #3] -#ifdef JAPAN - ldrb r0, [r0, #0x10a] - ldr r1, [r2, #0xb4] - cmp r0, #0 - ldreqb r0, [r1, #0x10a] -#else - ldrb r0, [r0, #0x10b] - ldr r1, [r2, #0xb4] - cmp r0, #0 - ldreqb r0, [r1, #0x10b] -#endif - cmpeq r0, #0 - beq _01FFBF44 - cmp sb, r2 - bne _01FFBF4C -_01FFBF44: - mov r0, #1 - b _01FFBF50 -_01FFBF4C: - mov r0, #0 -_01FFBF50: - cmp r0, #0 - ldrne r0, [r6, r7, lsl #3] - ldmneia sp!, {r3, r4, r5, r6, r7, r8, sb, sl, fp, pc} -_01FFBF5C: - add r5, r5, #1 -_01FFBF60: - cmp r5, #2 - blt _01FFBE80 - mov r0, #0 - ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, sl, fp, pc} - .align 2, 0 -_01FFBF70: .word _01FFB654 -_01FFBF74: .word DUNGEON_PTR - arm_func_end LightningRodStormDrainCheck - - arm_func_start sub_01FFBF78 -sub_01FFBF78: ; 0x01FFBF78 - stmdb sp!, {r4, r5, r6, lr} - sub sp, sp, #0x10 - mov r6, r0 - mov r5, r1 - mov r4, #0 - bl ResetAiCanAttackInDirection - mov r0, r6 - mov r1, r5 - bl CanSeeTarget - cmp r0, #0 - beq _01FFBFD8 - add r0, sp, #8 - mov r1, r4 - bl InitMove - add r0, sp, #8 - str r0, [sp] - mov ip, #1 - mov r2, r6 - mov r3, r5 - mov r0, r4 - mov r1, #0x30 - str ip, [sp, #4] - bl TryAddTargetToAiTargetList - mov r4, r0 -_01FFBFD8: - cmp r4, #0 - movne r0, #1 - moveq r0, #0 - and r0, r0, #0xff - add sp, sp, #0x10 - ldmia sp!, {r4, r5, r6, pc} - arm_func_end sub_01FFBF78 - ; 0x01FFBFF0 diff --git a/include/dungeon.h b/include/dungeon.h index bb2ded90..c929a9af 100644 --- a/include/dungeon.h +++ b/include/dungeon.h @@ -32,6 +32,11 @@ struct monster_slots { struct entity* wild_pokemon[DUNGEON_MAX_WILD_POKEMON]; }; +struct monster_id_struct { + struct entity *entity; + u32 entity_id; // 0x198E8: statuses::unique_id from that monster? +}; + struct weather { enum weather_id weather; // 0x0: current weather // 0x1: Default weather on the floor that will be reverted to if the current weather is @@ -1615,17 +1620,8 @@ struct dungeon { struct entity entities[149]; // 0x12DCC / 0x2A4 : All the entities in a dungeon // 0x198E4: An ally monster related to storm drain/lightning rod and maybe other checks? - struct entity* unk_ally_monster1; - u32 unk_ally_monster_unique_id1; // 0x198E8: statuses::unique_id from that monster? - // 0x198EC: An ally monster related to storm drain/lightning rod and maybe other checks? - struct entity* unk_ally_monster2; - u32 unk_ally_monster_unique_id2; // 0x198F0: statuses::unique_id from that monster? - // 0x198F4: An enemy monster related to storm drain/lightning rod and maybe other checks? - struct entity* unk_enemy_monster1; - u32 unk_enemy_monster_unique_id1; // 0x198F8: statuses::unique_id from that monster? - // 0x198FC: An enemy monster related to storm drain/lightning rod and maybe other checks? - struct entity* unk_enemy_monster2; - u32 unk_enemy_monster_unique_id2; // 0x19900: statuses::unique_id from that monster? + struct monster_id_struct storm_drain_lightning_rod[4]; // 0 = ally, 1 = enemy + // 0x19904: Pointer to the monster that will snatch the effect of a move. struct entity* snatch_monster; // 0x19908: Pointer to the entity to be spawned by the effect of Illuminate diff --git a/include/dungeon_ai_itcm.h b/include/dungeon_ai_itcm.h index 3e863c9c..e650413c 100644 --- a/include/dungeon_ai_itcm.h +++ b/include/dungeon_ai_itcm.h @@ -7,4 +7,9 @@ // Determines if an AI-controlled monster will use a move and which one it will use. void ChooseAiMove(struct entity *monster); +void sub_01FFBD20(struct entity *monster, struct entity *target); +void sub_01FFBDF4(struct entity *monster); +struct entity *LightningRodStormDrainCheck(struct entity *monster, struct entity* target, struct move *move, s32 arg3); +bool8 sub_01FFBF78(struct entity *pokemon, struct entity *target); + #endif //PMDSKY_DUNGEON_AI_ITCM_H diff --git a/main.lsf b/main.lsf index 5f3359fe..cacd3729 100644 --- a/main.lsf +++ b/main.lsf @@ -346,7 +346,6 @@ Autoload ITCM Object asm/itcm_1.o (.itcm) Object src/dungeon_ai_movement.o (.itcm) Object src/dungeon_ai_itcm.o (.itcm) - Object asm/itcm_01FFBD20.o (.itcm) } Autoload DTCM diff --git a/src/dungeon_ai_itcm.c b/src/dungeon_ai_itcm.c index 67d4a0cb..a143c109 100644 --- a/src/dungeon_ai_itcm.c +++ b/src/dungeon_ai_itcm.c @@ -6,6 +6,7 @@ #include "dungeon_ai_attack.h" #include "dungeon_ai_parameters.h" #include "dungeon_ai_targeting.h" +#include "dungeon_ai_targeting_1.h" #include "dungeon_capabilities_3.h" #include "dungeon_capabilities_4.h" #include "dungeon_logic_5.h" @@ -17,11 +18,15 @@ #include "dungeon_pokemon_attributes.h" #include "dungeon_pokemon_attributes_1.h" #include "dungeon_util_static.h" +#include "dungeon_visibility.h" #include "fixed_room_data.h" #include "main_0201398C.h" #include "moves_1.h" #include "overlay_29_022EBC50.h" #include "overlay_29_02338350.h" +#include "overlay_29_0231A9D4.h" +#include "overlay_29_0231ACAC.h" +#include "targeting.h" #ifdef SDK_ARM9 #include @@ -785,6 +790,114 @@ _01FFBD0C: } #endif +extern bool8 sub_01FFBF78(struct entity *pokemon, struct entity *target); +extern void ov29_0231B008(); + +void sub_01FFBD20(struct entity *monster, struct entity *target) +{ + s32 index; + struct monster_id_struct* temp_r4; + struct monster* info; + + if (!IsMonster__0231A9D4(target)) return; + + info = GetEntInfo(target); + if (info->is_not_team_member && !info->is_ally) + { + index = 1; + } else { + index = 0; + } + + temp_r4 = &DUNGEON_PTR[0]->storm_drain_lightning_rod[index * 2]; + if ((AbilityIsActiveVeneer(target, ABILITY_LIGHTNINGROD)) && (temp_r4->entity == NULL) && (sub_01FFBF78(monster, target))) + { + temp_r4->entity = target; + temp_r4->entity_id = info->unique_id; + } + + if (!AbilityIsActiveVeneer(target, ABILITY_STORM_DRAIN)) return; + + temp_r4++; + if (temp_r4->entity != NULL) return; + + if (sub_01FFBF78(monster, target)) + { + temp_r4->entity = target; + temp_r4->entity_id = info->unique_id; + } +} + +void sub_01FFBDF4(struct entity *monster) +{ + ov29_0231B008(); + + if (!EntityIsValid__02319F8C(monster)) return; + + for(s32 index = 0; index < DUNGEON_MAX_POKEMON; index++) + { + struct entity *target = DUNGEON_PTR[0]->active_monster_ptrs[index]; + if ((EntityIsValid__02319F8C(target)) && (monster != target)) + { + sub_01FFBD20(monster, target); + } + } +} + +extern enum type_id _01FFB654[4]; + +struct entity *LightningRodStormDrainCheck(struct entity *monster, struct entity* target, struct move *move, s32 arg3) +{ + s32 index; + struct monster_id_struct* temp_r6; + s32 var_r0; + + for(index = 0; index < 2; index++) + { + temp_r6 = &DUNGEON_PTR[0]->storm_drain_lightning_rod[index * 2]; + if ((!AbilityIsActiveVeneer(monster, ABILITY_MOLD_BREAKER)) && + (_01FFB654[arg3] == GetMoveTypeForMonster(monster, move)) && + ((GetEntityMoveTargetAndRange(monster, move, 0) & 0xF0) != 0x70) + ) { + if ((IsMonster__0231A9D4(temp_r6[arg3].entity)) && + (temp_r6[arg3].entity_id == GetEntInfo(temp_r6[arg3].entity)->unique_id) && + (GetTreatmentBetweenMonsters(temp_r6[arg3].entity, monster, TRUE, FALSE) == TREATMENT_TREAT_AS_ENEMY) + ) { + struct monster* info1 = GetEntInfo(target); + struct monster* info2 = GetEntInfo(temp_r6[arg3].entity); + + if ((!info1->two_turn_move_invincible && !info2->two_turn_move_invincible) || target == temp_r6[arg3].entity) { + var_r0 = 1; + } else { + goto _branch_0; + } + } else { +_branch_0: + var_r0 = 0; + } + if (var_r0 != 0) { + return temp_r6[arg3].entity; + } + } + } + + return 0; +} + +bool8 sub_01FFBF78(struct entity *pokemon, struct entity *target) +{ + struct move move; + s32 result; + + result = FALSE; + ResetAiCanAttackInDirection(); + if (CanSeeTarget(pokemon, target)) { + InitMove(&move, MOVE_NOTHING); + result = TryAddTargetToAiTargetList(0, 0x30, pokemon, target, &move, TRUE); + } + return result != 0; +} + #ifdef SDK_ARM9 #include #endif //SDK_ARM9