OSDN Git Service

[Refactor] #3736 activation_type のフィールド変数をconcptr からstring に差し替えた
[hengbandforosx/hengbandosx.git] / src / object-enchant / object-curse.cpp
1 #include "object-enchant/object-curse.h"
2 #include "flavor/flavor-describer.h"
3 #include "flavor/object-flavor-types.h"
4 #include "inventory/inventory-slot-types.h"
5 #include "object-enchant/item-feeling.h"
6 #include "object-enchant/tr-types.h"
7 #include "object-enchant/trc-types.h"
8 #include "object-hook/hook-armor.h"
9 #include "object-hook/hook-weapon.h"
10 #include "system/item-entity.h"
11 #include "system/player-type-definition.h"
12 #include "system/redrawing-flags-updater.h"
13 #include "util/bit-flags-calculator.h"
14 #include "util/enum-converter.h"
15 #include "view/display-messages.h"
16
17 namespace {
18 const EnumClassFlagGroup<CurseTraitType> TRC_SPECIAL_MASK({ CurseTraitType::TY_CURSE, CurseTraitType::AGGRAVATE });
19 const EnumClassFlagGroup<CurseTraitType> TRC_HEAVY_MASK({ CurseTraitType::TY_CURSE, CurseTraitType::AGGRAVATE, CurseTraitType::DRAIN_EXP, CurseTraitType::ADD_H_CURSE, CurseTraitType::CALL_DEMON, CurseTraitType::CALL_DRAGON, CurseTraitType::CALL_UNDEAD, CurseTraitType::TELEPORT });
20 }
21
22 /*!
23  * @brief アイテムに付加される可能性のある呪いを指定する。
24  * @param power 呪いの段階
25  * @param o_ptr 呪いをかけられる装備オブジェクトの構造体参照ポインタ
26  * @return 与える呪いのID
27  */
28 CurseTraitType get_curse(int power, ItemEntity *o_ptr)
29 {
30     CurseTraitType new_curse;
31
32     while (true) {
33         new_curse = i2enum<CurseTraitType>(rand_range(enum2i(CurseTraitType::TY_CURSE), enum2i(CurseTraitType::MAX) - 1));
34         if (power == 2) {
35             if (TRC_HEAVY_MASK.has_not(new_curse)) {
36                 continue;
37             }
38         } else if (power == 1) {
39             if (TRC_SPECIAL_MASK.has(new_curse)) {
40                 continue;
41             }
42         } else if (power == 0) {
43             if (TRC_HEAVY_MASK.has(new_curse)) {
44                 continue;
45             }
46         }
47
48         if (new_curse == CurseTraitType::LOW_MELEE && !o_ptr->is_weapon()) {
49             continue;
50         }
51         if (new_curse == CurseTraitType::LOW_AC && !o_ptr->is_protector()) {
52             continue;
53         }
54         break;
55     }
56
57     return new_curse;
58 }
59
60 /*!
61  * @brief 装備への呪い付加判定と付加処理
62  * @param player_ptr プレイヤーへの参照ポインタ
63  * @param chance 呪いの基本確率
64  * @param heavy_chance さらに重い呪いとなる確率
65  */
66 void curse_equipment(PlayerType *player_ptr, PERCENTAGE chance, PERCENTAGE heavy_chance)
67 {
68     if (randint1(100) > chance) {
69         return;
70     }
71
72     auto *o_ptr = &player_ptr->inventory_list[INVEN_MAIN_HAND + randint0(12)];
73     if (!o_ptr->is_valid()) {
74         return;
75     }
76
77     const auto oflags = o_ptr->get_flags();
78     const auto item_name = describe_flavor(player_ptr, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
79
80     /* Extra, biased saving throw for blessed items */
81     if (oflags.has(TR_BLESSED)) {
82 #ifdef JP
83         msg_format("祝福された%sは呪いを跳ね返した!", item_name.data());
84 #else
85         msg_format("Your blessed %s resist%s cursing!", item_name.data(), ((o_ptr->number > 1) ? "" : "s"));
86 #endif
87         /* Hmmm -- can we wear multiple items? If not, this is unnecessary */
88         return;
89     }
90
91     bool changed = false;
92     int curse_power = 0;
93     if ((randint1(100) <= heavy_chance) && (o_ptr->is_fixed_or_random_artifact() || o_ptr->is_ego())) {
94         if (o_ptr->curse_flags.has_not(CurseTraitType::HEAVY_CURSE)) {
95             changed = true;
96         }
97         o_ptr->curse_flags.set(CurseTraitType::HEAVY_CURSE);
98         o_ptr->curse_flags.set(CurseTraitType::CURSED);
99         curse_power++;
100     } else {
101         if (!o_ptr->is_cursed()) {
102             changed = true;
103         }
104         o_ptr->curse_flags.set(CurseTraitType::CURSED);
105     }
106
107     if (heavy_chance >= 50) {
108         curse_power++;
109     }
110
111     auto new_curse = get_curse(curse_power, o_ptr);
112     if (o_ptr->curse_flags.has_not(new_curse)) {
113         changed = true;
114         o_ptr->curse_flags.set(new_curse);
115     }
116
117     if (changed) {
118         msg_format(_("悪意に満ちた黒いオーラが%sをとりまいた...", "There is a malignant black aura surrounding %s..."), item_name.data());
119         o_ptr->feeling = FEEL_NONE;
120     }
121
122     RedrawingFlagsUpdater::get_instance().set_flag(StatusRecalculatingFlag::BONUS);
123 }