8 #include "mind/mind-mirror-master.h"
9 #include "core/disturbance.h"
10 #include "core/player-redraw-types.h"
11 #include "core/player-update-types.h"
12 #include "core/stuff-handler.h"
13 #include "effect/attribute-types.h"
14 #include "effect/effect-characteristics.h"
15 #include "effect/effect-feature.h"
16 #include "effect/effect-item.h"
17 #include "effect/effect-monster.h"
18 #include "effect/effect-processor.h"
19 #include "effect/spells-effect-util.h"
20 #include "floor/cave.h"
21 #include "floor/geometry.h"
22 #include "game-option/disturbance-options.h"
23 #include "game-option/map-screen-options.h"
24 #include "game-option/special-options.h"
25 #include "grid/feature.h"
26 #include "grid/grid.h"
27 #include "io/cursor.h"
28 #include "io/screen-util.h"
29 #include "mind/mind-magic-resistance.h"
30 #include "mind/mind-numbers.h"
31 #include "pet/pet-util.h"
32 #include "spell-class/spells-mirror-master.h"
33 #include "spell-kind/spells-detection.h"
34 #include "spell-kind/spells-floor.h"
35 #include "spell-kind/spells-launcher.h"
36 #include "spell-kind/spells-lite.h"
37 #include "spell-kind/spells-sight.h"
38 #include "spell-kind/spells-teleport.h"
39 #include "spell-kind/spells-world.h"
40 #include "status/body-improvement.h"
41 #include "status/buff-setter.h"
42 #include "status/sight-setter.h"
43 #include "system/floor-type-definition.h"
44 #include "system/grid-type-definition.h"
45 #include "system/player-type-definition.h"
46 #include "target/grid-selector.h"
47 #include "target/projection-path-calculator.h"
48 #include "target/target-getter.h"
49 #include "timed-effect/player-blindness.h"
50 #include "timed-effect/timed-effects.h"
51 #include "util/bit-flags-calculator.h"
52 #include "view/display-messages.h"
53 #include "world/world.h"
56 * @brief Multishadow effects is determined by turn
58 bool check_multishadow(PlayerType *player_ptr)
60 return (player_ptr->multishadow != 0) && ((w_ptr->game_turn & 1) != 0);
64 * @brief 鏡魔法「封魔結界」の効果処理
66 * @return 効果があったらTRUEを返す
68 bool binding_field(PlayerType *player_ptr, int dam)
70 POSITION mirror_x[10], mirror_y[10]; /* 鏡はもっと少ない */
71 int mirror_num = 0; /* 鏡の数 */
77 /* Default target of monsterspell is player */
78 monster_target_y = player_ptr->y;
79 monster_target_x = player_ptr->x;
81 for (POSITION x = 0; x < player_ptr->current_floor_ptr->width; x++) {
82 for (POSITION y = 0; y < player_ptr->current_floor_ptr->height; y++) {
83 if (player_ptr->current_floor_ptr->grid_array[y][x].is_mirror() && distance(player_ptr->y, player_ptr->x, y, x) <= get_max_range(player_ptr) && distance(player_ptr->y, player_ptr->x, y, x) != 0 && player_has_los_bold(player_ptr, y, x) && projectable(player_ptr, player_ptr->y, player_ptr->x, y, x)) {
84 mirror_y[mirror_num] = y;
85 mirror_x[mirror_num] = x;
95 point_x[0] = randint0(mirror_num);
97 point_x[1] = randint0(mirror_num);
98 } while (point_x[0] == point_x[1]);
100 point_y[0] = mirror_y[point_x[0]];
101 point_x[0] = mirror_x[point_x[0]];
102 point_y[1] = mirror_y[point_x[1]];
103 point_x[1] = mirror_x[point_x[1]];
104 point_y[2] = player_ptr->y;
105 point_x[2] = player_ptr->x;
107 POSITION x = point_x[0] + point_x[1] + point_x[2];
108 POSITION y = point_y[0] + point_y[1] + point_y[2];
110 POSITION centersign = (point_x[0] * 3 - x) * (point_y[1] * 3 - y) - (point_y[0] * 3 - y) * (point_x[1] * 3 - x);
111 if (centersign == 0) {
115 POSITION x1 = point_x[0] < point_x[1] ? point_x[0] : point_x[1];
116 x1 = x1 < point_x[2] ? x1 : point_x[2];
117 POSITION y1 = point_y[0] < point_y[1] ? point_y[0] : point_y[1];
118 y1 = y1 < point_y[2] ? y1 : point_y[2];
120 POSITION x2 = point_x[0] > point_x[1] ? point_x[0] : point_x[1];
121 x2 = x2 > point_x[2] ? x2 : point_x[2];
122 POSITION y2 = point_y[0] > point_y[1] ? point_y[0] : point_y[1];
123 y2 = y2 > point_y[2] ? y2 : point_y[2];
125 for (y = y1; y <= y2; y++) {
126 for (x = x1; x <= x2; x++) {
127 if (centersign * ((point_x[0] - x) * (point_y[1] - y) - (point_y[0] - y) * (point_x[1] - x)) >= 0 && centersign * ((point_x[1] - x) * (point_y[2] - y) - (point_y[1] - y) * (point_x[2] - x)) >= 0 && centersign * ((point_x[2] - x) * (point_y[0] - y) - (point_y[2] - y) * (point_x[0] - x)) >= 0) {
128 if (player_has_los_bold(player_ptr, y, x) && projectable(player_ptr, player_ptr->y, player_ptr->x, y, x)) {
129 if (!(player_ptr->effects()->blindness()->is_blind()) && panel_contains(y, x)) {
130 print_bolt_pict(player_ptr, y, x, y, x, AttributeType::MANA);
131 move_cursor_relative(y, x);
133 term_xtra(TERM_XTRA_DELAY, delay_factor);
140 for (y = y1; y <= y2; y++) {
141 for (x = x1; x <= x2; x++) {
142 if (centersign * ((point_x[0] - x) * (point_y[1] - y) - (point_y[0] - y) * (point_x[1] - x)) >= 0 && centersign * ((point_x[1] - x) * (point_y[2] - y) - (point_y[1] - y) * (point_x[2] - x)) >= 0 && centersign * ((point_x[2] - x) * (point_y[0] - y) - (point_y[2] - y) * (point_x[0] - x)) >= 0) {
143 if (player_has_los_bold(player_ptr, y, x) && projectable(player_ptr, player_ptr->y, player_ptr->x, y, x)) {
144 (void)affect_feature(player_ptr, 0, 0, y, x, dam, AttributeType::MANA);
150 for (y = y1; y <= y2; y++) {
151 for (x = x1; x <= x2; x++) {
152 if (centersign * ((point_x[0] - x) * (point_y[1] - y) - (point_y[0] - y) * (point_x[1] - x)) >= 0 && centersign * ((point_x[1] - x) * (point_y[2] - y) - (point_y[1] - y) * (point_x[2] - x)) >= 0 && centersign * ((point_x[2] - x) * (point_y[0] - y) - (point_y[2] - y) * (point_x[0] - x)) >= 0) {
153 if (player_has_los_bold(player_ptr, y, x) && projectable(player_ptr, player_ptr->y, player_ptr->x, y, x)) {
154 (void)affect_item(player_ptr, 0, 0, y, x, dam, AttributeType::MANA);
160 for (y = y1; y <= y2; y++) {
161 for (x = x1; x <= x2; x++) {
162 if (centersign * ((point_x[0] - x) * (point_y[1] - y) - (point_y[0] - y) * (point_x[1] - x)) >= 0 && centersign * ((point_x[1] - x) * (point_y[2] - y) - (point_y[1] - y) * (point_x[2] - x)) >= 0 && centersign * ((point_x[2] - x) * (point_y[0] - y) - (point_y[2] - y) * (point_x[0] - x)) >= 0) {
163 if (player_has_los_bold(player_ptr, y, x) && projectable(player_ptr, player_ptr->y, player_ptr->x, y, x)) {
164 (void)affect_monster(player_ptr, 0, 0, y, x, dam, AttributeType::MANA, (PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_JUMP), true);
171 msg_print(_("鏡が結界に耐えきれず、壊れてしまった。", "The field broke a mirror"));
172 SpellsMirrorMaster(player_ptr).remove_mirror(point_y[0], point_x[0]);
179 * 幻惑の光 @ 鏡使いだけでなく混沌の戦士も使える
180 * @param player_ptr プレイヤーへの参照ポインタ
183 bool confusing_light(PlayerType *player_ptr)
185 msg_print(_("辺りを睨んだ...", "You glare at nearby monsters..."));
186 slow_monsters(player_ptr, player_ptr->lev);
187 stun_monsters(player_ptr, player_ptr->lev * 4);
188 confuse_monsters(player_ptr, player_ptr->lev * 4);
189 turn_monsters(player_ptr, player_ptr->lev * 4);
190 stasis_monsters(player_ptr, player_ptr->lev * 4);
195 * Set "multishadow", notice observable changes
197 bool set_multishadow(PlayerType *player_ptr, TIME_EFFECT v, bool do_dec)
200 v = (v > 10000) ? 10000 : (v < 0) ? 0
203 if (player_ptr->is_dead) {
208 if (player_ptr->multishadow && !do_dec) {
209 if (player_ptr->multishadow > v) {
212 } else if (!player_ptr->multishadow) {
213 msg_print(_("あなたの周りに幻影が生まれた。", "Your Shadow enveloped you."));
217 if (player_ptr->multishadow) {
218 msg_print(_("幻影が消えた。", "Your Shadow disappears."));
223 player_ptr->multishadow = v;
224 player_ptr->redraw |= (PR_STATUS);
231 disturb(player_ptr, false, false);
233 player_ptr->update |= (PU_BONUS);
234 handle_stuff(player_ptr);
239 * @brief 一時的破片のオーラの継続時間をセットする / Set "dustrobe", notice observable changes
241 * @param do_dec 現在の継続時間より長い値のみ上書きする
242 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
244 bool set_dustrobe(PlayerType *player_ptr, TIME_EFFECT v, bool do_dec)
247 v = (v > 10000) ? 10000 : (v < 0) ? 0
250 if (player_ptr->is_dead) {
255 if (player_ptr->dustrobe && !do_dec) {
256 if (player_ptr->dustrobe > v) {
259 } else if (!player_ptr->dustrobe) {
260 msg_print(_("体が鏡のオーラで覆われた。", "You are enveloped by mirror shards."));
264 if (player_ptr->dustrobe) {
265 msg_print(_("鏡のオーラが消えた。", "The mirror shards disappear."));
270 player_ptr->dustrobe = v;
271 player_ptr->redraw |= (PR_STATUS);
278 disturb(player_ptr, false, false);
280 player_ptr->update |= (PU_BONUS);
281 handle_stuff(player_ptr);
286 * @brief 現在フロアに存在している鏡の数を数える / calculate mirrors
289 static int number_of_mirrors(floor_type *floor_ptr)
292 for (POSITION x = 0; x < floor_ptr->width; x++) {
293 for (POSITION y = 0; y < floor_ptr->height; y++) {
294 if (floor_ptr->grid_array[y][x].is_mirror()) {
305 * do_cmd_cast calls this function if the player's class is 'Mirror magic'.
306 * @param spell 発動する特殊技能のID
307 * @return 処理を実行したらTRUE、キャンセルした場合FALSEを返す。
309 bool cast_mirror_spell(PlayerType *player_ptr, MindMirrorMasterType spell)
312 PLAYER_LEVEL plev = player_ptr->lev;
316 auto *g_ptr = &player_ptr->current_floor_ptr->grid_array[player_ptr->y][player_ptr->x];
318 case MindMirrorMasterType::MIRROR_SEEING:
319 tmp = g_ptr->is_mirror() ? 4 : 0;
320 if (plev + tmp > 4) {
321 detect_monsters_normal(player_ptr, DETECT_RAD_DEFAULT);
323 if (plev + tmp > 18) {
324 detect_monsters_invis(player_ptr, DETECT_RAD_DEFAULT);
326 if (plev + tmp > 28) {
327 set_tim_esp(player_ptr, (TIME_EFFECT)plev, false);
329 if (plev + tmp > 38) {
330 map_area(player_ptr, DETECT_RAD_MAP);
332 if (tmp == 0 && plev < 5) {
333 msg_print(_("鏡がなくて集中できなかった!", "You need a mirror to concentrate!"));
336 case MindMirrorMasterType::MAKE_MIRROR:
337 if (number_of_mirrors(player_ptr->current_floor_ptr) < 4 + plev / 10) {
338 SpellsMirrorMaster(player_ptr).place_mirror();
340 msg_format(_("これ以上鏡は制御できない!", "There are too many mirrors to control!"));
344 case MindMirrorMasterType::DRIP_LIGHT:
345 if (!get_aim_dir(player_ptr, &dir)) {
349 if (plev > 9 && g_ptr->is_mirror()) {
350 fire_beam(player_ptr, AttributeType::LITE, dir, damroll(3 + ((plev - 1) / 5), 4));
352 fire_bolt(player_ptr, AttributeType::LITE, dir, damroll(3 + ((plev - 1) / 5), 4));
356 case MindMirrorMasterType::WRAPPED_MIRROR:
357 teleport_player(player_ptr, 10, TELEPORT_SPONTANEOUS);
359 case MindMirrorMasterType::MIRROR_LIGHT:
360 (void)lite_area(player_ptr, damroll(2, (plev / 2)), (plev / 10) + 1);
362 case MindMirrorMasterType::WANDERING_MIRROR:
363 teleport_player(player_ptr, plev * 5, TELEPORT_SPONTANEOUS);
365 case MindMirrorMasterType::ROBE_DUST:
366 set_dustrobe(player_ptr, 20 + randint1(20), false);
368 case MindMirrorMasterType::BANISHING_MIRROR:
369 if (!get_aim_dir(player_ptr, &dir)) {
373 (void)fire_beam(player_ptr, AttributeType::AWAY_ALL, dir, plev);
375 case MindMirrorMasterType::MIRROR_CRASHING:
376 if (!get_aim_dir(player_ptr, &dir)) {
380 fire_ball(player_ptr, AttributeType::SHARDS, dir, damroll(8 + ((plev - 5) / 4), 8), (plev > 20 ? (plev - 20) / 8 + 1 : 0));
382 case MindMirrorMasterType::SLEEPING_MIRROR:
383 for (x = 0; x < player_ptr->current_floor_ptr->width; x++) {
384 for (y = 0; y < player_ptr->current_floor_ptr->height; y++) {
385 if (player_ptr->current_floor_ptr->grid_array[y][x].is_mirror()) {
386 project(player_ptr, 0, 2, y, x, (int)plev, AttributeType::OLD_SLEEP,
387 (PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_JUMP | PROJECT_NO_HANGEKI));
393 case MindMirrorMasterType::SEEKER_RAY:
394 if (!get_aim_dir(player_ptr, &dir)) {
398 SpellsMirrorMaster(player_ptr).seeker_ray(dir, damroll(11 + (plev - 5) / 4, 8));
400 case MindMirrorMasterType::SEALING_MIRROR:
401 SpellsMirrorMaster(player_ptr).seal_of_mirror(plev * 4 + 100);
403 case MindMirrorMasterType::WATER_SHIELD:
404 t = 20 + randint1(20);
405 set_shield(player_ptr, t, false);
407 set_tim_reflect(player_ptr, t, false);
411 set_resist_magic(player_ptr, t, false);
415 case MindMirrorMasterType::SUPER_RAY:
416 if (!get_aim_dir(player_ptr, &dir)) {
420 SpellsMirrorMaster(player_ptr).super_ray(dir, damroll(11 + (plev - 5) / 4, 8));
422 case MindMirrorMasterType::ILLUSION_LIGHT:
423 tmp = g_ptr->is_mirror() ? 4 : 3;
424 slow_monsters(player_ptr, plev);
425 stun_monsters(player_ptr, plev * tmp * 2);
426 confuse_monsters(player_ptr, plev * tmp);
427 turn_monsters(player_ptr, plev * tmp);
428 stasis_monsters(player_ptr, plev * tmp);
430 case MindMirrorMasterType::MIRROR_SHIFT:
431 if (!g_ptr->is_mirror()) {
432 msg_print(_("鏡の国の場所がわからない!", "You cannot find out where the mirror is!"));
436 reserve_alter_reality(player_ptr, randint0(21) + 15);
438 case MindMirrorMasterType::MIRROR_TUNNEL:
439 msg_print(_("鏡の世界を通り抜け… ", "You try to enter the mirror..."));
440 return SpellsMirrorMaster(player_ptr).mirror_tunnel();
441 case MindMirrorMasterType::RECALL_MIRROR:
442 return recall_player(player_ptr, randint0(21) + 15);
443 case MindMirrorMasterType::MULTI_SHADOW:
444 set_multishadow(player_ptr, 6 + randint1(6), false);
446 case MindMirrorMasterType::BINDING_FIELD:
447 if (!binding_field(player_ptr, plev * 11 + 5)) {
448 msg_print(_("適当な鏡を選べなかった!", "You were not able to choose suitable mirrors!"));
452 case MindMirrorMasterType::RUFFNOR_MIRROR:
453 (void)set_invuln(player_ptr, randint1(4) + 4, false);
456 msg_print(_("なに?", "Zap?"));