OSDN Git Service

[Refactor] #40414 Separated racial-ninja.c/h from spells2.h..., OH YEAH!! NINJA IS...
[hengband/hengband.git] / src / mind / racial-ninja.c
1 #include "mind/racial-ninja.h"
2 #include "cmd-action/cmd-attack.h"
3 #include "combat/combat-options-type.h"
4 #include "floor/floor-object.h"
5 #include "io/targeting.h"
6 #include "effect/effect-characteristics.h"
7 #include "effect/spells-effect-util.h"
8 #include "object/object-generator.h"
9 #include "object/object-kind-hook.h"
10 #include "spell/spells3.h"
11
12 /*!
13  * @brief 変わり身処理
14  * @param caster_ptr プレーヤーへの参照ポインタ
15  * @param success 判定成功上の処理ならばTRUE
16  * @return 作用が実際にあった場合TRUEを返す
17  */
18 bool kawarimi(player_type *caster_ptr, bool success)
19 {
20     object_type forge;
21     object_type *q_ptr = &forge;
22
23     if (caster_ptr->is_dead)
24         return FALSE;
25     if (caster_ptr->confused || caster_ptr->blind || caster_ptr->paralyzed || caster_ptr->image)
26         return FALSE;
27     if (randint0(200) < caster_ptr->stun)
28         return FALSE;
29
30     if (!success && one_in_(3)) {
31         msg_print(_("失敗!逃げられなかった。", "Failed! You couldn't run away."));
32         caster_ptr->special_defense &= ~(NINJA_KAWARIMI);
33         caster_ptr->redraw |= (PR_STATUS);
34         return FALSE;
35     }
36
37     POSITION y = caster_ptr->y;
38     POSITION x = caster_ptr->x;
39
40     teleport_player(caster_ptr, 10 + randint1(90), TELEPORT_SPONTANEOUS);
41     object_wipe(q_ptr);
42     const int SV_WOODEN_STATUE = 0;
43     object_prep(q_ptr, lookup_kind(TV_STATUE, SV_WOODEN_STATUE));
44
45     q_ptr->pval = MON_NINJA;
46     (void)drop_near(caster_ptr, q_ptr, -1, y, x);
47
48     if (success)
49         msg_print(_("攻撃を受ける前に素早く身をひるがえした。", "You have turned around just before the attack hit you."));
50     else
51         msg_print(_("失敗!攻撃を受けてしまった。", "Failed! You are hit by the attack."));
52
53     caster_ptr->special_defense &= ~(NINJA_KAWARIMI);
54     caster_ptr->redraw |= (PR_STATUS);
55     return TRUE;
56 }
57
58 /*!
59  * @brief 入身処理 / "Rush Attack" routine for Samurai or Ninja
60  * @param caster_ptr プレーヤーへの参照ポインタ
61  * @param mdeath 目標モンスターが死亡したかを返す
62  * @return 作用が実際にあった場合TRUEを返す /  Return value is for checking "done"
63  */
64 bool rush_attack(player_type *attacker_ptr, bool *mdeath)
65 {
66     if (mdeath)
67         *mdeath = FALSE;
68
69     project_length = 5;
70     DIRECTION dir;
71     if (!get_aim_dir(attacker_ptr, &dir))
72         return FALSE;
73
74     int tx = attacker_ptr->x + project_length * ddx[dir];
75     int ty = attacker_ptr->y + project_length * ddy[dir];
76
77     if ((dir == 5) && target_okay(attacker_ptr)) {
78         tx = target_col;
79         ty = target_row;
80     }
81
82     int tm_idx = 0;
83     floor_type *floor_ptr = attacker_ptr->current_floor_ptr;
84     if (in_bounds(floor_ptr, ty, tx))
85         tm_idx = floor_ptr->grid_array[ty][tx].m_idx;
86
87     u16b path_g[32];
88     int path_n = project_path(attacker_ptr, path_g, project_length, attacker_ptr->y, attacker_ptr->x, ty, tx, PROJECT_STOP | PROJECT_KILL);
89     project_length = 0;
90     if (!path_n)
91         return TRUE;
92
93     ty = attacker_ptr->y;
94     tx = attacker_ptr->x;
95     bool tmp_mdeath = FALSE;
96     bool moved = FALSE;
97     for (int i = 0; i < path_n; i++) {
98         monster_type *m_ptr;
99
100         int ny = GRID_Y(path_g[i]);
101         int nx = GRID_X(path_g[i]);
102
103         if (is_cave_empty_bold(attacker_ptr, ny, nx) && player_can_enter(attacker_ptr, floor_ptr->grid_array[ny][nx].feat, 0)) {
104             ty = ny;
105             tx = nx;
106             continue;
107         }
108
109         if (!floor_ptr->grid_array[ny][nx].m_idx) {
110             if (tm_idx) {
111                 msg_print(_("失敗!", "Failed!"));
112             } else {
113                 msg_print(_("ここには入身では入れない。", "You can't move to that place."));
114             }
115
116             break;
117         }
118
119         if (!player_bold(attacker_ptr, ty, tx))
120             teleport_player_to(attacker_ptr, ty, tx, TELEPORT_NONMAGICAL);
121         update_monster(attacker_ptr, floor_ptr->grid_array[ny][nx].m_idx, TRUE);
122
123         m_ptr = &floor_ptr->m_list[floor_ptr->grid_array[ny][nx].m_idx];
124         if (tm_idx != floor_ptr->grid_array[ny][nx].m_idx) {
125 #ifdef JP
126             msg_format("%s%sが立ちふさがっている!", tm_idx ? "別の" : "", m_ptr->ml ? "モンスター" : "何か");
127 #else
128             msg_format("There is %s in the way!", m_ptr->ml ? (tm_idx ? "another monster" : "a monster") : "someone");
129 #endif
130         } else if (!player_bold(attacker_ptr, ty, tx)) {
131             GAME_TEXT m_name[MAX_NLEN];
132             monster_desc(attacker_ptr, m_name, m_ptr, 0);
133             msg_format(_("素早く%sの懐に入り込んだ!", "You quickly jump in and attack %s!"), m_name);
134         }
135
136         if (!player_bold(attacker_ptr, ty, tx))
137             teleport_player_to(attacker_ptr, ty, tx, TELEPORT_NONMAGICAL);
138         moved = TRUE;
139         tmp_mdeath = do_cmd_attack(attacker_ptr, ny, nx, HISSATSU_NYUSIN);
140
141         break;
142     }
143
144     if (!moved && !player_bold(attacker_ptr, ty, tx))
145         teleport_player_to(attacker_ptr, ty, tx, TELEPORT_NONMAGICAL);
146
147     if (mdeath)
148         *mdeath = tmp_mdeath;
149     return TRUE;
150 }