2 * @brief 剣術家のレイシャルパワー処理
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"
33 typedef struct samurai_slaying_type {
39 } samurai_slaying_type;
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)
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;
54 * @param attacker_ptr プレーヤーへの参照ポインタ
55 * @param samurai_slaying_ptr スレイ計算に必要なパラメータ群への参照ポインタ
58 static void hissatsu_burning_strike(player_type *attacker_ptr, samurai_slaying_type *samurai_slaying_ptr)
60 if (samurai_slaying_ptr->mode != HISSATSU_FIRE)
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);
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;
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;
80 } else if (samurai_slaying_ptr->mult < 35)
81 samurai_slaying_ptr->mult = 35;
86 if (samurai_slaying_ptr->r_ptr->flags3 & RF3_HURT_FIRE) {
87 if (samurai_slaying_ptr->mult < 50)
88 samurai_slaying_ptr->mult = 50;
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;
97 * @brief サーペンツタン (毒殺スレイ)
98 * @param attacker_ptr プレーヤーへの参照ポインタ
99 * @param samurai_slaying_ptr スレイ計算に必要なパラメータ群への参照ポインタ
102 static void hissatsu_serpent_tongue(player_type *attacker_ptr, samurai_slaying_type *samurai_slaying_ptr)
104 if (samurai_slaying_ptr->mode != HISSATSU_POISON)
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);
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;
124 * @brief 二重の極み^h^h^h^h^h 斬魔剣弐の太刀 (邪悪無生命スレイ)
125 * @param samurai_slaying_ptr スレイ計算に必要なパラメータ群への参照ポインタ
128 static void hissatsu_zanma_ken(samurai_slaying_type *samurai_slaying_ptr)
130 if (samurai_slaying_ptr->mode == HISSATSU_ZANMA)
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);
143 * @param attacker_ptr プレーヤーへの参照ポインタ
144 * @param samurai_slaying_ptr スレイ計算に必要なパラメータ群への参照ポインタ
147 static void hissatsu_rock_smash(player_type *attacker_ptr, samurai_slaying_type *samurai_slaying_ptr)
149 if (samurai_slaying_ptr->mode != HISSATSU_HAGAN)
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;
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;
164 * @brief 乱れ雪月花 (冷気スレイ)
165 * @param attacker_ptr プレーヤーへの参照ポインタ
166 * @param samurai_slaying_ptr スレイ計算に必要なパラメータ群への参照ポインタ
169 static void hissatsu_midare_setsugetsuka(player_type *attacker_ptr, samurai_slaying_type *samurai_slaying_ptr)
171 if (samurai_slaying_ptr->mode != HISSATSU_COLD)
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);
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;
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;
196 if (samurai_slaying_ptr->r_ptr->flags3 & RF3_HURT_COLD) {
197 if (samurai_slaying_ptr->mult < 50)
198 samurai_slaying_ptr->mult = 50;
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;
208 * @param attacker_ptr プレーヤーへの参照ポインタ
209 * @param samurai_slaying_ptr スレイ計算に必要なパラメータ群への参照ポインタ
212 static void hissatsu_lightning_eagle(player_type *attacker_ptr, samurai_slaying_type *samurai_slaying_ptr)
214 if (samurai_slaying_ptr->mode != HISSATSU_ELEC)
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);
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;
234 * @brief 赤流渦 (ペインバッカー)
235 * @param attacker_ptr プレーヤーへの参照ポインタ
236 * @param samurai_slaying_ptr スレイ計算に必要なパラメータ群への参照ポインタ
239 static void hissatsu_bloody_maelstroem(player_type *attacker_ptr, samurai_slaying_type *samurai_slaying_ptr)
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;
249 * @brief 慶雲鬼忍剣 (アンデッドスレイ)
250 * @param attacker_ptr プレーヤーへの参照ポインタ
251 * @param samurai_slaying_ptr スレイ計算に必要なパラメータ群への参照ポインタ
254 static void hissatsu_keiun_kininken(player_type *attacker_ptr, samurai_slaying_type *samurai_slaying_ptr)
256 if (samurai_slaying_ptr->mode != HISSATSU_UNDEAD)
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;
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);
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);
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倍)
284 MULTIPLY mult_hissatsu(player_type *attacker_ptr, MULTIPLY mult, BIT_FLAGS *flags, monster_type *m_ptr, combat_options mode)
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);
303 void concentration(player_type *creature_ptr)
305 int max_csp = MAX(creature_ptr->msp * 4, creature_ptr->lev * 5 + 5);
308 msg_print(_("今はペットを操ることに集中していないと。", "Your pets demand all of your attention."));
312 if (creature_ptr->special_defense & KATA_MASK) {
313 msg_print(_("今は構えに集中している。", "You're already concentrating on your stance."));
317 msg_print(_("精神を集中して気合いを溜めた。", "You concentrate to charge your power."));
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;
325 creature_ptr->redraw |= PR_MANA;
330 * @return 型を変化させたらTRUE、型の構え不能かキャンセルしたらFALSEを返す。
332 bool choose_kata(player_type *creature_ptr)
339 if (cmd_limit_confused(creature_ptr))
342 if (creature_ptr->stun) {
343 msg_print(_("意識がはっきりとしない。", "You are not clear headed"));
347 if (creature_ptr->afraid) {
348 msg_print(_("体が震えて構えられない!", "You are trembling with fear!"));
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);
362 prt(_(" どの型で構えますか?", " Choose Stance: "), 1, 14);
367 if (choice == ESCAPE) {
370 } else if ((choice == 'a') || (choice == 'A')) {
371 if (creature_ptr->action == ACTION_KATA) {
372 set_action(creature_ptr, ACTION_NONE);
374 msg_print(_("もともと構えていない。", "You are not in a special stance."));
377 } else if ((choice == 'b') || (choice == 'B')) {
380 } else if (((choice == 'c') || (choice == 'C')) && (creature_ptr->lev > 29)) {
383 } else if (((choice == 'd') || (choice == 'D')) && (creature_ptr->lev > 34)) {
386 } else if (((choice == 'e') || (choice == 'E')) && (creature_ptr->lev > 39)) {
392 set_action(creature_ptr, ACTION_KATA);
393 if (creature_ptr->special_defense & (KATA_IAI << new_kata)) {
394 msg_print(_("構え直した。", "You reassume a stance."));
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);
402 creature_ptr->redraw |= (PR_STATE | PR_STATUS);
408 * @brief 剣術家限定で、型等に応じて命中率を高める
409 * @param attacker_ptr プレーヤーへの参照ポインタ
410 * @param pa_ptr 直接攻撃構造体への参照ポインタ
413 int calc_attack_quality(player_type *attacker_ptr, player_attack_type *pa_ptr)
415 object_type *o_ptr = &attacker_ptr->inventory_list[INVEN_RARM + 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)
421 if (attacker_ptr->special_defense & KATA_KOUKIJIN)
424 if (attacker_ptr->sutemi)
425 chance = MAX(chance * 3 / 2, chance + 60);
427 int vir = virtue_number(attacker_ptr, V_VALOUR);
429 chance += (attacker_ptr->virtues[vir - 1] / 10);
436 * @param attacker_ptr プレーヤーへの参照ポインタ
437 * @param pa_ptr 直接攻撃構造体への参照ポインタ
440 void mineuchi(player_type *attacker_ptr, player_attack_type *pa_ptr)
442 if (pa_ptr->mode != HISSATSU_MINEUCHI)
445 pa_ptr->attack_damage = 0;
446 anger_monster(attacker_ptr, pa_ptr->m_ptr);
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);
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);
459 msg_format(_("%s はもうろうとした。", "%s is dazed."), pa_ptr->m_name);
461 (void)set_monster_stunned(attacker_ptr, pa_ptr->g_ptr->m_idx, monster_stunned_remaining(pa_ptr->m_ptr) + tmp);
466 * @param attacker_ptr プレーヤーへの参照ポインタ
467 * @param pa_ptr 直接攻撃構造体への参照ポインタ
470 void musou_counterattack(player_type *attacker_ptr, monap_type *monap_ptr)
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))
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);