OSDN Git Service

Merge pull request #3532 from sikabane-works/release/3.0.0.87-alpha
[hengbandforosx/hengbandosx.git] / src / market / building-recharger.cpp
1 #include "market/building-recharger.h"
2 #include "autopick/autopick.h"
3 #include "core/asking-player.h"
4 #include "core/window-redrawer.h"
5 #include "flavor/flavor-describer.h"
6 #include "flavor/object-flavor-types.h"
7 #include "floor/floor-object.h"
8 #include "inventory/inventory-slot-types.h"
9 #include "market/building-util.h"
10 #include "object-enchant/special-object-flags.h"
11 #include "object-hook/hook-magic.h"
12 #include "object/item-tester-hooker.h"
13 #include "object/item-use-flags.h"
14 #include "perception/object-perception.h"
15 #include "spell-kind/spells-perception.h"
16 #include "system/baseitem-info.h"
17 #include "system/item-entity.h"
18 #include "system/player-type-definition.h"
19 #include "system/redrawing-flags-updater.h"
20 #include "term/screen-processor.h"
21 #include "view/display-messages.h"
22
23 /*!
24  * @brief 魔道具の使用回数を回復させる施設のメインルーチン / Recharge rods, wands and staffs
25  * @details
26  * The player can select the number of charges to add\n
27  * (up to a limit), and the recharge never fails.\n
28  *\n
29  * The cost for rods depends on the level of the rod. The prices\n
30  * for recharging wands and staffs are dependent on the cost of\n
31  * the base-item.\n
32  * @param player_ptr プレイヤーへの参照ポインタ
33  */
34 void building_recharge(PlayerType *player_ptr)
35 {
36     msg_flag = false;
37     clear_bldg(4, 18);
38     prt(_("  再充填の費用はアイテムの種類によります。", "  The prices of recharge depend on the type."), 6, 0);
39     const auto q = _("どのアイテムに魔力を充填しますか? ", "Recharge which item? ");
40     const auto s = _("魔力を充填すべきアイテムがない。", "You have nothing to recharge.");
41     OBJECT_IDX item;
42     auto *o_ptr = choose_object(player_ptr, &item, q, s, (USE_INVEN | USE_FLOOR), FuncItemTester(&ItemEntity::can_recharge));
43     if (o_ptr == nullptr) {
44         return;
45     }
46
47     /*
48      * We don't want to give the player free info about
49      * the level of the item or the number of charges.
50      */
51     if (!o_ptr->is_known()) {
52         msg_format(_("充填する前に鑑定されている必要があります!", "The item must be identified first!"));
53         msg_print(nullptr);
54         if ((player_ptr->au >= 50) && input_check(_("$50で鑑定しますか? ", "Identify for 50 gold? "))) {
55             player_ptr->au -= 50;
56             identify_item(player_ptr, o_ptr);
57             const auto item_name = describe_flavor(player_ptr, o_ptr, 0);
58             msg_format(_("%s です。", "You have: %s."), item_name.data());
59             autopick_alter_item(player_ptr, item, false);
60             building_prt_gold(player_ptr);
61         }
62
63         return;
64     }
65
66     const auto &baseitem = o_ptr->get_baseitem();
67     const auto lev = baseitem.level;
68     const auto tval = o_ptr->bi_key.tval();
69     int price;
70     switch (tval) {
71     case ItemKindType::ROD:
72         if (o_ptr->timeout > 0) {
73             price = (lev * 50 * o_ptr->timeout) / baseitem.pval;
74             break;
75         }
76
77         price = 0;
78         msg_format(_("それは再充填する必要はありません。", "That doesn't need to be recharged."));
79         return;
80     case ItemKindType::STAFF:
81         price = (baseitem.cost / 10) * o_ptr->number;
82         price = std::max(10, price);
83         break;
84     default:
85         price = baseitem.cost / 10;
86         price = std::max(10, price);
87         break;
88     }
89
90     if ((tval == ItemKindType::WAND) && (o_ptr->pval / o_ptr->number >= baseitem.pval)) {
91         if (o_ptr->number > 1) {
92             msg_print(_("この魔法棒はもう充分に充填されています。", "These wands are already fully charged."));
93         } else {
94             msg_print(_("この魔法棒はもう充分に充填されています。", "This wand is already fully charged."));
95         }
96
97         return;
98     } else if ((tval == ItemKindType::STAFF) && o_ptr->pval >= baseitem.pval) {
99         if (o_ptr->number > 1) {
100             msg_print(_("この杖はもう充分に充填されています。", "These staffs are already fully charged."));
101         } else {
102             msg_print(_("この杖はもう充分に充填されています。", "This staff is already fully charged."));
103         }
104
105         return;
106     }
107
108     if (player_ptr->au < price) {
109         const auto item_name = describe_flavor(player_ptr, o_ptr, OD_NAME_ONLY);
110 #ifdef JP
111         msg_format("%sを再充填するには$%d 必要です!", item_name.data(), price);
112 #else
113         msg_format("You need %d gold to recharge %s!", price, item_name.data());
114 #endif
115         return;
116     }
117
118     if (tval == ItemKindType::ROD) {
119 #ifdef JP
120         if (input_check(format("そのロッドを$%d で再充填しますか?", price)))
121 #else
122         if (input_check(format("Recharge the %s for %d gold? ", ((o_ptr->number > 1) ? "rods" : "rod"), price)))
123 #endif
124
125         {
126             o_ptr->timeout = 0;
127         } else {
128             return;
129         }
130     } else {
131         int max_charges;
132         if (tval == ItemKindType::STAFF) {
133             max_charges = baseitem.pval - o_ptr->pval;
134         } else {
135             max_charges = o_ptr->number * baseitem.pval - o_ptr->pval;
136         }
137
138         const auto mes = _("一回分$%d で何回分充填しますか?", "Add how many charges for %d gold apiece? ");
139         const auto charges = input_quantity(std::min(player_ptr->au / price, max_charges), format(mes, price));
140         if (charges < 1) {
141             return;
142         }
143
144         price *= charges;
145         o_ptr->pval += static_cast<short>(charges);
146         o_ptr->ident &= ~(IDENT_EMPTY);
147     }
148
149     const auto item_name = describe_flavor(player_ptr, o_ptr, 0);
150 #ifdef JP
151     msg_format("%sを$%d で再充填しました。", item_name.data(), price);
152 #else
153     msg_format("%s^ %s recharged for %d gold.", item_name.data(), ((o_ptr->number > 1) ? "were" : "was"), price);
154 #endif
155     auto &rfu = RedrawingFlagsUpdater::get_instance();
156     static constexpr auto flags = {
157         StatusRecalculatingFlag::COMBINATION,
158         StatusRecalculatingFlag::REORDER,
159     };
160     rfu.set_flags(flags);
161     rfu.set_flag(SubWindowRedrawingFlag::INVENTORY);
162     player_ptr->au -= price;
163 }
164
165 /*!
166  * @brief 魔道具の使用回数を回復させる施設の一括処理向けサブルーチン / Recharge rods, wands and staffs
167  * @details
168  * The player can select the number of charges to add\n
169  * (up to a limit), and the recharge never fails.\n
170  *\n
171  * The cost for rods depends on the level of the rod. The prices\n
172  * for recharging wands and staffs are dependent on the cost of\n
173  * the base-item.\n
174  * @param player_ptr プレイヤーへの参照ポインタ
175  */
176 void building_recharge_all(PlayerType *player_ptr)
177 {
178     msg_flag = false;
179     clear_bldg(4, 18);
180     prt(_("  再充填の費用はアイテムの種類によります。", "  The prices of recharge depend on the type."), 6, 0);
181
182     auto price = 0;
183     auto total_cost = 0;
184     for (short i = 0; i < INVEN_PACK; i++) {
185         const auto &item = player_ptr->inventory_list[i];
186         if (!item.can_recharge()) {
187             continue;
188         }
189
190         if (!item.is_known()) {
191             total_cost += 50;
192         }
193
194         const auto &baseitem = item.get_baseitem();
195         const auto lev = baseitem.level;
196         switch (item.bi_key.tval()) {
197         case ItemKindType::ROD:
198             price = (lev * 50 * item.timeout) / baseitem.pval;
199             break;
200         case ItemKindType::STAFF:
201             price = (baseitem.cost / 10) * item.number;
202             price = std::max(10, price);
203             price = (baseitem.pval - item.pval) * price;
204             break;
205         case ItemKindType::WAND:
206             price = (baseitem.cost / 10);
207             price = std::max(10, price);
208             price = (item.number * baseitem.pval - item.pval) * price;
209             break;
210         default:
211             break;
212         }
213
214         if (price > 0) {
215             total_cost += price;
216         }
217     }
218
219     if (!total_cost) {
220         msg_print(_("充填する必要はありません。", "No need to recharge."));
221         msg_print(nullptr);
222         return;
223     }
224
225     if (player_ptr->au < total_cost) {
226         msg_format(_("すべてのアイテムを再充填するには$%d 必要です!", "You need %d gold to recharge all items!"), total_cost);
227         msg_print(nullptr);
228         return;
229     }
230
231     if (!input_check(format(_("すべてのアイテムを $%d で再充填しますか?", "Recharge all items for %d gold? "), total_cost))) {
232         return;
233     }
234
235     for (short i = 0; i < INVEN_PACK; i++) {
236         auto *o_ptr = &player_ptr->inventory_list[i];
237         const auto &baseitem = o_ptr->get_baseitem();
238         if (!o_ptr->can_recharge()) {
239             continue;
240         }
241
242         if (!o_ptr->is_known()) {
243             identify_item(player_ptr, o_ptr);
244             autopick_alter_item(player_ptr, i, false);
245         }
246
247         switch (o_ptr->bi_key.tval()) {
248         case ItemKindType::ROD:
249             o_ptr->timeout = 0;
250             break;
251         case ItemKindType::STAFF:
252             if (o_ptr->pval < baseitem.pval) {
253                 o_ptr->pval = baseitem.pval;
254             }
255
256             o_ptr->ident &= ~(IDENT_EMPTY);
257             break;
258         case ItemKindType::WAND:
259             if (o_ptr->pval < o_ptr->number * baseitem.pval) {
260                 o_ptr->pval = o_ptr->number * baseitem.pval;
261             }
262
263             o_ptr->ident &= ~(IDENT_EMPTY);
264             break;
265         default:
266             break;
267         }
268     }
269
270     msg_format(_("$%d で再充填しました。", "You pay %d gold."), total_cost);
271     msg_print(nullptr);
272     auto &rfu = RedrawingFlagsUpdater::get_instance();
273     static constexpr auto flags = {
274         StatusRecalculatingFlag::COMBINATION,
275         StatusRecalculatingFlag::REORDER,
276     };
277     rfu.set_flags(flags);
278     rfu.set_flag(SubWindowRedrawingFlag::INVENTORY);
279     player_ptr->au -= total_cost;
280 }