OSDN Git Service

Revert "Revert "Merge branch 'master' of git.osdn.net:/gitroot/hengband/hengband""
[hengband/hengband.git] / src / spell-realm / spells-crusade.c
1 /*!
2  * @brief 破邪魔法処理
3  * @date 2020/06/05
4  * @author Hourier
5  */
6
7 #include "spell-realm/spells-crusade.h"
8 #include "core/disturbance.h"
9 #include "core/player-redraw-types.h"
10 #include "core/player-update-types.h"
11 #include "core/stuff-handler.h"
12 #include "effect/effect-characteristics.h"
13 #include "effect/effect-processor.h"
14 #include "floor/cave.h"
15 #include "game-option/disturbance-options.h"
16 #include "grid/feature-flag-types.h"
17 #include "grid/grid.h"
18 #include "spell-realm/spells-crusade.h"
19 #include "spell/range-calc.h"
20 #include "spell/spell-types.h"
21 #include "system/floor-type-definition.h"
22 #include "target/projection-path-calculator.h"
23 #include "target/target-checker.h"
24 #include "target/target-getter.h"
25 #include "util/bit-flags-calculator.h"
26 #include "view/display-messages.h"
27
28 /*!
29  * @brief 破邪魔法「神の怒り」の処理としてターゲットを指定した後分解のボールを最大20回発生させる。
30  * @param caster_ptr プレーヤーへの参照ポインタ
31  * @param dam ダメージ
32  * @param rad 効力の半径
33  * @return ターゲットを指定し、実行したならばTRUEを返す。
34  */
35 bool cast_wrath_of_the_god(player_type *caster_ptr, HIT_POINT dam, POSITION rad)
36 {
37     DIRECTION dir;
38     if (!get_aim_dir(caster_ptr, &dir))
39         return FALSE;
40
41     POSITION tx = caster_ptr->x + 99 * ddx[dir];
42     POSITION ty = caster_ptr->y + 99 * ddy[dir];
43     if ((dir == 5) && target_okay(caster_ptr)) {
44         tx = target_col;
45         ty = target_row;
46     }
47
48     POSITION x = caster_ptr->x;
49     POSITION y = caster_ptr->y;
50     POSITION nx, ny;
51     while (TRUE) {
52         if ((y == ty) && (x == tx))
53             break;
54
55         ny = y;
56         nx = x;
57         mmove2(&ny, &nx, caster_ptr->y, caster_ptr->x, ty, tx);
58         if (get_max_range(caster_ptr) <= distance(caster_ptr->y, caster_ptr->x, ny, nx))
59             break;
60         if (!cave_have_flag_bold(caster_ptr->current_floor_ptr, ny, nx, FF_PROJECT))
61             break;
62         if ((dir != 5) && caster_ptr->current_floor_ptr->grid_array[ny][nx].m_idx != 0)
63             break;
64
65         x = nx;
66         y = ny;
67     }
68
69     tx = x;
70     ty = y;
71
72     int b = 10 + randint1(10);
73     for (int i = 0; i < b; i++) {
74         int count = 20, d = 0;
75
76         while (count--) {
77             int dx, dy;
78
79             x = tx - 5 + randint0(11);
80             y = ty - 5 + randint0(11);
81
82             dx = (tx > x) ? (tx - x) : (x - tx);
83             dy = (ty > y) ? (ty - y) : (y - ty);
84
85             d = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1));
86             if (d < 5)
87                 break;
88         }
89
90         if (count < 0)
91             continue;
92
93         if (!in_bounds(caster_ptr->current_floor_ptr, y, x) || cave_stop_disintegration(caster_ptr->current_floor_ptr, y, x)
94             || !in_disintegration_range(caster_ptr->current_floor_ptr, ty, tx, y, x))
95             continue;
96
97         project(caster_ptr, 0, rad, y, x, dam, GF_DISINTEGRATE, PROJECT_JUMP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL, -1);
98     }
99
100     return TRUE;
101 }
102
103 /*!
104  * @brief 一時的聖なるのオーラの継続時間をセットする / Set "tim_sh_holy", notice observable changes
105  * @param v 継続時間
106  * @param do_dec 現在の継続時間より長い値のみ上書きする
107  * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
108  */
109 bool set_tim_sh_holy(player_type *creature_ptr, TIME_EFFECT v, bool do_dec)
110 {
111     bool notice = FALSE;
112     v = (v > 10000) ? 10000 : (v < 0) ? 0 : v;
113
114     if (creature_ptr->is_dead)
115         return FALSE;
116
117     if (v) {
118         if (creature_ptr->tim_sh_holy && !do_dec) {
119             if (creature_ptr->tim_sh_holy > v)
120                 return FALSE;
121         } else if (!creature_ptr->tim_sh_holy) {
122             msg_print(_("体が聖なるオーラで覆われた。", "You are enveloped by a holy aura!"));
123             notice = TRUE;
124         }
125     } else {
126         if (creature_ptr->tim_sh_holy) {
127             msg_print(_("聖なるオーラが消えた。", "The holy aura disappeared."));
128             notice = TRUE;
129         }
130     }
131
132     creature_ptr->tim_sh_holy = v;
133     creature_ptr->redraw |= (PR_STATUS);
134
135     if (!notice)
136         return FALSE;
137
138     if (disturb_state)
139         disturb(creature_ptr, FALSE, FALSE);
140     creature_ptr->update |= (PU_BONUS);
141     handle_stuff(creature_ptr);
142     return TRUE;
143 }
144
145 /*!
146  * @brief 目には目をの残り時間をセットする / Set "tim_eyeeye", notice observable changes
147  * @param v 継続時間
148  * @param do_dec 現在の継続時間より長い値のみ上書きする
149  * @return ステータスに影響を及ぼす変化があった場合TRUEを返す
150  * @details 呪術領域でも使えるが、汎用性と行数の兼ね合いを考えて破邪側に入れた
151  */
152 bool set_tim_eyeeye(player_type *creature_ptr, TIME_EFFECT v, bool do_dec)
153 {
154     bool notice = FALSE;
155     v = (v > 10000) ? 10000 : (v < 0) ? 0 : v;
156
157     if (creature_ptr->is_dead)
158         return FALSE;
159
160     if (v) {
161         if (creature_ptr->tim_eyeeye && !do_dec) {
162             if (creature_ptr->tim_eyeeye > v)
163                 return FALSE;
164         } else if (!creature_ptr->tim_eyeeye) {
165             msg_print(_("法の守り手になった気がした!", "You feel like a keeper of commandments!"));
166             notice = TRUE;
167         }
168     } else {
169         if (creature_ptr->tim_eyeeye) {
170             msg_print(_("懲罰を執行することができなくなった。", "You no longer feel like a keeper."));
171             notice = TRUE;
172         }
173     }
174
175     creature_ptr->tim_eyeeye = v;
176     creature_ptr->redraw |= (PR_STATUS);
177
178     if (!notice)
179         return FALSE;
180
181     if (disturb_state)
182         disturb(creature_ptr, FALSE, FALSE);
183     creature_ptr->update |= (PU_BONUS);
184     handle_stuff(creature_ptr);
185     return TRUE;
186 }