OSDN Git Service

[Refactor] #40014 Separated monster-util.c/h from monster1.h and monster2.c/h
[hengband/hengband.git] / src / player-attack / attack-chaos-effect.c
1 /*!
2  * @brief カオス武器で攻撃した際の追加効果処理
3  * @date 2020/05/23
4  * @author Hourier
5  * @details 不可分な処理であるゴールデンハンマーによるアイテム奪取処理も入っている
6  */
7
8 #include "player-attack/attack-chaos-effect.h"
9 #include "art-definition/art-weapon-types.h"
10 #include "floor/floor.h"
11 #include "monster/monster-status.h"
12 #include "monster/monster1.h"
13 #include "monster/monster2.h"
14 #include "inventory/inventory-object.h"
15 #include "object/object-flavor.h"
16 #include "object/object-mark-types.h"
17 #include "realm/realm-hex-numbers.h"
18 #include "spell-realm/spells-hex.h"
19 #include "spell-kind/spells-teleport.h"
20 #include "spell/spells3.h"
21
22 /*!
23  * @brief カオス武器か混乱の手でモンスターを混乱させる処理
24  * @param attacker_ptr プレーヤーへの参照ポインタ
25  * @param pa_ptr 直接攻撃構造体への参照ポインタ
26  * @return 死んだらTRUE、生きていたらFALSE
27  * @return なし
28  */
29 static void attack_confuse(player_type *attacker_ptr, player_attack_type *pa_ptr)
30 {
31     if (attacker_ptr->special_attack & ATTACK_CONFUSE) {
32         attacker_ptr->special_attack &= ~(ATTACK_CONFUSE);
33         msg_print(_("手の輝きがなくなった。", "Your hands stop glowing."));
34         attacker_ptr->redraw |= (PR_STATUS);
35     }
36
37     monster_race *r_ptr = &r_info[pa_ptr->m_ptr->r_idx];
38     if (r_ptr->flags3 & RF3_NO_CONF) {
39         if (is_original_ap_and_seen(attacker_ptr, pa_ptr->m_ptr))
40             r_ptr->r_flags3 |= RF3_NO_CONF;
41         msg_format(_("%^sには効果がなかった。", "%^s is unaffected."), pa_ptr->m_name);
42
43     } else if (randint0(100) < r_ptr->level) {
44         msg_format(_("%^sには効果がなかった。", "%^s is unaffected."), pa_ptr->m_name);
45     } else {
46         msg_format(_("%^sは混乱したようだ。", "%^s appears confused."), pa_ptr->m_name);
47         (void)set_monster_confused(attacker_ptr, pa_ptr->g_ptr->m_idx, monster_confused_remaining(pa_ptr->m_ptr) + 10 + randint0(attacker_ptr->lev) / 5);
48     }
49 }
50
51 /*!
52  * @breif カオス武器でのテレポート・アウェイを行うか判定する (抵抗されたら無効)
53  * @param attacker_ptr プレーヤーへの参照ポインタ
54  * @param pa_ptr 直接攻撃構造体への参照ポインタ
55  * @return 抵抗されたらTRUE、アウェイされるならFALSE
56  */
57 static bool judge_tereprt_resistance(player_type *attacker_ptr, player_attack_type *pa_ptr)
58 {
59     monster_race *r_ptr = &r_info[pa_ptr->m_ptr->r_idx];
60     if ((r_ptr->flagsr & RFR_RES_TELE) == 0)
61         return FALSE;
62
63     if (r_ptr->flags1 & RF1_UNIQUE) {
64         if (is_original_ap_and_seen(attacker_ptr, pa_ptr->m_ptr))
65             r_ptr->r_flagsr |= RFR_RES_TELE;
66
67         msg_format(_("%^sには効果がなかった。", "%^s is unaffected!"), pa_ptr->m_name);
68         return TRUE;
69     }
70
71     if (r_ptr->level > randint1(100)) {
72         if (is_original_ap_and_seen(attacker_ptr, pa_ptr->m_ptr))
73             r_ptr->r_flagsr |= RFR_RES_TELE;
74
75         msg_format(_("%^sは抵抗力を持っている!", "%^s resists!"), pa_ptr->m_name);
76         return TRUE;
77     }
78
79     return FALSE;
80 }
81
82 /*!
83  * @brief カオス武器でのテレポート・アウェイを実行する
84  * @param attacker_ptr プレーヤーへの参照ポインタ
85  * @param pa_ptr 直接攻撃構造体への参照ポインタ
86  * @param num 現在の攻撃回数 (テレポートしてしまったら追加攻撃できないのでその補正)
87  * @return なし
88  */
89 static void attack_teleport_away(player_type *attacker_ptr, player_attack_type *pa_ptr, int *num)
90 {
91     if (judge_tereprt_resistance(attacker_ptr, pa_ptr))
92         return;
93
94     msg_format(_("%^sは消えた!", "%^s disappears!"), pa_ptr->m_name);
95     teleport_away(attacker_ptr, pa_ptr->g_ptr->m_idx, 50, TELEPORT_PASSIVE);
96     *num = pa_ptr->num_blow + 1;
97     *(pa_ptr->mdeath) = TRUE;
98 }
99
100 /*!
101  * @brief カオス武器でのテレポート・アウェイを実行する
102  * @param attacker_ptr プレーヤーへの参照ポインタ
103  * @param pa_ptr 直接攻撃構造体への参照ポインタ
104  * @param y モンスターのY座標
105  * @param x モンスターのX座標
106  * @return なし
107  */
108 static void attack_polymorph(player_type *attacker_ptr, player_attack_type *pa_ptr, POSITION y, POSITION x)
109 {
110     monster_race *r_ptr = &r_info[pa_ptr->m_ptr->r_idx];
111     if (((r_ptr->flags1 & (RF1_UNIQUE | RF1_QUESTOR)) != 0) || ((r_ptr->flagsr & RFR_EFF_RES_CHAO_MASK) != 0))
112         return;
113
114     if (polymorph_monster(attacker_ptr, y, x)) {
115         msg_format(_("%^sは変化した!", "%^s changes!"), pa_ptr->m_name);
116         *(pa_ptr->fear) = FALSE;
117         pa_ptr->weak = FALSE;
118     } else
119         msg_format(_("%^sには効果がなかった。", "%^s is unaffected."), pa_ptr->m_name);
120
121     pa_ptr->m_ptr = &attacker_ptr->current_floor_ptr->m_list[pa_ptr->g_ptr->m_idx];
122     monster_desc(attacker_ptr, pa_ptr->m_name, pa_ptr->m_ptr, 0);
123 }
124
125 /*!
126  * @brief ゴールデンハンマーによるアイテム奪取処理
127  * @param attacker_ptr プレーヤーへの参照ポインタ
128  * @param pa_ptr 直接攻撃構造体への参照ポインタ
129  * @return なし
130  */
131 static void attack_golden_hammer(player_type *attacker_ptr, player_attack_type *pa_ptr)
132 {
133     floor_type *floor_ptr = attacker_ptr->current_floor_ptr;
134     monster_type *target_ptr = &floor_ptr->m_list[pa_ptr->g_ptr->m_idx];
135     if (target_ptr->hold_o_idx == 0)
136         return;
137
138     object_type *q_ptr = &floor_ptr->o_list[target_ptr->hold_o_idx];
139     GAME_TEXT o_name[MAX_NLEN];
140     object_desc(attacker_ptr, o_name, q_ptr, OD_NAME_ONLY);
141     q_ptr->held_m_idx = 0;
142     q_ptr->marked = OM_TOUCHED;
143     target_ptr->hold_o_idx = q_ptr->next_o_idx;
144     q_ptr->next_o_idx = 0;
145     msg_format(_("%sを奪った。", "You snatched %s."), o_name);
146     store_item_to_inventory(attacker_ptr, q_ptr);
147 }
148
149 /*!
150  * @brief カオス武器その他でモンスターのステータスを変化させる
151  * @param attacker_ptr プレーヤーへの参照ポインタ
152  * @param pa_ptr 直接攻撃構造体への参照ポインタ
153  * @param y モンスターのY座標
154  * @param x モンスターのX座標
155  * @param num 現在の攻撃回数
156  * @return なし
157  */
158 void change_monster_stat(player_type *attacker_ptr, player_attack_type *pa_ptr, const POSITION y, const POSITION x, int *num)
159 {
160     monster_race *r_ptr = &r_info[pa_ptr->m_ptr->r_idx];
161     object_type *o_ptr = &attacker_ptr->inventory_list[INVEN_RARM + pa_ptr->hand];
162     if ((attacker_ptr->special_attack & ATTACK_CONFUSE) || (pa_ptr->chaos_effect == CE_CONFUSION) || (pa_ptr->mode == HISSATSU_CONF)
163         || hex_spelling(attacker_ptr, HEX_CONFUSION))
164         attack_confuse(attacker_ptr, pa_ptr);
165     else if (pa_ptr->chaos_effect == CE_TELE_AWAY)
166         attack_teleport_away(attacker_ptr, pa_ptr, num);
167     else if ((pa_ptr->chaos_effect == CE_POLYMORPH) && (randint1(90) > r_ptr->level))
168         attack_polymorph(attacker_ptr, pa_ptr, y, x);
169     else if (o_ptr->name1 == ART_G_HAMMER)
170         attack_golden_hammer(attacker_ptr, pa_ptr);
171 }