8 #include "object-use/read-execution.h"
9 #include "action/action-limited.h"
10 #include "artifact/fixed-art-types.h"
11 #include "avatar/avatar.h"
12 #include "core/player-redraw-types.h"
13 #include "core/player-update-types.h"
14 #include "core/show-file.h"
15 #include "core/window-redrawer.h"
16 #include "flavor/flavor-describer.h"
17 #include "flavor/object-flavor-types.h"
18 #include "inventory/inventory-object.h"
19 #include "inventory/inventory-slot-types.h"
20 #include "io/files-util.h"
21 #include "main/sound-definitions-table.h"
22 #include "main/sound-of-music.h"
23 #include "monster-floor/monster-summon.h"
24 #include "monster-floor/place-monster-types.h"
25 #include "object-use/item-use-checker.h"
26 #include "object/object-info.h"
27 #include "object/object-kind.h"
28 #include "perception/object-perception.h"
29 #include "player-info/equipment-info.h"
30 #include "player-status/player-energy.h"
31 #include "player/attack-defense-types.h"
32 #include "player/digestion-processor.h"
33 #include "player/player-damage.h"
34 #include "player/player-status-flags.h"
35 #include "spell-kind/magic-item-recharger.h"
36 #include "spell-kind/spells-curse-removal.h"
37 #include "spell-kind/spells-detection.h"
38 #include "spell-kind/spells-enchant.h"
39 #include "spell-kind/spells-floor.h"
40 #include "spell-kind/spells-genocide.h"
41 #include "spell-kind/spells-grid.h"
42 #include "spell-kind/spells-launcher.h"
43 #include "spell-kind/spells-lite.h"
44 #include "spell-kind/spells-neighbor.h"
45 #include "spell-kind/spells-perception.h"
46 #include "spell-kind/spells-sight.h"
47 #include "spell-kind/spells-teleport.h"
48 #include "spell-kind/spells-world.h"
49 #include "spell-realm/spells-hex.h"
50 #include "spell-realm/spells-song.h"
51 #include "spell/spell-types.h"
52 #include "spell/spells-object.h"
53 #include "spell/spells-summon.h"
54 #include "spell/summon-types.h"
55 #include "status/bad-status-setter.h"
56 #include "status/body-improvement.h"
57 #include "status/buff-setter.h"
58 #include "status/element-resistance.h"
59 #include "status/experience.h"
60 #include "store/rumor.h"
61 #include "sv-definition/sv-scroll-types.h"
62 #include "system/floor-type-definition.h"
63 #include "system/object-type-definition.h"
64 #include "system/player-type-definition.h"
65 #include "term/screen-processor.h"
66 #include "util/angband-files.h"
67 #include "view/display-messages.h"
71 * @param player_ptr プレイヤーへの参照ポインタ
72 * @param item 読むオブジェクトの所持品ID
74 ObjectReadEntity::ObjectReadEntity(player_type *player_ptr, INVENTORY_IDX item)
75 : player_ptr(player_ptr)
82 * @param known 判明済ならばTRUE
84 void ObjectReadEntity::execute(bool known)
86 auto *o_ptr = ref_item(this->player_ptr, this->item);
87 PlayerEnergy(this->player_ptr).set_player_turn_energy(100);
88 if (!this->check_can_read()) {
92 if (music_singing_any(this->player_ptr)) {
93 stop_singing(this->player_ptr);
96 SpellHex spell_hex(this->player_ptr);
97 if (spell_hex.is_spelling_any() && ((this->player_ptr->lev < 35) || spell_hex.is_casting_full_capacity())) {
98 (void)SpellHex(this->player_ptr).stop_all_spells();
102 auto lev = k_info[o_ptr->k_idx].level;
104 if (o_ptr->tval == ItemKindType::SCROLL) {
105 switch (o_ptr->sval) {
106 case SV_SCROLL_DARKNESS: {
107 if (!has_resist_blind(this->player_ptr) && !has_resist_dark(this->player_ptr))
108 (void)BadStatusSetter(this->player_ptr).mod_blindness(3 + randint1(5));
110 if (unlite_area(this->player_ptr, 10, 3))
115 case SV_SCROLL_AGGRAVATE_MONSTER: {
116 msg_print(_("カン高くうなる様な音が辺りを覆った。", "There is a high pitched humming noise."));
117 aggravate_monsters(this->player_ptr, 0);
121 case SV_SCROLL_CURSE_ARMOR: {
122 if (curse_armor(this->player_ptr))
127 case SV_SCROLL_CURSE_WEAPON: {
129 if (has_melee_weapon(this->player_ptr, INVEN_MAIN_HAND)) {
131 if (has_melee_weapon(this->player_ptr, INVEN_SUB_HAND) && one_in_(2))
133 } else if (has_melee_weapon(this->player_ptr, INVEN_SUB_HAND))
136 if (k && curse_weapon_object(this->player_ptr, false, &this->player_ptr->inventory_list[k]))
141 case SV_SCROLL_SUMMON_MONSTER: {
142 for (auto k = 0; k < randint1(3); k++) {
143 if (summon_specific(this->player_ptr, 0, this->player_ptr->y, this->player_ptr->x, this->player_ptr->current_floor_ptr->dun_level, SUMMON_NONE,
144 PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET)) {
151 case SV_SCROLL_SUMMON_UNDEAD: {
152 for (auto k = 0; k < randint1(3); k++) {
153 if (summon_specific(this->player_ptr, 0, this->player_ptr->y, this->player_ptr->x, this->player_ptr->current_floor_ptr->dun_level, SUMMON_UNDEAD,
154 PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET)) {
161 case SV_SCROLL_SUMMON_PET: {
163 this->player_ptr, -1, this->player_ptr->y, this->player_ptr->x, this->player_ptr->current_floor_ptr->dun_level, SUMMON_NONE, PM_ALLOW_GROUP | PM_FORCE_PET))
168 case SV_SCROLL_SUMMON_KIN: {
169 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))
174 case SV_SCROLL_TRAP_CREATION: {
175 if (trap_creation(this->player_ptr, this->player_ptr->y, this->player_ptr->x))
180 case SV_SCROLL_PHASE_DOOR: {
181 teleport_player(this->player_ptr, 10, TELEPORT_SPONTANEOUS);
185 case SV_SCROLL_TELEPORT: {
186 teleport_player(this->player_ptr, 100, TELEPORT_SPONTANEOUS);
190 case SV_SCROLL_TELEPORT_LEVEL: {
191 (void)teleport_level(this->player_ptr, 0);
195 case SV_SCROLL_WORD_OF_RECALL: {
196 if (!recall_player(this->player_ptr, randint0(21) + 15))
202 case SV_SCROLL_IDENTIFY: {
203 if (!ident_spell(this->player_ptr, false))
209 case SV_SCROLL_STAR_IDENTIFY: {
210 if (!identify_fully(this->player_ptr, false))
216 case SV_SCROLL_REMOVE_CURSE: {
217 if (remove_curse(this->player_ptr))
222 case SV_SCROLL_STAR_REMOVE_CURSE: {
223 if (remove_all_curse(this->player_ptr))
228 case SV_SCROLL_ENCHANT_ARMOR: {
230 if (!enchant_spell(this->player_ptr, 0, 0, 1))
235 case SV_SCROLL_ENCHANT_WEAPON_TO_HIT: {
236 if (!enchant_spell(this->player_ptr, 1, 0, 0))
242 case SV_SCROLL_ENCHANT_WEAPON_TO_DAM: {
243 if (!enchant_spell(this->player_ptr, 0, 1, 0))
249 case SV_SCROLL_STAR_ENCHANT_ARMOR: {
250 if (!enchant_spell(this->player_ptr, 0, 0, randint1(3) + 2))
256 case SV_SCROLL_STAR_ENCHANT_WEAPON: {
257 if (!enchant_spell(this->player_ptr, randint1(3), randint1(3), 0))
263 case SV_SCROLL_RECHARGING: {
264 if (!recharge(this->player_ptr, 130))
270 case SV_SCROLL_MUNDANITY: {
272 if (!mundane_spell(this->player_ptr, false))
277 case SV_SCROLL_LIGHT: {
278 if (lite_area(this->player_ptr, damroll(2, 8), 2))
283 case SV_SCROLL_MAPPING: {
284 map_area(this->player_ptr, DETECT_RAD_MAP);
288 case SV_SCROLL_DETECT_GOLD: {
289 if (detect_treasure(this->player_ptr, DETECT_RAD_DEFAULT) || detect_objects_gold(this->player_ptr, DETECT_RAD_DEFAULT))
294 case SV_SCROLL_DETECT_ITEM: {
295 if (detect_objects_normal(this->player_ptr, DETECT_RAD_DEFAULT))
300 case SV_SCROLL_DETECT_TRAP: {
301 if (detect_traps(this->player_ptr, DETECT_RAD_DEFAULT, known))
306 case SV_SCROLL_DETECT_DOOR: {
307 if (detect_doors(this->player_ptr, DETECT_RAD_DEFAULT) || detect_stairs(this->player_ptr, DETECT_RAD_DEFAULT))
312 case SV_SCROLL_DETECT_INVIS: {
313 if (detect_monsters_invis(this->player_ptr, DETECT_RAD_DEFAULT))
318 case SV_SCROLL_SATISFY_HUNGER: {
319 if (set_food(this->player_ptr, PY_FOOD_MAX - 1))
324 case SV_SCROLL_BLESSING: {
325 if (set_blessed(this->player_ptr, this->player_ptr->blessed + randint1(12) + 6, false))
330 case SV_SCROLL_HOLY_CHANT: {
331 if (set_blessed(this->player_ptr, this->player_ptr->blessed + randint1(24) + 12, false))
336 case SV_SCROLL_HOLY_PRAYER: {
337 if (set_blessed(this->player_ptr, this->player_ptr->blessed + randint1(48) + 24, false))
342 case SV_SCROLL_MONSTER_CONFUSION: {
343 if (!(this->player_ptr->special_attack & ATTACK_CONFUSE)) {
344 msg_print(_("手が輝き始めた。", "Your hands begin to glow."));
345 this->player_ptr->special_attack |= ATTACK_CONFUSE;
346 this->player_ptr->redraw |= PR_STATUS;
352 case SV_SCROLL_PROTECTION_FROM_EVIL: {
353 auto k = 3 * this->player_ptr->lev;
354 if (set_protevil(this->player_ptr, this->player_ptr->protevil + randint1(25) + k, false))
359 case SV_SCROLL_RUNE_OF_PROTECTION: {
360 create_rune_protection_one(this->player_ptr);
364 case SV_SCROLL_TRAP_DOOR_DESTRUCTION: {
365 if (destroy_doors_touch(this->player_ptr))
370 case SV_SCROLL_STAR_DESTRUCTION: {
371 if (destroy_area(this->player_ptr, this->player_ptr->y, this->player_ptr->x, 13 + randint0(5), false))
374 msg_print(_("ダンジョンが揺れた...", "The dungeon trembles..."));
378 case SV_SCROLL_DISPEL_UNDEAD: {
379 if (dispel_undead(this->player_ptr, 80))
384 case SV_SCROLL_SPELL: {
385 if ((this->player_ptr->pclass == CLASS_WARRIOR) || (this->player_ptr->pclass == CLASS_IMITATOR) || (this->player_ptr->pclass == CLASS_MINDCRAFTER)
386 || (this->player_ptr->pclass == CLASS_SORCERER) || (this->player_ptr->pclass == CLASS_ARCHER) || (this->player_ptr->pclass == CLASS_MAGIC_EATER)
387 || (this->player_ptr->pclass == CLASS_RED_MAGE) || (this->player_ptr->pclass == CLASS_SAMURAI) || (this->player_ptr->pclass == CLASS_BLUE_MAGE)
388 || (this->player_ptr->pclass == CLASS_CAVALRY) || (this->player_ptr->pclass == CLASS_BERSERKER) || (this->player_ptr->pclass == CLASS_SMITH)
389 || (this->player_ptr->pclass == CLASS_MIRROR_MASTER) || (this->player_ptr->pclass == CLASS_NINJA) || (this->player_ptr->pclass == CLASS_SNIPER))
392 this->player_ptr->add_spells++;
393 this->player_ptr->update |= PU_SPELLS;
397 case SV_SCROLL_GENOCIDE: {
398 (void)symbol_genocide(this->player_ptr, 300, true);
402 case SV_SCROLL_MASS_GENOCIDE: {
403 (void)mass_genocide(this->player_ptr, 300, true);
407 case SV_SCROLL_ACQUIREMENT: {
408 acquirement(this->player_ptr, this->player_ptr->y, this->player_ptr->x, 1, true, false, false);
412 case SV_SCROLL_STAR_ACQUIREMENT: {
413 acquirement(this->player_ptr, this->player_ptr->y, this->player_ptr->x, randint1(2) + 1, true, false, false);
417 case SV_SCROLL_FIRE: {
418 fire_ball(this->player_ptr, GF_FIRE, 0, 666, 4);
419 if (!(is_oppose_fire(this->player_ptr) || has_resist_fire(this->player_ptr) || has_immune_fire(this->player_ptr)))
420 take_hit(this->player_ptr, DAMAGE_NOESCAPE, 50 + randint1(50), _("炎の巻物", "a Scroll of Fire"));
425 case SV_SCROLL_ICE: {
426 fire_ball(this->player_ptr, GF_ICE, 0, 777, 4);
427 if (!(is_oppose_cold(this->player_ptr) || has_resist_cold(this->player_ptr) || has_immune_cold(this->player_ptr)))
428 take_hit(this->player_ptr, DAMAGE_NOESCAPE, 100 + randint1(100), _("氷の巻物", "a Scroll of Ice"));
433 case SV_SCROLL_CHAOS: {
434 fire_ball(this->player_ptr, GF_CHAOS, 0, 1000, 4);
435 if (!has_resist_chaos(this->player_ptr))
436 take_hit(this->player_ptr, DAMAGE_NOESCAPE, 111 + randint1(111), _("ログルスの巻物", "a Scroll of Logrus"));
441 case SV_SCROLL_RUMOR: {
442 msg_print(_("巻物にはメッセージが書かれている:", "There is message on the scroll. It says:"));
444 display_rumor(this->player_ptr, true);
446 msg_print(_("巻物は煙を立てて消え去った!", "The scroll disappears in a puff of smoke!"));
450 case SV_SCROLL_ARTIFACT: {
452 if (!artifact_scroll(this->player_ptr))
457 case SV_SCROLL_RESET_RECALL: {
459 if (!reset_recall(this->player_ptr))
464 case SV_SCROLL_AMUSEMENT: {
466 amusement(this->player_ptr, this->player_ptr->y, this->player_ptr->x, 1, false);
469 case SV_SCROLL_STAR_AMUSEMENT: {
471 amusement(this->player_ptr, this->player_ptr->y, this->player_ptr->x, randint1(2) + 1, false);
475 } else if (o_ptr->name1 == ART_GHB) {
476 msg_print(_("私は苦労して『グレーター・ヘル=ビースト』を倒した。", "I had a very hard time to kill the Greater hell-beast, "));
477 msg_print(_("しかし手に入ったのはこのきたないTシャツだけだった。", "but all I got was this lousy t-shirt!"));
479 } else if (o_ptr->name1 == ART_POWER) {
480 msg_print(_("「一つの指輪は全てを統べ、", "'One Ring to rule them all, "));
482 msg_print(_("一つの指輪は全てを見つけ、", "One Ring to find them, "));
484 msg_print(_("一つの指輪は全てを捕らえて", "One Ring to bring them all "));
486 msg_print(_("暗闇の中に繋ぎとめる。」", "and in the darkness bind them.'"));
488 } else if (o_ptr->tval == ItemKindType::PARCHMENT) {
489 GAME_TEXT o_name[MAX_NLEN];
492 auto q = format("book-%d_jp.txt", o_ptr->sval);
493 describe_flavor(this->player_ptr, o_name, o_ptr, OD_NAME_ONLY);
494 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, q);
495 (void)show_file(this->player_ptr, true, buf, o_name, 0, 0);
500 BIT_FLAGS inventory_flags = PU_COMBINE | PU_REORDER | (this->player_ptr->update & PU_AUTODESTROY);
501 this->player_ptr->update &= ~(PU_COMBINE | PU_REORDER | PU_AUTODESTROY);
503 if (!(o_ptr->is_aware())) {
504 chg_virtue(this->player_ptr, V_PATIENCE, -1);
505 chg_virtue(this->player_ptr, V_CHANCE, 1);
506 chg_virtue(this->player_ptr, V_KNOWLEDGE, -1);
510 if (ident && !o_ptr->is_aware()) {
511 object_aware(this->player_ptr, o_ptr);
512 gain_exp(this->player_ptr, (lev + (this->player_ptr->lev >> 1)) / this->player_ptr->lev);
515 this->player_ptr->window_flags |= PW_INVEN | PW_EQUIP | PW_PLAYER;
516 this->player_ptr->update |= inventory_flags;
521 vary_item(this->player_ptr, this->item, -1);
524 bool ObjectReadEntity::check_can_read()
526 if (cmd_limit_time_walk(this->player_ptr)) {
530 if (this->player_ptr->pclass == CLASS_BERSERKER) {
531 msg_print(_("巻物なんて読めない。", "You cannot read."));
535 return ItemUseChecker(this->player_ptr).check_stun(_("朦朧としていて読めなかった!", "You were not able to read it by the stun!"));