OSDN Git Service

[Refactor] #2523 PlayerType::poisoned をPlayerPoison の呼び出しに差し替えた
[hengbandforosx/hengbandosx.git] / src / object-use / quaff / quaff-effects.cpp
1 /*
2  * @brief 薬を飲んだ時の効果処理
3  * @date 2022/03/10
4  * @author Hourier
5  */
6
7 #include "object-use/quaff/quaff-effects.h"
8 #include "avatar/avatar.h"
9 #include "birth/birth-stat.h"
10 #include "core/player-update-types.h"
11 #include "game-option/birth-options.h"
12 #include "mutation/mutation-investor-remover.h"
13 #include "object/object-info.h"
14 #include "player-base/player-class.h"
15 #include "player-base/player-race.h"
16 #include "player-info/race-info.h"
17 #include "player-info/self-info.h"
18 #include "player/attack-defense-types.h"
19 #include "player/digestion-processor.h"
20 #include "player/eldritch-horror.h"
21 #include "player/player-damage.h"
22 #include "player/player-status-flags.h"
23 #include "spell-kind/spells-detection.h"
24 #include "spell-kind/spells-floor.h"
25 #include "spell-kind/spells-perception.h"
26 #include "spell-kind/spells-teleport.h"
27 #include "spell/spells-status.h"
28 #include "status/bad-status-setter.h"
29 #include "status/base-status.h"
30 #include "status/body-improvement.h"
31 #include "status/buff-setter.h"
32 #include "status/element-resistance.h"
33 #include "status/experience.h"
34 #include "status/shape-changer.h"
35 #include "status/sight-setter.h"
36 #include "sv-definition/sv-potion-types.h"
37 #include "system/angband.h"
38 #include "system/object-type-definition.h"
39 #include "system/player-type-definition.h"
40 #include "timed-effect/player-acceleration.h"
41 #include "timed-effect/player-poison.h"
42 #include "timed-effect/timed-effects.h"
43 #include "util/bit-flags-calculator.h"
44 #include "view/display-messages.h"
45
46 QuaffEffects::QuaffEffects(PlayerType *player_ptr)
47     : player_ptr(player_ptr)
48 {
49 }
50
51 bool QuaffEffects::influence(const ObjectType &o_ref)
52 {
53     if (o_ref.tval != ItemKindType::POTION) {
54         return false;
55     }
56
57     switch (o_ref.sval) {
58     case SV_POTION_WATER:
59         msg_print(_("口の中がさっぱりした。", "That was refreshing."));
60         msg_print(_("のどの渇きが少しおさまった。", "You feel less thirsty."));
61         return true;
62     case SV_POTION_APPLE_JUICE:
63         msg_print(_("甘くてサッパリとしていて、とてもおいしい。", "It's sweet, refreshing and very tasty."));
64         msg_print(_("のどの渇きが少しおさまった。", "You feel less thirsty."));
65         return true;
66     case SV_POTION_SLIME_MOLD:
67         msg_print(_("なんとも不気味な味だ。", "That was strange."));
68         msg_print(_("のどの渇きが少しおさまった。", "You feel less thirsty."));
69         return true;
70     case SV_POTION_SLOWNESS:
71         return BadStatusSetter(this->player_ptr).set_deceleration(randint1(25) + 15, false);
72     case SV_POTION_SALT_WATER:
73         return this->salt_water();
74     case SV_POTION_POISON:
75         return this->poison();
76     case SV_POTION_BLINDNESS:
77         return this->blindness();
78     case SV_POTION_BOOZE:
79         return this->booze();
80         break;
81     case SV_POTION_SLEEP:
82         return this->sleep();
83     case SV_POTION_LOSE_MEMORIES:
84         return this->lose_memories();
85     case SV_POTION_RUINATION:
86         return this->ruination();
87     case SV_POTION_DEC_STR:
88         return do_dec_stat(this->player_ptr, A_STR);
89     case SV_POTION_DEC_INT:
90         return do_dec_stat(this->player_ptr, A_INT);
91     case SV_POTION_DEC_WIS:
92         return do_dec_stat(this->player_ptr, A_WIS);
93     case SV_POTION_DEC_DEX:
94         return do_dec_stat(this->player_ptr, A_DEX);
95     case SV_POTION_DEC_CON:
96         return do_dec_stat(this->player_ptr, A_CON);
97     case SV_POTION_DEC_CHR:
98         return do_dec_stat(this->player_ptr, A_CHR);
99     case SV_POTION_DETONATIONS:
100         return this->detonation();
101     case SV_POTION_DEATH:
102         return this->death();
103     case SV_POTION_INFRAVISION:
104         return set_tim_infra(this->player_ptr, this->player_ptr->tim_infra + 100 + randint1(100), false);
105     case SV_POTION_DETECT_INVIS:
106         return set_tim_invis(this->player_ptr, this->player_ptr->tim_invis + 12 + randint1(12), false);
107     case SV_POTION_SLOW_POISON: {
108         const auto player_poison = this->player_ptr->effects()->poison();
109         return BadStatusSetter(this->player_ptr).poison(player_poison->current() / 2);
110     }
111     case SV_POTION_CURE_POISON:
112         return BadStatusSetter(this->player_ptr).poison(0);
113     case SV_POTION_BOLDNESS:
114         return BadStatusSetter(this->player_ptr).fear(0);
115     case SV_POTION_SPEED:
116         return this->speed();
117     case SV_POTION_RESIST_HEAT:
118         return set_oppose_fire(this->player_ptr, this->player_ptr->oppose_fire + randint1(10) + 10, false);
119     case SV_POTION_RESIST_COLD:
120         return set_oppose_cold(this->player_ptr, this->player_ptr->oppose_cold + randint1(10) + 10, false);
121     case SV_POTION_HEROISM:
122         return heroism(this->player_ptr, 25);
123     case SV_POTION_BESERK_STRENGTH:
124         return berserk(this->player_ptr, randint1(25) + 25);
125     case SV_POTION_CURE_LIGHT:
126         return cure_light_wounds(this->player_ptr, 2, 8);
127     case SV_POTION_CURE_SERIOUS:
128         return cure_serious_wounds(this->player_ptr, 4, 8);
129     case SV_POTION_CURE_CRITICAL:
130         return cure_critical_wounds(this->player_ptr, damroll(6, 8));
131     case SV_POTION_HEALING:
132         return cure_critical_wounds(this->player_ptr, 300);
133     case SV_POTION_STAR_HEALING:
134         return cure_critical_wounds(this->player_ptr, 1200);
135     case SV_POTION_LIFE:
136         return life_stream(this->player_ptr, true, true);
137     case SV_POTION_RESTORE_MANA:
138         return restore_mana(this->player_ptr, true);
139     case SV_POTION_RESTORE_EXP:
140         return restore_level(this->player_ptr);
141     case SV_POTION_RES_STR:
142         return do_res_stat(this->player_ptr, A_STR);
143     case SV_POTION_RES_INT:
144         return do_res_stat(this->player_ptr, A_INT);
145     case SV_POTION_RES_WIS:
146         return do_res_stat(this->player_ptr, A_WIS);
147     case SV_POTION_RES_DEX:
148         return do_res_stat(this->player_ptr, A_DEX);
149     case SV_POTION_RES_CON:
150         return do_res_stat(this->player_ptr, A_CON);
151     case SV_POTION_RES_CHR:
152         return do_res_stat(this->player_ptr, A_CHR);
153     case SV_POTION_INC_STR:
154         return do_inc_stat(this->player_ptr, A_STR);
155     case SV_POTION_INC_INT:
156         return do_inc_stat(this->player_ptr, A_INT);
157     case SV_POTION_INC_WIS:
158         return do_inc_stat(this->player_ptr, A_WIS);
159     case SV_POTION_INC_DEX:
160         return do_inc_stat(this->player_ptr, A_DEX);
161     case SV_POTION_INC_CON:
162         return do_inc_stat(this->player_ptr, A_CON);
163     case SV_POTION_INC_CHR:
164         return do_inc_stat(this->player_ptr, A_CHR);
165     case SV_POTION_POLY_SELF:
166         do_poly_self(this->player_ptr);
167         return true;
168     case SV_POTION_AUGMENTATION:
169         return this->augmentation();
170     case SV_POTION_ENLIGHTENMENT:
171         return this->enlightenment();
172     case SV_POTION_STAR_ENLIGHTENMENT:
173         return this->star_enlightenment();
174     case SV_POTION_SELF_KNOWLEDGE:
175         msg_print(_("自分自身のことが少しは分かった気がする...", "You begin to know yourself a little better..."));
176         msg_print(nullptr);
177         self_knowledge(this->player_ptr);
178         return true;
179     case SV_POTION_EXPERIENCE:
180         return this->experience();
181     case SV_POTION_RESISTANCE:
182         return this->resistance();
183     case SV_POTION_CURING:
184         return true_healing(this->player_ptr, 50);
185     case SV_POTION_INVULNERABILITY:
186         (void)set_invuln(this->player_ptr, this->player_ptr->invuln + randint1(4) + 4, false);
187         return true;
188     case SV_POTION_NEW_LIFE:
189         return this->new_life();
190     case SV_POTION_NEO_TSUYOSHI:
191         return this->neo_tsuyoshi();
192     case SV_POTION_TSUYOSHI:
193         return this->tsuyoshi();
194     case SV_POTION_POLYMORPH:
195         return this->polymorph();
196     default:
197         return false;
198     }
199 }
200
201 /*!
202  * @brief 塩水の薬
203  * @return 常にtrue
204  */
205 bool QuaffEffects::salt_water()
206 {
207     msg_print(_("うぇ!思わず吐いてしまった。", "The potion makes you vomit!"));
208     switch (PlayerRace(this->player_ptr).food()) {
209     case PlayerRaceFoodType::RATION:
210     case PlayerRaceFoodType::WATER:
211     case PlayerRaceFoodType::BLOOD:
212         (void)set_food(this->player_ptr, PY_FOOD_STARVE - 1);
213         break;
214     default:
215         break;
216     }
217
218     BadStatusSetter bss(this->player_ptr);
219     (void)bss.poison(0);
220     (void)bss.mod_paralysis(4);
221     return true;
222 }
223
224 /*!
225  * @brief 毒の薬
226  * @return 毒の効果を受けたらtrue
227  */
228 bool QuaffEffects::poison()
229 {
230     if (has_resist_pois(this->player_ptr) || is_oppose_pois(this->player_ptr)) {
231         return false;
232     }
233
234     return BadStatusSetter(this->player_ptr).mod_poison(randint0(15) + 10);
235 }
236
237 /*!
238  * @brief 盲目の薬
239  * @return 盲目になったらtrue
240  */
241 bool QuaffEffects::blindness()
242 {
243     if (has_resist_blind(this->player_ptr)) {
244         return false;
245     }
246
247     return BadStatusSetter(this->player_ptr).mod_blindness(randint0(100) + 100);
248 }
249
250 /*!
251  * @brief 酔っ払いの薬
252  * @return カオス耐性があるかその他の一部確率でFALSE、それ以外はTRUE
253  */
254 bool QuaffEffects::booze()
255 {
256     auto ident = false;
257     auto is_monk = PlayerClass(this->player_ptr).equals(PlayerClassType::MONK);
258     if (!is_monk) {
259         chg_virtue(this->player_ptr, V_HARMONY, -1);
260     } else if (!has_resist_conf(this->player_ptr)) {
261         set_bits(this->player_ptr->special_attack, ATTACK_SUIKEN);
262     }
263
264     BadStatusSetter bss(this->player_ptr);
265     if (!has_resist_conf(this->player_ptr) && bss.confusion(randint0(20) + 15)) {
266         ident = true;
267     }
268
269     if (has_resist_chaos(this->player_ptr)) {
270         return ident;
271     }
272
273     if (one_in_(2) && bss.mod_hallucination(randint0(150) + 150)) {
274         ident = true;
275     }
276
277     if (!is_monk || !one_in_(13)) {
278         return ident;
279     }
280
281     ident = true;
282     if (one_in_(3)) {
283         lose_all_info(this->player_ptr);
284     } else {
285         wiz_dark(this->player_ptr);
286     }
287
288     (void)teleport_player_aux(this->player_ptr, 100, false, i2enum<teleport_flags>(TELEPORT_NONMAGICAL | TELEPORT_PASSIVE));
289     wiz_dark(this->player_ptr);
290     msg_print(_("知らない場所で目が醒めた。頭痛がする。", "You wake up somewhere with a sore head..."));
291     msg_print(_("何も思い出せない。どうやってここへ来たのかも分からない!", "You can't remember a thing or how you got here!"));
292     return ident;
293 }
294
295 /*!
296  * @brief 眠りの薬
297  * @return 麻痺したか否か
298  */
299 bool QuaffEffects::sleep()
300 {
301     if (this->player_ptr->free_act) {
302         return false;
303     }
304
305     msg_print(_("あなたは眠ってしまった。", "You fall asleep."));
306     if (ironman_nightmare) {
307         msg_print(_("恐ろしい光景が頭に浮かんできた。", "A horrible vision enters your mind."));
308         sanity_blast(this->player_ptr, nullptr, false);
309     }
310
311     return BadStatusSetter(this->player_ptr).mod_paralysis(randint0(4) + 4);
312 }
313
314 /*!
315  * @brief 記憶喪失の薬
316  * @return 経験値が下がったか
317  */
318 bool QuaffEffects::lose_memories()
319 {
320     if (this->player_ptr->hold_exp || (this->player_ptr->exp <= 0)) {
321         return false;
322     }
323
324     msg_print(_("過去の記憶が薄れていく気がする。", "You feel your memories fade."));
325     chg_virtue(this->player_ptr, V_KNOWLEDGE, -5);
326     lose_exp(this->player_ptr, this->player_ptr->exp / 4);
327     return true;
328 }
329
330 /*!
331  * @brief 破滅の薬
332  * @return 常にtrue
333  */
334 bool QuaffEffects::ruination()
335 {
336     msg_print(_("身も心も弱ってきて、精気が抜けていくようだ。", "Your nerves and muscles feel weak and lifeless!"));
337     take_hit(this->player_ptr, DAMAGE_LOSELIFE, damroll(10, 10), _("破滅の薬", "a potion of Ruination"));
338     (void)dec_stat(this->player_ptr, A_DEX, 25, true);
339     (void)dec_stat(this->player_ptr, A_WIS, 25, true);
340     (void)dec_stat(this->player_ptr, A_CON, 25, true);
341     (void)dec_stat(this->player_ptr, A_STR, 25, true);
342     (void)dec_stat(this->player_ptr, A_CHR, 25, true);
343     (void)dec_stat(this->player_ptr, A_INT, 25, true);
344     return true;
345 }
346
347 /*!
348  * @brief 爆発の薬 / Fumble ramble
349  * @return 常にtrue
350  */
351 bool QuaffEffects::detonation()
352 {
353     msg_print(_("体の中で激しい爆発が起きた!", "Massive explosions rupture your body!"));
354     take_hit(this->player_ptr, DAMAGE_NOESCAPE, damroll(50, 20), _("爆発の薬", "a potion of Detonation"));
355     BadStatusSetter bss(this->player_ptr);
356     (void)bss.mod_stun(75);
357     (void)bss.mod_cut(5000);
358     return true;
359 }
360
361 /*!
362  * @brief 死の薬
363  * @return 常にtrue
364  */
365 bool QuaffEffects::death()
366 {
367     chg_virtue(this->player_ptr, V_VITALITY, -1);
368     chg_virtue(this->player_ptr, V_UNLIFE, 5);
369     msg_print(_("死の予感が体中を駆けめぐった。", "A feeling of Death flows through your body."));
370     take_hit(this->player_ptr, DAMAGE_LOSELIFE, 5000, _("死の薬", "a potion of Death"));
371     return true;
372 }
373
374 /*!
375  * @brief スピードの薬
376  * @return 加速したらtrue、加速効果が切れていない状態で重ね飲みしたらfalse
377  */
378 bool QuaffEffects::speed()
379 {
380     if (this->player_ptr->effects()->acceleration()->is_fast()) {
381         (void)mod_acceleration(this->player_ptr, 5, false);
382         return false;
383     }
384
385     return set_acceleration(this->player_ptr, randint1(25) + 15, false);
386 }
387
388 /*!
389  * @brief 増強の薬
390  * @return アビリティスコアのどれか1つでも向上したらtrue
391  */
392 bool QuaffEffects::augmentation()
393 {
394     auto ident = false;
395     if (do_inc_stat(this->player_ptr, A_STR)) {
396         ident = true;
397     }
398
399     if (do_inc_stat(this->player_ptr, A_INT)) {
400         ident = true;
401     }
402
403     if (do_inc_stat(this->player_ptr, A_WIS)) {
404         ident = true;
405     }
406
407     if (do_inc_stat(this->player_ptr, A_DEX)) {
408         ident = true;
409     }
410
411     if (do_inc_stat(this->player_ptr, A_CON)) {
412         ident = true;
413     }
414
415     if (do_inc_stat(this->player_ptr, A_CHR)) {
416         ident = true;
417     }
418
419     return ident;
420 }
421
422 /*!
423  * @brief 啓蒙の薬
424  * @return 常にtrue
425  */
426 bool QuaffEffects::enlightenment()
427 {
428     msg_print(_("自分の置かれている状況が脳裏に浮かんできた...", "An image of your surroundings forms in your mind..."));
429     chg_virtue(this->player_ptr, V_KNOWLEDGE, 1);
430     chg_virtue(this->player_ptr, V_ENLIGHTEN, 1);
431     wiz_lite(this->player_ptr, false);
432     return true;
433 }
434
435 /*!
436  * @brief *啓蒙*の薬
437  * @return 常にtrue
438  */
439 bool QuaffEffects::star_enlightenment()
440 {
441     msg_print(_("更なる啓蒙を感じた...", "You begin to feel more enlightened..."));
442     chg_virtue(this->player_ptr, V_KNOWLEDGE, 1);
443     chg_virtue(this->player_ptr, V_ENLIGHTEN, 2);
444     msg_print(nullptr);
445     wiz_lite(this->player_ptr, false);
446     (void)do_inc_stat(this->player_ptr, A_INT);
447     (void)do_inc_stat(this->player_ptr, A_WIS);
448     (void)detect_traps(this->player_ptr, DETECT_RAD_DEFAULT, true);
449     (void)detect_doors(this->player_ptr, DETECT_RAD_DEFAULT);
450     (void)detect_stairs(this->player_ptr, DETECT_RAD_DEFAULT);
451     (void)detect_treasure(this->player_ptr, DETECT_RAD_DEFAULT);
452     (void)detect_objects_gold(this->player_ptr, DETECT_RAD_DEFAULT);
453     (void)detect_objects_normal(this->player_ptr, DETECT_RAD_DEFAULT);
454     identify_pack(this->player_ptr);
455     self_knowledge(this->player_ptr);
456     return true;
457 }
458
459 /*!
460  * @brief 経験の薬
461  * @return 経験値が増えたらtrue
462  */
463 bool QuaffEffects::experience()
464 {
465     if (PlayerRace(this->player_ptr).equals(PlayerRaceType::ANDROID)) {
466         return false;
467     }
468
469     chg_virtue(this->player_ptr, V_ENLIGHTEN, 1);
470     if (this->player_ptr->exp >= PY_MAX_EXP) {
471         return false;
472     }
473
474     auto ee = (this->player_ptr->exp / 2) + 10;
475     constexpr int max_exp = 100000;
476     if (ee > max_exp) {
477         ee = max_exp;
478     }
479
480     msg_print(_("更に経験を積んだような気がする。", "You feel more experienced."));
481     gain_exp(this->player_ptr, ee);
482     return true;
483 }
484
485 /*!
486  * @brief 耐性の薬
487  * @return 経験値が増えたらtrue
488  */
489 bool QuaffEffects::resistance()
490 {
491     (void)set_oppose_acid(this->player_ptr, this->player_ptr->oppose_acid + randint1(20) + 20, false);
492     (void)set_oppose_elec(this->player_ptr, this->player_ptr->oppose_elec + randint1(20) + 20, false);
493     (void)set_oppose_fire(this->player_ptr, this->player_ptr->oppose_fire + randint1(20) + 20, false);
494     (void)set_oppose_cold(this->player_ptr, this->player_ptr->oppose_cold + randint1(20) + 20, false);
495     (void)set_oppose_pois(this->player_ptr, this->player_ptr->oppose_pois + randint1(20) + 20, false);
496     return true;
497 }
498
499 /*!
500  * @brief 新生の薬
501  * @return 常にtrue
502  */
503 bool QuaffEffects::new_life()
504 {
505     roll_hitdice(this->player_ptr, SPOP_NONE);
506     get_max_stats(this->player_ptr);
507     this->player_ptr->update |= PU_BONUS;
508     lose_all_mutations(this->player_ptr);
509     return true;
510 }
511
512 /*!
513  * @brief ネオ・つよしスペシャルの薬
514  * @return 常にtrue
515  */
516 bool QuaffEffects::neo_tsuyoshi()
517 {
518     (void)BadStatusSetter(this->player_ptr).hallucination(0);
519     (void)set_tsuyoshi(this->player_ptr, this->player_ptr->tsuyoshi + randint1(100) + 100, false);
520     return true;
521 }
522
523 /*!
524  * @brief つよしスペシャルの薬
525  * @return 常にtrue
526  */
527 bool QuaffEffects::tsuyoshi()
528 {
529     msg_print(_("「オクレ兄さん!」", "Brother OKURE!"));
530     msg_print(nullptr);
531     this->player_ptr->tsuyoshi = 1;
532     (void)set_tsuyoshi(this->player_ptr, 0, true);
533     if (!has_resist_chaos(this->player_ptr)) {
534         (void)BadStatusSetter(this->player_ptr).hallucination(50 + randint1(50));
535     }
536
537     return true;
538 }
539
540 /*!
541  * @brief 自己変容の薬
542  * @return 突然変異を得たか失ったらtrue、そのままならfalse
543  */
544 bool QuaffEffects::polymorph()
545 {
546     if (this->player_ptr->muta.any() && one_in_(23)) {
547         lose_all_mutations(this->player_ptr);
548         return false;
549     }
550
551     auto ident = false;
552     do {
553         if (one_in_(2)) {
554             if (gain_mutation(this->player_ptr, 0)) {
555                 ident = true;
556             }
557         } else if (lose_mutation(this->player_ptr, 0)) {
558             ident = true;
559         }
560     } while (!ident || one_in_(2));
561     return ident;
562 }