OSDN Git Service

4081e4e91de98b721cfa824ddc08b45eab5263bd
[hengband/hengband.git] / src / status / bad-status-setter.c
1 #include "status/bad-status-setter.h"
2 #include "core/disturbance.h"
3 #include "core/player-redraw-types.h"
4 #include "core/player-update-types.h"
5 #include "core/stuff-handler.h"
6 #include "core/window-redrawer.h"
7 #include "game-option/disturbance-options.h"
8 #include "mind/mind-sniper.h"
9 #include "player/attack-defense-types.h"
10 #include "player-info/avatar.h"
11 #include "player/player-race.h"
12 #include "player/player-status-flags.h"
13 #include "player/special-defense-types.h"
14 #include "spell-realm/spells-hex.h"
15 #include "status/base-status.h"
16 #include "status/buff-setter.h"
17 #include "view/display-messages.h"
18
19 /*!
20  * @brief 盲目の継続時間をセットする / Set "blind", notice observable changes
21  * @param v 継続時間
22  * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
23  * @details
24  * Note the use of "PU_UN_LITE" and "PU_UN_VIEW", which is needed to\n
25  * memorize any terrain features which suddenly become "visible".\n
26  * Note that blindness is currently the only thing which can affect\n
27  * "player_can_see_bold()".\n
28  */
29 bool set_blind(player_type *creature_ptr, TIME_EFFECT v)
30 {
31     bool notice = FALSE;
32     v = (v > 10000) ? 10000 : (v < 0) ? 0 : v;
33
34     if (creature_ptr->is_dead)
35         return FALSE;
36
37     if (v) {
38         if (!creature_ptr->blind) {
39             if (creature_ptr->prace == RACE_ANDROID) {
40                 msg_print(_("センサーをやられた!", "You are blind!"));
41             } else {
42                 msg_print(_("目が見えなくなってしまった!", "You are blind!"));
43             }
44
45             notice = TRUE;
46             chg_virtue(creature_ptr, V_ENLIGHTEN, -1);
47         }
48     }
49
50     else {
51         if (creature_ptr->blind) {
52             if (creature_ptr->prace == RACE_ANDROID) {
53                 msg_print(_("センサーが復旧した。", "You can see again."));
54             } else {
55                 msg_print(_("やっと目が見えるようになった。", "You can see again."));
56             }
57
58             notice = TRUE;
59         }
60     }
61
62     creature_ptr->blind = v;
63     creature_ptr->redraw |= (PR_STATUS);
64     if (!notice)
65         return FALSE;
66     if (disturb_state)
67         disturb(creature_ptr, FALSE, FALSE);
68
69     creature_ptr->update |= (PU_UN_VIEW | PU_UN_LITE | PU_VIEW | PU_LITE | PU_MONSTERS | PU_MON_LITE);
70     creature_ptr->redraw |= (PR_MAP);
71     creature_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
72     handle_stuff(creature_ptr);
73     return TRUE;
74 }
75
76 /*!
77  * @brief 混乱の継続時間をセットする / Set "confused", notice observable changes
78  * @param v 継続時間
79  * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
80  */
81 bool set_confused(player_type *creature_ptr, TIME_EFFECT v)
82 {
83     bool notice = FALSE;
84     v = (v > 10000) ? 10000 : (v < 0) ? 0 : v;
85
86     if (creature_ptr->is_dead)
87         return FALSE;
88
89     if (v) {
90         if (!creature_ptr->confused) {
91             msg_print(_("あなたは混乱した!", "You are confused!"));
92
93             if (creature_ptr->action == ACTION_LEARN) {
94                 msg_print(_("学習が続けられない!", "You cannot continue learning!"));
95                 creature_ptr->new_mane = FALSE;
96
97                 creature_ptr->redraw |= (PR_STATE);
98                 creature_ptr->action = ACTION_NONE;
99             }
100             if (creature_ptr->action == ACTION_KAMAE) {
101                 msg_print(_("構えがとけた。", "You lose your stance."));
102                 creature_ptr->special_defense &= ~(KAMAE_MASK);
103                 creature_ptr->update |= (PU_BONUS);
104                 creature_ptr->redraw |= (PR_STATE);
105                 creature_ptr->action = ACTION_NONE;
106             } else if (creature_ptr->action == ACTION_KATA) {
107                 msg_print(_("型が崩れた。", "You lose your stance."));
108                 creature_ptr->special_defense &= ~(KATA_MASK);
109                 creature_ptr->update |= (PU_BONUS);
110                 creature_ptr->update |= (PU_MONSTERS);
111                 creature_ptr->redraw |= (PR_STATE);
112                 creature_ptr->redraw |= (PR_STATUS);
113                 creature_ptr->action = ACTION_NONE;
114             }
115
116             /* Sniper */
117             if (creature_ptr->concent)
118                 reset_concentration(creature_ptr, TRUE);
119
120             if (hex_spelling_any(creature_ptr))
121                 stop_hex_spell_all(creature_ptr);
122
123             notice = TRUE;
124             creature_ptr->counter = FALSE;
125             chg_virtue(creature_ptr, V_HARMONY, -1);
126         }
127     } else {
128         if (creature_ptr->confused) {
129             msg_print(_("やっと混乱がおさまった。", "You feel less confused now."));
130             creature_ptr->special_attack &= ~(ATTACK_SUIKEN);
131             notice = TRUE;
132         }
133     }
134
135     creature_ptr->confused = v;
136     creature_ptr->redraw |= (PR_STATUS);
137
138     if (!notice)
139         return FALSE;
140
141     if (disturb_state)
142         disturb(creature_ptr, FALSE, FALSE);
143     handle_stuff(creature_ptr);
144     return TRUE;
145 }
146
147 /*!
148  * @brief 毒の継続時間をセットする / Set "poisoned", notice observable changes
149  * @param v 継続時間
150  * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
151  */
152 bool set_poisoned(player_type *creature_ptr, TIME_EFFECT v)
153 {
154     bool notice = FALSE;
155     v = (v > 10000) ? 10000 : (v < 0) ? 0 : v;
156
157     if (creature_ptr->is_dead)
158         return FALSE;
159
160     if (v) {
161         if (!creature_ptr->poisoned) {
162             msg_print(_("毒に侵されてしまった!", "You are poisoned!"));
163             notice = TRUE;
164         }
165     } else {
166         if (creature_ptr->poisoned) {
167             msg_print(_("やっと毒の痛みがなくなった。", "You are no longer poisoned."));
168             notice = TRUE;
169         }
170     }
171
172     creature_ptr->poisoned = v;
173     creature_ptr->redraw |= (PR_STATUS);
174
175     if (!notice)
176         return FALSE;
177
178     if (disturb_state)
179         disturb(creature_ptr, FALSE, FALSE);
180     handle_stuff(creature_ptr);
181     return TRUE;
182 }
183
184 /*!
185  * @brief 恐怖の継続時間をセットする / Set "afraid", notice observable changes
186  * @param v 継続時間
187  * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
188  */
189 bool set_afraid(player_type *creature_ptr, TIME_EFFECT v)
190 {
191     bool notice = FALSE;
192     v = (v > 10000) ? 10000 : (v < 0) ? 0 : v;
193
194     if (creature_ptr->is_dead)
195         return FALSE;
196
197     if (v) {
198         if (!creature_ptr->afraid) {
199             msg_print(_("何もかも恐くなってきた!", "You are terrified!"));
200
201             if (creature_ptr->special_defense & KATA_MASK) {
202                 msg_print(_("型が崩れた。", "You lose your stance."));
203                 creature_ptr->special_defense &= ~(KATA_MASK);
204                 creature_ptr->update |= (PU_BONUS);
205                 creature_ptr->update |= (PU_MONSTERS);
206                 creature_ptr->redraw |= (PR_STATE);
207                 creature_ptr->redraw |= (PR_STATUS);
208                 creature_ptr->action = ACTION_NONE;
209             }
210
211             notice = TRUE;
212             creature_ptr->counter = FALSE;
213             chg_virtue(creature_ptr, V_VALOUR, -1);
214         }
215     } else {
216         if (creature_ptr->afraid) {
217             msg_print(_("やっと恐怖を振り払った。", "You feel bolder now."));
218             notice = TRUE;
219         }
220     }
221
222     creature_ptr->afraid = v;
223     creature_ptr->redraw |= (PR_STATUS);
224
225     if (!notice)
226         return FALSE;
227
228     if (disturb_state)
229         disturb(creature_ptr, FALSE, FALSE);
230     handle_stuff(creature_ptr);
231     return TRUE;
232 }
233
234 /*!
235  * @brief 麻痺の継続時間をセットする / Set "paralyzed", notice observable changes
236  * @param v 継続時間
237  * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
238  */
239 bool set_paralyzed(player_type *creature_ptr, TIME_EFFECT v)
240 {
241     bool notice = FALSE;
242     v = (v > 10000) ? 10000 : (v < 0) ? 0 : v;
243
244     if (creature_ptr->is_dead)
245         return FALSE;
246
247     if (v) {
248         if (!creature_ptr->paralyzed) {
249             msg_print(_("体が麻痺してしまった!", "You are paralyzed!"));
250             if (creature_ptr->concent)
251                 reset_concentration(creature_ptr, TRUE);
252             if (hex_spelling_any(creature_ptr))
253                 stop_hex_spell_all(creature_ptr);
254
255             creature_ptr->counter = FALSE;
256             notice = TRUE;
257         }
258     } else {
259         if (creature_ptr->paralyzed) {
260             msg_print(_("やっと動けるようになった。", "You can move again."));
261             notice = TRUE;
262         }
263     }
264
265     creature_ptr->paralyzed = v;
266     creature_ptr->redraw |= (PR_STATUS);
267
268     if (!notice)
269         return FALSE;
270
271     if (disturb_state)
272         disturb(creature_ptr, FALSE, FALSE);
273     creature_ptr->redraw |= (PR_STATE);
274     handle_stuff(creature_ptr);
275     return TRUE;
276 }
277
278 /*!
279  * @brief 幻覚の継続時間をセットする / Set "image", notice observable changes
280  * @param v 継続時間
281  * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
282  * @details Note that we must redraw the map when hallucination changes.
283  */
284 bool set_image(player_type *creature_ptr, TIME_EFFECT v)
285 {
286     bool notice = FALSE;
287     v = (v > 10000) ? 10000 : (v < 0) ? 0 : v;
288
289     if (creature_ptr->is_dead)
290         return FALSE;
291     if (creature_ptr->pseikaku == PERSONALITY_CHARGEMAN)
292         v = 0;
293
294     if (v) {
295         set_tsuyoshi(creature_ptr, 0, TRUE);
296         if (!creature_ptr->image) {
297             msg_print(_("ワーオ!何もかも虹色に見える!", "Oh, wow! Everything looks so cosmic now!"));
298
299             /* Sniper */
300             if (creature_ptr->concent)
301                 reset_concentration(creature_ptr, TRUE);
302
303             creature_ptr->counter = FALSE;
304             notice = TRUE;
305         }
306     } else {
307         if (creature_ptr->image) {
308             msg_print(_("やっとはっきりと物が見えるようになった。", "You can see clearly again."));
309             notice = TRUE;
310         }
311     }
312
313     creature_ptr->image = v;
314     creature_ptr->redraw |= (PR_STATUS);
315
316     if (!notice)
317         return FALSE;
318
319     if (disturb_state)
320         disturb(creature_ptr, FALSE, TRUE);
321
322     creature_ptr->redraw |= (PR_MAP | PR_HEALTH | PR_UHEALTH);
323     creature_ptr->update |= (PU_MONSTERS);
324     creature_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
325     handle_stuff(creature_ptr);
326     return TRUE;
327 }
328
329 /*!
330  * @brief 減速の継続時間をセットする / Set "slow", notice observable changes
331  * @param v 継続時間
332  * @param do_dec 現在の継続時間より長い値のみ上書きする
333  * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
334  */
335 bool set_slow(player_type *creature_ptr, TIME_EFFECT v, bool do_dec)
336 {
337     bool notice = FALSE;
338     v = (v > 10000) ? 10000 : (v < 0) ? 0 : v;
339
340     if (creature_ptr->is_dead)
341         return FALSE;
342
343     if (v) {
344         if (creature_ptr->slow && !do_dec) {
345             if (creature_ptr->slow > v)
346                 return FALSE;
347         } else if (!creature_ptr->slow) {
348             msg_print(_("体の動きが遅くなってしまった!", "You feel yourself moving slower!"));
349             notice = TRUE;
350         }
351     } else {
352         if (creature_ptr->slow) {
353             msg_print(_("動きの遅さがなくなったようだ。", "You feel yourself speed up."));
354             notice = TRUE;
355         }
356     }
357
358     creature_ptr->slow = v;
359     if (!notice)
360         return FALSE;
361
362     if (disturb_state)
363         disturb(creature_ptr, FALSE, FALSE);
364     creature_ptr->update |= (PU_BONUS);
365     handle_stuff(creature_ptr);
366     return TRUE;
367 }
368
369 /*!
370  * @brief 朦朧の継続時間をセットする / Set "stun", notice observable changes
371  * @param v 継続時間
372  * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
373  * @details
374  * Note the special code to only notice "range" changes.
375  */
376 bool set_stun(player_type *creature_ptr, TIME_EFFECT v)
377 {
378     int old_aux, new_aux;
379     bool notice = FALSE;
380     v = (v > 10000) ? 10000 : (v < 0) ? 0 : v;
381     if (creature_ptr->is_dead)
382         return FALSE;
383     if (is_specific_player_race(creature_ptr, RACE_GOLEM) || ((creature_ptr->pclass == CLASS_BERSERKER) && (creature_ptr->lev > 34)))
384         v = 0;
385
386     if (creature_ptr->stun > 100) {
387         old_aux = 3;
388     } else if (creature_ptr->stun > 50) {
389         old_aux = 2;
390     } else if (creature_ptr->stun > 0) {
391         old_aux = 1;
392     } else {
393         old_aux = 0;
394     }
395
396     if (v > 100) {
397         new_aux = 3;
398     } else if (v > 50) {
399         new_aux = 2;
400     } else if (v > 0) {
401         new_aux = 1;
402     } else {
403         new_aux = 0;
404     }
405
406     if (new_aux > old_aux) {
407         switch (new_aux) {
408         case 1:
409             msg_print(_("意識がもうろうとしてきた。", "You have been stunned."));
410             break;
411         case 2:
412             msg_print(_("意識がひどくもうろうとしてきた。", "You have been heavily stunned."));
413             break;
414         case 3:
415             msg_print(_("頭がクラクラして意識が遠のいてきた。", "You have been knocked out."));
416             break;
417         }
418
419         if (randint1(1000) < v || one_in_(16)) {
420             msg_print(_("割れるような頭痛がする。", "A vicious blow hits your head."));
421
422             if (one_in_(3)) {
423                 if (!has_sustain_int(creature_ptr))
424                     (void)do_dec_stat(creature_ptr, A_INT);
425                 if (!creature_ptr->sustain_wis)
426                     (void)do_dec_stat(creature_ptr, A_WIS);
427             } else if (one_in_(2)) {
428                 if (!has_sustain_int(creature_ptr))
429                     (void)do_dec_stat(creature_ptr, A_INT);
430             } else {
431                 if (!creature_ptr->sustain_wis)
432                     (void)do_dec_stat(creature_ptr, A_WIS);
433             }
434         }
435
436         if (creature_ptr->special_defense & KATA_MASK) {
437             msg_print(_("型が崩れた。", "You lose your stance."));
438             creature_ptr->special_defense &= ~(KATA_MASK);
439             creature_ptr->update |= (PU_BONUS);
440             creature_ptr->update |= (PU_MONSTERS);
441             creature_ptr->redraw |= (PR_STATE);
442             creature_ptr->redraw |= (PR_STATUS);
443             creature_ptr->action = ACTION_NONE;
444         }
445
446         if (creature_ptr->concent)
447             reset_concentration(creature_ptr, TRUE);
448         if (hex_spelling_any(creature_ptr))
449             stop_hex_spell_all(creature_ptr);
450
451         notice = TRUE;
452     } else if (new_aux < old_aux) {
453         if (new_aux == 0) {
454             msg_print(_("やっと朦朧状態から回復した。", "You are no longer stunned."));
455             if (disturb_state)
456                 disturb(creature_ptr, FALSE, FALSE);
457         }
458
459         notice = TRUE;
460     }
461
462     creature_ptr->stun = v;
463
464     if (!notice)
465         return FALSE;
466
467     if (disturb_state)
468         disturb(creature_ptr, FALSE, FALSE);
469     creature_ptr->update |= (PU_BONUS);
470     creature_ptr->redraw |= (PR_STUN);
471     handle_stuff(creature_ptr);
472     return TRUE;
473 }
474
475 /*!
476  * @brief 出血の継続時間をセットする / Set "cut", notice observable changes
477  * @param v 継続時間
478  * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
479  * @details
480  * Note the special code to only notice "range" changes.
481  */
482 bool set_cut(player_type *creature_ptr, TIME_EFFECT v)
483 {
484     int old_aux, new_aux;
485     bool notice = FALSE;
486     v = (v > 10000) ? 10000 : (v < 0) ? 0 : v;
487     if (creature_ptr->is_dead)
488         return FALSE;
489
490     if ((creature_ptr->prace == RACE_GOLEM || creature_ptr->prace == RACE_SKELETON || creature_ptr->prace == RACE_SPECTRE
491             || (creature_ptr->prace == RACE_ZOMBIE && creature_ptr->lev > 11))
492         && !creature_ptr->mimic_form)
493         v = 0;
494
495     if (creature_ptr->cut > 1000) {
496         old_aux = 7;
497     } else if (creature_ptr->cut > 200) {
498         old_aux = 6;
499     } else if (creature_ptr->cut > 100) {
500         old_aux = 5;
501     } else if (creature_ptr->cut > 50) {
502         old_aux = 4;
503     } else if (creature_ptr->cut > 25) {
504         old_aux = 3;
505     } else if (creature_ptr->cut > 10) {
506         old_aux = 2;
507     } else if (creature_ptr->cut > 0) {
508         old_aux = 1;
509     } else {
510         old_aux = 0;
511     }
512
513     if (v > 1000) {
514         new_aux = 7;
515     } else if (v > 200) {
516         new_aux = 6;
517     } else if (v > 100) {
518         new_aux = 5;
519     } else if (v > 50) {
520         new_aux = 4;
521     } else if (v > 25) {
522         new_aux = 3;
523     } else if (v > 10) {
524         new_aux = 2;
525     } else if (v > 0) {
526         new_aux = 1;
527     } else {
528         new_aux = 0;
529     }
530
531     if (new_aux > old_aux) {
532         switch (new_aux) {
533         case 1:
534             msg_print(_("かすり傷を負ってしまった。", "You have been given a graze."));
535             break;
536         case 2:
537             msg_print(_("軽い傷を負ってしまった。", "You have been given a light cut."));
538             break;
539         case 3:
540             msg_print(_("ひどい傷を負ってしまった。", "You have been given a bad cut."));
541             break;
542         case 4:
543             msg_print(_("大変な傷を負ってしまった。", "You have been given a nasty cut."));
544             break;
545         case 5:
546             msg_print(_("重大な傷を負ってしまった。", "You have been given a severe cut."));
547             break;
548         case 6:
549             msg_print(_("ひどい深手を負ってしまった。", "You have been given a deep gash."));
550             break;
551         case 7:
552             msg_print(_("致命的な傷を負ってしまった。", "You have been given a mortal wound."));
553             break;
554         }
555
556         notice = TRUE;
557         if (randint1(1000) < v || one_in_(16)) {
558             if (!creature_ptr->sustain_chr) {
559                 msg_print(_("ひどい傷跡が残ってしまった。", "You have been horribly scarred."));
560                 do_dec_stat(creature_ptr, A_CHR);
561             }
562         }
563     } else if (new_aux < old_aux) {
564         if (new_aux == 0) {
565             msg_format(_("やっと%s。", "You are no longer bleeding."), creature_ptr->prace == RACE_ANDROID ? "怪我が直った" : "出血が止まった");
566             if (disturb_state)
567                 disturb(creature_ptr, FALSE, FALSE);
568         }
569
570         notice = TRUE;
571     }
572
573     creature_ptr->cut = v;
574     if (!notice)
575         return FALSE;
576
577     if (disturb_state)
578         disturb(creature_ptr, FALSE, FALSE);
579     creature_ptr->update |= (PU_BONUS);
580     creature_ptr->redraw |= (PR_CUT);
581     handle_stuff(creature_ptr);
582     return TRUE;
583 }