OSDN Git Service

3f94d2ccda5a931d420862eec477ae4905629215
[hengbandforosx/hengbandosx.git] / src / monster-attack / monster-attack-status.cpp
1 /*!
2  * @brief プレイヤーのステータス (麻痺等)に影響を与えるモンスターの打撃処理
3  * @date 2020/05/31
4  * @author Hourier
5  */
6
7 #include "monster-attack/monster-attack-status.h"
8 #include "core/player-update-types.h"
9 #include "mind/mind-mirror-master.h"
10 #include "monster-attack/monster-attack-player.h"
11 #include "monster-race/monster-race.h"
12 #include "monster-race/race-indice-types.h"
13 #include "player-base/player-race.h"
14 #include "player/player-status-flags.h"
15 #include "status/bad-status-setter.h"
16 #include "status/base-status.h"
17 #include "status/experience.h"
18 #include "system/monster-entity.h"
19 #include "system/monster-race-info.h"
20 #include "system/player-type-definition.h"
21 #include "system/redrawing-flags-updater.h"
22 #include "timed-effect/player-paralysis.h"
23 #include "timed-effect/timed-effects.h"
24 #include "view/display-messages.h"
25
26 void process_blind_attack(PlayerType *player_ptr, MonsterAttackPlayer *monap_ptr)
27 {
28     if (has_resist_blind(player_ptr) || check_multishadow(player_ptr)) {
29         return;
30     }
31
32     auto is_dio = monap_ptr->m_ptr->r_idx == MonsterRaceId::DIO;
33     auto dio_msg = _("どうだッ!この血の目潰しはッ!", "How is it! This blood-blinding!");
34     if (is_dio && PlayerRace(player_ptr).equals(PlayerRaceType::SKELETON)) {
35         msg_print(dio_msg);
36         msg_print(_("しかし、あなたには元々目はなかった!", "However, you don't have eyes!"));
37         return;
38     }
39
40     if (!BadStatusSetter(player_ptr).mod_blindness(10 + randint1(monap_ptr->rlev))) {
41         return;
42     }
43
44     if (is_dio) {
45         msg_print(dio_msg);
46     }
47
48     monap_ptr->obvious = true;
49 }
50
51 void process_terrify_attack(PlayerType *player_ptr, MonsterAttackPlayer *monap_ptr)
52 {
53     if (check_multishadow(player_ptr)) {
54         return;
55     }
56
57     auto *r_ptr = &monraces_info[monap_ptr->m_ptr->r_idx];
58     if (has_resist_fear(player_ptr)) {
59         msg_print(_("しかし恐怖に侵されなかった!", "You stand your ground!"));
60         monap_ptr->obvious = true;
61         return;
62     }
63
64     if (randint0(100 + r_ptr->level / 2) < player_ptr->skill_sav) {
65         msg_print(_("しかし恐怖に侵されなかった!", "You stand your ground!"));
66         monap_ptr->obvious = true;
67         return;
68     }
69
70     if (BadStatusSetter(player_ptr).mod_fear(3 + randint1(monap_ptr->rlev))) {
71         monap_ptr->obvious = true;
72     }
73 }
74
75 void process_paralyze_attack(PlayerType *player_ptr, MonsterAttackPlayer *monap_ptr)
76 {
77     if (check_multishadow(player_ptr)) {
78         return;
79     }
80
81     auto *r_ptr = &monraces_info[monap_ptr->m_ptr->r_idx];
82     if (player_ptr->free_act) {
83         msg_print(_("しかし効果がなかった!", "You are unaffected!"));
84         monap_ptr->obvious = true;
85         return;
86     }
87
88     if (randint0(100 + r_ptr->level / 2) < player_ptr->skill_sav) {
89         msg_print(_("しかし効力を跳ね返した!", "You resist the effects!"));
90         monap_ptr->obvious = true;
91         return;
92     }
93
94     auto is_paralyzed = player_ptr->effects()->paralysis()->is_paralyzed();
95     if (!is_paralyzed && BadStatusSetter(player_ptr).set_paralysis(3 + randint1(monap_ptr->rlev))) {
96         monap_ptr->obvious = true;
97     }
98 }
99
100 void process_lose_all_attack(PlayerType *player_ptr, MonsterAttackPlayer *monap_ptr)
101 {
102     if (do_dec_stat(player_ptr, A_STR)) {
103         monap_ptr->obvious = true;
104     }
105
106     if (do_dec_stat(player_ptr, A_DEX)) {
107         monap_ptr->obvious = true;
108     }
109
110     if (do_dec_stat(player_ptr, A_CON)) {
111         monap_ptr->obvious = true;
112     }
113
114     if (do_dec_stat(player_ptr, A_INT)) {
115         monap_ptr->obvious = true;
116     }
117
118     if (do_dec_stat(player_ptr, A_WIS)) {
119         monap_ptr->obvious = true;
120     }
121
122     if (do_dec_stat(player_ptr, A_CHR)) {
123         monap_ptr->obvious = true;
124     }
125 }
126
127 void process_stun_attack(PlayerType *player_ptr, MonsterAttackPlayer *monap_ptr)
128 {
129     if (has_resist_sound(player_ptr) || check_multishadow(player_ptr)) {
130         return;
131     }
132
133     auto *r_ptr = &monraces_info[monap_ptr->m_ptr->r_idx];
134     if (BadStatusSetter(player_ptr).mod_stun(10 + randint1(r_ptr->level / 4))) {
135         monap_ptr->obvious = true;
136     }
137 }
138
139 /*!
140  * @brief 時間逆転攻撃による能力低下
141  * @param player_ptr プレイヤーへの参照ポインタ
142  * @monap_ptr モンスターからモンスターへの直接攻撃構造体への参照ポインタ
143  */
144 static void describe_disability(PlayerType *player_ptr, MonsterAttackPlayer *monap_ptr)
145 {
146     int stat = randint0(6);
147     switch (stat) {
148     case A_STR:
149         monap_ptr->act = _("強く", "strong");
150         break;
151     case A_INT:
152         monap_ptr->act = _("聡明で", "bright");
153         break;
154     case A_WIS:
155         monap_ptr->act = _("賢明で", "wise");
156         break;
157     case A_DEX:
158         monap_ptr->act = _("器用で", "agile");
159         break;
160     case A_CON:
161         monap_ptr->act = _("健康で", "hale");
162         break;
163     case A_CHR:
164         monap_ptr->act = _("美しく", "beautiful");
165         break;
166     }
167
168     msg_format(_("あなたは以前ほど%sなくなってしまった...。", "You're not as %s as you used to be..."), monap_ptr->act);
169     player_ptr->stat_cur[stat] = (player_ptr->stat_cur[stat] * 3) / 4;
170     if (player_ptr->stat_cur[stat] < 3) {
171         player_ptr->stat_cur[stat] = 3;
172     }
173 }
174
175 void process_monster_attack_time(PlayerType *player_ptr, MonsterAttackPlayer *monap_ptr)
176 {
177     if (has_resist_time(player_ptr) || check_multishadow(player_ptr)) {
178         return;
179     }
180
181     auto &rfu = RedrawingFlagsUpdater::get_instance();
182     switch (randint1(10)) {
183     case 1:
184     case 2:
185     case 3:
186     case 4:
187     case 5:
188         if (PlayerRace(player_ptr).equals(PlayerRaceType::ANDROID)) {
189             break;
190         }
191
192         msg_print(_("人生が逆戻りした気がする。", "You feel like a chunk of the past has been ripped away."));
193         lose_exp(player_ptr, 100 + (player_ptr->exp / 100) * MON_DRAIN_LIFE);
194         break;
195     case 6:
196     case 7:
197     case 8:
198     case 9:
199         describe_disability(player_ptr, monap_ptr);
200         rfu.set_flag(StatusRedrawingFlag::BONUS);
201         break;
202     case 10:
203         msg_print(_("あなたは以前ほど力強くなくなってしまった...。", "You're not as powerful as you used to be..."));
204         for (auto i = 0; i < A_MAX; i++) {
205             player_ptr->stat_cur[i] = (player_ptr->stat_cur[i] * 7) / 8;
206             if (player_ptr->stat_cur[i] < 3) {
207                 player_ptr->stat_cur[i] = 3;
208             }
209         }
210
211         rfu.set_flag(StatusRedrawingFlag::BONUS);
212         break;
213     }
214 }