7 #include "object-use/quaff/quaff-effects.h"
8 #include "avatar/avatar.h"
9 #include "birth/birth-stat.h"
10 #include "game-option/birth-options.h"
11 #include "mutation/mutation-investor-remover.h"
12 #include "object/object-info.h"
13 #include "player-base/player-class.h"
14 #include "player-base/player-race.h"
15 #include "player-info/race-info.h"
16 #include "player-info/self-info.h"
17 #include "player/attack-defense-types.h"
18 #include "player/digestion-processor.h"
19 #include "player/eldritch-horror.h"
20 #include "player/player-damage.h"
21 #include "player/player-status-flags.h"
22 #include "spell-kind/spells-detection.h"
23 #include "spell-kind/spells-floor.h"
24 #include "spell-kind/spells-perception.h"
25 #include "spell-kind/spells-teleport.h"
26 #include "spell/spells-status.h"
27 #include "status/bad-status-setter.h"
28 #include "status/base-status.h"
29 #include "status/body-improvement.h"
30 #include "status/buff-setter.h"
31 #include "status/element-resistance.h"
32 #include "status/experience.h"
33 #include "status/shape-changer.h"
34 #include "status/sight-setter.h"
35 #include "sv-definition/sv-potion-types.h"
36 #include "system/angband.h"
37 #include "system/item-entity.h"
38 #include "system/player-type-definition.h"
39 #include "system/redrawing-flags-updater.h"
40 #include "timed-effect/timed-effects.h"
41 #include "util/bit-flags-calculator.h"
42 #include "util/dice.h"
43 #include "view/display-messages.h"
45 QuaffEffects::QuaffEffects(PlayerType *player_ptr)
46 : player_ptr(player_ptr)
50 bool QuaffEffects::influence(const ItemEntity &item)
52 if (item.bi_key.tval() != ItemKindType::POTION) {
56 switch (*item.bi_key.sval()) {
58 msg_print(_("口の中がさっぱりした。", "That was refreshing."));
59 msg_print(_("のどの渇きが少しおさまった。", "You feel less thirsty."));
61 case SV_POTION_APPLE_JUICE:
62 msg_print(_("甘くてサッパリとしていて、とてもおいしい。", "It's sweet, refreshing and very tasty."));
63 msg_print(_("のどの渇きが少しおさまった。", "You feel less thirsty."));
65 case SV_POTION_SLIME_MOLD:
66 msg_print(_("なんとも不気味な味だ。", "That was strange."));
67 msg_print(_("のどの渇きが少しおさまった。", "You feel less thirsty."));
69 case SV_POTION_SLOWNESS:
70 return BadStatusSetter(this->player_ptr).set_deceleration(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();
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).set_poison(this->player_ptr->effects()->poison().current() / 2);
108 case SV_POTION_CURE_POISON:
109 return BadStatusSetter(this->player_ptr).set_poison(0);
110 case SV_POTION_BOLDNESS:
111 return BadStatusSetter(this->player_ptr).set_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, Dice::roll(2, 8));
124 case SV_POTION_CURE_SERIOUS:
125 return cure_serious_wounds(this->player_ptr, Dice::roll(4, 8));
126 case SV_POTION_CURE_CRITICAL:
127 return cure_critical_wounds(this->player_ptr, Dice::roll(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);
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);
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..."));
174 self_knowledge(this->player_ptr);
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);
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();
202 bool QuaffEffects::salt_water()
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);
215 BadStatusSetter bss(this->player_ptr);
216 (void)bss.set_poison(0);
217 (void)bss.mod_paralysis(4);
223 * @return 毒の効果を受けたらtrue
225 bool QuaffEffects::poison()
227 if (has_resist_pois(this->player_ptr) || is_oppose_pois(this->player_ptr)) {
231 return BadStatusSetter(this->player_ptr).mod_poison(randint0(15) + 10);
236 * @return 盲目になったらtrue
238 bool QuaffEffects::blindness()
240 if (has_resist_blind(this->player_ptr)) {
244 return BadStatusSetter(this->player_ptr).mod_blindness(randint0(100) + 100);
249 * @return カオス耐性があるかその他の一部確率でFALSE、それ以外はTRUE
251 bool QuaffEffects::booze()
254 auto is_monk = PlayerClass(this->player_ptr).equals(PlayerClassType::MONK);
256 chg_virtue(this->player_ptr, Virtue::HARMONY, -1);
257 } else if (!has_resist_conf(this->player_ptr)) {
258 set_bits(this->player_ptr->special_attack, ATTACK_SUIKEN);
261 BadStatusSetter bss(this->player_ptr);
262 if (!has_resist_conf(this->player_ptr) && bss.set_confusion(randint0(20) + 15)) {
266 if (has_resist_chaos(this->player_ptr)) {
270 if (one_in_(2) && bss.mod_hallucination(randint0(150) + 150)) {
274 if (is_monk || !one_in_(13)) {
280 lose_all_info(this->player_ptr);
282 wiz_dark(this->player_ptr);
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!"));
296 bool QuaffEffects::sleep()
298 if (this->player_ptr->free_act) {
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);
308 return BadStatusSetter(this->player_ptr).mod_paralysis(randint0(4) + 4);
315 bool QuaffEffects::lose_memories()
317 if (this->player_ptr->hold_exp || (this->player_ptr->exp <= 0)) {
321 msg_print(_("過去の記憶が薄れていく気がする。", "You feel your memories fade."));
322 chg_virtue(this->player_ptr, Virtue::KNOWLEDGE, -5);
323 lose_exp(this->player_ptr, this->player_ptr->exp / 4);
331 bool QuaffEffects::ruination()
333 msg_print(_("身も心も弱ってきて、精気が抜けていくようだ。", "Your nerves and muscles feel weak and lifeless!"));
334 take_hit(this->player_ptr, DAMAGE_LOSELIFE, Dice::roll(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);
345 * @brief 爆発の薬 / Fumble ramble
348 bool QuaffEffects::detonation()
350 msg_print(_("体の中で激しい爆発が起きた!", "Massive explosions rupture your body!"));
351 take_hit(this->player_ptr, DAMAGE_NOESCAPE, Dice::roll(50, 20), _("爆発の薬", "a potion of Detonation"));
352 BadStatusSetter bss(this->player_ptr);
353 (void)bss.mod_stun(75);
354 (void)bss.mod_cut(5000);
362 bool QuaffEffects::death()
364 chg_virtue(this->player_ptr, Virtue::VITALITY, -1);
365 chg_virtue(this->player_ptr, Virtue::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"));
373 * @return 加速したらtrue、加速効果が切れていない状態で重ね飲みしたらfalse
375 bool QuaffEffects::speed()
377 if (this->player_ptr->effects()->acceleration().is_fast()) {
378 (void)mod_acceleration(this->player_ptr, 5, false);
382 return set_acceleration(this->player_ptr, randint1(25) + 15, false);
387 * @return アビリティスコアのどれか1つでも向上したらtrue
389 bool QuaffEffects::augmentation()
392 if (do_inc_stat(this->player_ptr, A_STR)) {
396 if (do_inc_stat(this->player_ptr, A_INT)) {
400 if (do_inc_stat(this->player_ptr, A_WIS)) {
404 if (do_inc_stat(this->player_ptr, A_DEX)) {
408 if (do_inc_stat(this->player_ptr, A_CON)) {
412 if (do_inc_stat(this->player_ptr, A_CHR)) {
423 bool QuaffEffects::enlightenment()
425 msg_print(_("自分の置かれている状況が脳裏に浮かんできた...", "An image of your surroundings forms in your mind..."));
426 chg_virtue(this->player_ptr, Virtue::KNOWLEDGE, 1);
427 chg_virtue(this->player_ptr, Virtue::ENLIGHTEN, 1);
428 wiz_lite(this->player_ptr, false);
436 bool QuaffEffects::star_enlightenment()
438 msg_print(_("更なる啓蒙を感じた...", "You begin to feel more enlightened..."));
439 chg_virtue(this->player_ptr, Virtue::KNOWLEDGE, 1);
440 chg_virtue(this->player_ptr, Virtue::ENLIGHTEN, 2);
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);
458 * @return 経験値が増えたらtrue
460 bool QuaffEffects::experience()
462 if (PlayerRace(this->player_ptr).equals(PlayerRaceType::ANDROID)) {
466 chg_virtue(this->player_ptr, Virtue::ENLIGHTEN, 1);
467 if (this->player_ptr->exp >= PY_MAX_EXP) {
471 auto ee = (this->player_ptr->exp / 2) + 10;
472 constexpr int max_exp = 100000;
477 msg_print(_("更に経験を積んだような気がする。", "You feel more experienced."));
478 gain_exp(this->player_ptr, ee);
484 * @return 経験値が増えたらtrue
486 bool QuaffEffects::resistance()
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);
500 bool QuaffEffects::new_life()
502 roll_hitdice(this->player_ptr, SPOP_NONE);
503 get_max_stats(this->player_ptr);
504 RedrawingFlagsUpdater::get_instance().set_flag(StatusRecalculatingFlag::BONUS);
505 lose_all_mutations(this->player_ptr);
510 * @brief ネオ・つよしスペシャルの薬
513 bool QuaffEffects::neo_tsuyoshi()
515 (void)BadStatusSetter(this->player_ptr).hallucination(0);
516 (void)set_tsuyoshi(this->player_ptr, this->player_ptr->tsuyoshi + randint1(100) + 100, false);
524 bool QuaffEffects::tsuyoshi()
526 msg_print(_("「オクレ兄さん!」", "Brother OKURE!"));
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));
539 * @return 突然変異を得たか失ったらtrue、そのままならfalse
541 bool QuaffEffects::polymorph()
543 if (this->player_ptr->muta.any() && one_in_(23)) {
544 lose_all_mutations(this->player_ptr);
551 if (gain_mutation(this->player_ptr, 0)) {
554 } else if (lose_mutation(this->player_ptr, 0)) {
557 } while (!ident || one_in_(2));