5 * @todo 少し長い。switch/case文と効果処理を分離してもいいかも
8 #include "object-use/quaff-execution.h"
9 #include "avatar/avatar.h"
10 #include "birth/birth-stat.h"
11 #include "core/player-update-types.h"
12 #include "core/window-redrawer.h"
13 #include "game-option/birth-options.h"
14 #include "game-option/disturbance-options.h"
15 #include "inventory/inventory-object.h"
16 #include "main/sound-definitions-table.h"
17 #include "main/sound-of-music.h"
18 #include "mutation/mutation-investor-remover.h"
19 #include "object-use/item-use-checker.h"
20 #include "object/object-broken.h"
21 #include "object/object-info.h"
22 #include "object/object-kind.h"
23 #include "perception/object-perception.h"
24 #include "player-base/player-race.h"
25 #include "player-info/mimic-info-table.h"
26 #include "player-info/self-info.h"
27 #include "player-status/player-energy.h"
28 #include "player/attack-defense-types.h"
29 #include "player/digestion-processor.h"
30 #include "player/eldritch-horror.h"
31 #include "player/player-damage.h"
32 #include "player/player-status-flags.h"
33 #include "realm/realm-hex-numbers.h"
34 #include "spell-kind/spells-detection.h"
35 #include "spell-kind/spells-floor.h"
36 #include "spell-kind/spells-perception.h"
37 #include "spell-kind/spells-teleport.h"
38 #include "spell-realm/spells-hex.h"
39 #include "spell-realm/spells-song.h"
40 #include "spell/spells-status.h"
41 #include "status/bad-status-setter.h"
42 #include "status/base-status.h"
43 #include "status/body-improvement.h"
44 #include "status/buff-setter.h"
45 #include "status/element-resistance.h"
46 #include "status/experience.h"
47 #include "status/shape-changer.h"
48 #include "status/sight-setter.h"
49 #include "sv-definition/sv-potion-types.h"
50 #include "system/object-type-definition.h"
51 #include "system/player-type-definition.h"
52 #include "term/screen-processor.h"
53 #include "view/display-messages.h"
57 * @param player_ptr プレイヤーへの参照ポインタ
59 ObjectQuaffEntity::ObjectQuaffEntity(player_type *player_ptr)
60 : player_ptr(player_ptr)
66 * @param item 飲む薬オブジェクトの所持品ID
68 * 効果発動のあと、食料タイプによって空腹度を少し充足する。
70 void ObjectQuaffEntity::execute(INVENTORY_IDX item)
72 PlayerEnergy(this->player_ptr).set_player_turn_energy(100);
73 if (!this->check_can_quaff()) {
77 if (music_singing_any(this->player_ptr))
78 stop_singing(this->player_ptr);
80 SpellHex spell_hex(this->player_ptr);
81 if (spell_hex.is_spelling_any() && !spell_hex.is_spelling_specific(HEX_INHALE)) {
82 (void)SpellHex(this->player_ptr).stop_all_spells();
85 auto *o_ptr = ref_item(this->player_ptr, item);
88 q_ptr->copy_from(o_ptr);
90 vary_item(this->player_ptr, item, -1);
93 if (q_ptr->tval == ItemKindType::POTION) {
94 switch (q_ptr->sval) {
96 msg_print(_("口の中がさっぱりした。", "That was refreshing."));
97 msg_print(_("のどの渇きが少しおさまった。", "You feel less thirsty."));
101 case SV_POTION_APPLE_JUICE:
102 msg_print(_("甘くてサッパリとしていて、とてもおいしい。", "It's sweet, refreshing and very tasty."));
103 msg_print(_("のどの渇きが少しおさまった。", "You feel less thirsty."));
107 case SV_POTION_SLIME_MOLD:
108 msg_print(_("なんとも不気味な味だ。", "That was strange."));
109 msg_print(_("のどの渇きが少しおさまった。", "You feel less thirsty."));
113 case SV_POTION_SLOWNESS:
114 if (BadStatusSetter(this->player_ptr).slowness(randint1(25) + 15, false))
118 case SV_POTION_SALT_WATER: {
119 msg_print(_("うぇ!思わず吐いてしまった。", "The potion makes you vomit!"));
120 switch (PlayerRace(this->player_ptr).food()) {
121 case PlayerRaceFoodType::RATION:
122 case PlayerRaceFoodType::WATER:
123 case PlayerRaceFoodType::BLOOD:
124 (void)set_food(this->player_ptr, PY_FOOD_STARVE - 1);
130 BadStatusSetter bss(this->player_ptr);
132 (void)bss.mod_paralysis(4);
136 case SV_POTION_POISON:
137 if (!(has_resist_pois(this->player_ptr) || is_oppose_pois(this->player_ptr))) {
138 if (BadStatusSetter(this->player_ptr).mod_poison(randint0(15) + 10)) {
144 case SV_POTION_BLINDNESS:
145 if (!has_resist_blind(this->player_ptr)) {
146 if (BadStatusSetter(this->player_ptr).mod_blindness(randint0(100) + 100)) {
152 case SV_POTION_BOOZE:
156 case SV_POTION_SLEEP:
157 if (this->player_ptr->free_act) {
161 msg_print(_("あなたは眠ってしまった。", "You fall asleep."));
162 if (ironman_nightmare) {
163 msg_print(_("恐ろしい光景が頭に浮かんできた。", "A horrible vision enters your mind."));
164 sanity_blast(this->player_ptr, nullptr, false);
167 if (BadStatusSetter(this->player_ptr).mod_paralysis(randint0(4) + 4)) {
172 case SV_POTION_LOSE_MEMORIES:
173 if (!this->player_ptr->hold_exp && (this->player_ptr->exp > 0)) {
174 msg_print(_("過去の記憶が薄れていく気がする。", "You feel your memories fade."));
175 chg_virtue(this->player_ptr, V_KNOWLEDGE, -5);
177 lose_exp(this->player_ptr, this->player_ptr->exp / 4);
182 case SV_POTION_RUINATION:
183 msg_print(_("身も心も弱ってきて、精気が抜けていくようだ。", "Your nerves and muscles feel weak and lifeless!"));
184 take_hit(this->player_ptr, DAMAGE_LOSELIFE, damroll(10, 10), _("破滅の薬", "a potion of Ruination"));
186 (void)dec_stat(this->player_ptr, A_DEX, 25, true);
187 (void)dec_stat(this->player_ptr, A_WIS, 25, true);
188 (void)dec_stat(this->player_ptr, A_CON, 25, true);
189 (void)dec_stat(this->player_ptr, A_STR, 25, true);
190 (void)dec_stat(this->player_ptr, A_CHR, 25, true);
191 (void)dec_stat(this->player_ptr, A_INT, 25, true);
195 case SV_POTION_DEC_STR:
196 if (do_dec_stat(this->player_ptr, A_STR))
200 case SV_POTION_DEC_INT:
201 if (do_dec_stat(this->player_ptr, A_INT))
205 case SV_POTION_DEC_WIS:
206 if (do_dec_stat(this->player_ptr, A_WIS))
210 case SV_POTION_DEC_DEX:
211 if (do_dec_stat(this->player_ptr, A_DEX))
215 case SV_POTION_DEC_CON:
216 if (do_dec_stat(this->player_ptr, A_CON))
220 case SV_POTION_DEC_CHR:
221 if (do_dec_stat(this->player_ptr, A_CHR))
225 case SV_POTION_DETONATIONS:
226 ident = detonation();
229 case SV_POTION_DEATH:
230 chg_virtue(this->player_ptr, V_VITALITY, -1);
231 chg_virtue(this->player_ptr, V_UNLIFE, 5);
232 msg_print(_("死の予感が体中を駆けめぐった。", "A feeling of Death flows through your body."));
233 take_hit(this->player_ptr, DAMAGE_LOSELIFE, 5000, _("死の薬", "a potion of Death"));
237 case SV_POTION_INFRAVISION:
238 if (set_tim_infra(this->player_ptr, this->player_ptr->tim_infra + 100 + randint1(100), false)) {
243 case SV_POTION_DETECT_INVIS:
244 if (set_tim_invis(this->player_ptr, this->player_ptr->tim_invis + 12 + randint1(12), false)) {
249 case SV_POTION_SLOW_POISON:
250 if (BadStatusSetter(this->player_ptr).poison(this->player_ptr->poisoned / 2))
254 case SV_POTION_CURE_POISON:
255 if (BadStatusSetter(this->player_ptr).poison(0))
259 case SV_POTION_BOLDNESS:
260 if (BadStatusSetter(this->player_ptr).afraidness(0))
264 case SV_POTION_SPEED:
265 if (!this->player_ptr->fast) {
266 if (set_fast(this->player_ptr, randint1(25) + 15, false))
269 (void)set_fast(this->player_ptr, this->player_ptr->fast + 5, false);
273 case SV_POTION_RESIST_HEAT:
274 if (set_oppose_fire(this->player_ptr, this->player_ptr->oppose_fire + randint1(10) + 10, false)) {
279 case SV_POTION_RESIST_COLD:
280 if (set_oppose_cold(this->player_ptr, this->player_ptr->oppose_cold + randint1(10) + 10, false)) {
285 case SV_POTION_HEROISM:
286 ident = heroism(this->player_ptr, 25);
289 case SV_POTION_BESERK_STRENGTH:
290 ident = berserk(this->player_ptr, randint1(25) + 25);
293 case SV_POTION_CURE_LIGHT:
294 ident = cure_light_wounds(this->player_ptr, 2, 8);
297 case SV_POTION_CURE_SERIOUS:
298 ident = cure_serious_wounds(this->player_ptr, 4, 8);
301 case SV_POTION_CURE_CRITICAL:
302 ident = cure_critical_wounds(this->player_ptr, damroll(6, 8));
305 case SV_POTION_HEALING:
306 ident = cure_critical_wounds(this->player_ptr, 300);
309 case SV_POTION_STAR_HEALING:
310 ident = cure_critical_wounds(this->player_ptr, 1200);
314 ident = life_stream(this->player_ptr, true, true);
317 case SV_POTION_RESTORE_MANA:
318 ident = restore_mana(this->player_ptr, true);
321 case SV_POTION_RESTORE_EXP:
322 if (restore_level(this->player_ptr))
326 case SV_POTION_RES_STR:
327 if (do_res_stat(this->player_ptr, A_STR))
331 case SV_POTION_RES_INT:
332 if (do_res_stat(this->player_ptr, A_INT))
336 case SV_POTION_RES_WIS:
337 if (do_res_stat(this->player_ptr, A_WIS))
341 case SV_POTION_RES_DEX:
342 if (do_res_stat(this->player_ptr, A_DEX))
346 case SV_POTION_RES_CON:
347 if (do_res_stat(this->player_ptr, A_CON))
351 case SV_POTION_RES_CHR:
352 if (do_res_stat(this->player_ptr, A_CHR))
356 case SV_POTION_INC_STR:
357 if (do_inc_stat(this->player_ptr, A_STR))
361 case SV_POTION_INC_INT:
362 if (do_inc_stat(this->player_ptr, A_INT))
366 case SV_POTION_INC_WIS:
367 if (do_inc_stat(this->player_ptr, A_WIS))
371 case SV_POTION_INC_DEX:
372 if (do_inc_stat(this->player_ptr, A_DEX))
376 case SV_POTION_INC_CON:
377 if (do_inc_stat(this->player_ptr, A_CON))
381 case SV_POTION_INC_CHR:
382 if (do_inc_stat(this->player_ptr, A_CHR))
386 case SV_POTION_POLY_SELF:
387 do_poly_self(this->player_ptr);
391 case SV_POTION_AUGMENTATION:
392 if (do_inc_stat(this->player_ptr, A_STR))
394 if (do_inc_stat(this->player_ptr, A_INT))
396 if (do_inc_stat(this->player_ptr, A_WIS))
398 if (do_inc_stat(this->player_ptr, A_DEX))
400 if (do_inc_stat(this->player_ptr, A_CON))
402 if (do_inc_stat(this->player_ptr, A_CHR))
406 case SV_POTION_ENLIGHTENMENT:
407 msg_print(_("自分の置かれている状況が脳裏に浮かんできた...", "An image of your surroundings forms in your mind..."));
408 chg_virtue(this->player_ptr, V_KNOWLEDGE, 1);
409 chg_virtue(this->player_ptr, V_ENLIGHTEN, 1);
410 wiz_lite(this->player_ptr, false);
414 case SV_POTION_STAR_ENLIGHTENMENT:
415 msg_print(_("更なる啓蒙を感じた...", "You begin to feel more enlightened..."));
416 chg_virtue(this->player_ptr, V_KNOWLEDGE, 1);
417 chg_virtue(this->player_ptr, V_ENLIGHTEN, 2);
419 wiz_lite(this->player_ptr, false);
420 (void)do_inc_stat(this->player_ptr, A_INT);
421 (void)do_inc_stat(this->player_ptr, A_WIS);
422 (void)detect_traps(this->player_ptr, DETECT_RAD_DEFAULT, true);
423 (void)detect_doors(this->player_ptr, DETECT_RAD_DEFAULT);
424 (void)detect_stairs(this->player_ptr, DETECT_RAD_DEFAULT);
425 (void)detect_treasure(this->player_ptr, DETECT_RAD_DEFAULT);
426 (void)detect_objects_gold(this->player_ptr, DETECT_RAD_DEFAULT);
427 (void)detect_objects_normal(this->player_ptr, DETECT_RAD_DEFAULT);
428 identify_pack(this->player_ptr);
429 self_knowledge(this->player_ptr);
433 case SV_POTION_SELF_KNOWLEDGE:
434 msg_print(_("自分自身のことが少しは分かった気がする...", "You begin to know yourself a little better..."));
436 self_knowledge(this->player_ptr);
440 case SV_POTION_EXPERIENCE:
441 if (this->player_ptr->prace == PlayerRaceType::ANDROID)
443 chg_virtue(this->player_ptr, V_ENLIGHTEN, 1);
444 if (this->player_ptr->exp < PY_MAX_EXP) {
445 EXP ee = (this->player_ptr->exp / 2) + 10;
448 msg_print(_("更に経験を積んだような気がする。", "You feel more experienced."));
449 gain_exp(this->player_ptr, ee);
454 case SV_POTION_RESISTANCE:
455 (void)set_oppose_acid(this->player_ptr, this->player_ptr->oppose_acid + randint1(20) + 20, false);
456 (void)set_oppose_elec(this->player_ptr, this->player_ptr->oppose_elec + randint1(20) + 20, false);
457 (void)set_oppose_fire(this->player_ptr, this->player_ptr->oppose_fire + randint1(20) + 20, false);
458 (void)set_oppose_cold(this->player_ptr, this->player_ptr->oppose_cold + randint1(20) + 20, false);
459 (void)set_oppose_pois(this->player_ptr, this->player_ptr->oppose_pois + randint1(20) + 20, false);
463 case SV_POTION_CURING:
464 if (true_healing(this->player_ptr, 50))
468 case SV_POTION_INVULNERABILITY:
469 (void)set_invuln(this->player_ptr, this->player_ptr->invuln + randint1(4) + 4, false);
473 case SV_POTION_NEW_LIFE:
474 roll_hitdice(this->player_ptr, SPOP_NONE);
475 get_max_stats(this->player_ptr);
476 this->player_ptr->update |= PU_BONUS;
477 lose_all_mutations(this->player_ptr);
481 case SV_POTION_NEO_TSUYOSHI:
482 (void)BadStatusSetter(this->player_ptr).hallucination(0);
483 (void)set_tsuyoshi(this->player_ptr, this->player_ptr->tsuyoshi + randint1(100) + 100, false);
487 case SV_POTION_TSUYOSHI:
488 msg_print(_("「オクレ兄さん!」", "Brother OKURE!"));
490 this->player_ptr->tsuyoshi = 1;
491 (void)set_tsuyoshi(this->player_ptr, 0, true);
492 if (!has_resist_chaos(this->player_ptr)) {
493 (void)BadStatusSetter(this->player_ptr).hallucination(50 + randint1(50));
498 case SV_POTION_POLYMORPH:
499 if (this->player_ptr->muta.any() && one_in_(23)) {
500 lose_all_mutations(this->player_ptr);
504 if (gain_mutation(this->player_ptr, 0))
506 } else if (lose_mutation(this->player_ptr, 0))
508 } while (!ident || one_in_(2));
514 if (PlayerRace(this->player_ptr).equals(PlayerRaceType::SKELETON)) {
515 msg_print(_("液体の一部はあなたのアゴを素通りして落ちた!", "Some of the fluid falls through your jaws!"));
516 (void)potion_smash_effect(this->player_ptr, 0, this->player_ptr->y, this->player_ptr->x, q_ptr->k_idx);
519 this->player_ptr->update |= PU_COMBINE | PU_REORDER;
520 if (!(q_ptr->is_aware())) {
521 chg_virtue(this->player_ptr, V_PATIENCE, -1);
522 chg_virtue(this->player_ptr, V_CHANCE, 1);
523 chg_virtue(this->player_ptr, V_KNOWLEDGE, -1);
526 /* The item has been tried */
529 /* An identification was made */
530 if (ident && !q_ptr->is_aware()) {
531 object_aware(this->player_ptr, q_ptr);
532 gain_exp(this->player_ptr, (k_info[q_ptr->k_idx].level + (this->player_ptr->lev >> 1)) / this->player_ptr->lev);
535 this->player_ptr->window_flags |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
537 if (PlayerRace(this->player_ptr).equals(PlayerRaceType::SKELETON))
538 return; //!< @note スケルトンは水分で飢えを満たせない
540 switch (PlayerRace(this->player_ptr).food()) {
541 case PlayerRaceFoodType::WATER:
542 msg_print(_("水分を取り込んだ。", "You are moistened."));
543 set_food(this->player_ptr, std::min<short>(this->player_ptr->food + q_ptr->pval + std::max<short>(0, q_ptr->pval * 10) + 2000, PY_FOOD_MAX - 1));
545 case PlayerRaceFoodType::OIL:
546 if (q_ptr->tval == ItemKindType::FLASK) {
547 msg_print(_("オイルを補給した。", "You replenish yourself with the oil."));
548 set_food(this->player_ptr, this->player_ptr->food + 5000);
550 set_food(this->player_ptr, this->player_ptr->food + ((q_ptr->pval) / 20));
553 case PlayerRaceFoodType::BLOOD:
554 (void)set_food(this->player_ptr, this->player_ptr->food + (q_ptr->pval / 10));
556 case PlayerRaceFoodType::MANA:
557 case PlayerRaceFoodType::CORPSE:
558 set_food(this->player_ptr, this->player_ptr->food + ((q_ptr->pval) / 20));
561 (void)set_food(this->player_ptr, this->player_ptr->food + q_ptr->pval);
566 bool ObjectQuaffEntity::check_can_quaff()
568 if (this->player_ptr->timewalk) {
573 msg_print(_("瓶から水が流れ出てこない!", "The potion doesn't flow out from the bottle."));
578 return ItemUseChecker(this->player_ptr).check_stun(_("朦朧としていて瓶の蓋を開けられなかった!", "You were not able to quaff it by the stun!"));
583 * @param player_ptr プレイヤーへの参照ポインタ
584 * @return カオス耐性があるかその他の一部確率でFALSE、それ以外はTRUE
586 bool ObjectQuaffEntity::booze()
589 if (this->player_ptr->pclass != PlayerClassType::MONK)
590 chg_virtue(this->player_ptr, V_HARMONY, -1);
591 else if (!has_resist_conf(this->player_ptr))
592 this->player_ptr->special_attack |= ATTACK_SUIKEN;
594 BadStatusSetter bss(this->player_ptr);
595 if (!has_resist_conf(this->player_ptr) && bss.confusion(randint0(20) + 15)) {
599 if (has_resist_chaos(this->player_ptr)) {
603 if (one_in_(2) && bss.mod_hallucination(randint0(150) + 150)) {
607 if (one_in_(13) && (this->player_ptr->pclass != PlayerClassType::MONK)) {
610 lose_all_info(this->player_ptr);
612 wiz_dark(this->player_ptr);
614 (void)teleport_player_aux(this->player_ptr, 100, false, i2enum<teleport_flags>(TELEPORT_NONMAGICAL | TELEPORT_PASSIVE));
615 wiz_dark(this->player_ptr);
616 msg_print(_("知らない場所で目が醒めた。頭痛がする。", "You wake up somewhere with a sore head..."));
617 msg_print(_("何も思い出せない。どうやってここへ来たのかも分からない!", "You can't remember a thing or how you got here!"));
624 * @brief 爆発の薬の効果処理 / Fumble ramble
625 * @param player_ptr プレイヤーへの参照ポインタ
628 bool ObjectQuaffEntity::detonation()
630 msg_print(_("体の中で激しい爆発が起きた!", "Massive explosions rupture your body!"));
631 take_hit(this->player_ptr, DAMAGE_NOESCAPE, damroll(50, 20), _("爆発の薬", "a potion of Detonation"));
632 BadStatusSetter bss(this->player_ptr);
633 (void)bss.mod_stun(75);
634 (void)bss.mod_cut(5000);