mirror of
https://github.com/pret/pmd-sky.git
synced 2026-03-21 17:25:15 -05:00
204 lines
6.9 KiB
C
204 lines
6.9 KiB
C
#include "dungeon.h"
|
|
#include "dungeon_logic_3.h"
|
|
#include "dungeon_logic_7.h"
|
|
#include "dungeon_mode.h"
|
|
#include "dungeon_pokemon_attributes_1.h"
|
|
#include "dungeon_recruitment.h"
|
|
#include "dungeon_recruitment_2.h"
|
|
#include "has_played_old_game.h"
|
|
#include "dg_random.h"
|
|
#include "dungeon_visibility.h"
|
|
#include "enums.h"
|
|
#include "fixed_room_data_1.h"
|
|
#include "main_0205283C.h" // GetRecruitRate1 and GetRecruitRate2
|
|
#include "main_0208655C.h"
|
|
#include "math.h"
|
|
#include "overlay_29_0230E578.h" // ItemIsActive__0230E578
|
|
|
|
extern bool8 IsLegendaryChallengeFloor(void);
|
|
extern bool8 IsCurrentMissionTypeExact(u32 mission_type, u32 mission_subtype);
|
|
extern bool8 IsMonsterOnTeam(s16 monsterId, s32 checkType);
|
|
extern void ov29_022E1B28(s32);
|
|
extern void ov29_022E81F8(void);
|
|
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;
|
|
}
|
|
|
|
// DebugRecruitingEnabled always returns TRUE
|
|
if (DebugRecruitingEnabled(monster_id) == FALSE) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (monster_id == MONSTER_MEW) {
|
|
// The cast is needed to produce assembly code that matches the original.
|
|
// Accessing dungeon_objective using the enum directly gives
|
|
// different assembly code.
|
|
if (*(volatile s8 *)&DUNGEON_PTR[0]->dungeon_objective == OBJECTIVE_RESCUE) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
if (monster_id == MONSTER_DEOXYS_ATTACK) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (monster_id == MONSTER_DEOXYS_DEFENSE) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (monster_id == MONSTER_DEOXYS_SPEED) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (monster_id == MONSTER_REGIROCK) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (monster_id == MONSTER_REGICE) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (monster_id == MONSTER_REGISTEEL) {
|
|
return FALSE;
|
|
} else {
|
|
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 (IsMonsterLoneOutlaw(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 identifies 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 == -INFINITY)
|
|
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;
|
|
}
|