1 #include "spell-kind/spells-polymorph.h"
2 #include "core/stuff-handler.h"
3 #include "floor/floor-object.h"
4 #include "monster-floor/monster-generator.h"
5 #include "monster-floor/monster-remover.h"
6 #include "monster-floor/place-monster-types.h"
7 #include "monster-race/monster-race.h"
8 #include "monster-race/race-flags1.h"
9 #include "monster/monster-flag-types.h"
10 #include "monster/monster-info.h"
11 #include "monster/monster-list.h"
12 #include "monster/monster-status.h"
13 #include "monster/monster-util.h"
14 #include "system/floor-type-definition.h"
15 #include "system/grid-type-definition.h"
16 #include "system/monster-race-definition.h"
17 #include "system/monster-type-definition.h"
18 #include "system/object-type-definition.h"
19 #include "system/player-type-definition.h"
20 #include "target/target-checker.h"
23 * @brief 変身処理向けにモンスターの近隣レベル帯モンスターを返す /
24 * Helper function -- return a "nearby" race for polymorphing
25 * @param floor_ptr 配置するフロアの参照ポインタ
26 * @param r_idx 基準となるモンスター種族ID
27 * @return 変更先のモンスター種族ID
29 * Note that this function is one of the more "dangerous" ones...
31 static MONRACE_IDX poly_r_idx(PlayerType *player_ptr, MONRACE_IDX r_idx)
33 monster_race *r_ptr = &r_info[r_idx];
34 if ((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->flags1 & RF1_QUESTOR))
37 DEPTH lev1 = r_ptr->level - ((randint1(20) / randint1(9)) + 1);
38 DEPTH lev2 = r_ptr->level + ((randint1(20) / randint1(9)) + 1);
40 for (int i = 0; i < 1000; i++) {
41 r = get_mon_num(player_ptr, 0, (player_ptr->current_floor_ptr->dun_level + r_ptr->level) / 2 + 5, 0);
46 if (r_ptr->flags1 & RF1_UNIQUE)
48 if ((r_ptr->level < lev1) || (r_ptr->level > lev2))
59 * @brief 指定座標にいるモンスターを変身させる /
60 * Helper function -- return a "nearby" race for polymorphing
61 * @param player_ptr プレイヤーへの参照ポインタ
64 * @return 実際に変身したらTRUEを返す
66 bool polymorph_monster(PlayerType *player_ptr, POSITION y, POSITION x)
68 floor_type *floor_ptr = player_ptr->current_floor_ptr;
69 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
70 monster_type *m_ptr = &floor_ptr->m_list[g_ptr->m_idx];
71 MONRACE_IDX new_r_idx;
72 MONRACE_IDX old_r_idx = m_ptr->r_idx;
73 bool targeted = target_who == g_ptr->m_idx;
74 bool health_tracked = player_ptr->health_who == g_ptr->m_idx;
76 if (floor_ptr->inside_arena || player_ptr->phase_out)
78 if ((player_ptr->riding == g_ptr->m_idx) || m_ptr->mflag2.has(MonsterConstantFlagType::KAGE))
81 monster_type back_m = *m_ptr;
82 new_r_idx = poly_r_idx(player_ptr, old_r_idx);
83 if (new_r_idx == old_r_idx)
86 bool preserve_hold_objects = !back_m.hold_o_idx_list.empty();
89 if (is_friendly(m_ptr))
90 mode |= PM_FORCE_FRIENDLY;
93 if (m_ptr->mflag2.has(MonsterConstantFlagType::NOPET))
96 m_ptr->hold_o_idx_list.clear();
97 delete_monster_idx(player_ptr, g_ptr->m_idx);
98 bool polymorphed = false;
99 if (place_monster_aux(player_ptr, 0, y, x, new_r_idx, mode)) {
100 floor_ptr->m_list[hack_m_idx_ii].nickname = back_m.nickname;
101 floor_ptr->m_list[hack_m_idx_ii].parent_m_idx = back_m.parent_m_idx;
102 floor_ptr->m_list[hack_m_idx_ii].hold_o_idx_list = back_m.hold_o_idx_list;
105 if (place_monster_aux(player_ptr, 0, y, x, old_r_idx, (mode | PM_NO_KAGE | PM_IGNORE_TERRAIN))) {
106 floor_ptr->m_list[hack_m_idx_ii] = back_m;
107 mproc_init(floor_ptr);
109 preserve_hold_objects = false;
112 if (preserve_hold_objects) {
113 for (const auto this_o_idx : back_m.hold_o_idx_list) {
114 ObjectType *o_ptr = &floor_ptr->o_list[this_o_idx];
115 o_ptr->held_m_idx = hack_m_idx_ii;
118 for (auto it = back_m.hold_o_idx_list.begin(); it != back_m.hold_o_idx_list.end();) {
119 OBJECT_IDX this_o_idx = *it++;
120 delete_object_idx(player_ptr, this_o_idx);
125 target_who = hack_m_idx_ii;
127 health_track(player_ptr, hack_m_idx_ii);