OSDN Git Service

[Refactor] #40014 Separated monster-summonc./h from monster-generator.c/h
[hengband/hengband.git] / src / monster-floor / monster-summon.c
1 #include "monster-floor/monster-summon.h"
2 #include "dungeon/dungeon.h"
3 #include "floor/floor.h"
4 #include "main/sound-definitions-table.h"
5 #include "monster-floor/monster-generator.h" // todo 相互依存してしまった、何とかする.
6 #include "monster-floor/place-monster-types.h"
7 #include "monster-race/monster-race-hook.h"
8 #include "monster-race/race-flags1.h"
9 #include "monster-race/race-flags7.h"
10 #include "monster/monster-info.h"
11 #include "monster/monster-list.h"
12 #include "monster/monster-util.h"
13 #include "mspell/summon-checker.h"
14 #include "spell/spells-summon.h"
15 #include "system/monster-type-definition.h"
16
17 /*!
18  * @var summon_specific_who
19  * @brief 召喚を行ったプレイヤーあるいはモンスターのIDを示すグローバル変数 / Hack -- the index of the summoning monster
20  * @todo summon_specific_who グローバル変数の除去と関数引数への代替を行う
21  */
22 int summon_specific_who = -1;
23
24 /*!
25  * @var summon_unique_okay
26  * @brief 召喚対象にユニークを含めるかを示すグローバル変数 / summoning unique enable
27  * @todo summon_unique_okay グローバル変数の除去と関数引数への代替を行う
28  */
29 bool summon_unique_okay = FALSE;
30
31 /*!
32  * todo ここにplayer_typeを追加すると関数ポインタ周りの収拾がつかなくなるので保留
33  * @brief モンスターが召喚の基本条件に合っているかをチェックする / Hack -- help decide if a monster race is "okay" to summon
34  * @param r_idx チェックするモンスター種族ID
35  * @return 召喚対象にできるならばTRUE
36  */
37 static bool summon_specific_okay(MONRACE_IDX r_idx)
38 {
39     monster_race *r_ptr = &r_info[r_idx];
40     monster_type *m_ptr = &p_ptr->current_floor_ptr->m_list[summon_specific_who];
41     if (!mon_hook_dungeon(r_idx))
42         return FALSE;
43
44     if (summon_specific_who > 0) {
45         if (monster_has_hostile_align(p_ptr, m_ptr, 0, 0, r_ptr))
46             return FALSE;
47     } else if (summon_specific_who < 0) {
48         if (monster_has_hostile_align(p_ptr, NULL, 10, -10, r_ptr)) {
49             if (!one_in_(ABS(p_ptr->align) / 2 + 1))
50                 return FALSE;
51         }
52     }
53
54     if (!summon_unique_okay && ((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->flags7 & RF7_NAZGUL)))
55         return FALSE;
56
57     if (!summon_specific_type)
58         return TRUE;
59
60     if ((summon_specific_who < 0) && ((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->flags7 & RF7_NAZGUL)) && monster_has_hostile_align(p_ptr, NULL, 10, -10, r_ptr))
61         return FALSE;
62
63     if ((r_ptr->flags7 & RF7_CHAMELEON) && (d_info[p_ptr->dungeon_idx].flags1 & DF1_CHAMELEON))
64         return TRUE;
65
66     return (check_summon_specific(p_ptr, m_ptr->r_idx, r_idx));
67 }
68
69 /*!
70  * @brief モンスターを召喚により配置する / Place a monster (of the specified "type") near the given location. Return TRUE if a monster was actually summoned.
71  * @param player_ptr プレーヤーへの参照ポインタ
72  * @param who 召喚主のモンスター情報ID
73  * @param y1 目標地点y座標
74  * @param x1 目標地点x座標
75  * @param lev 相当生成階
76  * @param type 召喚種別
77  * @param mode 生成オプション
78  * @return 召喚できたらtrueを返す
79  */
80 bool summon_specific(player_type *player_ptr, MONSTER_IDX who, POSITION y1, POSITION x1, DEPTH lev, int type, BIT_FLAGS mode)
81 {
82     floor_type *floor_ptr = player_ptr->current_floor_ptr;
83     if (floor_ptr->inside_arena)
84         return FALSE;
85
86     POSITION x, y;
87     if (!mon_scatter(player_ptr, 0, &y, &x, y1, x1, 2))
88         return FALSE;
89
90     summon_specific_who = who;
91     summon_specific_type = type;
92     summon_unique_okay = (mode & PM_ALLOW_UNIQUE) ? TRUE : FALSE;
93     get_mon_num_prep(player_ptr, summon_specific_okay, get_monster_hook2(player_ptr, y, x));
94
95     MONRACE_IDX r_idx = get_mon_num(player_ptr, (floor_ptr->dun_level + lev) / 2 + 5, 0);
96     if (!r_idx) {
97         summon_specific_type = 0;
98         return FALSE;
99     }
100
101     if ((type == SUMMON_BLUE_HORROR) || (type == SUMMON_DAWN))
102         mode |= PM_NO_KAGE;
103
104     if (!place_monster_aux(player_ptr, who, y, x, r_idx, mode)) {
105         summon_specific_type = 0;
106         return FALSE;
107     }
108
109     summon_specific_type = 0;
110     sound(SOUND_SUMMON);
111     return TRUE;
112 }
113
114 /*!
115  * @brief 特定モンスター種族を召喚により生成する / A "dangerous" function, creates a pet of the specified type
116  * @param player_ptr プレーヤーへの参照ポインタ
117  * @param who 召喚主のモンスター情報ID
118  * @param oy 目標地点y座標
119  * @param ox 目標地点x座標
120  * @param r_idx 生成するモンスター種族ID
121  * @param mode 生成オプション
122  * @return 召喚できたらtrueを返す
123  */
124 bool summon_named_creature(player_type *player_ptr, MONSTER_IDX who, POSITION oy, POSITION ox, MONRACE_IDX r_idx, BIT_FLAGS mode)
125 {
126     if (r_idx >= max_r_idx)
127         return FALSE;
128
129     POSITION x, y;
130     if (player_ptr->current_floor_ptr->inside_arena)
131         return FALSE;
132
133     if (!mon_scatter(player_ptr, r_idx, &y, &x, oy, ox, 2))
134         return FALSE;
135
136     return place_monster_aux(player_ptr, who, y, x, r_idx, (mode | PM_NO_KAGE));
137 }