OSDN Git Service

Merge pull request #3569 from sikabane-works/release/3.0.0.88-alpha
[hengbandforosx/hengbandosx.git] / src / spell-kind / spells-enchant.cpp
1 #include "spell-kind/spells-enchant.h"
2 #include "artifact/random-art-generator.h"
3 #include "avatar/avatar.h"
4 #include "flavor/flavor-describer.h"
5 #include "flavor/object-flavor-types.h"
6 #include "floor/floor-object.h"
7 #include "game-option/disturbance-options.h"
8 #include "game-option/play-record-options.h"
9 #include "inventory/inventory-object.h"
10 #include "io/write-diary.h"
11 #include "object-hook/hook-perception.h"
12 #include "object-hook/hook-weapon.h"
13 #include "object/item-tester-hooker.h"
14 #include "object/item-use-flags.h"
15 #include "racial/racial-android.h"
16 #include "system/item-entity.h"
17 #include "system/player-type-definition.h"
18 #include "term/screen-processor.h"
19 #include "view/display-messages.h"
20 #include <memory>
21
22 /*!
23  * @brief アーティファクト生成の巻物処理 /
24  * @param player_ptr プレイヤーへの参照ポインタ
25  * @return 生成が実際に試みられたらTRUEを返す
26  */
27 bool artifact_scroll(PlayerType *player_ptr)
28 {
29     concptr q = _("どのアイテムを強化しますか? ", "Enchant which item? ");
30     concptr s = _("強化できるアイテムがない。", "You have nothing to enchant.");
31     ItemEntity *o_ptr;
32     OBJECT_IDX item;
33     o_ptr = choose_object(player_ptr, &item, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR | IGNORE_BOTHHAND_SLOT), FuncItemTester(object_is_nameless_weapon_armour));
34     if (!o_ptr) {
35         return false;
36     }
37
38     const auto item_name = describe_flavor(player_ptr, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
39 #ifdef JP
40     msg_format("%s は眩い光を発した!", item_name.data());
41 #else
42     msg_format("%s %s radiate%s a blinding light!", ((item >= 0) ? "Your" : "The"), item_name.data(), ((o_ptr->number > 1) ? "" : "s"));
43 #endif
44
45     bool okay = false;
46     if (o_ptr->is_fixed_or_random_artifact()) {
47 #ifdef JP
48         msg_format("%sは既に伝説のアイテムです!", item_name.data());
49 #else
50         msg_format("The %s %s already %s!", item_name.data(), ((o_ptr->number > 1) ? "are" : "is"), ((o_ptr->number > 1) ? "artifacts" : "an artifact"));
51 #endif
52         okay = false;
53     } else if (o_ptr->is_ego()) {
54 #ifdef JP
55         msg_format("%sは既に名のあるアイテムです!", item_name.data());
56 #else
57         msg_format("The %s %s already %s!", item_name.data(), ((o_ptr->number > 1) ? "are" : "is"), ((o_ptr->number > 1) ? "ego items" : "an ego item"));
58 #endif
59         okay = false;
60     } else if (o_ptr->is_smith()) {
61 #ifdef JP
62         msg_format("%sは既に強化されています!", item_name.data());
63 #else
64         msg_format("The %s %s already %s!", item_name.data(), ((o_ptr->number > 1) ? "are" : "is"), ((o_ptr->number > 1) ? "customized items" : "a customized item"));
65 #endif
66     } else {
67         if (o_ptr->number > 1) {
68             msg_print(_("複数のアイテムに魔法をかけるだけのエネルギーはありません!", "Not enough energy to enchant more than one object!"));
69 #ifdef JP
70             msg_format("%d 個の%sが壊れた!", (o_ptr->number) - 1, item_name.data());
71 #else
72             msg_format("%d of your %s %s destroyed!", (o_ptr->number) - 1, item_name.data(), (o_ptr->number > 2 ? "were" : "was"));
73 #endif
74
75             if (item >= 0) {
76                 inven_item_increase(player_ptr, item, 1 - (o_ptr->number));
77             } else {
78                 floor_item_increase(player_ptr, 0 - item, 1 - (o_ptr->number));
79             }
80         }
81
82         okay = become_random_artifact(player_ptr, o_ptr, true);
83     }
84
85     if (!okay) {
86         if (flush_failure) {
87             flush();
88         }
89
90         msg_print(_("強化に失敗した。", "The enchantment failed."));
91         if (one_in_(3)) {
92             chg_virtue(player_ptr, Virtue::ENCHANT, -1);
93         }
94
95         calc_android_exp(player_ptr);
96         return true;
97     }
98
99     if (record_rand_art) {
100         const auto diary_item_name = describe_flavor(player_ptr, o_ptr, OD_NAME_ONLY);
101         exe_write_diary(player_ptr, DiaryKind::ART_SCROLL, 0, diary_item_name);
102     }
103
104     chg_virtue(player_ptr, Virtue::ENCHANT, 1);
105     calc_android_exp(player_ptr);
106     return true;
107 }
108
109 /*!
110  * @brief アイテム凡庸化のメインルーチン処理 /
111  * Identify an object in the inventory (or on the floor)
112  * @param player_ptr プレイヤーへの参照ポインタ
113  * @param only_equip 装備品のみを対象とするならばTRUEを返す
114  * @return 実際に凡庸化をを行ったならばTRUEを返す
115  * @details
116  * <pre>
117  * Mundanify an object in the inventory (or on the floor)
118  * This routine does *not* automatically combine objects.
119  * Returns TRUE if something was mundanified, else FALSE.
120  * </pre>
121  */
122 bool mundane_spell(PlayerType *player_ptr, bool only_equip)
123 {
124     std::unique_ptr<ItemTester> item_tester = std::make_unique<AllMatchItemTester>();
125     if (only_equip) {
126         item_tester = std::make_unique<FuncItemTester>(&ItemEntity::is_weapon_armour_ammo);
127     }
128
129     OBJECT_IDX item;
130     ItemEntity *o_ptr;
131     concptr q = _("どのアイテムを凡庸化しますか?", "Mundanify which item? ");
132     concptr s = _("凡庸化できるアイテムがない。", "You have nothing to mundanify.");
133
134     o_ptr = choose_object(player_ptr, &item, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR | IGNORE_BOTHHAND_SLOT), *item_tester);
135     if (!o_ptr) {
136         return false;
137     }
138
139     msg_print(_("まばゆい閃光が走った!", "There is a bright flash of light!"));
140     POSITION iy = o_ptr->iy;
141     POSITION ix = o_ptr->ix;
142     auto marked = o_ptr->marked;
143     auto inscription = std::move(o_ptr->inscription);
144
145     o_ptr->prep(o_ptr->bi_id);
146
147     o_ptr->iy = iy;
148     o_ptr->ix = ix;
149     o_ptr->marked = marked;
150     o_ptr->inscription = std::move(inscription);
151
152     calc_android_exp(player_ptr);
153     return true;
154 }