OSDN Git Service

[Refactor] #40014 Separated race-indice-types.h from monster.h
[hengband/hengband.git] / src / mind / mind-ninja.c
1 #include "mind/mind-ninja.h"
2 #include "cmd-action/cmd-attack.h"
3 #include "combat/combat-options-type.h"
4 #include "effect/effect-characteristics.h"
5 #include "effect/spells-effect-util.h"
6 #include "floor/floor-object.h"
7 #include "io/targeting.h"
8 #include "monster-race/race-indice-types.h"
9 #include "object-enchant/trc-types.h"
10 #include "object/object-generator.h"
11 #include "object/object-kind-hook.h"
12 #include "player/player-effects.h"
13 #include "spell-kind/spells-teleport.h"
14
15 /*!
16  * @brief 変わり身処理
17  * @param caster_ptr プレーヤーへの参照ポインタ
18  * @param success 判定成功上の処理ならばTRUE
19  * @return 作用が実際にあった場合TRUEを返す
20  */
21 bool kawarimi(player_type *caster_ptr, bool success)
22 {
23     object_type forge;
24     object_type *q_ptr = &forge;
25
26     if (caster_ptr->is_dead)
27         return FALSE;
28     if (caster_ptr->confused || caster_ptr->blind || caster_ptr->paralyzed || caster_ptr->image)
29         return FALSE;
30     if (randint0(200) < caster_ptr->stun)
31         return FALSE;
32
33     if (!success && one_in_(3)) {
34         msg_print(_("失敗!逃げられなかった。", "Failed! You couldn't run away."));
35         caster_ptr->special_defense &= ~(NINJA_KAWARIMI);
36         caster_ptr->redraw |= (PR_STATUS);
37         return FALSE;
38     }
39
40     POSITION y = caster_ptr->y;
41     POSITION x = caster_ptr->x;
42
43     teleport_player(caster_ptr, 10 + randint1(90), TELEPORT_SPONTANEOUS);
44     object_wipe(q_ptr);
45     const int SV_WOODEN_STATUE = 0;
46     object_prep(q_ptr, lookup_kind(TV_STATUE, SV_WOODEN_STATUE));
47
48     q_ptr->pval = MON_NINJA;
49     (void)drop_near(caster_ptr, q_ptr, -1, y, x);
50
51     if (success)
52         msg_print(_("攻撃を受ける前に素早く身をひるがえした。", "You have turned around just before the attack hit you."));
53     else
54         msg_print(_("失敗!攻撃を受けてしまった。", "Failed! You are hit by the attack."));
55
56     caster_ptr->special_defense &= ~(NINJA_KAWARIMI);
57     caster_ptr->redraw |= (PR_STATUS);
58     return TRUE;
59 }
60
61 /*!
62  * @brief 入身処理 / "Rush Attack" routine for Samurai or Ninja
63  * @param caster_ptr プレーヤーへの参照ポインタ
64  * @param mdeath 目標モンスターが死亡したかを返す
65  * @return 作用が実際にあった場合TRUEを返す /  Return value is for checking "done"
66  */
67 bool rush_attack(player_type *attacker_ptr, bool *mdeath)
68 {
69     if (mdeath)
70         *mdeath = FALSE;
71
72     project_length = 5;
73     DIRECTION dir;
74     if (!get_aim_dir(attacker_ptr, &dir))
75         return FALSE;
76
77     int tx = attacker_ptr->x + project_length * ddx[dir];
78     int ty = attacker_ptr->y + project_length * ddy[dir];
79
80     if ((dir == 5) && target_okay(attacker_ptr)) {
81         tx = target_col;
82         ty = target_row;
83     }
84
85     int tm_idx = 0;
86     floor_type *floor_ptr = attacker_ptr->current_floor_ptr;
87     if (in_bounds(floor_ptr, ty, tx))
88         tm_idx = floor_ptr->grid_array[ty][tx].m_idx;
89
90     u16b path_g[32];
91     int path_n = project_path(attacker_ptr, path_g, project_length, attacker_ptr->y, attacker_ptr->x, ty, tx, PROJECT_STOP | PROJECT_KILL);
92     project_length = 0;
93     if (!path_n)
94         return TRUE;
95
96     ty = attacker_ptr->y;
97     tx = attacker_ptr->x;
98     bool tmp_mdeath = FALSE;
99     bool moved = FALSE;
100     for (int i = 0; i < path_n; i++) {
101         monster_type *m_ptr;
102
103         int ny = GRID_Y(path_g[i]);
104         int nx = GRID_X(path_g[i]);
105
106         if (is_cave_empty_bold(attacker_ptr, ny, nx) && player_can_enter(attacker_ptr, floor_ptr->grid_array[ny][nx].feat, 0)) {
107             ty = ny;
108             tx = nx;
109             continue;
110         }
111
112         if (!floor_ptr->grid_array[ny][nx].m_idx) {
113             if (tm_idx) {
114                 msg_print(_("失敗!", "Failed!"));
115             } else {
116                 msg_print(_("ここには入身では入れない。", "You can't move to that place."));
117             }
118
119             break;
120         }
121
122         if (!player_bold(attacker_ptr, ty, tx))
123             teleport_player_to(attacker_ptr, ty, tx, TELEPORT_NONMAGICAL);
124         update_monster(attacker_ptr, floor_ptr->grid_array[ny][nx].m_idx, TRUE);
125
126         m_ptr = &floor_ptr->m_list[floor_ptr->grid_array[ny][nx].m_idx];
127         if (tm_idx != floor_ptr->grid_array[ny][nx].m_idx) {
128 #ifdef JP
129             msg_format("%s%sが立ちふさがっている!", tm_idx ? "別の" : "", m_ptr->ml ? "モンスター" : "何か");
130 #else
131             msg_format("There is %s in the way!", m_ptr->ml ? (tm_idx ? "another monster" : "a monster") : "someone");
132 #endif
133         } else if (!player_bold(attacker_ptr, ty, tx)) {
134             GAME_TEXT m_name[MAX_NLEN];
135             monster_desc(attacker_ptr, m_name, m_ptr, 0);
136             msg_format(_("素早く%sの懐に入り込んだ!", "You quickly jump in and attack %s!"), m_name);
137         }
138
139         if (!player_bold(attacker_ptr, ty, tx))
140             teleport_player_to(attacker_ptr, ty, tx, TELEPORT_NONMAGICAL);
141         moved = TRUE;
142         tmp_mdeath = do_cmd_attack(attacker_ptr, ny, nx, HISSATSU_NYUSIN);
143
144         break;
145     }
146
147     if (!moved && !player_bold(attacker_ptr, ty, tx))
148         teleport_player_to(attacker_ptr, ty, tx, TELEPORT_NONMAGICAL);
149
150     if (mdeath)
151         *mdeath = tmp_mdeath;
152     return TRUE;
153 }
154
155 /*!
156  * @brief 盗賊と忍者における不意打ち
157  * @param attacker_ptr プレーヤーへの参照ポインタ
158  * @param pa_ptr 直接攻撃構造体への参照ポインタ
159  * @return なし
160  */
161 void process_surprise_attack(player_type *attacker_ptr, player_attack_type *pa_ptr)
162 {
163     monster_race *r_ptr = &r_info[pa_ptr->m_ptr->r_idx];
164     if (!has_melee_weapon(attacker_ptr, INVEN_RARM + pa_ptr->hand) || attacker_ptr->icky_wield[pa_ptr->hand])
165         return;
166
167     int tmp = attacker_ptr->lev * 6 + (attacker_ptr->skill_stl + 10) * 4;
168     if (attacker_ptr->monlite && (pa_ptr->mode != HISSATSU_NYUSIN))
169         tmp /= 3;
170     if (attacker_ptr->cursed & TRC_AGGRAVATE)
171         tmp /= 2;
172     if (r_ptr->level > (attacker_ptr->lev * attacker_ptr->lev / 20 + 10))
173         tmp /= 3;
174     if (MON_CSLEEP(pa_ptr->m_ptr) && pa_ptr->m_ptr->ml) {
175         /* Can't backstab creatures that we can't see, right? */
176         pa_ptr->backstab = TRUE;
177     } else if ((attacker_ptr->special_defense & NINJA_S_STEALTH) && (randint0(tmp) > (r_ptr->level + 20)) && pa_ptr->m_ptr->ml
178         && !(r_ptr->flagsr & RFR_RES_ALL)) {
179         pa_ptr->surprise_attack = TRUE;
180     } else if (MON_MONFEAR(pa_ptr->m_ptr) && pa_ptr->m_ptr->ml) {
181         pa_ptr->stab_fleeing = TRUE;
182     }
183 }
184
185 void print_surprise_attack(player_attack_type *pa_ptr)
186 {
187     if (pa_ptr->backstab)
188         msg_format(_("あなたは冷酷にも眠っている無力な%sを突き刺した!", "You cruelly stab the helpless, sleeping %s!"), pa_ptr->m_name);
189     else if (pa_ptr->surprise_attack)
190         msg_format(_("不意を突いて%sに強烈な一撃を喰らわせた!", "You make surprise attack, and hit %s with a powerful blow!"), pa_ptr->m_name);
191     else if (pa_ptr->stab_fleeing)
192         msg_format(_("逃げる%sを背中から突き刺した!", "You backstab the fleeing %s!"), pa_ptr->m_name);
193     else if (!pa_ptr->monk_attack)
194         msg_format(_("%sを攻撃した。", "You hit %s."), pa_ptr->m_name);
195 }
196
197 /*!
198  * @brief 盗賊と忍者における不意打ちのダメージ計算
199  * @param attacker_ptr プレーヤーへの参照ポインタ
200  * @param pa_ptr 直接攻撃構造体への参照ポインタ
201  * @return なし
202  */
203 void calc_surprise_attack_damage(player_type *attacker_ptr, player_attack_type *pa_ptr)
204 {
205     if (pa_ptr->backstab) {
206         pa_ptr->attack_damage *= (3 + (attacker_ptr->lev / 20));
207         return;
208     }
209
210     if (pa_ptr->surprise_attack) {
211         pa_ptr->attack_damage = pa_ptr->attack_damage * (5 + (attacker_ptr->lev * 2 / 25)) / 2;
212         return;
213     }
214
215     if (pa_ptr->stab_fleeing)
216         pa_ptr->attack_damage = (3 * pa_ptr->attack_damage) / 2;
217 }
218
219 void hayagake(player_type *creature_ptr)
220 {
221     if (creature_ptr->action == ACTION_HAYAGAKE) {
222         set_action(creature_ptr, ACTION_NONE);
223         creature_ptr->energy_use = 0;
224         return;
225     }
226
227     grid_type *g_ptr = &creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x];
228     feature_type *f_ptr = &f_info[g_ptr->feat];
229
230     if (!have_flag(f_ptr->flags, FF_PROJECT) || (!creature_ptr->levitation && have_flag(f_ptr->flags, FF_DEEP))) {
231         msg_print(_("ここでは素早く動けない。", "You cannot run in here."));
232     } else {
233         set_action(creature_ptr, ACTION_HAYAGAKE);
234     }
235
236     creature_ptr->energy_use = 0;
237 }