OSDN Git Service

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