OSDN Git Service

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