From c48972a630496454dc44871687092d635aec1e13 Mon Sep 17 00:00:00 2001 From: slaw-22 <> Date: Sun, 28 Sep 2025 18:09:03 +0000 Subject: [PATCH] Decomp RecruitCheck --- ...9_0230DBD0.inc => overlay_29_0230E064.inc} | 28 -- asm/overlay_10_022C4394.s | 20 +- asm/overlay_10_rodata_022C464C.s | 20 +- ...ay_29_0230DBD0.s => overlay_29_0230E064.s} | 317 +----------------- include/dungeon_recruitment.h | 2 + include/enums.h | 15 + main.lsf | 2 +- src/dungeon_recruitment.c | 158 ++++++++- 8 files changed, 196 insertions(+), 366 deletions(-) rename asm/include/{overlay_29_0230DBD0.inc => overlay_29_0230E064.inc} (60%) rename asm/{overlay_29_0230DBD0.s => overlay_29_0230E064.s} (56%) diff --git a/asm/include/overlay_29_0230DBD0.inc b/asm/include/overlay_29_0230E064.inc similarity index 60% rename from asm/include/overlay_29_0230DBD0.inc rename to asm/include/overlay_29_0230E064.inc index 086c236a..dbc2ffd1 100644 --- a/asm/include/overlay_29_0230DBD0.inc +++ b/asm/include/overlay_29_0230E064.inc @@ -1,56 +1,28 @@ #pragma once -.public CanSeeTarget .public DUNGEON_PTR .public DungeonModeSetupAndShowNameKeyboard -.public DungeonRandInt .public EnableAllLearnableIqSkills .public EnsureCanStandCurrentTile .public GetActiveTeamMember .public GetDirectionTowardsPosition -.public GetFirstEmptyMemberIdx .public GetMessageLogPreprocessorArgs .public GetNameString -.public GetRecruitRate1 -.public GetRecruitRate2 .public HandleFaint -.public HasPlayedOldGame .public InitTeamMember -.public IqSkillIsEnabled -.public IsCurrentMissionTypeExact -.public IsFullFloorFixedRoom -.public IsLegendaryChallengeFloor .public IsMonsterOnTeam -.public IsRecruitingAllowed -.public ItemIsActive__0230E578 .public LogMessageByIdWithPopupCheckUser -.public MonsterIsType -.public RECRUITMENT_LEVEL_BOOST_TABLE .public SetMessageLogPreprocessorArgsString .public SetPokemonJoined .public SetPreprocessorArgsIdVal .public SetPreprocessorArgsStringToName -.public SpecificRecruitCheck .public StrcpySimple .public StrncpyName .public StrncpySimpleNoPad .public SubstitutePlaceholderStringTags -.public abs -.public ov10_022C4410 -.public ov10_022C441C -.public ov10_022C443C -.public ov10_022C447C -.public ov10_022C44FC -.public ov10_022C46FC -.public ov10_022C4700 -.public ov10_022C4704 -.public ov10_022C4708 -.public ov10_022C470C -.public ov29_022E1B28 .public ov29_022E68BC .public ov29_022E8104 .public ov29_022E81F8 .public ov29_022EACAC -.public ov29_022FBDE0 .public ov29_02304A48 .public ov29_02305F60 .public ov29_0230E5A8 diff --git a/asm/overlay_10_022C4394.s b/asm/overlay_10_022C4394.s index a355780a..0a424892 100644 --- a/asm/overlay_10_022C4394.s +++ b/asm/overlay_10_022C4394.s @@ -41,8 +41,8 @@ ov10_022C4404: .global FIRST_DUNGEON_WITH_MONSTER_HOUSE_TRAPS FIRST_DUNGEON_WITH_MONSTER_HOUSE_TRAPS: .byte 0x1C, 0x00, 0x00, 0x00 - .global ov10_022C4410 -ov10_022C4410: + .global FIERY_DRUM_RECRUIT_BOOST +FIERY_DRUM_RECRUIT_BOOST: .byte 0xC8, 0x00, 0x00, 0x00 .global BAD_POISON_DAMAGE_COOLDOWN BAD_POISON_DAMAGE_COOLDOWN: @@ -50,8 +50,8 @@ BAD_POISON_DAMAGE_COOLDOWN: .global ov10_022C4418 ov10_022C4418: .byte 0x14, 0x00, 0x00, 0x00 - .global ov10_022C441C -ov10_022C441C: + .global ICY_FLUTE_RECRUIT_BOOST +ICY_FLUTE_RECRUIT_BOOST: .byte 0xC8, 0x00, 0x00, 0x00 .global PROTEIN_STAT_BOOST PROTEIN_STAT_BOOST: @@ -74,8 +74,8 @@ ov10_022C4434: .global OREN_BERRY_DAMAGE OREN_BERRY_DAMAGE: .byte 0x0A, 0x00, 0x00, 0x00 - .global ov10_022C443C -ov10_022C443C: + .global GOLDEN_MASK_RECRUIT_BOOST +GOLDEN_MASK_RECRUIT_BOOST: .byte 0xC9, 0x00, 0x00, 0x00 .global IRON_TAIL_LOWER_DEFENSE_CHANCE IRON_TAIL_LOWER_DEFENSE_CHANCE: @@ -122,8 +122,8 @@ UNOWN_STONE_DROP_CHANCE: .global SITRUS_BERRY_HP_RESTORATION SITRUS_BERRY_HP_RESTORATION: .byte 0x64, 0x00, 0x00, 0x00 - .global ov10_022C447C -ov10_022C447C: + .global AMBER_TEAR_RECRUIT_BOOST +AMBER_TEAR_RECRUIT_BOOST: .byte 0x96, 0x00, 0x00, 0x00 .global ov10_022C4480 ov10_022C4480: @@ -218,8 +218,8 @@ ORAN_BERRY_FULL_HP_BOOST: .global LIFE_SEED_HP_BOOST LIFE_SEED_HP_BOOST: .byte 0x03, 0x00, 0x00, 0x00 - .global ov10_022C44FC -ov10_022C44FC: + .global FRIEND_BOW_FAST_FRIEND_BOOST +FRIEND_BOW_FAST_FRIEND_BOOST: .byte 0x32, 0x00, 0x00, 0x00 .global OCTAZOOKA_LOWER_ACCURACY_CHANCE OCTAZOOKA_LOWER_ACCURACY_CHANCE: diff --git a/asm/overlay_10_rodata_022C464C.s b/asm/overlay_10_rodata_022C464C.s index 599857af..3b8b01d5 100644 --- a/asm/overlay_10_rodata_022C464C.s +++ b/asm/overlay_10_rodata_022C464C.s @@ -134,20 +134,20 @@ HEALING_WISH_HP_RESTORATION: .global ov10_022C46F8 ov10_022C46F8: .byte 0x9C, 0xFF, 0x00, 0x00 - .global ov10_022C46FC -ov10_022C46FC: + .global SKY_MELODICA_RECRUIT_BOOST +SKY_MELODICA_RECRUIT_BOOST: .byte 0xC8, 0x00, 0x00, 0x00 - .global ov10_022C4700 -ov10_022C4700: + .global GRASS_CORNET_RECRUIT_BOOST +GRASS_CORNET_RECRUIT_BOOST: .byte 0xC8, 0x00, 0x00, 0x00 - .global ov10_022C4704 -ov10_022C4704: + .global ROCK_HORN_RECRUIT_BOOST +ROCK_HORN_RECRUIT_BOOST: .byte 0xC8, 0x00, 0x00, 0x00 - .global ov10_022C4708 -ov10_022C4708: + .global AQUA_MONICA_RECRUIT_BOOST +AQUA_MONICA_RECRUIT_BOOST: .byte 0xC8, 0x00, 0x00, 0x00 - .global ov10_022C470C -ov10_022C470C: + .global TERRA_CYMBAL_RECRUIT_BOOST +TERRA_CYMBAL_RECRUIT_BOOST: .byte 0xC8, 0x00, 0x00, 0x00 .global ME_FIRST_MULTIPLIER ME_FIRST_MULTIPLIER: diff --git a/asm/overlay_29_0230DBD0.s b/asm/overlay_29_0230E064.s similarity index 56% rename from asm/overlay_29_0230DBD0.s rename to asm/overlay_29_0230E064.s index 98dc4d67..0e006c85 100644 --- a/asm/overlay_29_0230DBD0.s +++ b/asm/overlay_29_0230E064.s @@ -1,323 +1,8 @@ .include "asm/macros.inc" - .include "overlay_29_0230DBD0.inc" + .include "overlay_29_0230E064.inc" .text - arm_func_start RecruitCheck -RecruitCheck: ; 0x0230DBD0 - stmdb sp!, {r3, r4, r5, r6, r7, r8, sb, lr} - ldr r2, _0230E024 ; =DUNGEON_PTR - mov r8, r0 - ldr r0, [r2] - mov r7, r1 - ldrb r0, [r0, #0x748] - ldr r5, [r8, #0xb4] - ldr r6, [r7, #0xb4] - bl IsRecruitingAllowed - cmp r0, #0 - beq _0230DC28 - bl IsFullFloorFixedRoom - cmp r0, #0 - bne _0230DC28 - bl IsLegendaryChallengeFloor - cmp r0, #0 - bne _0230DC28 - mov r0, #0xa - mov r1, #6 - bl IsCurrentMissionTypeExact - cmp r0, #0 - beq _0230DC30 -_0230DC28: - mov r0, #0 - ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, pc} -_0230DC30: - ldr r0, _0230E024 ; =DUNGEON_PTR - ldr r1, [r0] - ldrb r0, [r1, #0x75d] - cmp r0, #0 - movne r0, #0 - ldmneia sp!, {r3, r4, r5, r6, r7, r8, sb, pc} - ldrb r0, [r1, #0x748] - cmp r0, #0x5b - bne _0230DC70 - ldrsh r1, [r6, #2] - ldr r0, _0230E028 ; =0x000001E6 - cmp r1, r0 - addne r0, r0, #0x258 - cmpne r1, r0 - moveq r0, #0 - ldmeqia sp!, {r3, r4, r5, r6, r7, r8, sb, pc} -_0230DC70: - ldrsh r0, [r6, #2] - cmp r0, #0x91 - cmpne r0, #0x90 - cmpne r0, #0x92 - ldrne r2, _0230E02C ; =0x0000010F - cmpne r0, r2 - subne r1, r2, #1 - cmpne r0, r1 - cmpne r0, #0x110 - cmpne r0, #0x19c - addne r1, r2, #0x8e - cmpne r0, r1 - addne r1, r2, #0x92 - cmpne r0, r1 - cmpne r0, #0x1a0 - addne r1, r2, #0x93 - cmpne r0, r1 - addne r1, r2, #0x8a - cmpne r0, r1 - addne r1, r2, #0x8b - cmpne r0, r1 - addne r1, r2, #0x8c - cmpne r0, r1 - beq _0230DCF0 - ldr r1, _0230E030 ; =0xFFFFFDEA - add r1, r0, r1 - mov r1, r1, lsl #0x10 - mov r1, r1, asr #0x10 - mov r1, r1, lsl #0x10 - mov r1, r1, lsr #0x10 - cmp r1, #1 - bhi _0230DD04 -_0230DCF0: - mov r1, #1 - bl IsMonsterOnTeam - cmp r0, #0 - movne r0, #0 - ldmneia sp!, {r3, r4, r5, r6, r7, r8, sb, pc} -_0230DD04: - mov r0, r6 - bl ov29_022FBDE0 - cmp r0, #0 - movne r0, #0 - ldmneia sp!, {r3, r4, r5, r6, r7, r8, sb, pc} - ldrsh r0, [r6, #2] - bl SpecificRecruitCheck - cmp r0, #0 - moveq r0, #0 - ldmeqia sp!, {r3, r4, r5, r6, r7, r8, sb, pc} - ldrsh r1, [r8, #4] - ldrsh r0, [r7, #4] - sub r0, r1, r0 - bl abs - cmp r0, #1 - bgt _0230DD5C - ldrsh r1, [r8, #6] - ldrsh r0, [r7, #6] - sub r0, r1, r0 - bl abs - cmp r0, #1 - ble _0230DD64 -_0230DD5C: - mov r0, #0 - ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, pc} -_0230DD64: - ldrb r0, [r6, #0x48] - cmp r0, #0xfa - ldrneb r0, [r6, #0xbc] - cmpne r0, #7 - moveq r0, #0 - ldmeqia sp!, {r3, r4, r5, r6, r7, r8, sb, pc} - mov r0, r7 - mov r1, r8 - bl CanSeeTarget - cmp r0, #0 - moveq r0, #0 - ldmeqia sp!, {r3, r4, r5, r6, r7, r8, sb, pc} - mov r0, #1 - bl ov29_022E1B28 - bl ov29_022E81F8 - ldrsh r0, [r6, #2] - mov r1, #1 - bl IsMonsterOnTeam - mov sb, r0 - mov r0, #0x3e8 - bl DungeonRandInt - mov r4, r0 - bl HasPlayedOldGame - cmp r0, #0 - beq _0230DDE0 - cmp sb, #0 - bne _0230DDE0 - ldrsh r0, [r6, #2] - bl GetRecruitRate2 - mov r6, r0 - b _0230DDEC -_0230DDE0: - ldrsh r0, [r6, #2] - bl GetRecruitRate1 - mov r6, r0 -_0230DDEC: - cmp r6, #0 - ble _0230DDFC - cmp sb, #0 - movne r6, r6, asr #1 -_0230DDFC: - ldr r0, _0230E034 ; =0xFFFFFC19 - cmp r6, r0 - moveq r0, #0 - ldmeqia sp!, {r3, r4, r5, r6, r7, r8, sb, pc} - mov r0, r8 - mov r1, #0x35 - bl ItemIsActive__0230E578 - cmp r0, #0 - ldrne r0, _0230E038 ; =ov10_022C44FC - ldrnesh r0, [r0] - addne r6, r6, r0 - bne _0230DFD4 - mov r0, r8 - mov r1, #0x39 - bl ItemIsActive__0230E578 - cmp r0, #0 - ldrne r0, _0230E03C ; =ov10_022C443C - ldrnesh r0, [r0] - addne r6, r6, r0 - bne _0230DFD4 - mov r0, r8 - mov r1, #0x3a - bl ItemIsActive__0230E578 - cmp r0, #0 - ldrne r0, _0230E040 ; =ov10_022C447C - ldrnesh r0, [r0] - addne r6, r6, r0 - bne _0230DFD4 - mov r0, r8 - mov r1, #0x3b - bl ItemIsActive__0230E578 - cmp r0, #0 - beq _0230DEA0 - mov r0, r7 - mov r1, #6 - bl MonsterIsType - cmp r0, #0 - ldrne r0, _0230E044 ; =ov10_022C441C - ldrnesh r0, [r0] - addne r6, r6, r0 - b _0230DFD4 -_0230DEA0: - mov r0, r8 - mov r1, #0x3c - bl ItemIsActive__0230E578 - cmp r0, #0 - beq _0230DED4 - mov r0, r7 - mov r1, #2 - bl MonsterIsType - cmp r0, #0 - ldrne r0, _0230E048 ; =ov10_022C4410 - ldrnesh r0, [r0] - addne r6, r6, r0 - b _0230DFD4 -_0230DED4: - mov r0, r8 - mov r1, #0x3d - bl ItemIsActive__0230E578 - cmp r0, #0 - beq _0230DF08 - mov r0, r7 - mov r1, #9 - bl MonsterIsType - cmp r0, #0 - ldrne r0, _0230E04C ; =ov10_022C470C - ldrnesh r0, [r0] - addne r6, r6, r0 - b _0230DFD4 -_0230DF08: - mov r0, r8 - mov r1, #0x3e - bl ItemIsActive__0230E578 - cmp r0, #0 - beq _0230DF3C - mov r0, r7 - mov r1, #3 - bl MonsterIsType - cmp r0, #0 - ldrne r0, _0230E050 ; =ov10_022C4708 - ldrnesh r0, [r0] - addne r6, r6, r0 - b _0230DFD4 -_0230DF3C: - mov r0, r8 - mov r1, #0x3f - bl ItemIsActive__0230E578 - cmp r0, #0 - beq _0230DF70 - mov r0, r7 - mov r1, #0xd - bl MonsterIsType - cmp r0, #0 - ldrne r0, _0230E054 ; =ov10_022C4704 - ldrnesh r0, [r0] - addne r6, r6, r0 - b _0230DFD4 -_0230DF70: - mov r0, r8 - mov r1, #0x40 - bl ItemIsActive__0230E578 - cmp r0, #0 - beq _0230DFA4 - mov r0, r7 - mov r1, #4 - bl MonsterIsType - cmp r0, #0 - ldrne r0, _0230E058 ; =ov10_022C4700 - ldrnesh r0, [r0] - addne r6, r6, r0 - b _0230DFD4 -_0230DFA4: - mov r0, r8 - mov r1, #0x41 - bl ItemIsActive__0230E578 - cmp r0, #0 - beq _0230DFD4 - mov r0, r7 - mov r1, #0xa - bl MonsterIsType - cmp r0, #0 - ldrne r0, _0230E05C ; =ov10_022C46FC - ldrnesh r0, [r0] - addne r6, r6, r0 -_0230DFD4: - mov r0, r8 - mov r1, #0x1e - bl IqSkillIsEnabled - cmp r0, #0 - ldrne r0, _0230E038 ; =ov10_022C44FC - ldrb r1, [r5, #0xa] - ldrnesh r0, [r0] - mov r1, r1, lsl #1 - addne r6, r6, r0 - ldr r0, _0230E060 ; =RECRUITMENT_LEVEL_BOOST_TABLE - ldrsh r0, [r0, r1] - add r0, r6, r0 - cmp r4, r0 - mov r0, #0 - ldmgeia sp!, {r3, r4, r5, r6, r7, r8, sb, pc} - bl GetFirstEmptyMemberIdx - cmp r0, #0 - movlt r0, #0 - movge r0, #1 - ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, pc} - .align 2, 0 -_0230E024: .word DUNGEON_PTR -_0230E028: .word 0x000001E6 -_0230E02C: .word 0x0000010F -_0230E030: .word 0xFFFFFDEA -_0230E034: .word 0xFFFFFC19 -_0230E038: .word ov10_022C44FC -_0230E03C: .word ov10_022C443C -_0230E040: .word ov10_022C447C -_0230E044: .word ov10_022C441C -_0230E048: .word ov10_022C4410 -_0230E04C: .word ov10_022C470C -_0230E050: .word ov10_022C4708 -_0230E054: .word ov10_022C4704 -_0230E058: .word ov10_022C4700 -_0230E05C: .word ov10_022C46FC -_0230E060: .word RECRUITMENT_LEVEL_BOOST_TABLE - arm_func_end RecruitCheck - arm_func_start TryRecruit TryRecruit: ; 0x0230E064 #ifdef JAPAN diff --git a/include/dungeon_recruitment.h b/include/dungeon_recruitment.h index aa230179..c53a0103 100644 --- a/include/dungeon_recruitment.h +++ b/include/dungeon_recruitment.h @@ -2,7 +2,9 @@ #define PMDSKY_DUNGEON_RECRUITMENT_H #include "util.h" +#include "dungeon_mode.h" +bool8 RecruitCheck(struct entity* leader, struct entity* target); bool8 SpecificRecruitCheck(u32 monster_id); extern bool8 DebugRecruitingEnabled(u32 monster_id); diff --git a/include/enums.h b/include/enums.h index ef64bc91..1e7f6cb9 100644 --- a/include/enums.h +++ b/include/enums.h @@ -2345,6 +2345,21 @@ enum mission_type { MISSION_SPECIAL_EPISODE = 14, }; +// Mission subtype for MISSION_ARREST_OUTLAW +// 0-3 all occur naturally in-game, the distinction is in intensity of the mission. +// Each uses a different table of outlaws of varying difficulties. +enum mission_subtype_outlaw { + MISSION_OUTLAW_NORMAL_0 = 0, // in mission_template, client is magnezone + MISSION_OUTLAW_NORMAL_1 = 1, // in mission_template, client is magnezone + MISSION_OUTLAW_NORMAL_2 = 2, // in mission_template, client is magnemite + MISSION_OUTLAW_NORMAL_3 = 3, // in mission_template, client is magnemite + MISSION_OUTLAW_ESCORT = 4, + MISSION_OUTLAW_FLEEING = 5, + // One of 30 specific pairings (IE: Vespiquen/Combee, Golduck/Psyduck, Cloyster/Clampearl) + MISSION_OUTLAW_HIDEOUT = 6, + MISSION_OUTLAW_MONSTER_HOUSE = 7, +}; + // Fixed room ID. Fixed rooms can be full floor layouts, like most end-of-dungeon boss chambers, // multi-room layouts in the case of Treasure Memos, or single rooms within a larger floor layout // like with key chambers. diff --git a/main.lsf b/main.lsf index dac9a5ee..7f9f7862 100644 --- a/main.lsf +++ b/main.lsf @@ -492,7 +492,7 @@ Overlay OVY_29 Object asm/overlay_29_rodata_02352894.o Object asm/overlay_29_0230BBAC.o Object src/dungeon_recruitment.o - Object asm/overlay_29_0230DBD0.o + Object asm/overlay_29_0230E064.o Object src/overlay_29_0230E578.o Object asm/overlay_29_0230E5A8.o Object src/dungeon_ai_items.o diff --git a/src/dungeon_recruitment.c b/src/dungeon_recruitment.c index 91cda483..70d8e946 100644 --- a/src/dungeon_recruitment.c +++ b/src/dungeon_recruitment.c @@ -1,7 +1,43 @@ #include "dungeon_recruitment.h" #include "dungeon.h" +#include "dungeon_mode.h" +#include "dungeon_logic_3.h" +#include "dungeon_pokemon_attributes_1.h" +#include "main_0208655C.h" +#include "enums.h" +#include "dungeon_visibility.h" +#include "dg_random.h" +#include "main_0205283C.h" // GetRecruitRate1 and GetRecruitRate2 +#include "overlay_29_0230E578.h" // ItemIsActive__0230E578 -bool8 SpecificRecruitCheck(u32 monster_id) { +extern bool8 IsRecruitingAllowed(u8 dungeon_id); +extern bool8 IsFullFloorFixedRoom(void); +extern bool8 IsLegendaryChallengeFloor(void); +extern bool8 IsCurrentMissionTypeExact(u32 mission_type, u32 mission_subtype); +extern bool8 IsMonsterOnTeam(s16 monsterId, s32 checkType); +extern bool8 ov29_022FBDE0(struct monster* stats); +extern void ov29_022E1B28(s32); +extern void ov29_022E81F8(void); +extern bool8 HasPlayedOldGame(void); +extern s16 GetRecruitRate1(s16 monsterId); +extern s16 GetRecruitRate2(s16 monsterId); +extern s32 GetFirstEmptyMemberIdx(u32); + +extern const s16 FRIEND_BOW_FAST_FRIEND_BOOST; +extern const s16 GOLDEN_MASK_RECRUIT_BOOST; +extern const s16 AMBER_TEAR_RECRUIT_BOOST; +extern const s16 ICY_FLUTE_RECRUIT_BOOST; +extern const s16 FIERY_DRUM_RECRUIT_BOOST; +extern const s16 TERRA_CYMBAL_RECRUIT_BOOST; +extern const s16 AQUA_MONICA_RECRUIT_BOOST; +extern const s16 ROCK_HORN_RECRUIT_BOOST; +extern const s16 GRASS_CORNET_RECRUIT_BOOST; +extern const s16 SKY_MELODICA_RECRUIT_BOOST; + +extern s16 RECRUITMENT_LEVEL_BOOST_TABLE[]; + +bool8 SpecificRecruitCheck(u32 monster_id) +{ if (DUNGEON_PTR[0]->recruiting_enabled == FALSE) { return FALSE; } @@ -46,3 +82,123 @@ bool8 SpecificRecruitCheck(u32 monster_id) { return TRUE; } } + +bool8 RecruitCheck(struct entity* leader, struct entity* target) +{ + s32 random_roll; + struct monster* leader_monster_info = leader->info; + struct monster* target_monster_info = target->info; + + s32 recruit_rate; + bool8 already_on_team; + s16 target_mon_id; + + if (!IsRecruitingAllowed(DUNGEON_PTR[0]->id) || + IsFullFloorFixedRoom() || + IsLegendaryChallengeFloor() || + IsCurrentMissionTypeExact(MISSION_ARREST_OUTLAW, MISSION_OUTLAW_HIDEOUT)) + return FALSE; + + if (DUNGEON_PTR[0]->send_home_disabled != FALSE) + return FALSE; + + if (DUNGEON_PTR[0]->id == DUNGEON_LABYRINTH_CAVE) { + target_mon_id = target_monster_info->id; + if (target_mon_id == MONSTER_GABITE || target_mon_id == MONSTER_GABITE_SECONDARY) + return FALSE; + } + + target_mon_id = target_monster_info->id; + + if (target_mon_id == MONSTER_ZAPDOS || target_mon_id == MONSTER_ARTICUNO + || target_mon_id == MONSTER_MOLTRES || target_mon_id == MONSTER_ENTEI + || target_mon_id == MONSTER_RAIKOU || target_mon_id == MONSTER_SUICUNE + || target_mon_id == MONSTER_LATIAS || target_mon_id == MONSTER_LATIOS + || target_mon_id == MONSTER_JIRACHI || target_mon_id == MONSTER_RAYQUAZA + || target_mon_id == MONSTER_DEOXYS_NORMAL || target_mon_id == MONSTER_REGIROCK + || target_mon_id == MONSTER_REGICE || target_mon_id == MONSTER_REGISTEEL + || (u16)(s16)(target_mon_id - 534) <= 1) { + if (IsMonsterOnTeam(target_mon_id, 1)) + return FALSE; + } + + if (ov29_022FBDE0(target_monster_info)) + return FALSE; + + if (!SpecificRecruitCheck(target_monster_info->id)) + return FALSE; + + if (abs(leader->pos.x - target->pos.x) > 1 || abs(leader->pos.y - target->pos.y) > 1) + return FALSE; + + // joined_at identifdies the dungeon a monster joined at, but is also used as a unique identifier for special monsters + if (target_monster_info->joined_at == DUNGEON_CLIENT || target_monster_info->monster_behavior == BEHAVIOR_RESCUE_TARGET) + return FALSE; + + if (!CanSeeTarget(target, leader)) + return FALSE; + + // These two calls are likely updating the UI. + ov29_022E1B28(1); + ov29_022E81F8(); + + already_on_team = IsMonsterOnTeam(target_monster_info->id, 1); + random_roll = DungeonRandInt(1000); + + if (HasPlayedOldGame() && !already_on_team) { + // recruit rate 2 is usually higher than recruit rate 1 (if they are different) + recruit_rate = GetRecruitRate2(target_monster_info->id); + } else { + recruit_rate = GetRecruitRate1(target_monster_info->id); + } + + if (recruit_rate > 0 && already_on_team) { + recruit_rate = recruit_rate >>= 1; + } + + if (recruit_rate == -999) + return FALSE; + + if (ItemIsActive__0230E578(leader, ITEM_FRIEND_BOW)) { + recruit_rate += FRIEND_BOW_FAST_FRIEND_BOOST; + } else if (ItemIsActive__0230E578(leader, ITEM_GOLDEN_MASK)) { + recruit_rate += GOLDEN_MASK_RECRUIT_BOOST; + } else if (ItemIsActive__0230E578(leader, ITEM_AMBER_TEAR)) { + recruit_rate += AMBER_TEAR_RECRUIT_BOOST; + } else if (ItemIsActive__0230E578(leader, ITEM_ICY_FLUTE)) { + if (MonsterIsType(target, TYPE_ICE))recruit_rate += ICY_FLUTE_RECRUIT_BOOST; + } else if (ItemIsActive__0230E578(leader, ITEM_FIERY_DRUM)) { + if (MonsterIsType(target, TYPE_FIRE)) recruit_rate += FIERY_DRUM_RECRUIT_BOOST; + } else if (ItemIsActive__0230E578(leader, ITEM_TERRA_CYMBAL)) { + if (MonsterIsType(target, TYPE_GROUND)) recruit_rate += TERRA_CYMBAL_RECRUIT_BOOST; + } else if (ItemIsActive__0230E578(leader, ITEM_AQUA_MONICA)) { + if (MonsterIsType(target, TYPE_WATER)) recruit_rate += AQUA_MONICA_RECRUIT_BOOST; + } else if (ItemIsActive__0230E578(leader, ITEM_ROCK_HORN)) { + if (MonsterIsType(target, TYPE_ROCK)) recruit_rate += ROCK_HORN_RECRUIT_BOOST; + } else if (ItemIsActive__0230E578(leader, ITEM_GRASS_CORNET)) { + if (MonsterIsType(target, TYPE_GRASS)) recruit_rate += GRASS_CORNET_RECRUIT_BOOST; + } else if (ItemIsActive__0230E578(leader, ITEM_SKY_MELODICA)) { + if (MonsterIsType(target, TYPE_FLYING)) recruit_rate += SKY_MELODICA_RECRUIT_BOOST; + } + + if (IqSkillIsEnabled(leader, IQ_FAST_FRIEND)) { + recruit_rate += FRIEND_BOW_FAST_FRIEND_BOOST; + } + + recruit_rate += RECRUITMENT_LEVEL_BOOST_TABLE[leader_monster_info->level]; + + if (random_roll >= recruit_rate) + return FALSE; + + s32 free_slot_index = GetFirstEmptyMemberIdx(0); + + if(free_slot_index < 0) { + return FALSE; + } + + if(free_slot_index >= 0) { + return TRUE; + } + + return TRUE; +}