OSDN Git Service

[Refactor] #39970 Separated multiply_*_curse() from occur_curse_effects()
[hengband/hengband.git] / src / inventory / inventory-curse.c
1 #include "angband.h"
2 #include "inventory/inventory-curse.h"
3 #include "object-flavor.h"
4 #include "spells-summon.h"
5 #include "player-damage.h"
6 #include "player-move.h"
7 #include "spell/spells2.h"
8 #include "spell/spells3.h"
9 #include "files.h"
10 #include "object-curse.h"
11 #include "artifact.h"
12 #include "object-hook.h"
13 #include "player-effects.h"
14 #include "object/object-kind.h"
15
16 static bool is_specific_curse(BIT_FLAGS flag)
17 {
18     return (flag == TRC_ADD_L_CURSE) ||
19         (flag == TRC_ADD_H_CURSE) ||
20         (flag == TRC_DRAIN_HP) ||
21         (flag == TRC_DRAIN_MANA) ||
22         (flag == TRC_CALL_ANIMAL) ||
23         (flag == TRC_CALL_DEMON) ||
24         (flag == TRC_CALL_DRAGON) ||
25         (flag == TRC_CALL_UNDEAD) ||
26         (flag == TRC_COWARDICE) ||
27         (flag == TRC_LOW_MELEE) ||
28         (flag == TRC_LOW_AC) ||
29         (flag == TRC_LOW_MAGIC) ||
30         (flag == TRC_FAST_DIGEST) ||
31         (flag == TRC_SLOW_REGEN);
32 }
33
34 static void choise_cursed_item(BIT_FLAGS flag, object_type *o_ptr, int *choices, int *number, int item_num)
35 {
36     if (!is_specific_curse(flag))
37         return;
38
39     u32b cf = 0L;
40     BIT_FLAGS flgs[TR_FLAG_SIZE];
41     object_flags(o_ptr, flgs);
42     switch (flag) {
43     case TRC_ADD_L_CURSE:
44         cf = TR_ADD_L_CURSE;
45         break;
46     case TRC_ADD_H_CURSE:
47         cf = TR_ADD_H_CURSE;
48         break;
49     case TRC_DRAIN_HP:
50         cf = TR_DRAIN_HP;
51         break;
52     case TRC_DRAIN_MANA:
53         cf = TR_DRAIN_MANA;
54         break;
55     case TRC_CALL_ANIMAL:
56         cf = TR_CALL_ANIMAL;
57         break;
58     case TRC_CALL_DEMON:
59         cf = TR_CALL_DEMON;
60         break;
61     case TRC_CALL_DRAGON:
62         cf = TR_CALL_DRAGON;
63         break;
64     case TRC_CALL_UNDEAD:
65         cf = TR_CALL_UNDEAD;
66         break;
67     case TRC_COWARDICE:
68         cf = TR_COWARDICE;
69         break;
70     case TRC_LOW_MELEE:
71         cf = TR_LOW_MELEE;
72         break;
73     case TRC_LOW_AC:
74         cf = TR_LOW_AC;
75         break;
76     case TRC_LOW_MAGIC:
77         cf = TR_LOW_MAGIC;
78         break;
79     case TRC_FAST_DIGEST:
80         cf = TR_FAST_DIGEST;
81         break;
82     case TRC_SLOW_REGEN:
83         cf = TR_SLOW_REGEN;
84         break;
85     default:
86         break;
87     }
88
89     if (!have_flag(flgs, cf))
90         return;
91
92     choices[*number] = item_num;
93     (*number)++;
94 }
95
96 /*!
97  * @brief 現在呪いを保持している装備品を一つランダムに探し出す / Choose one of items that have cursed flag
98  * @param flag 探し出したい呪いフラグ配列
99  * @return 該当の呪いが一つでもあった場合にランダムに選ばれた装備品のオブジェクト構造体参照ポインタを返す。\n
100  * 呪いがない場合NULLを返す。
101  */
102 object_type *choose_cursed_obj_name(player_type* player_ptr, BIT_FLAGS flag)
103 {
104     int choices[INVEN_TOTAL - INVEN_RARM];
105     int number = 0;
106     if (!(player_ptr->cursed & flag))
107         return NULL;
108
109     for (int i = INVEN_RARM; i < INVEN_TOTAL; i++) {
110         object_type* o_ptr = &player_ptr->inventory_list[i];
111         if (o_ptr->curse_flags & flag) {
112             choices[number] = i;
113             number++;
114             continue;
115         } 
116         
117         choise_cursed_item(flag, o_ptr, choices, &number, i);
118     }
119
120     return &player_ptr->inventory_list[choices[randint0(number)]];
121 }
122
123 /*!
124  * @brief 呪われている、トランプエゴ等による装備品由来のテレポートを実行する
125  * @param creature_ptr プレーヤーへの参照ポインタ
126  * @return なし
127  */
128 static void curse_teleport(player_type* creature_ptr)
129 {
130     if (((creature_ptr->cursed & TRC_TELEPORT_SELF) == 0) || !one_in_(200))
131         return;
132
133     GAME_TEXT o_name[MAX_NLEN];
134     object_type* o_ptr;
135     int i_keep = 0, count = 0;
136     for (int i = INVEN_RARM; i < INVEN_TOTAL; i++) {
137         BIT_FLAGS flgs[TR_FLAG_SIZE];
138         o_ptr = &creature_ptr->inventory_list[i];
139         if (!o_ptr->k_idx)
140             continue;
141
142         object_flags(o_ptr, flgs);
143
144         if (!have_flag(flgs, TR_TELEPORT))
145             continue;
146
147         if (o_ptr->inscription && my_strchr(quark_str(o_ptr->inscription), '.'))
148             continue;
149
150         count++;
151         if (one_in_(count))
152             i_keep = i;
153     }
154
155     o_ptr = &creature_ptr->inventory_list[i_keep];
156     object_desc(creature_ptr, o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
157     msg_format(_("%sがテレポートの能力を発動させようとしている。", "Your %s is activating teleportation."), o_name);
158     if (get_check_strict(_("テレポートしますか?", "Teleport? "), CHECK_OKAY_CANCEL)) {
159         disturb(creature_ptr, FALSE, TRUE);
160         teleport_player(creature_ptr, 50, TELEPORT_SPONTANEOUS);
161     } else {
162         msg_format(_("%sに{.}(ピリオド)と銘を刻むと発動を抑制できます。",
163                        "You can inscribe {.} on your %s to disable random teleportation. "), o_name);
164         disturb(creature_ptr, TRUE, TRUE);
165     }
166 }
167
168 /*!
169  * @details 元々呪い効果の発揮ルーチン中にいたので、整合性保持のためここに置いておく
170  */
171 static void occur_chainsword_effect(player_type* creature_ptr)
172 {
173     if (((creature_ptr->cursed & TRC_CHAINSWORD) == 0) || !one_in_(CHAINSWORD_NOISE))
174         return;
175
176     char noise[1024];
177     if (!get_rnd_line(_("chainswd_j.txt", "chainswd.txt"), 0, noise))
178         msg_print(noise);
179     disturb(creature_ptr, FALSE, FALSE);
180 }
181
182 static void curse_drain_exp(player_type *creature_ptr)
183 {
184     if ((creature_ptr->prace == RACE_ANDROID) || ((creature_ptr->cursed & TRC_DRAIN_EXP) == 0) || !one_in_(4))
185         return;
186
187     creature_ptr->exp -= (creature_ptr->lev + 1) / 2;
188     if (creature_ptr->exp < 0)
189         creature_ptr->exp = 0;
190
191     creature_ptr->max_exp -= (creature_ptr->lev + 1) / 2;
192     if (creature_ptr->max_exp < 0)
193         creature_ptr->max_exp = 0;
194
195     check_experience(creature_ptr);
196 }
197
198 static void multiply_low_curse(player_type* creature_ptr)
199 {
200     if (((creature_ptr->cursed & TRC_ADD_L_CURSE) == 0) || !one_in_(2000))
201         return;
202
203     object_type* o_ptr;
204     o_ptr = choose_cursed_obj_name(creature_ptr, TRC_ADD_L_CURSE);
205     BIT_FLAGS new_curse = get_curse(0, o_ptr);
206     if ((o_ptr->curse_flags & new_curse))
207         return;
208
209     GAME_TEXT o_name[MAX_NLEN];
210     object_desc(creature_ptr, o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
211     o_ptr->curse_flags |= new_curse;
212     msg_format(_("悪意に満ちた黒いオーラが%sをとりまいた...", "There is a malignant black aura surrounding your %s..."), o_name);
213     o_ptr->feeling = FEEL_NONE;
214     creature_ptr->update |= (PU_BONUS);
215 }
216
217 static void multiply_high_curse(player_type* creature_ptr)
218 {
219     if (((creature_ptr->cursed & TRC_ADD_H_CURSE) == 0) || !one_in_(2000))
220         return;
221
222     object_type* o_ptr;
223     o_ptr = choose_cursed_obj_name(creature_ptr, TRC_ADD_H_CURSE);
224     BIT_FLAGS new_curse = get_curse(1, o_ptr);
225     if ((o_ptr->curse_flags & new_curse))
226         return;
227
228     GAME_TEXT o_name[MAX_NLEN];
229     object_desc(creature_ptr, o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
230     o_ptr->curse_flags |= new_curse;
231     msg_format(_("悪意に満ちた黒いオーラが%sをとりまいた...", "There is a malignant black aura surrounding your %s..."), o_name);
232     o_ptr->feeling = FEEL_NONE;
233     creature_ptr->update |= (PU_BONUS);
234 }
235
236 static void occur_curse_effects(player_type *creature_ptr)
237 {
238     if (((creature_ptr->cursed & TRC_P_FLAG_MASK) == 0) || creature_ptr->phase_out || creature_ptr->wild_mode)
239         return;
240
241     curse_teleport(creature_ptr);
242     occur_chainsword_effect(creature_ptr);
243     if ((creature_ptr->cursed & TRC_TY_CURSE) && one_in_(TY_CURSE_CHANCE)) {
244         int count = 0;
245         (void)activate_ty_curse(creature_ptr, FALSE, &count);
246     }
247
248     curse_drain_exp(creature_ptr);
249     multiply_low_curse(creature_ptr);
250     multiply_high_curse(creature_ptr);
251     if ((creature_ptr->cursed & TRC_CALL_ANIMAL) && one_in_(2500)) {
252         if (summon_specific(creature_ptr, 0, creature_ptr->y, creature_ptr->x, creature_ptr->current_floor_ptr->dun_level, SUMMON_ANIMAL, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET))) {
253             GAME_TEXT o_name[MAX_NLEN];
254             object_desc(creature_ptr, o_name, choose_cursed_obj_name(creature_ptr, TRC_CALL_ANIMAL), (OD_OMIT_PREFIX | OD_NAME_ONLY));
255             msg_format(_("%sが動物を引き寄せた!", "Your %s has attracted an animal!"), o_name);
256             disturb(creature_ptr, FALSE, TRUE);
257         }
258     }
259
260     if ((creature_ptr->cursed & TRC_CALL_DEMON) && one_in_(1111)) {
261         if (summon_specific(creature_ptr, 0, creature_ptr->y, creature_ptr->x, creature_ptr->current_floor_ptr->dun_level, SUMMON_DEMON, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET))) {
262             GAME_TEXT o_name[MAX_NLEN];
263             object_desc(creature_ptr, o_name, choose_cursed_obj_name(creature_ptr, TRC_CALL_DEMON), (OD_OMIT_PREFIX | OD_NAME_ONLY));
264             msg_format(_("%sが悪魔を引き寄せた!", "Your %s has attracted a demon!"), o_name);
265             disturb(creature_ptr, FALSE, TRUE);
266         }
267     }
268
269     if ((creature_ptr->cursed & TRC_CALL_DRAGON) && one_in_(800)) {
270         if (summon_specific(creature_ptr, 0, creature_ptr->y, creature_ptr->x, creature_ptr->current_floor_ptr->dun_level, SUMMON_DRAGON,
271                 (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET))) {
272             GAME_TEXT o_name[MAX_NLEN];
273             object_desc(creature_ptr, o_name, choose_cursed_obj_name(creature_ptr, TRC_CALL_DRAGON), (OD_OMIT_PREFIX | OD_NAME_ONLY));
274             msg_format(_("%sがドラゴンを引き寄せた!", "Your %s has attracted an dragon!"), o_name);
275             disturb(creature_ptr, FALSE, TRUE);
276         }
277     }
278
279     if ((creature_ptr->cursed & TRC_CALL_UNDEAD) && one_in_(1111)) {
280         if (summon_specific(creature_ptr, 0, creature_ptr->y, creature_ptr->x, creature_ptr->current_floor_ptr->dun_level, SUMMON_UNDEAD,
281                 (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET))) {
282             GAME_TEXT o_name[MAX_NLEN];
283             object_desc(creature_ptr, o_name, choose_cursed_obj_name(creature_ptr, TRC_CALL_UNDEAD), (OD_OMIT_PREFIX | OD_NAME_ONLY));
284             msg_format(_("%sが死霊を引き寄せた!", "Your %s has attracted an undead!"), o_name);
285             disturb(creature_ptr, FALSE, TRUE);
286         }
287     }
288
289     if ((creature_ptr->cursed & TRC_COWARDICE) && one_in_(1500)) {
290         if (!creature_ptr->resist_fear) {
291             disturb(creature_ptr, FALSE, TRUE);
292             msg_print(_("とても暗い... とても恐い!", "It's so dark... so scary!"));
293             set_afraid(creature_ptr, creature_ptr->afraid + 13 + randint1(26));
294         }
295     }
296
297     if ((creature_ptr->cursed & TRC_TELEPORT) && one_in_(200) && !creature_ptr->anti_tele) {
298         disturb(creature_ptr, FALSE, TRUE);
299         teleport_player(creature_ptr, 40, TELEPORT_PASSIVE);
300     }
301
302     if ((creature_ptr->cursed & TRC_DRAIN_HP) && one_in_(666)) {
303         GAME_TEXT o_name[MAX_NLEN];
304         object_desc(creature_ptr, o_name, choose_cursed_obj_name(creature_ptr, TRC_DRAIN_HP), (OD_OMIT_PREFIX | OD_NAME_ONLY));
305         msg_format(_("%sはあなたの体力を吸収した!", "Your %s drains HP from you!"), o_name);
306         take_hit(creature_ptr, DAMAGE_LOSELIFE, MIN(creature_ptr->lev * 2, 100), o_name, -1);
307     }
308
309     if ((creature_ptr->cursed & TRC_DRAIN_MANA) && creature_ptr->csp && one_in_(666)) {
310         GAME_TEXT o_name[MAX_NLEN];
311         object_desc(creature_ptr, o_name, choose_cursed_obj_name(creature_ptr, TRC_DRAIN_MANA), (OD_OMIT_PREFIX | OD_NAME_ONLY));
312         msg_format(_("%sはあなたの魔力を吸収した!", "Your %s drains mana from you!"), o_name);
313         creature_ptr->csp -= MIN(creature_ptr->lev, 50);
314         if (creature_ptr->csp < 0) {
315             creature_ptr->csp = 0;
316             creature_ptr->csp_frac = 0;
317         }
318
319         creature_ptr->redraw |= PR_MANA;
320     }
321 }
322
323 /*!
324  * @brief 10ゲームターンが進行するごとに装備効果の発動判定を行う処理
325  * / Handle curse effects once every 10 game turns
326  * @param creature_ptr プレーヤーへの参照ポインタ
327  * @return なし
328  */
329 void execute_cursed_items_effect(player_type* creature_ptr)
330 {
331     occur_curse_effects(creature_ptr);
332     if (!one_in_(999) || creature_ptr->anti_magic)
333         return;
334
335     object_type* o_ptr = &creature_ptr->inventory_list[INVEN_LITE];
336     if (o_ptr->name1 != ART_JUDGE)
337         return;
338
339     if (object_is_known(o_ptr))
340         msg_print(_("『審判の宝石』はあなたの体力を吸収した!", "The Jewel of Judgement drains life from you!"));
341     else
342         msg_print(_("なにかがあなたの体力を吸収した!", "Something drains life from you!"));
343
344     take_hit(creature_ptr, DAMAGE_LOSELIFE, MIN(creature_ptr->lev, 50), _("審判の宝石", "the Jewel of Judgement"), -1);
345 }