OSDN Git Service

[Refactor] #3286 Removed player-redraw-types.h
[hengbandforosx/hengbandosx.git] / src / spell-realm / spells-craft.cpp
1 #include "spell-realm/spells-craft.h"
2 #include "avatar/avatar.h"
3 #include "core/disturbance.h"
4 #include "core/stuff-handler.h"
5 #include "flavor/flavor-describer.h"
6 #include "flavor/object-flavor-types.h"
7 #include "floor/floor-object.h"
8 #include "game-option/disturbance-options.h"
9 #include "inventory/inventory-slot-types.h"
10 #include "io/input-key-acceptor.h"
11 #include "object-enchant/object-ego.h"
12 #include "object/item-use-flags.h"
13 #include "object/object-flags.h"
14 #include "player-info/equipment-info.h"
15 #include "player/attack-defense-types.h"
16 #include "player/special-defense-types.h"
17 #include "racial/racial-android.h"
18 #include "spell/spells-object.h"
19 #include "sv-definition/sv-protector-types.h"
20 #include "system/item-entity.h"
21 #include "system/player-type-definition.h"
22 #include "system/redrawing-flags-updater.h"
23 #include "term/screen-processor.h"
24 #include "term/term-color-types.h"
25 #include "view/display-messages.h"
26
27 /*!
28  * @brief 一時的元素スレイの継続時間をセットする / Set a temporary elemental brand. Clear all other brands. Print status messages. -LM-
29  * @param attack_type スレイのタイプID
30  * @param v 継続時間
31  * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
32  */
33 bool set_ele_attack(PlayerType *player_ptr, uint32_t attack_type, TIME_EFFECT v)
34 {
35     v = (v > 10000) ? 10000 : (v < 0) ? 0
36                                       : v;
37
38     if ((player_ptr->special_attack & (ATTACK_ACID)) && (attack_type != ATTACK_ACID)) {
39         player_ptr->special_attack &= ~(ATTACK_ACID);
40         msg_print(_("酸で攻撃できなくなった。", "Your temporary acidic brand fades away."));
41     }
42
43     if ((player_ptr->special_attack & (ATTACK_ELEC)) && (attack_type != ATTACK_ELEC)) {
44         player_ptr->special_attack &= ~(ATTACK_ELEC);
45         msg_print(_("電撃で攻撃できなくなった。", "Your temporary electrical brand fades away."));
46     }
47
48     if ((player_ptr->special_attack & (ATTACK_FIRE)) && (attack_type != ATTACK_FIRE)) {
49         player_ptr->special_attack &= ~(ATTACK_FIRE);
50         msg_print(_("火炎で攻撃できなくなった。", "Your temporary fiery brand fades away."));
51     }
52
53     if ((player_ptr->special_attack & (ATTACK_COLD)) && (attack_type != ATTACK_COLD)) {
54         player_ptr->special_attack &= ~(ATTACK_COLD);
55         msg_print(_("冷気で攻撃できなくなった。", "Your temporary frost brand fades away."));
56     }
57
58     if ((player_ptr->special_attack & (ATTACK_POIS)) && (attack_type != ATTACK_POIS)) {
59         player_ptr->special_attack &= ~(ATTACK_POIS);
60         msg_print(_("毒で攻撃できなくなった。", "Your temporary poison brand fades away."));
61     }
62
63     if ((v) && (attack_type)) {
64         player_ptr->special_attack |= (attack_type);
65         player_ptr->ele_attack = v;
66 #ifdef JP
67         msg_format("%sで攻撃できるようになった!",
68             ((attack_type == ATTACK_ACID)
69                     ? "酸"
70                     : ((attack_type == ATTACK_ELEC)
71                               ? "電撃"
72                               : ((attack_type == ATTACK_FIRE) ? "火炎"
73                                                               : ((attack_type == ATTACK_COLD) ? "冷気" : ((attack_type == ATTACK_POIS) ? "毒" : "(なし)"))))));
74 #else
75         msg_format("For a while, the blows you deal will %s",
76             ((attack_type == ATTACK_ACID)
77                     ? "melt with acid!"
78                     : ((attack_type == ATTACK_ELEC)
79                               ? "shock your foes!"
80                               : ((attack_type == ATTACK_FIRE)
81                                         ? "burn with fire!"
82                                         : ((attack_type == ATTACK_COLD) ? "chill to the bone!"
83                                                                         : ((attack_type == ATTACK_POIS) ? "poison your enemies!" : "do nothing special."))))));
84 #endif
85     }
86
87     if (disturb_state) {
88         disturb(player_ptr, false, false);
89     }
90
91     auto &rfu = RedrawingFlagsUpdater::get_instance();
92     rfu.set_flag(MainWindowRedrawingFlag::TIMED_EFFECT);
93     rfu.set_flag(StatusRedrawingFlag::BONUS);
94     handle_stuff(player_ptr);
95
96     return true;
97 }
98
99 /*!
100  * @brief 一時的元素免疫の継続時間をセットする / Set a temporary elemental brand.  Clear all other brands.  Print status messages. -LM-
101  * @param immune_type 免疫のタイプID
102  * @param v 継続時間
103  * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
104  */
105 bool set_ele_immune(PlayerType *player_ptr, uint32_t immune_type, TIME_EFFECT v)
106 {
107     v = (v > 10000) ? 10000 : (v < 0) ? 0
108                                       : v;
109
110     if ((player_ptr->special_defense & (DEFENSE_ACID)) && (immune_type != DEFENSE_ACID)) {
111         player_ptr->special_defense &= ~(DEFENSE_ACID);
112         msg_print(_("酸の攻撃で傷つけられるようになった。。", "You are no longer immune to acid."));
113     }
114
115     if ((player_ptr->special_defense & (DEFENSE_ELEC)) && (immune_type != DEFENSE_ELEC)) {
116         player_ptr->special_defense &= ~(DEFENSE_ELEC);
117         msg_print(_("電撃の攻撃で傷つけられるようになった。。", "You are no longer immune to electricity."));
118     }
119
120     if ((player_ptr->special_defense & (DEFENSE_FIRE)) && (immune_type != DEFENSE_FIRE)) {
121         player_ptr->special_defense &= ~(DEFENSE_FIRE);
122         msg_print(_("火炎の攻撃で傷つけられるようになった。。", "You are no longer immune to fire."));
123     }
124
125     if ((player_ptr->special_defense & (DEFENSE_COLD)) && (immune_type != DEFENSE_COLD)) {
126         player_ptr->special_defense &= ~(DEFENSE_COLD);
127         msg_print(_("冷気の攻撃で傷つけられるようになった。。", "You are no longer immune to cold."));
128     }
129
130     if ((player_ptr->special_defense & (DEFENSE_POIS)) && (immune_type != DEFENSE_POIS)) {
131         player_ptr->special_defense &= ~(DEFENSE_POIS);
132         msg_print(_("毒の攻撃で傷つけられるようになった。。", "You are no longer immune to poison."));
133     }
134
135     if ((v) && (immune_type)) {
136         player_ptr->special_defense |= (immune_type);
137         player_ptr->ele_immune = v;
138         msg_format(_("%sの攻撃を受けつけなくなった!", "For a while, you are immune to %s"),
139             ((immune_type == DEFENSE_ACID)
140                     ? _("酸", "acid!")
141                     : ((immune_type == DEFENSE_ELEC)
142                               ? _("電撃", "electricity!")
143                               : ((immune_type == DEFENSE_FIRE)
144                                         ? _("火炎", "fire!")
145                                         : ((immune_type == DEFENSE_COLD)
146                                                   ? _("冷気", "cold!")
147                                                   : ((immune_type == DEFENSE_POIS) ? _("毒", "poison!") : _("(なし)", "nothing special.")))))));
148     }
149
150     if (disturb_state) {
151         disturb(player_ptr, false, false);
152     }
153
154     auto &rfu = RedrawingFlagsUpdater::get_instance();
155     rfu.set_flag(MainWindowRedrawingFlag::TIMED_EFFECT);
156     rfu.set_flag(StatusRedrawingFlag::BONUS);
157     handle_stuff(player_ptr);
158
159     return true;
160 }
161
162 /*
163  * Choose a warrior-mage elemental attack. -LM-
164  */
165 bool choose_ele_attack(PlayerType *player_ptr)
166 {
167     if (!has_melee_weapon(player_ptr, INVEN_MAIN_HAND) && !has_melee_weapon(player_ptr, INVEN_SUB_HAND)) {
168         msg_format(_("武器を持たないと魔法剣は使えない。", "You cannot use temporary branding with no weapon."));
169         return false;
170     }
171
172     screen_save();
173     int num = (player_ptr->lev - 20) / 5;
174     c_prt(TERM_RED, _("        a) 焼棄", "        a) Fire Brand"), 2, 14);
175
176     if (num >= 2) {
177         c_prt(TERM_L_WHITE, _("        b) 凍結", "        b) Cold Brand"), 3, 14);
178     } else {
179         prt("", 3, 14);
180     }
181
182     if (num >= 3) {
183         c_prt(TERM_GREEN, _("        c) 毒殺", "        c) Poison Brand"), 4, 14);
184     } else {
185         prt("", 4, 14);
186     }
187
188     if (num >= 4) {
189         c_prt(TERM_L_DARK, _("        d) 溶解", "        d) Acid Brand"), 5, 14);
190     } else {
191         prt("", 5, 14);
192     }
193
194     if (num >= 5) {
195         c_prt(TERM_BLUE, _("        e) 電撃", "        e) Elec Brand"), 6, 14);
196     } else {
197         prt("", 6, 14);
198     }
199
200     prt("", 7, 14);
201     prt("", 8, 14);
202     prt("", 9, 14);
203
204     prt("", 1, 0);
205     prt(_("        どの元素攻撃をしますか?", "        Choose a temporary elemental brand "), 1, 14);
206
207     char choice = inkey();
208
209     if ((choice == 'a') || (choice == 'A')) {
210         set_ele_attack(player_ptr, ATTACK_FIRE, player_ptr->lev / 2 + randint1(player_ptr->lev / 2));
211     } else if (((choice == 'b') || (choice == 'B')) && (num >= 2)) {
212         set_ele_attack(player_ptr, ATTACK_COLD, player_ptr->lev / 2 + randint1(player_ptr->lev / 2));
213     } else if (((choice == 'c') || (choice == 'C')) && (num >= 3)) {
214         set_ele_attack(player_ptr, ATTACK_POIS, player_ptr->lev / 2 + randint1(player_ptr->lev / 2));
215     } else if (((choice == 'd') || (choice == 'D')) && (num >= 4)) {
216         set_ele_attack(player_ptr, ATTACK_ACID, player_ptr->lev / 2 + randint1(player_ptr->lev / 2));
217     } else if (((choice == 'e') || (choice == 'E')) && (num >= 5)) {
218         set_ele_attack(player_ptr, ATTACK_ELEC, player_ptr->lev / 2 + randint1(player_ptr->lev / 2));
219     } else {
220         msg_print(_("魔法剣を使うのをやめた。", "You cancel the temporary branding."));
221         screen_load();
222         return false;
223     }
224
225     screen_load();
226     return true;
227 }
228 /*
229  * Choose a elemental immune. -LM-
230  */
231 bool choose_ele_immune(PlayerType *player_ptr, TIME_EFFECT immune_turn)
232 {
233     screen_save();
234
235     c_prt(TERM_RED, _("        a) 火炎", "        a) Immunity to fire"), 2, 14);
236     c_prt(TERM_L_WHITE, _("        b) 冷気", "        b) Immunity to cold"), 3, 14);
237     c_prt(TERM_L_DARK, _("        c) 酸", "        c) Immunity to acid"), 4, 14);
238     c_prt(TERM_BLUE, _("        d) 電撃", "        d) Immunity to elec"), 5, 14);
239
240     prt("", 6, 14);
241     prt("", 7, 14);
242     prt("", 8, 14);
243     prt("", 9, 14);
244
245     prt("", 1, 0);
246     prt(_("        どの元素の免疫をつけますか?", "        Choose a temporary elemental immunity "), 1, 14);
247
248     char choice = inkey();
249
250     if ((choice == 'a') || (choice == 'A')) {
251         set_ele_immune(player_ptr, DEFENSE_FIRE, immune_turn);
252     } else if ((choice == 'b') || (choice == 'B')) {
253         set_ele_immune(player_ptr, DEFENSE_COLD, immune_turn);
254     } else if ((choice == 'c') || (choice == 'C')) {
255         set_ele_immune(player_ptr, DEFENSE_ACID, immune_turn);
256     } else if ((choice == 'd') || (choice == 'D')) {
257         set_ele_immune(player_ptr, DEFENSE_ELEC, immune_turn);
258     } else {
259         msg_print(_("免疫を付けるのをやめた。", "You cancel the temporary immunity."));
260         screen_load();
261         return false;
262     }
263
264     screen_load();
265     return true;
266 }
267
268 /*!
269  * @brief 盾磨き処理 /
270  * pulish shield
271  * @return ターン消費を要する処理を行ったならばTRUEを返す
272  */
273 bool pulish_shield(PlayerType *player_ptr)
274 {
275     const auto q = _("どの盾を磨きますか?", "Polish which shield? ");
276     const auto s = _("磨く盾がありません。", "You have no shield to polish.");
277     const auto options = USE_EQUIP | USE_INVEN | USE_FLOOR | IGNORE_BOTHHAND_SLOT;
278     short item;
279     auto *o_ptr = choose_object(player_ptr, &item, q, s, options, TvalItemTester(ItemKindType::SHIELD));
280     if (o_ptr == nullptr) {
281         return false;
282     }
283
284     const auto item_name = describe_flavor(player_ptr, o_ptr, OD_OMIT_PREFIX | OD_NAME_ONLY);
285     auto is_pulish_successful = o_ptr->is_valid() && !o_ptr->is_fixed_or_random_artifact() && !o_ptr->is_ego();
286     is_pulish_successful &= !o_ptr->is_cursed();
287     is_pulish_successful &= (o_ptr->bi_key.sval() != SV_MIRROR_SHIELD);
288     if (is_pulish_successful) {
289 #ifdef JP
290         msg_format("%sは輝いた!", item_name.data());
291 #else
292         msg_format("%s %s shine%s!", ((item >= 0) ? "Your" : "The"), item_name.data(), ((o_ptr->number > 1) ? "" : "s"));
293 #endif
294         o_ptr->ego_idx = EgoType::REFLECTION;
295         enchant_equipment(player_ptr, o_ptr, randint0(3) + 4, ENCH_TOAC);
296         o_ptr->discount = 99;
297         chg_virtue(player_ptr, Virtue::ENCHANT, 2);
298         return true;
299     }
300
301     if (flush_failure) {
302         flush();
303     }
304
305     msg_print(_("失敗した。", "Failed."));
306     chg_virtue(player_ptr, Virtue::ENCHANT, -2);
307     calc_android_exp(player_ptr);
308     return false;
309 }