OSDN Git Service

Merge pull request #3904 from Hourier/Change-Signature-GetDirection
[hengbandforosx/hengbandosx.git] / src / spell-kind / spells-launcher.cpp
1 #include "spell-kind/spells-launcher.h"
2 #include "effect/effect-characteristics.h"
3 #include "effect/effect-processor.h"
4 #include "floor/geometry.h"
5 #include "system/player-type-definition.h"
6 #include "target/target-checker.h"
7 #include "util/bit-flags-calculator.h"
8
9 /*!
10  * @brief ボール系スペルの発動 / Cast a ball spell
11  * @param player_ptr プレイヤーへの参照ポインタ
12  * @param typ 効果属性
13  * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
14  * @param dam 威力
15  * @param rad 半径
16  * @return 作用が実際にあった場合TRUEを返す
17  * @details
18  * <pre>
19  * Stop if we hit a monster, act as a "ball"
20  * Allow "target" mode to pass over monsters
21  * Affect grids, objects, and monsters
22  * </pre>
23  */
24 bool fire_ball(PlayerType *player_ptr, AttributeType typ, DIRECTION dir, int dam, POSITION rad, std::optional<CapturedMonsterType *> cap_mon_ptr)
25 {
26     BIT_FLAGS flg = PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
27     if (typ == AttributeType::CHARM_LIVING) {
28         flg |= PROJECT_HIDE;
29     }
30
31     POSITION tx = player_ptr->x + 99 * ddx[dir];
32     POSITION ty = player_ptr->y + 99 * ddy[dir];
33
34     if ((dir == 5) && target_okay(player_ptr)) {
35         flg &= ~(PROJECT_STOP);
36         tx = target_col;
37         ty = target_row;
38     }
39
40     return project(player_ptr, 0, rad, ty, tx, dam, typ, flg, cap_mon_ptr).notice;
41 }
42
43 /*!
44  * @brief ブレス系スペルの発動 / Cast a breath spell
45  * @param player_ptr プレイヤーへの参照ポインタ
46  * @param typ 効果属性
47  * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
48  * @param dam 威力
49  * @param rad 半径
50  * @return 作用が実際にあった場合TRUEを返す
51  * @details
52  * <pre>
53  * Stop if we hit a monster, act as a "ball"
54  * Allow "target" mode to pass over monsters
55  * Affect grids, objects, and monsters
56  * </pre>
57  */
58 bool fire_breath(PlayerType *player_ptr, AttributeType typ, DIRECTION dir, int dam, POSITION rad)
59 {
60     BIT_FLAGS flg = PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_BREATH;
61
62     auto tx = player_ptr->x + 99 * ddx[dir];
63     auto ty = player_ptr->y + 99 * ddy[dir];
64
65     if ((dir == 5) && target_okay(player_ptr)) {
66         reset_bits(flg, PROJECT_STOP);
67         tx = target_col;
68         ty = target_row;
69     }
70
71     return project(player_ptr, 0, rad, ty, tx, dam, typ, flg).notice;
72 }
73
74 /*!
75  * @brief ロケット系スペルの発動(詳細な差は確認中) / Cast a ball spell
76  * @param player_ptr プレイヤーへの参照ポインタ
77  * @param typ 効果属性
78  * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
79  * @param dam 威力
80  * @param rad 半径
81  * @return 作用が実際にあった場合TRUEを返す
82  * @details
83  * <pre>
84  * Stop if we hit a monster, act as a "ball"
85  * Allow "target" mode to pass over monsters
86  * Affect grids, objects, and monsters
87  * </pre>
88  */
89 bool fire_rocket(PlayerType *player_ptr, AttributeType typ, DIRECTION dir, int dam, POSITION rad)
90 {
91     POSITION tx = player_ptr->x + 99 * ddx[dir];
92     POSITION ty = player_ptr->y + 99 * ddy[dir];
93     if ((dir == 5) && target_okay(player_ptr)) {
94         tx = target_col;
95         ty = target_row;
96     }
97
98     BIT_FLAGS flg = PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
99     return project(player_ptr, 0, rad, ty, tx, dam, typ, flg).notice;
100 }
101
102 /*!
103  * @brief ボール(ハイド)系スペルの発動 / Cast a ball spell
104  * @param player_ptr プレイヤーへの参照ポインタ
105  * @param typ 効果属性
106  * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
107  * @param dam 威力
108  * @param rad 半径
109  * @return 作用が実際にあった場合TRUEを返す
110  * @details
111  * <pre>
112  * Stop if we hit a monster, act as a "ball"
113  * Allow "target" mode to pass over monsters
114  * Affect grids, objects, and monsters
115  * </pre>
116  */
117 bool fire_ball_hide(PlayerType *player_ptr, AttributeType typ, DIRECTION dir, int dam, POSITION rad)
118 {
119     POSITION tx = player_ptr->x + 99 * ddx[dir];
120     POSITION ty = player_ptr->y + 99 * ddy[dir];
121     BIT_FLAGS flg = PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_HIDE;
122     if ((dir == 5) && target_okay(player_ptr)) {
123         flg &= ~(PROJECT_STOP);
124         tx = target_col;
125         ty = target_row;
126     }
127
128     return project(player_ptr, 0, rad, ty, tx, dam, typ, flg).notice;
129 }
130
131 /*!
132  * @brief メテオ系スペルの発動 / Cast a meteor spell
133  * @param player_ptr プレイヤーへの参照ポインタ
134  * @param src_idx スぺル詠唱者のモンスターID(0=プレイヤー)
135  * @param typ 効果属性
136  * @param dam 威力
137  * @param rad 半径
138  * @param y 中心点Y座標
139  * @param x 中心点X座標
140  * @return 作用が実際にあった場合TRUEを返す
141  * @details
142  * <pre>
143  * Cast a meteor spell, defined as a ball spell cast by an arbitary monster,
144  * player, or outside source, that starts out at an arbitrary location, and
145  * leaving no trail from the "caster" to the target.  This function is
146  * especially useful for bombardments and similar. -LM-
147  * Option to hurt the player.
148  * </pre>
149  */
150 bool fire_meteor(PlayerType *player_ptr, MONSTER_IDX src_idx, AttributeType typ, POSITION y, POSITION x, int dam, POSITION rad)
151 {
152     BIT_FLAGS flg = PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
153     return project(player_ptr, src_idx, rad, y, x, dam, typ, flg).notice;
154 }
155
156 /*!
157  * @brief ブラスト系スペルの発動 / Cast a blast spell
158  * @param player_ptr プレイヤーへの参照ポインタ
159  * @param typ 効果属性
160  * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
161  * @param dd 威力ダイス数
162  * @param ds 威力ダイス目
163  * @param num 基本回数
164  * @param dev 回数分散
165  * @return 作用が実際にあった場合TRUEを返す
166  */
167 bool fire_blast(PlayerType *player_ptr, AttributeType typ, DIRECTION dir, DICE_NUMBER dd, DICE_SID ds, int num, int dev)
168 {
169     POSITION ty, tx, y, x;
170     POSITION ly, lx;
171     if (dir == 5) {
172         tx = target_col;
173         ty = target_row;
174
175         lx = 20 * (tx - player_ptr->x) + player_ptr->x;
176         ly = 20 * (ty - player_ptr->y) + player_ptr->y;
177     } else {
178         ly = ty = player_ptr->y + 20 * ddy[dir];
179         lx = tx = player_ptr->x + 20 * ddx[dir];
180     }
181
182     int ld = distance(player_ptr->y, player_ptr->x, ly, lx);
183     BIT_FLAGS flg = PROJECT_FAST | PROJECT_THRU | PROJECT_STOP | PROJECT_KILL | PROJECT_REFLECTABLE | PROJECT_GRID;
184     bool result = true;
185     for (int i = 0; i < num; i++) {
186         while (true) {
187             /* Get targets for some bolts */
188             y = rand_spread(ly, ld * dev / 20);
189             x = rand_spread(lx, ld * dev / 20);
190
191             if (distance(ly, lx, y, x) <= ld * dev / 20) {
192                 break;
193             }
194         }
195
196         /* Analyze the "dir" and the "target". */
197         const auto proj_res = project(player_ptr, 0, 0, y, x, damroll(dd, ds), typ, flg);
198         if (!proj_res.notice) {
199             result = false;
200         }
201     }
202
203     return result;
204 }
205
206 /*!
207  * @brief ボルト系スペルの発動 / Cast a bolt spell.
208  * @param player_ptr プレイヤーへの参照ポインタ
209  * @param typ 効果属性
210  * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
211  * @param dam 威力
212  * @return 作用が実際にあった場合TRUEを返す
213  * @details
214  * <pre>
215  * Stop if we hit a monster, as a "bolt".
216  * Affect monsters and grids (not objects).
217  * </pre>
218  */
219 bool fire_bolt(PlayerType *player_ptr, AttributeType typ, DIRECTION dir, int dam)
220 {
221     BIT_FLAGS flg = PROJECT_STOP | PROJECT_KILL | PROJECT_GRID;
222     if (typ != AttributeType::MONSTER_SHOOT) {
223         flg |= PROJECT_REFLECTABLE;
224     }
225     return project_hook(player_ptr, typ, dir, dam, flg);
226 }
227
228 /*!
229  * @brief ビーム系スペルの発動 / Cast a beam spell.
230  * @param player_ptr プレイヤーへの参照ポインタ
231  * @param typ 効果属性
232  * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
233  * @param dam 威力
234  * @return 作用が実際にあった場合TRUEを返す
235  * @details
236  * <pre>
237  * Pass through monsters, as a "beam".
238  * Affect monsters, grids and objects.
239  * </pre>
240  */
241 bool fire_beam(PlayerType *player_ptr, AttributeType typ, DIRECTION dir, int dam)
242 {
243     BIT_FLAGS flg = PROJECT_BEAM | PROJECT_KILL | PROJECT_GRID | PROJECT_ITEM;
244     return project_hook(player_ptr, typ, dir, dam, flg);
245 }
246
247 /*!
248  * @brief 確率に応じたボルト系/ビーム系スペルの発動 / Cast a bolt spell, or rarely, a beam spell.
249  * @param player_ptr プレイヤーへの参照ポインタ
250  * @param prob ビーム化する確率(%)
251  * @param typ 効果属性
252  * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
253  * @param dam 威力
254  * @return 作用が実際にあった場合TRUEを返す
255  * @details
256  * <pre>
257  * Pass through monsters, as a "beam".
258  * Affect monsters, grids and objects.
259  * </pre>
260  */
261 bool fire_bolt_or_beam(PlayerType *player_ptr, PERCENTAGE prob, AttributeType typ, DIRECTION dir, int dam)
262 {
263     if (randint0(100) < prob) {
264         return (fire_beam(player_ptr, typ, dir, dam));
265     }
266
267     return (fire_bolt(player_ptr, typ, dir, dam));
268 }
269
270 /*!
271  * @brief 指定方向に飛び道具を飛ばす (フラグ任意指定) / Apply a "project()" in a direction (or at the target)
272  * @param player_ptr プレイヤーへの参照ポインタ
273  * @param typ 効果属性
274  * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
275  * @param dam 威力
276  * @param flg フラグ
277  * @return 作用が実際にあった場合TRUEを返す
278  */
279 bool project_hook(PlayerType *player_ptr, AttributeType typ, DIRECTION dir, int dam, BIT_FLAGS flg)
280 {
281     flg |= (PROJECT_THRU);
282     POSITION tx = player_ptr->x + ddx[dir];
283     POSITION ty = player_ptr->y + ddy[dir];
284     if ((dir == 5) && target_okay(player_ptr)) {
285         tx = target_col;
286         ty = target_row;
287     }
288
289     return project(player_ptr, 0, 0, ty, tx, dam, typ, flg).notice;
290 }