OSDN Git Service

[Refactor] #3286 Removed player-redraw-types.h
[hengbandforosx/hengbandosx.git] / src / object-use / read / scroll-read-executor.cpp
1 /*
2  * @brief 読むことができるアイテム群の内、巻物を読んだ時の効果や処理を記述する.
3  * @date 2022/02/26
4  * @author Hourier
5  */
6
7 #include "object-use/read/scroll-read-executor.h"
8 #include "monster-floor/monster-summon.h"
9 #include "monster-floor/place-monster-types.h"
10 #include "player-base/player-class.h"
11 #include "player-info/equipment-info.h"
12 #include "player/attack-defense-types.h"
13 #include "player/digestion-processor.h"
14 #include "player/player-damage.h"
15 #include "player/player-status-flags.h"
16 #include "spell-kind/magic-item-recharger.h"
17 #include "spell-kind/spells-curse-removal.h"
18 #include "spell-kind/spells-detection.h"
19 #include "spell-kind/spells-enchant.h"
20 #include "spell-kind/spells-floor.h"
21 #include "spell-kind/spells-genocide.h"
22 #include "spell-kind/spells-grid.h"
23 #include "spell-kind/spells-launcher.h"
24 #include "spell-kind/spells-lite.h"
25 #include "spell-kind/spells-neighbor.h"
26 #include "spell-kind/spells-perception.h"
27 #include "spell-kind/spells-sight.h"
28 #include "spell-kind/spells-teleport.h"
29 #include "spell-kind/spells-world.h"
30 #include "spell/spells-object.h"
31 #include "spell/spells-summon.h"
32 #include "spell/summon-types.h"
33 #include "status/bad-status-setter.h"
34 #include "status/body-improvement.h"
35 #include "status/buff-setter.h"
36 #include "status/element-resistance.h"
37 #include "store/rumor.h"
38 #include "sv-definition/sv-scroll-types.h"
39 #include "system/floor-type-definition.h"
40 #include "system/item-entity.h"
41 #include "system/player-type-definition.h"
42 #include "system/redrawing-flags-updater.h"
43 #include "util/bit-flags-calculator.h"
44 #include "view/display-messages.h"
45
46 ScrollReadExecutor::ScrollReadExecutor(PlayerType *player_ptr, ItemEntity *o_ptr, bool known)
47     : player_ptr(player_ptr)
48     , o_ptr(o_ptr)
49     , known(known)
50 {
51 }
52
53 bool ScrollReadExecutor::is_identified() const
54 {
55     return this->ident;
56 }
57
58 bool ScrollReadExecutor::read()
59 {
60     auto used_up = true;
61     auto *floor_ptr = this->player_ptr->current_floor_ptr;
62     switch (this->o_ptr->bi_key.sval().value()) {
63     case SV_SCROLL_DARKNESS:
64         if (!has_resist_blind(this->player_ptr) && !has_resist_dark(this->player_ptr)) {
65             (void)BadStatusSetter(this->player_ptr).mod_blindness(3 + randint1(5));
66         }
67
68         if (unlite_area(this->player_ptr, 10, 3)) {
69             this->ident = true;
70         }
71
72         break;
73     case SV_SCROLL_AGGRAVATE_MONSTER:
74         msg_print(_("カン高くうなる様な音が辺りを覆った。", "There is a high pitched humming noise."));
75         aggravate_monsters(this->player_ptr, 0);
76         this->ident = true;
77         break;
78     case SV_SCROLL_CURSE_ARMOR:
79         if (curse_armor(this->player_ptr)) {
80             this->ident = true;
81         }
82
83         break;
84     case SV_SCROLL_CURSE_WEAPON: {
85         auto k = 0;
86         if (has_melee_weapon(this->player_ptr, INVEN_MAIN_HAND)) {
87             k = INVEN_MAIN_HAND;
88             if (has_melee_weapon(this->player_ptr, INVEN_SUB_HAND) && one_in_(2)) {
89                 k = INVEN_SUB_HAND;
90             }
91         } else if (has_melee_weapon(this->player_ptr, INVEN_SUB_HAND)) {
92             k = INVEN_SUB_HAND;
93         }
94
95         if (k && curse_weapon_object(this->player_ptr, false, &this->player_ptr->inventory_list[k])) {
96             this->ident = true;
97         }
98
99         break;
100     }
101     case SV_SCROLL_SUMMON_MONSTER:
102         for (auto k = 0; k < randint1(3); k++) {
103             if (summon_specific(this->player_ptr, 0, this->player_ptr->y, this->player_ptr->x, floor_ptr->dun_level, SUMMON_NONE,
104                     PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET)) {
105                 this->ident = true;
106             }
107         }
108
109         break;
110     case SV_SCROLL_SUMMON_UNDEAD:
111         for (auto k = 0; k < randint1(3); k++) {
112             if (summon_specific(this->player_ptr, 0, this->player_ptr->y, this->player_ptr->x, floor_ptr->dun_level, SUMMON_UNDEAD,
113                     PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET)) {
114                 this->ident = true;
115             }
116         }
117
118         break;
119     case SV_SCROLL_SUMMON_PET:
120         if (summon_specific(
121                 this->player_ptr, -1, this->player_ptr->y, this->player_ptr->x, floor_ptr->dun_level, SUMMON_NONE, PM_ALLOW_GROUP | PM_FORCE_PET)) {
122             this->ident = true;
123         }
124
125         break;
126     case SV_SCROLL_SUMMON_KIN:
127         if (summon_kin_player(this->player_ptr, this->player_ptr->lev, this->player_ptr->y, this->player_ptr->x, PM_FORCE_PET | PM_ALLOW_GROUP)) {
128             this->ident = true;
129         }
130
131         break;
132     case SV_SCROLL_TRAP_CREATION:
133         if (trap_creation(this->player_ptr, this->player_ptr->y, this->player_ptr->x)) {
134             this->ident = true;
135         }
136
137         break;
138     case SV_SCROLL_PHASE_DOOR:
139         teleport_player(this->player_ptr, 10, TELEPORT_SPONTANEOUS);
140         this->ident = true;
141         break;
142     case SV_SCROLL_TELEPORT:
143         teleport_player(this->player_ptr, 100, TELEPORT_SPONTANEOUS);
144         this->ident = true;
145         break;
146     case SV_SCROLL_TELEPORT_LEVEL: {
147         (void)teleport_level(this->player_ptr, 0);
148         this->ident = true;
149         break;
150     }
151     case SV_SCROLL_WORD_OF_RECALL:
152         if (!recall_player(this->player_ptr, randint0(21) + 15)) {
153             used_up = false;
154         }
155
156         this->ident = true;
157         break;
158     case SV_SCROLL_IDENTIFY:
159         if (!ident_spell(this->player_ptr, false)) {
160             used_up = false;
161         }
162
163         this->ident = true;
164         break;
165     case SV_SCROLL_STAR_IDENTIFY:
166         if (!identify_fully(this->player_ptr, false)) {
167             used_up = false;
168         }
169
170         this->ident = true;
171         break;
172     case SV_SCROLL_REMOVE_CURSE:
173         if (remove_curse(this->player_ptr)) {
174             this->ident = true;
175         }
176
177         break;
178     case SV_SCROLL_STAR_REMOVE_CURSE:
179         if (remove_all_curse(this->player_ptr)) {
180             this->ident = true;
181         }
182
183         break;
184     case SV_SCROLL_ENCHANT_ARMOR:
185         this->ident = true;
186         if (!enchant_spell(this->player_ptr, 0, 0, 1)) {
187             used_up = false;
188         }
189
190         break;
191     case SV_SCROLL_ENCHANT_WEAPON_TO_HIT:
192         if (!enchant_spell(this->player_ptr, 1, 0, 0)) {
193             used_up = false;
194         }
195
196         this->ident = true;
197         break;
198     case SV_SCROLL_ENCHANT_WEAPON_TO_DAM:
199         if (!enchant_spell(this->player_ptr, 0, 1, 0)) {
200             used_up = false;
201         }
202
203         this->ident = true;
204         break;
205     case SV_SCROLL_STAR_ENCHANT_ARMOR:
206         if (!enchant_spell(this->player_ptr, 0, 0, randint1(3) + 2)) {
207             used_up = false;
208         }
209
210         this->ident = true;
211         break;
212     case SV_SCROLL_STAR_ENCHANT_WEAPON:
213         if (!enchant_spell(this->player_ptr, randint1(3), randint1(3), 0)) {
214             used_up = false;
215         }
216
217         this->ident = true;
218         break;
219     case SV_SCROLL_RECHARGING:
220         if (!recharge(this->player_ptr, 130)) {
221             used_up = false;
222         }
223
224         this->ident = true;
225         break;
226     case SV_SCROLL_MUNDANITY:
227         this->ident = true;
228         if (!mundane_spell(this->player_ptr, false)) {
229             used_up = false;
230         }
231
232         break;
233     case SV_SCROLL_LIGHT:
234         if (lite_area(this->player_ptr, damroll(2, 8), 2)) {
235             this->ident = true;
236         }
237
238         break;
239     case SV_SCROLL_MAPPING:
240         map_area(this->player_ptr, DETECT_RAD_MAP);
241         this->ident = true;
242         break;
243     case SV_SCROLL_DETECT_GOLD:
244         if (detect_treasure(this->player_ptr, DETECT_RAD_DEFAULT) || detect_objects_gold(this->player_ptr, DETECT_RAD_DEFAULT)) {
245             this->ident = true;
246         }
247
248         break;
249     case SV_SCROLL_DETECT_ITEM:
250         if (detect_objects_normal(this->player_ptr, DETECT_RAD_DEFAULT)) {
251             this->ident = true;
252         }
253
254         break;
255     case SV_SCROLL_DETECT_TRAP:
256         if (detect_traps(this->player_ptr, DETECT_RAD_DEFAULT, this->known)) {
257             this->ident = true;
258         }
259
260         break;
261     case SV_SCROLL_DETECT_DOOR:
262         if (detect_doors(this->player_ptr, DETECT_RAD_DEFAULT) || detect_stairs(this->player_ptr, DETECT_RAD_DEFAULT)) {
263             this->ident = true;
264         }
265
266         break;
267     case SV_SCROLL_DETECT_INVIS:
268         if (detect_monsters_invis(this->player_ptr, DETECT_RAD_DEFAULT)) {
269             this->ident = true;
270         }
271
272         break;
273     case SV_SCROLL_SATISFY_HUNGER: {
274         if (set_food(this->player_ptr, PY_FOOD_MAX - 1)) {
275             this->ident = true;
276         }
277
278         break;
279     }
280     case SV_SCROLL_BLESSING:
281         if (set_blessed(this->player_ptr, this->player_ptr->blessed + randint1(12) + 6, false)) {
282             this->ident = true;
283         }
284
285         break;
286     case SV_SCROLL_HOLY_CHANT:
287         if (set_blessed(this->player_ptr, this->player_ptr->blessed + randint1(24) + 12, false)) {
288             this->ident = true;
289         }
290
291         break;
292     case SV_SCROLL_HOLY_PRAYER:
293         if (set_blessed(this->player_ptr, this->player_ptr->blessed + randint1(48) + 24, false)) {
294             this->ident = true;
295         }
296
297         break;
298     case SV_SCROLL_MONSTER_CONFUSION:
299         if (any_bits(this->player_ptr->special_attack, ATTACK_CONFUSE)) {
300             break;
301         }
302
303         msg_print(_("手が輝き始めた。", "Your hands begin to glow."));
304         this->player_ptr->special_attack |= ATTACK_CONFUSE;
305         RedrawingFlagsUpdater::get_instance().set_flag(MainWindowRedrawingFlag::TIMED_EFFECT);
306         this->ident = true;
307         break;
308     case SV_SCROLL_PROTECTION_FROM_EVIL: {
309         auto k = 3 * this->player_ptr->lev;
310         if (set_protevil(this->player_ptr, this->player_ptr->protevil + randint1(25) + k, false)) {
311             this->ident = true;
312         }
313
314         break;
315     }
316     case SV_SCROLL_RUNE_OF_PROTECTION:
317         create_rune_protection_one(this->player_ptr);
318         this->ident = true;
319         break;
320     case SV_SCROLL_TRAP_DOOR_DESTRUCTION:
321         if (destroy_doors_touch(this->player_ptr)) {
322             this->ident = true;
323         }
324
325         break;
326     case SV_SCROLL_STAR_DESTRUCTION:
327         if (destroy_area(this->player_ptr, this->player_ptr->y, this->player_ptr->x, 13 + randint0(5), false)) {
328             this->ident = true;
329         } else {
330             msg_print(_("ダンジョンが揺れた...", "The dungeon trembles..."));
331         }
332
333         break;
334     case SV_SCROLL_DISPEL_UNDEAD:
335         if (dispel_undead(this->player_ptr, 80)) {
336             this->ident = true;
337         }
338
339         break;
340     case SV_SCROLL_SPELL:
341         if (!PlayerClass(this->player_ptr).has_number_of_spells_learned()) {
342             break;
343         }
344
345         this->player_ptr->add_spells++;
346         RedrawingFlagsUpdater::get_instance().set_flag(StatusRedrawingFlag::SPELLS);
347         this->ident = true;
348         break;
349     case SV_SCROLL_GENOCIDE:
350         (void)symbol_genocide(this->player_ptr, 300, true);
351         this->ident = true;
352         break;
353     case SV_SCROLL_MASS_GENOCIDE:
354         (void)mass_genocide(this->player_ptr, 300, true);
355         this->ident = true;
356         break;
357     case SV_SCROLL_ACQUIREMENT:
358         acquirement(this->player_ptr, this->player_ptr->y, this->player_ptr->x, 1, true, false, false);
359         this->ident = true;
360         break;
361     case SV_SCROLL_STAR_ACQUIREMENT:
362         acquirement(this->player_ptr, this->player_ptr->y, this->player_ptr->x, randint1(2) + 1, true, false, false);
363         this->ident = true;
364         break;
365     case SV_SCROLL_FIRE:
366         fire_ball(this->player_ptr, AttributeType::FIRE, 0, 666, 4);
367         if (!(is_oppose_fire(this->player_ptr) || has_resist_fire(this->player_ptr) || has_immune_fire(this->player_ptr))) {
368             take_hit(this->player_ptr, DAMAGE_NOESCAPE, 50 + randint1(50), _("炎の巻物", "a Scroll of Fire"));
369         }
370
371         this->ident = true;
372         break;
373     case SV_SCROLL_ICE:
374         fire_ball(this->player_ptr, AttributeType::ICE, 0, 777, 4);
375         if (!(is_oppose_cold(this->player_ptr) || has_resist_cold(this->player_ptr) || has_immune_cold(this->player_ptr))) {
376             take_hit(this->player_ptr, DAMAGE_NOESCAPE, 100 + randint1(100), _("氷の巻物", "a Scroll of Ice"));
377         }
378
379         this->ident = true;
380         break;
381     case SV_SCROLL_CHAOS:
382         fire_ball(this->player_ptr, AttributeType::CHAOS, 0, 1000, 4);
383         if (!has_resist_chaos(this->player_ptr)) {
384             take_hit(this->player_ptr, DAMAGE_NOESCAPE, 111 + randint1(111), _("ログルスの巻物", "a Scroll of Logrus"));
385         }
386
387         this->ident = true;
388         break;
389     case SV_SCROLL_RUMOR:
390         msg_print(_("巻物にはメッセージが書かれている:", "There is message on the scroll. It says:"));
391         msg_print(nullptr);
392         display_rumor(this->player_ptr, true);
393         msg_print(nullptr);
394         msg_print(_("巻物は煙を立てて消え去った!", "The scroll disappears in a puff of smoke!"));
395         this->ident = true;
396         break;
397     case SV_SCROLL_ARTIFACT:
398         this->ident = true;
399         if (!artifact_scroll(this->player_ptr)) {
400             used_up = false;
401         }
402
403         break;
404     case SV_SCROLL_RESET_RECALL:
405         this->ident = true;
406         if (!reset_recall(this->player_ptr)) {
407             used_up = false;
408         }
409
410         break;
411     case SV_SCROLL_AMUSEMENT:
412         this->ident = true;
413         generate_amusement(this->player_ptr, 1, false);
414         break;
415     case SV_SCROLL_STAR_AMUSEMENT:
416         this->ident = true;
417         generate_amusement(this->player_ptr, randint1(2) + 1, false);
418         break;
419     default:
420         break;
421     }
422
423     return used_up;
424 }