OSDN Git Service

Reworded English description for sniper's exploding arrow ability.
[hengband/hengband.git] / src / mind / mind-samurai.c
1 /*!
2  * @brief 剣術家のレイシャルパワー処理
3  * @date 2020/05/16
4  * @author Hourier
5  */
6
7 #include "mind/mind-samurai.h"
8 #include "action/action-limited.h"
9 #include "cmd-action/cmd-attack.h"
10 #include "cmd-action/cmd-pet.h"
11 #include "core/player-redraw-types.h"
12 #include "core/player-update-types.h"
13 #include "inventory/inventory-slot-types.h"
14 #include "io/input-key-acceptor.h"
15 #include "mind/stances-table.h"
16 #include "monster-race/monster-race-hook.h"
17 #include "monster-race/monster-race.h"
18 #include "monster-race/race-flags-resistance.h"
19 #include "monster-race/race-flags3.h"
20 #include "monster/monster-describer.h"
21 #include "monster/monster-info.h"
22 #include "monster/monster-status-setter.h"
23 #include "monster/monster-status.h"
24 #include "object-enchant/tr-types.h"
25 #include "player/attack-defense-types.h"
26 #include "player-info/avatar.h"
27 #include "status/action-setter.h"
28 #include "term/screen-processor.h"
29 #include "util/bit-flags-calculator.h"
30 #include "util/int-char-converter.h"
31 #include "view/display-messages.h"
32
33 typedef struct samurai_slaying_type {
34     MULTIPLY mult;
35     BIT_FLAGS *flags;
36     monster_type *m_ptr;
37     combat_options mode;
38     monster_race *r_ptr;
39 } samurai_slaying_type;
40
41 static samurai_slaying_type *initialize_samurai_slaying_type(
42     samurai_slaying_type *samurai_slaying_ptr, MULTIPLY mult, BIT_FLAGS *flags, monster_type *m_ptr, combat_options mode, monster_race *r_ptr)
43 {
44     samurai_slaying_ptr->mult = mult;
45     samurai_slaying_ptr->flags = flags;
46     samurai_slaying_ptr->m_ptr = m_ptr;
47     samurai_slaying_ptr->mode = mode;
48     samurai_slaying_ptr->r_ptr = r_ptr;
49     return samurai_slaying_ptr;
50 }
51
52 /*!
53  * @nrief 焔霊 (焼棄スレイ)
54  * @param attacker_ptr プレーヤーへの参照ポインタ
55  * @param samurai_slaying_ptr スレイ計算に必要なパラメータ群への参照ポインタ
56  * @return なし
57  */
58 static void hissatsu_burning_strike(player_type *attacker_ptr, samurai_slaying_type *samurai_slaying_ptr)
59 {
60     if (samurai_slaying_ptr->mode != HISSATSU_FIRE)
61         return;
62
63     /* Notice immunity */
64     if (samurai_slaying_ptr->r_ptr->flagsr & RFR_EFF_IM_FIRE_MASK) {
65         if (is_original_ap_and_seen(attacker_ptr, samurai_slaying_ptr->m_ptr))
66             samurai_slaying_ptr->r_ptr->r_flagsr |= (samurai_slaying_ptr->r_ptr->flagsr & RFR_EFF_IM_FIRE_MASK);
67
68         return;
69     }
70
71     /* Otherwise, take the damage */
72     if (has_flag(samurai_slaying_ptr->flags, TR_BRAND_FIRE)) {
73         if (samurai_slaying_ptr->r_ptr->flags3 & RF3_HURT_FIRE) {
74             if (samurai_slaying_ptr->mult < 70)
75                 samurai_slaying_ptr->mult = 70;
76
77             if (is_original_ap_and_seen(attacker_ptr, samurai_slaying_ptr->m_ptr))
78                 samurai_slaying_ptr->r_ptr->r_flags3 |= RF3_HURT_FIRE;
79
80         } else if (samurai_slaying_ptr->mult < 35)
81             samurai_slaying_ptr->mult = 35;
82
83         return;
84     }
85
86     if (samurai_slaying_ptr->r_ptr->flags3 & RF3_HURT_FIRE) {
87         if (samurai_slaying_ptr->mult < 50)
88             samurai_slaying_ptr->mult = 50;
89
90         if (is_original_ap_and_seen(attacker_ptr, samurai_slaying_ptr->m_ptr))
91             samurai_slaying_ptr->r_ptr->r_flags3 |= RF3_HURT_FIRE;
92     } else if (samurai_slaying_ptr->mult < 25)
93         samurai_slaying_ptr->mult = 25;
94 }
95
96 /*!
97  * @brief サーペンツタン (毒殺スレイ)
98  * @param attacker_ptr プレーヤーへの参照ポインタ
99  * @param samurai_slaying_ptr スレイ計算に必要なパラメータ群への参照ポインタ
100  * @return なし
101  */
102 static void hissatsu_serpent_tongue(player_type *attacker_ptr, samurai_slaying_type *samurai_slaying_ptr)
103 {
104     if (samurai_slaying_ptr->mode != HISSATSU_POISON)
105         return;
106
107     /* Notice immunity */
108     if (samurai_slaying_ptr->r_ptr->flagsr & RFR_EFF_IM_POIS_MASK) {
109         if (is_original_ap_and_seen(attacker_ptr, samurai_slaying_ptr->m_ptr))
110             samurai_slaying_ptr->r_ptr->r_flagsr |= (samurai_slaying_ptr->r_ptr->flagsr & RFR_EFF_IM_POIS_MASK);
111
112         return;
113     }
114
115     /* Otherwise, take the damage */
116     if (has_flag(samurai_slaying_ptr->flags, TR_BRAND_POIS)) {
117         if (samurai_slaying_ptr->mult < 35)
118             samurai_slaying_ptr->mult = 35;
119     } else if (samurai_slaying_ptr->mult < 25)
120         samurai_slaying_ptr->mult = 25;
121 }
122
123 /*!
124  * @brief 二重の極み^h^h^h^h^h 斬魔剣弐の太刀 (邪悪無生命スレイ)
125  * @param samurai_slaying_ptr スレイ計算に必要なパラメータ群への参照ポインタ
126  * @return なし
127  */
128 static void hissatsu_zanma_ken(samurai_slaying_type *samurai_slaying_ptr)
129 {
130     if (samurai_slaying_ptr->mode == HISSATSU_ZANMA)
131         return;
132
133     if (!monster_living(samurai_slaying_ptr->m_ptr->r_idx) && (samurai_slaying_ptr->r_ptr->flags3 & RF3_EVIL)) {
134         if (samurai_slaying_ptr->mult < 15)
135             samurai_slaying_ptr->mult = 25;
136         else if (samurai_slaying_ptr->mult < 50)
137             samurai_slaying_ptr->mult = MIN(50, samurai_slaying_ptr->mult + 20);
138     }
139 }
140
141 /*!
142  * @brief 破岩斬 (岩石スレイ)
143  * @param attacker_ptr プレーヤーへの参照ポインタ
144  * @param samurai_slaying_ptr スレイ計算に必要なパラメータ群への参照ポインタ
145  * @return なし
146  */
147 static void hissatsu_rock_smash(player_type *attacker_ptr, samurai_slaying_type *samurai_slaying_ptr)
148 {
149     if (samurai_slaying_ptr->mode != HISSATSU_HAGAN)
150         return;
151
152     if (samurai_slaying_ptr->r_ptr->flags3 & RF3_HURT_ROCK) {
153         if (is_original_ap_and_seen(attacker_ptr, samurai_slaying_ptr->m_ptr))
154             samurai_slaying_ptr->r_ptr->r_flags3 |= RF3_HURT_ROCK;
155
156         if (samurai_slaying_ptr->mult == 10)
157             samurai_slaying_ptr->mult = 40;
158         else if (samurai_slaying_ptr->mult < 60)
159             samurai_slaying_ptr->mult = 60;
160     }
161 }
162
163 /*!
164  * @brief 乱れ雪月花 (冷気スレイ)
165  * @param attacker_ptr プレーヤーへの参照ポインタ
166  * @param samurai_slaying_ptr スレイ計算に必要なパラメータ群への参照ポインタ
167  * @return なし
168  */
169 static void hissatsu_midare_setsugetsuka(player_type *attacker_ptr, samurai_slaying_type *samurai_slaying_ptr)
170 {
171     if (samurai_slaying_ptr->mode != HISSATSU_COLD)
172         return;
173
174     /* Notice immunity */
175     if (samurai_slaying_ptr->r_ptr->flagsr & RFR_EFF_IM_COLD_MASK) {
176         if (is_original_ap_and_seen(attacker_ptr, samurai_slaying_ptr->m_ptr))
177             samurai_slaying_ptr->r_ptr->r_flagsr |= (samurai_slaying_ptr->r_ptr->flagsr & RFR_EFF_IM_COLD_MASK);
178
179         return;
180     }
181
182     /* Otherwise, take the damage */
183     if (has_flag(samurai_slaying_ptr->flags, TR_BRAND_COLD)) {
184         if (samurai_slaying_ptr->r_ptr->flags3 & RF3_HURT_COLD) {
185             if (samurai_slaying_ptr->mult < 70)
186                 samurai_slaying_ptr->mult = 70;
187
188             if (is_original_ap_and_seen(attacker_ptr, samurai_slaying_ptr->m_ptr))
189                 samurai_slaying_ptr->r_ptr->r_flags3 |= RF3_HURT_COLD;
190         } else if (samurai_slaying_ptr->mult < 35)
191             samurai_slaying_ptr->mult = 35;
192
193         return;
194     }
195
196     if (samurai_slaying_ptr->r_ptr->flags3 & RF3_HURT_COLD) {
197         if (samurai_slaying_ptr->mult < 50)
198             samurai_slaying_ptr->mult = 50;
199
200         if (is_original_ap_and_seen(attacker_ptr, samurai_slaying_ptr->m_ptr))
201             samurai_slaying_ptr->r_ptr->r_flags3 |= RF3_HURT_COLD;
202     } else if (samurai_slaying_ptr->mult < 25)
203         samurai_slaying_ptr->mult = 25;
204 }
205
206 /*!
207  * @brief 雷撃鷲爪斬
208  * @param attacker_ptr プレーヤーへの参照ポインタ
209  * @param samurai_slaying_ptr スレイ計算に必要なパラメータ群への参照ポインタ
210  * @return なし
211  */
212 static void hissatsu_lightning_eagle(player_type *attacker_ptr, samurai_slaying_type *samurai_slaying_ptr)
213 {
214     if (samurai_slaying_ptr->mode != HISSATSU_ELEC)
215         return;
216
217     /* Notice immunity */
218     if (samurai_slaying_ptr->r_ptr->flagsr & RFR_EFF_IM_ELEC_MASK) {
219         if (is_original_ap_and_seen(attacker_ptr, samurai_slaying_ptr->m_ptr))
220             samurai_slaying_ptr->r_ptr->r_flagsr |= (samurai_slaying_ptr->r_ptr->flagsr & RFR_EFF_IM_ELEC_MASK);
221
222         return;
223     }
224
225     /* Otherwise, take the damage */
226     if (has_flag(samurai_slaying_ptr->flags, TR_BRAND_ELEC)) {
227         if (samurai_slaying_ptr->mult < 70)
228             samurai_slaying_ptr->mult = 70;
229     } else if (samurai_slaying_ptr->mult < 50)
230         samurai_slaying_ptr->mult = 50;
231 }
232
233 /*!
234  * @brief 赤流渦 (ペインバッカー)
235  * @param attacker_ptr プレーヤーへの参照ポインタ
236  * @param samurai_slaying_ptr スレイ計算に必要なパラメータ群への参照ポインタ
237  * @return なし
238  */
239 static void hissatsu_bloody_maelstroem(player_type *attacker_ptr, samurai_slaying_type *samurai_slaying_ptr)
240 {
241     if ((samurai_slaying_ptr->mode == HISSATSU_SEKIRYUKA) && attacker_ptr->cut && monster_living(samurai_slaying_ptr->m_ptr->r_idx)) {
242         MULTIPLY tmp = MIN(100, MAX(10, attacker_ptr->cut / 10));
243         if (samurai_slaying_ptr->mult < tmp)
244             samurai_slaying_ptr->mult = tmp;
245     }
246 }
247
248 /*!
249  * @brief 慶雲鬼忍剣 (アンデッドスレイ)
250  * @param attacker_ptr プレーヤーへの参照ポインタ
251  * @param samurai_slaying_ptr スレイ計算に必要なパラメータ群への参照ポインタ
252  * @return なし
253  */
254 static void hissatsu_keiun_kininken(player_type *attacker_ptr, samurai_slaying_type *samurai_slaying_ptr)
255 {
256     if (samurai_slaying_ptr->mode != HISSATSU_UNDEAD)
257         return;
258
259     if (samurai_slaying_ptr->r_ptr->flags3 & RF3_UNDEAD)
260         if (is_original_ap_and_seen(attacker_ptr, samurai_slaying_ptr->m_ptr)) {
261             samurai_slaying_ptr->r_ptr->r_flags3 |= RF3_UNDEAD;
262
263             if (samurai_slaying_ptr->mult == 10)
264                 samurai_slaying_ptr->mult = 70;
265             else if (samurai_slaying_ptr->mult < 140)
266                 samurai_slaying_ptr->mult = MIN(140, samurai_slaying_ptr->mult + 60);
267         }
268
269     if (samurai_slaying_ptr->mult == 10)
270         samurai_slaying_ptr->mult = 40;
271     else if (samurai_slaying_ptr->mult < 60)
272         samurai_slaying_ptr->mult = MIN(60, samurai_slaying_ptr->mult + 30);
273 }
274
275 /*!
276  * @brief 剣術のスレイ倍率計算を行う /
277  * Calcurate magnification of hissatsu technics
278  * @param mult 剣術のスレイ効果以前に算出している多要素の倍率(/10倍)
279  * @param flags 剣術に使用する武器のスレイフラグ配列
280  * @param m_ptr 目標となるモンスターの構造体参照ポインタ
281  * @param mode 剣術のスレイ型ID
282  * @return スレイの倍率(/10倍)
283  */
284 MULTIPLY mult_hissatsu(player_type *attacker_ptr, MULTIPLY mult, BIT_FLAGS *flags, monster_type *m_ptr, combat_options mode)
285 {
286     monster_race *r_ptr = &r_info[m_ptr->r_idx];
287     samurai_slaying_type tmp_slaying;
288     samurai_slaying_type *samurai_slaying_ptr = initialize_samurai_slaying_type(&tmp_slaying, mult, flags, m_ptr, mode, r_ptr);
289     hissatsu_burning_strike(attacker_ptr, samurai_slaying_ptr);
290     hissatsu_serpent_tongue(attacker_ptr, samurai_slaying_ptr);
291     hissatsu_zanma_ken(samurai_slaying_ptr);
292     hissatsu_rock_smash(attacker_ptr, samurai_slaying_ptr);
293     hissatsu_midare_setsugetsuka(attacker_ptr, samurai_slaying_ptr);
294     hissatsu_lightning_eagle(attacker_ptr, samurai_slaying_ptr);
295     hissatsu_bloody_maelstroem(attacker_ptr, samurai_slaying_ptr);
296     hissatsu_keiun_kininken(attacker_ptr, samurai_slaying_ptr);
297     if (mult > 150)
298         mult = 150;
299
300     return mult;
301 }
302
303 void concentration(player_type *creature_ptr)
304 {
305     int max_csp = MAX(creature_ptr->msp * 4, creature_ptr->lev * 5 + 5);
306
307     if (total_friends) {
308         msg_print(_("今はペットを操ることに集中していないと。", "Your pets demand all of your attention."));
309         return;
310     }
311
312     if (creature_ptr->special_defense & KATA_MASK) {
313         msg_print(_("今は構えに集中している。", "You're already concentrating on your stance."));
314         return;
315     }
316
317     msg_print(_("精神を集中して気合いを溜めた。", "You concentrate to charge your power."));
318
319     creature_ptr->csp += creature_ptr->msp / 2;
320     if (creature_ptr->csp >= max_csp) {
321         creature_ptr->csp = max_csp;
322         creature_ptr->csp_frac = 0;
323     }
324
325     creature_ptr->redraw |= PR_MANA;
326 }
327
328 /*!
329  * @brief 剣術家の型設定処理
330  * @return 型を変化させたらTRUE、型の構え不能かキャンセルしたらFALSEを返す。
331  */
332 bool choose_kata(player_type *creature_ptr)
333 {
334     char choice;
335     int new_kata = 0;
336     int i;
337     char buf[80];
338
339     if (cmd_limit_confused(creature_ptr))
340         return FALSE;
341
342     if (creature_ptr->stun) {
343         msg_print(_("意識がはっきりとしない。", "You are not clear headed"));
344         return FALSE;
345     }
346
347     if (creature_ptr->afraid) {
348         msg_print(_("体が震えて構えられない!", "You are trembling with fear!"));
349         return FALSE;
350     }
351
352     screen_save();
353     prt(_(" a) 型を崩す", " a) No Form"), 2, 20);
354     for (i = 0; i < MAX_KATA; i++) {
355         if (creature_ptr->lev >= samurai_stances[i].min_level) {
356             sprintf(buf, _(" %c) %sの型    %s", " %c) Stance of %-12s  %s"), I2A(i + 1), samurai_stances[i].desc, samurai_stances[i].info);
357             prt(buf, 3 + i, 20);
358         }
359     }
360
361     prt("", 1, 0);
362     prt(_("        どの型で構えますか?", "        Choose Stance: "), 1, 14);
363
364     while (TRUE) {
365         choice = inkey();
366
367         if (choice == ESCAPE) {
368             screen_load();
369             return FALSE;
370         } else if ((choice == 'a') || (choice == 'A')) {
371             if (creature_ptr->action == ACTION_KATA) {
372                 set_action(creature_ptr, ACTION_NONE);
373             } else
374                 msg_print(_("もともと構えていない。", "You are not in a special stance."));
375             screen_load();
376             return TRUE;
377         } else if ((choice == 'b') || (choice == 'B')) {
378             new_kata = 0;
379             break;
380         } else if (((choice == 'c') || (choice == 'C')) && (creature_ptr->lev > 29)) {
381             new_kata = 1;
382             break;
383         } else if (((choice == 'd') || (choice == 'D')) && (creature_ptr->lev > 34)) {
384             new_kata = 2;
385             break;
386         } else if (((choice == 'e') || (choice == 'E')) && (creature_ptr->lev > 39)) {
387             new_kata = 3;
388             break;
389         }
390     }
391
392     set_action(creature_ptr, ACTION_KATA);
393     if (creature_ptr->special_defense & (KATA_IAI << new_kata)) {
394         msg_print(_("構え直した。", "You reassume a stance."));
395     } else {
396         creature_ptr->special_defense &= ~(KATA_MASK);
397         creature_ptr->update |= (PU_BONUS | PU_MONSTERS);
398         msg_format(_("%sの型で構えた。", "You assume the %s stance."), samurai_stances[new_kata].desc);
399         creature_ptr->special_defense |= (KATA_IAI << new_kata);
400     }
401
402     creature_ptr->redraw |= (PR_STATE | PR_STATUS);
403     screen_load();
404     return TRUE;
405 }
406
407 /*!
408  * @brief 剣術家限定で、型等に応じて命中率を高める
409  * @param attacker_ptr プレーヤーへの参照ポインタ
410  * @param pa_ptr 直接攻撃構造体への参照ポインタ
411  * @return 上昇後の命中率
412  */
413 int calc_attack_quality(player_type *attacker_ptr, player_attack_type *pa_ptr)
414 {
415     object_type *o_ptr = &attacker_ptr->inventory_list[INVEN_MAIN_HAND + pa_ptr->hand];
416     int bonus = attacker_ptr->to_h[pa_ptr->hand] + o_ptr->to_h;
417     int chance = (attacker_ptr->skill_thn + (bonus * BTH_PLUS_ADJ));
418     if (pa_ptr->mode == HISSATSU_IAI)
419         chance += 60;
420
421     if (attacker_ptr->special_defense & KATA_KOUKIJIN)
422         chance += 150;
423
424     if (attacker_ptr->sutemi)
425         chance = MAX(chance * 3 / 2, chance + 60);
426
427     int vir = virtue_number(attacker_ptr, V_VALOUR);
428     if (vir != 0)
429         chance += (attacker_ptr->virtues[vir - 1] / 10);
430
431     return chance;
432 }
433
434 /*!
435  * @brief 峰打ちの効果処理
436  * @param attacker_ptr プレーヤーへの参照ポインタ
437  * @param pa_ptr 直接攻撃構造体への参照ポインタ
438  * @return なし
439  */
440 void mineuchi(player_type *attacker_ptr, player_attack_type *pa_ptr)
441 {
442     if (pa_ptr->mode != HISSATSU_MINEUCHI)
443         return;
444
445     pa_ptr->attack_damage = 0;
446     anger_monster(attacker_ptr, pa_ptr->m_ptr);
447
448     monster_race *r_ptr = &r_info[pa_ptr->m_ptr->r_idx];
449     if ((r_ptr->flags3 & (RF3_NO_STUN))) {
450         msg_format(_("%s には効果がなかった。", "%s is not effected."), pa_ptr->m_name);
451         return;
452     }
453
454     int tmp = (10 + randint1(15) + attacker_ptr->lev / 5);
455     if (monster_stunned_remaining(pa_ptr->m_ptr)) {
456         msg_format(_("%sはひどくもうろうとした。", "%s is more dazed."), pa_ptr->m_name);
457         tmp /= 2;
458     } else
459         msg_format(_("%s はもうろうとした。", "%s is dazed."), pa_ptr->m_name);
460
461     (void)set_monster_stunned(attacker_ptr, pa_ptr->g_ptr->m_idx, monster_stunned_remaining(pa_ptr->m_ptr) + tmp);
462 }
463
464 /*!
465  * @brief 無想による反撃処理
466  * @param attacker_ptr プレーヤーへの参照ポインタ
467  * @param pa_ptr 直接攻撃構造体への参照ポインタ
468  * @return なし
469  */
470 void musou_counterattack(player_type *attacker_ptr, monap_type *monap_ptr)
471 {
472     if ((!attacker_ptr->counter && ((attacker_ptr->special_defense & KATA_MUSOU) == 0)) || !monap_ptr->alive || attacker_ptr->is_dead || !monap_ptr->m_ptr->ml
473         || (attacker_ptr->csp <= 7))
474         return;
475
476     char m_target_name[MAX_NLEN];
477     monster_desc(attacker_ptr, m_target_name, monap_ptr->m_ptr, 0);
478     attacker_ptr->csp -= 7;
479     msg_format(_("%^sに反撃した!", "You counterattacked %s!"), m_target_name);
480     do_cmd_attack(attacker_ptr, monap_ptr->m_ptr->fy, monap_ptr->m_ptr->fx, HISSATSU_COUNTER);
481     monap_ptr->fear = FALSE;
482     attacker_ptr->redraw |= (PR_MANA);
483 }