1 #include "inventory/inventory-curse.h"
2 #include "artifact/fixed-art-types.h"
3 #include "core/asking-player.h"
4 #include "core/disturbance.h"
5 #include "core/player-redraw-types.h"
6 #include "core/player-update-types.h"
7 #include "flavor/flavor-describer.h"
8 #include "flavor/object-flavor-types.h"
9 #include "inventory/inventory-slot-types.h"
10 #include "io/files-util.h"
11 #include "monster-floor/monster-summon.h"
12 #include "monster-floor/place-monster-types.h"
13 #include "object-enchant/item-feeling.h"
14 #include "object-enchant/object-curse.h"
15 #include "object-enchant/special-object-flags.h"
16 #include "object-enchant/tr-types.h"
17 #include "object-enchant/trc-types.h"
18 #include "object/object-flags.h"
19 #include "perception/object-perception.h"
20 #include "player/player-damage.h"
21 #include "player/player-race-types.h"
22 #include "player/player-status-flags.h"
23 #include "spell-kind/spells-random.h"
24 #include "spell-kind/spells-teleport.h"
25 #include "spell/summon-types.h"
26 #include "status/bad-status-setter.h"
27 #include "system/floor-type-definition.h"
28 #include "util/bit-flags-calculator.h"
29 #include "util/quarks.h"
30 #include "util/string-processor.h"
31 #include "view/display-messages.h"
33 #define TRC_P_FLAG_MASK \
34 (TRC_TELEPORT_SELF | TRC_CHAINSWORD | TRC_TY_CURSE | TRC_DRAIN_EXP | TRC_ADD_L_CURSE | TRC_ADD_H_CURSE | TRC_CALL_ANIMAL | TRC_CALL_DEMON \
35 | TRC_CALL_DRAGON | TRC_COWARDICE | TRC_TELEPORT | TRC_DRAIN_HP | TRC_DRAIN_MANA | TRC_CALL_UNDEAD)
37 static bool is_specific_curse(BIT_FLAGS flag)
39 return (flag == TRC_ADD_L_CURSE) || (flag == TRC_ADD_H_CURSE) || (flag == TRC_DRAIN_HP) || (flag == TRC_DRAIN_MANA) || (flag == TRC_CALL_ANIMAL)
40 || (flag == TRC_CALL_DEMON) || (flag == TRC_CALL_DRAGON) || (flag == TRC_CALL_UNDEAD) || (flag == TRC_COWARDICE) || (flag == TRC_LOW_MELEE)
41 || (flag == TRC_LOW_AC) || (flag == TRC_LOW_MAGIC) || (flag == TRC_FAST_DIGEST) || (flag == TRC_SLOW_REGEN);
44 static void choise_cursed_item(player_type *creature_ptr, BIT_FLAGS flag, object_type *o_ptr, int *choices, int *number, int item_num)
46 if (!is_specific_curse(flag))
50 BIT_FLAGS flgs[TR_FLAG_SIZE];
51 object_flags(creature_ptr, o_ptr, flgs);
99 if (!has_flag(flgs, (long)cf))
102 choices[*number] = item_num;
107 * @brief 現在呪いを保持している装備品を一つランダムに探し出す / Choose one of items that have cursed flag
108 * @param flag 探し出したい呪いフラグ配列
109 * @return 該当の呪いが一つでもあった場合にランダムに選ばれた装備品のオブジェクト構造体参照ポインタを返す。\n
112 object_type *choose_cursed_obj_name(player_type *creature_ptr, BIT_FLAGS flag)
114 int choices[INVEN_TOTAL - INVEN_MAIN_HAND];
116 if (!(creature_ptr->cursed & flag))
119 for (int i = INVEN_MAIN_HAND; i < INVEN_TOTAL; i++) {
120 object_type *o_ptr = &creature_ptr->inventory_list[i];
121 if (o_ptr->curse_flags & flag) {
127 choise_cursed_item(creature_ptr, flag, o_ptr, choices, &number, i);
130 return &creature_ptr->inventory_list[choices[randint0(number)]];
134 * @brief 呪われている、トランプエゴ等による装備品由来のテレポートを実行する
135 * @param creature_ptr プレーヤーへの参照ポインタ
138 static void curse_teleport(player_type *creature_ptr)
140 if (((creature_ptr->cursed & TRC_TELEPORT_SELF) == 0) || !one_in_(200))
143 GAME_TEXT o_name[MAX_NLEN];
145 int i_keep = 0, count = 0;
146 for (int i = INVEN_MAIN_HAND; i < INVEN_TOTAL; i++) {
147 BIT_FLAGS flgs[TR_FLAG_SIZE];
148 o_ptr = &creature_ptr->inventory_list[i];
152 object_flags(creature_ptr, o_ptr, flgs);
154 if (!has_flag(flgs, TR_TELEPORT))
157 if (o_ptr->inscription && angband_strchr(quark_str(o_ptr->inscription), '.'))
165 o_ptr = &creature_ptr->inventory_list[i_keep];
166 describe_flavor(creature_ptr, o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
167 msg_format(_("%sがテレポートの能力を発動させようとしている。", "Your %s tries to teleport you."), o_name);
168 if (get_check_strict(creature_ptr, _("テレポートしますか?", "Teleport? "), CHECK_OKAY_CANCEL)) {
169 disturb(creature_ptr, FALSE, TRUE);
170 teleport_player(creature_ptr, 50, TELEPORT_SPONTANEOUS);
172 msg_format(_("%sに{.}(ピリオド)と銘を刻むと発動を抑制できます。", "You can inscribe {.} on your %s to disable random teleportation. "), o_name);
173 disturb(creature_ptr, TRUE, TRUE);
178 * @details 元々呪い効果の発揮ルーチン中にいたので、整合性保持のためここに置いておく
180 static void occur_chainsword_effect(player_type *creature_ptr)
182 if (((creature_ptr->cursed & TRC_CHAINSWORD) == 0) || !one_in_(CHAINSWORD_NOISE))
186 if (!get_rnd_line(_("chainswd_j.txt", "chainswd.txt"), 0, noise))
188 disturb(creature_ptr, FALSE, FALSE);
191 static void curse_drain_exp(player_type *creature_ptr)
193 if ((creature_ptr->prace == RACE_ANDROID) || ((creature_ptr->cursed & TRC_DRAIN_EXP) == 0) || !one_in_(4))
196 creature_ptr->exp -= (creature_ptr->lev + 1) / 2;
197 if (creature_ptr->exp < 0)
198 creature_ptr->exp = 0;
200 creature_ptr->max_exp -= (creature_ptr->lev + 1) / 2;
201 if (creature_ptr->max_exp < 0)
202 creature_ptr->max_exp = 0;
204 check_experience(creature_ptr);
207 static void multiply_low_curse(player_type *creature_ptr)
209 if (((creature_ptr->cursed & TRC_ADD_L_CURSE) == 0) || !one_in_(2000))
213 o_ptr = choose_cursed_obj_name(creature_ptr, TRC_ADD_L_CURSE);
214 BIT_FLAGS new_curse = get_curse(creature_ptr, 0, o_ptr);
215 if ((o_ptr->curse_flags & new_curse))
218 GAME_TEXT o_name[MAX_NLEN];
219 describe_flavor(creature_ptr, o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
220 o_ptr->curse_flags |= new_curse;
221 msg_format(_("悪意に満ちた黒いオーラが%sをとりまいた...", "There is a malignant black aura surrounding your %s..."), o_name);
222 o_ptr->feeling = FEEL_NONE;
223 creature_ptr->update |= (PU_BONUS);
226 static void multiply_high_curse(player_type *creature_ptr)
228 if (((creature_ptr->cursed & TRC_ADD_H_CURSE) == 0) || !one_in_(2000))
232 o_ptr = choose_cursed_obj_name(creature_ptr, TRC_ADD_H_CURSE);
233 BIT_FLAGS new_curse = get_curse(creature_ptr, 1, o_ptr);
234 if ((o_ptr->curse_flags & new_curse))
237 GAME_TEXT o_name[MAX_NLEN];
238 describe_flavor(creature_ptr, o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
239 o_ptr->curse_flags |= new_curse;
240 msg_format(_("悪意に満ちた黒いオーラが%sをとりまいた...", "There is a malignant black aura surrounding your %s..."), o_name);
241 o_ptr->feeling = FEEL_NONE;
242 creature_ptr->update |= (PU_BONUS);
245 static void curse_call_monster(player_type *creature_ptr)
247 const int call_type = PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET;
248 const int obj_desc_type = OD_OMIT_PREFIX | OD_NAME_ONLY;
249 floor_type *floor_ptr = creature_ptr->current_floor_ptr;
250 if ((creature_ptr->cursed & TRC_CALL_ANIMAL) && one_in_(2500)) {
251 if (summon_specific(creature_ptr, 0, creature_ptr->y, creature_ptr->x, floor_ptr->dun_level, SUMMON_ANIMAL, call_type)) {
252 GAME_TEXT o_name[MAX_NLEN];
253 describe_flavor(creature_ptr, o_name, choose_cursed_obj_name(creature_ptr, TRC_CALL_ANIMAL), obj_desc_type);
254 msg_format(_("%sが動物を引き寄せた!", "Your %s has attracted an animal!"), o_name);
255 disturb(creature_ptr, FALSE, TRUE);
259 if ((creature_ptr->cursed & TRC_CALL_DEMON) && one_in_(1111)) {
260 if (summon_specific(creature_ptr, 0, creature_ptr->y, creature_ptr->x, floor_ptr->dun_level, SUMMON_DEMON, call_type)) {
261 GAME_TEXT o_name[MAX_NLEN];
262 describe_flavor(creature_ptr, o_name, choose_cursed_obj_name(creature_ptr, TRC_CALL_DEMON), obj_desc_type);
263 msg_format(_("%sが悪魔を引き寄せた!", "Your %s has attracted a demon!"), o_name);
264 disturb(creature_ptr, FALSE, TRUE);
268 if ((creature_ptr->cursed & TRC_CALL_DRAGON) && one_in_(800)) {
269 if (summon_specific(creature_ptr, 0, creature_ptr->y, creature_ptr->x, floor_ptr->dun_level, SUMMON_DRAGON, call_type)) {
270 GAME_TEXT o_name[MAX_NLEN];
271 describe_flavor(creature_ptr, o_name, choose_cursed_obj_name(creature_ptr, TRC_CALL_DRAGON), obj_desc_type);
272 msg_format(_("%sがドラゴンを引き寄せた!", "Your %s has attracted a dragon!"), o_name);
273 disturb(creature_ptr, FALSE, TRUE);
277 if ((creature_ptr->cursed & TRC_CALL_UNDEAD) && one_in_(1111)) {
278 if (summon_specific(creature_ptr, 0, creature_ptr->y, creature_ptr->x, floor_ptr->dun_level, SUMMON_UNDEAD, call_type)) {
279 GAME_TEXT o_name[MAX_NLEN];
280 describe_flavor(creature_ptr, o_name, choose_cursed_obj_name(creature_ptr, TRC_CALL_UNDEAD), obj_desc_type);
281 msg_format(_("%sが死霊を引き寄せた!", "Your %s has attracted an undead!"), o_name);
282 disturb(creature_ptr, FALSE, TRUE);
287 static void curse_cowardice(player_type *creature_ptr)
289 if (((creature_ptr->cursed & TRC_COWARDICE) == 0) || !one_in_(1500))
292 if (has_resist_fear(creature_ptr))
295 disturb(creature_ptr, FALSE, TRUE);
296 msg_print(_("とても暗い... とても恐い!", "It's so dark... so scary!"));
297 set_afraid(creature_ptr, creature_ptr->afraid + 13 + randint1(26));
300 static void curse_drain_hp(player_type *creature_ptr)
302 if (((creature_ptr->cursed & TRC_DRAIN_HP) == 0) || !one_in_(666))
305 GAME_TEXT o_name[MAX_NLEN];
306 describe_flavor(creature_ptr, o_name, choose_cursed_obj_name(creature_ptr, TRC_DRAIN_HP), (OD_OMIT_PREFIX | OD_NAME_ONLY));
307 msg_format(_("%sはあなたの体力を吸収した!", "Your %s drains HP from you!"), o_name);
308 take_hit(creature_ptr, DAMAGE_LOSELIFE, MIN(creature_ptr->lev * 2, 100), o_name, -1);
311 static void curse_drain_mp(player_type *creature_ptr)
313 if (((creature_ptr->cursed & TRC_DRAIN_MANA) == 0) || (creature_ptr->csp == 0) || !one_in_(666))
316 GAME_TEXT o_name[MAX_NLEN];
317 describe_flavor(creature_ptr, o_name, choose_cursed_obj_name(creature_ptr, TRC_DRAIN_MANA), (OD_OMIT_PREFIX | OD_NAME_ONLY));
318 msg_format(_("%sはあなたの魔力を吸収した!", "Your %s drains mana from you!"), o_name);
319 creature_ptr->csp -= MIN(creature_ptr->lev, 50);
320 if (creature_ptr->csp < 0) {
321 creature_ptr->csp = 0;
322 creature_ptr->csp_frac = 0;
325 creature_ptr->redraw |= PR_MANA;
328 static void occur_curse_effects(player_type *creature_ptr)
330 if (((creature_ptr->cursed & TRC_P_FLAG_MASK) == 0) || creature_ptr->phase_out || creature_ptr->wild_mode)
333 curse_teleport(creature_ptr);
334 occur_chainsword_effect(creature_ptr);
335 if ((creature_ptr->cursed & TRC_TY_CURSE) && one_in_(TY_CURSE_CHANCE)) {
337 (void)activate_ty_curse(creature_ptr, FALSE, &count);
340 curse_drain_exp(creature_ptr);
341 multiply_low_curse(creature_ptr);
342 multiply_high_curse(creature_ptr);
343 curse_call_monster(creature_ptr);
344 curse_cowardice(creature_ptr);
345 if ((creature_ptr->cursed & TRC_TELEPORT) && one_in_(200) && !creature_ptr->anti_tele) {
346 disturb(creature_ptr, FALSE, TRUE);
347 teleport_player(creature_ptr, 40, TELEPORT_PASSIVE);
350 curse_drain_hp(creature_ptr);
351 curse_drain_mp(creature_ptr);
355 * @brief 10ゲームターンが進行するごとに装備効果の発動判定を行う処理
356 * / Handle curse effects once every 10 game turns
357 * @param creature_ptr プレーヤーへの参照ポインタ
360 void execute_cursed_items_effect(player_type *creature_ptr)
362 occur_curse_effects(creature_ptr);
363 if (!one_in_(999) || creature_ptr->anti_magic)
366 object_type *o_ptr = &creature_ptr->inventory_list[INVEN_LITE];
367 if (o_ptr->name1 != ART_JUDGE)
370 if (object_is_known(o_ptr))
371 msg_print(_("『審判の宝石』はあなたの体力を吸収した!", "The Jewel of Judgement drains life from you!"));
373 msg_print(_("なにかがあなたの体力を吸収した!", "Something drains life from you!"));
375 take_hit(creature_ptr, DAMAGE_LOSELIFE, MIN(creature_ptr->lev, 50), _("審判の宝石", "the Jewel of Judgement"), -1);