OSDN Git Service

Merge remote-tracking branch 'remotes/origin/For2.2.2-Fix-Hourier' into For2.2.2...
[hengband/hengband.git] / src / core / hp-mp-processor.c
1 #include "core/hp-mp-processor.h"
2 #include "cmd-action/cmd-pet.h"
3 #include "core/hp-mp-regenerator.h"
4 #include "core/player-redraw-types.h"
5 #include "core/window-redrawer.h"
6 #include "flavor/flavor-describer.h"
7 #include "flavor/object-flavor-types.h"
8 #include "floor/pattern-walk.h"
9 #include "grid/feature.h"
10 #include "grid/grid.h"
11 #include "inventory/inventory-slot-types.h"
12 #include "monster-race/monster-race.h"
13 #include "monster-race/race-flags2.h"
14 #include "monster-race/race-flags3.h"
15 #include "object-enchant/object-ego.h"
16 #include "object-enchant/trc-types.h"
17 #include "player/attack-defense-types.h"
18 #include "player/avatar.h"
19 #include "player/player-damage.h"
20 #include "player/player-race-types.h"
21 #include "player/player-race.h"
22 #include "player/special-defense-types.h"
23 #include "status/bad-status-setter.h"
24 #include "status/element-resistance.h"
25 #include "system/floor-type-definition.h"
26 #include "util/bit-flags-calculator.h"
27 #include "view/display-messages.h"
28 #include "world/world.h"
29
30 /*!
31  * @brief 10ゲームターンが進行するごとにプレイヤーのHPとMPの増減処理を行う。
32  *  / Handle timed damage and regeneration every 10 game turns
33  * @return なし
34  */
35 void process_player_hp_mp(player_type *creature_ptr)
36 {
37     feature_type *f_ptr = &f_info[creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x].feat];
38     bool cave_no_regen = FALSE;
39     int upkeep_factor = 0;
40     int regen_amount = PY_REGEN_NORMAL;
41     if (creature_ptr->poisoned && !is_invuln(creature_ptr)) {
42         take_hit(creature_ptr, DAMAGE_NOESCAPE, 1, _("毒", "poison"), -1);
43     }
44
45     if (creature_ptr->cut && !is_invuln(creature_ptr)) {
46         HIT_POINT dam;
47         if (creature_ptr->cut > 1000) {
48             dam = 200;
49         } else if (creature_ptr->cut > 200) {
50             dam = 80;
51         } else if (creature_ptr->cut > 100) {
52             dam = 32;
53         } else if (creature_ptr->cut > 50) {
54             dam = 16;
55         } else if (creature_ptr->cut > 25) {
56             dam = 7;
57         } else if (creature_ptr->cut > 10) {
58             dam = 3;
59         } else {
60             dam = 1;
61         }
62
63         take_hit(creature_ptr, DAMAGE_NOESCAPE, dam, _("致命傷", "a fatal wound"), -1);
64     }
65
66     if (is_specific_player_race(creature_ptr, RACE_VAMPIRE) || (creature_ptr->mimic_form == MIMIC_VAMPIRE)) {
67         if (!creature_ptr->current_floor_ptr->dun_level && !creature_ptr->resist_lite && !is_invuln(creature_ptr) && is_daytime()) {
68             if ((creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x].info & (CAVE_GLOW | CAVE_MNDK)) == CAVE_GLOW) {
69                 msg_print(_("日光があなたのアンデッドの肉体を焼き焦がした!", "The sun's rays scorch your undead flesh!"));
70                 take_hit(creature_ptr, DAMAGE_NOESCAPE, 1, _("日光", "sunlight"), -1);
71                 cave_no_regen = TRUE;
72             }
73         }
74
75         if (creature_ptr->inventory_list[INVEN_LITE].tval && (creature_ptr->inventory_list[INVEN_LITE].name2 != EGO_LITE_DARKNESS)
76             && !creature_ptr->resist_lite) {
77             object_type *o_ptr = &creature_ptr->inventory_list[INVEN_LITE];
78             GAME_TEXT o_name[MAX_NLEN];
79             char ouch[MAX_NLEN + 40];
80             describe_flavor(creature_ptr, o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
81             msg_format(_("%sがあなたのアンデッドの肉体を焼き焦がした!", "The %s scorches your undead flesh!"), o_name);
82
83             cave_no_regen = TRUE;
84             describe_flavor(creature_ptr, o_name, o_ptr, OD_NAME_ONLY);
85             sprintf(ouch, _("%sを装備したダメージ", "wielding %s"), o_name);
86
87             if (!is_invuln(creature_ptr))
88                 take_hit(creature_ptr, DAMAGE_NOESCAPE, 1, ouch, -1);
89         }
90     }
91
92     if (have_flag(f_ptr->flags, FF_LAVA) && !is_invuln(creature_ptr) && !creature_ptr->immune_fire) {
93         int damage = 0;
94
95         if (have_flag(f_ptr->flags, FF_DEEP)) {
96             damage = 6000 + randint0(4000);
97         } else if (!creature_ptr->levitation) {
98             damage = 3000 + randint0(2000);
99         }
100
101         if (damage) {
102             if (is_specific_player_race(creature_ptr, RACE_ENT))
103                 damage += damage / 3;
104             if (creature_ptr->resist_fire)
105                 damage = damage / 3;
106             if (is_oppose_fire(creature_ptr))
107                 damage = damage / 3;
108             if (creature_ptr->levitation)
109                 damage = damage / 5;
110
111             damage = damage / 100 + (randint0(100) < (damage % 100));
112
113             if (creature_ptr->levitation) {
114                 msg_print(_("熱で火傷した!", "The heat burns you!"));
115                 take_hit(creature_ptr, DAMAGE_NOESCAPE, damage,
116                     format(_("%sの上に浮遊したダメージ", "flying over %s"),
117                         f_name + f_info[get_feat_mimic(&creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x])].name),
118                     -1);
119             } else {
120                 concptr name = f_name + f_info[get_feat_mimic(&creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x])].name;
121                 msg_format(_("%sで火傷した!", "The %s burns you!"), name);
122                 take_hit(creature_ptr, DAMAGE_NOESCAPE, damage, name, -1);
123             }
124
125             cave_no_regen = TRUE;
126         }
127     }
128
129     if (have_flag(f_ptr->flags, FF_COLD_PUDDLE) && !is_invuln(creature_ptr) && !creature_ptr->immune_cold) {
130         int damage = 0;
131
132         if (have_flag(f_ptr->flags, FF_DEEP)) {
133             damage = 6000 + randint0(4000);
134         } else if (!creature_ptr->levitation) {
135             damage = 3000 + randint0(2000);
136         }
137
138         if (damage) {
139             if (creature_ptr->resist_cold)
140                 damage = damage / 3;
141             if (is_oppose_cold(creature_ptr))
142                 damage = damage / 3;
143             if (creature_ptr->levitation)
144                 damage = damage / 5;
145
146             damage = damage / 100 + (randint0(100) < (damage % 100));
147
148             if (creature_ptr->levitation) {
149                 msg_print(_("冷気に覆われた!", "The cold engulfs you!"));
150                 take_hit(creature_ptr, DAMAGE_NOESCAPE, damage,
151                     format(_("%sの上に浮遊したダメージ", "flying over %s"),
152                         f_name + f_info[get_feat_mimic(&creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x])].name),
153                     -1);
154             } else {
155                 concptr name = f_name + f_info[get_feat_mimic(&creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x])].name;
156                 msg_format(_("%sに凍えた!", "The %s frostbites you!"), name);
157                 take_hit(creature_ptr, DAMAGE_NOESCAPE, damage, name, -1);
158             }
159
160             cave_no_regen = TRUE;
161         }
162     }
163
164     if (have_flag(f_ptr->flags, FF_ELEC_PUDDLE) && !is_invuln(creature_ptr) && !creature_ptr->immune_elec) {
165         int damage = 0;
166
167         if (have_flag(f_ptr->flags, FF_DEEP)) {
168             damage = 6000 + randint0(4000);
169         } else if (!creature_ptr->levitation) {
170             damage = 3000 + randint0(2000);
171         }
172
173         if (damage) {
174             if (creature_ptr->resist_elec)
175                 damage = damage / 3;
176             if (is_oppose_elec(creature_ptr))
177                 damage = damage / 3;
178             if (creature_ptr->levitation)
179                 damage = damage / 5;
180
181             damage = damage / 100 + (randint0(100) < (damage % 100));
182
183             if (creature_ptr->levitation) {
184                 msg_print(_("電撃を受けた!", "The electricity shocks you!"));
185                 take_hit(creature_ptr, DAMAGE_NOESCAPE, damage,
186                     format(_("%sの上に浮遊したダメージ", "flying over %s"),
187                         f_name + f_info[get_feat_mimic(&creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x])].name),
188                     -1);
189             } else {
190                 concptr name = f_name + f_info[get_feat_mimic(&creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x])].name;
191                 msg_format(_("%sに感電した!", "The %s shocks you!"), name);
192                 take_hit(creature_ptr, DAMAGE_NOESCAPE, damage, name, -1);
193             }
194
195             cave_no_regen = TRUE;
196         }
197     }
198
199     if (have_flag(f_ptr->flags, FF_ACID_PUDDLE) && !is_invuln(creature_ptr) && !creature_ptr->immune_acid) {
200         int damage = 0;
201
202         if (have_flag(f_ptr->flags, FF_DEEP)) {
203             damage = 6000 + randint0(4000);
204         } else if (!creature_ptr->levitation) {
205             damage = 3000 + randint0(2000);
206         }
207
208         if (damage) {
209             if (creature_ptr->resist_acid)
210                 damage = damage / 3;
211             if (is_oppose_acid(creature_ptr))
212                 damage = damage / 3;
213             if (creature_ptr->levitation)
214                 damage = damage / 5;
215
216             damage = damage / 100 + (randint0(100) < (damage % 100));
217
218             if (creature_ptr->levitation) {
219                 msg_print(_("酸が飛び散った!", "The acid melts you!"));
220                 take_hit(creature_ptr, DAMAGE_NOESCAPE, damage,
221                     format(_("%sの上に浮遊したダメージ", "flying over %s"),
222                         f_name + f_info[get_feat_mimic(&creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x])].name),
223                     -1);
224             } else {
225                 concptr name = f_name + f_info[get_feat_mimic(&creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x])].name;
226                 msg_format(_("%sに溶かされた!", "The %s melts you!"), name);
227                 take_hit(creature_ptr, DAMAGE_NOESCAPE, damage, name, -1);
228             }
229
230             cave_no_regen = TRUE;
231         }
232     }
233
234     if (have_flag(f_ptr->flags, FF_POISON_PUDDLE) && !is_invuln(creature_ptr)) {
235         int damage = 0;
236
237         if (have_flag(f_ptr->flags, FF_DEEP)) {
238             damage = 6000 + randint0(4000);
239         } else if (!creature_ptr->levitation) {
240             damage = 3000 + randint0(2000);
241         }
242
243         if (damage) {
244             if (creature_ptr->resist_pois)
245                 damage = damage / 3;
246             if (is_oppose_pois(creature_ptr))
247                 damage = damage / 3;
248             if (creature_ptr->levitation)
249                 damage = damage / 5;
250
251             damage = damage / 100 + (randint0(100) < (damage % 100));
252
253             if (creature_ptr->levitation) {
254                 msg_print(_("毒気を吸い込んだ!", "The gas poisons you!"));
255                 take_hit(creature_ptr, DAMAGE_NOESCAPE, damage,
256                     format(_("%sの上に浮遊したダメージ", "flying over %s"),
257                         f_name + f_info[get_feat_mimic(&creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x])].name),
258                     -1);
259                 if (creature_ptr->resist_pois)
260                     (void)set_poisoned(creature_ptr, creature_ptr->poisoned + 1);
261             } else {
262                 concptr name = f_name + f_info[get_feat_mimic(&creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x])].name;
263                 msg_format(_("%sに毒された!", "The %s poisons you!"), name);
264                 take_hit(creature_ptr, DAMAGE_NOESCAPE, damage, name, -1);
265                 if (creature_ptr->resist_pois)
266                     (void)set_poisoned(creature_ptr, creature_ptr->poisoned + 3);
267             }
268
269             cave_no_regen = TRUE;
270         }
271     }
272
273     if (have_flag(f_ptr->flags, FF_WATER) && have_flag(f_ptr->flags, FF_DEEP) && !creature_ptr->levitation && !creature_ptr->can_swim
274         && !creature_ptr->resist_water) {
275         if (creature_ptr->total_weight > weight_limit(creature_ptr)) {
276             msg_print(_("溺れている!", "You are drowning!"));
277             take_hit(creature_ptr, DAMAGE_NOESCAPE, randint1(creature_ptr->lev), _("溺れ", "drowning"), -1);
278             cave_no_regen = TRUE;
279         }
280     }
281
282     if (creature_ptr->riding) {
283         HIT_POINT damage;
284         if ((r_info[creature_ptr->current_floor_ptr->m_list[creature_ptr->riding].r_idx].flags2 & RF2_AURA_FIRE) && !creature_ptr->immune_fire) {
285             damage = r_info[creature_ptr->current_floor_ptr->m_list[creature_ptr->riding].r_idx].level / 2;
286             if (is_specific_player_race(creature_ptr, RACE_ENT))
287                 damage += damage / 3;
288             if (creature_ptr->resist_fire)
289                 damage = damage / 3;
290             if (is_oppose_fire(creature_ptr))
291                 damage = damage / 3;
292             msg_print(_("熱い!", "It's hot!"));
293             take_hit(creature_ptr, DAMAGE_NOESCAPE, damage, _("炎のオーラ", "Fire aura"), -1);
294         }
295         if ((r_info[creature_ptr->current_floor_ptr->m_list[creature_ptr->riding].r_idx].flags2 & RF2_AURA_ELEC) && !creature_ptr->immune_elec) {
296             damage = r_info[creature_ptr->current_floor_ptr->m_list[creature_ptr->riding].r_idx].level / 2;
297             if (is_specific_player_race(creature_ptr, RACE_ANDROID))
298                 damage += damage / 3;
299             if (creature_ptr->resist_elec)
300                 damage = damage / 3;
301             if (is_oppose_elec(creature_ptr))
302                 damage = damage / 3;
303             msg_print(_("痛い!", "It hurts!"));
304             take_hit(creature_ptr, DAMAGE_NOESCAPE, damage, _("電気のオーラ", "Elec aura"), -1);
305         }
306         if ((r_info[creature_ptr->current_floor_ptr->m_list[creature_ptr->riding].r_idx].flags3 & RF3_AURA_COLD) && !creature_ptr->immune_cold) {
307             damage = r_info[creature_ptr->current_floor_ptr->m_list[creature_ptr->riding].r_idx].level / 2;
308             if (creature_ptr->resist_cold)
309                 damage = damage / 3;
310             if (is_oppose_cold(creature_ptr))
311                 damage = damage / 3;
312             msg_print(_("冷たい!", "It's cold!"));
313             take_hit(creature_ptr, DAMAGE_NOESCAPE, damage, _("冷気のオーラ", "Cold aura"), -1);
314         }
315     }
316
317     /* Spectres -- take damage when moving through walls */
318     /*
319      * Added: ANYBODY takes damage if inside through walls
320      * without wraith form -- NOTE: Spectres will never be
321      * reduced below 0 hp by being inside a stone wall; others
322      * WILL BE!
323      */
324     if (!have_flag(f_ptr->flags, FF_MOVE) && !have_flag(f_ptr->flags, FF_CAN_FLY)) {
325         if (!is_invuln(creature_ptr) && !creature_ptr->wraith_form && !creature_ptr->tim_pass_wall
326             && ((creature_ptr->chp > (creature_ptr->lev / 5)) || !creature_ptr->pass_wall)) {
327             concptr dam_desc;
328             cave_no_regen = TRUE;
329
330             if (creature_ptr->pass_wall) {
331                 msg_print(_("体の分子が分解した気がする!", "Your molecules feel disrupted!"));
332                 dam_desc = _("密度", "density");
333             } else {
334                 msg_print(_("崩れた岩に押し潰された!", "You are being crushed!"));
335                 dam_desc = _("硬い岩", "solid rock");
336             }
337
338             take_hit(creature_ptr, DAMAGE_NOESCAPE, 1 + (creature_ptr->lev / 5), dam_desc, -1);
339         }
340     }
341
342     if (creature_ptr->food < PY_FOOD_WEAK) {
343         if (creature_ptr->food < PY_FOOD_STARVE) {
344             regen_amount = 0;
345         } else if (creature_ptr->food < PY_FOOD_FAINT) {
346             regen_amount = PY_REGEN_FAINT;
347         } else {
348             regen_amount = PY_REGEN_WEAK;
349         }
350     }
351
352     if (pattern_effect(creature_ptr)) {
353         cave_no_regen = TRUE;
354     } else {
355         if (creature_ptr->regenerate) {
356             regen_amount = regen_amount * 2;
357         }
358         if (creature_ptr->special_defense & (KAMAE_MASK | KATA_MASK)) {
359             regen_amount /= 2;
360         }
361         if (creature_ptr->cursed & TRC_SLOW_REGEN) {
362             regen_amount /= 5;
363         }
364     }
365
366     if ((creature_ptr->action == ACTION_SEARCH) || (creature_ptr->action == ACTION_REST)) {
367         regen_amount = regen_amount * 2;
368     }
369
370     upkeep_factor = calculate_upkeep(creature_ptr);
371     if ((creature_ptr->action == ACTION_LEARN) || (creature_ptr->action == ACTION_HAYAGAKE) || (creature_ptr->special_defense & KATA_KOUKIJIN)) {
372         upkeep_factor += 100;
373     }
374
375     regenmana(creature_ptr, upkeep_factor, regen_amount);
376     if (creature_ptr->pclass == CLASS_MAGIC_EATER) {
377         regenmagic(creature_ptr, regen_amount);
378     }
379
380     if ((creature_ptr->csp == 0) && (creature_ptr->csp_frac == 0)) {
381         while (upkeep_factor > 100) {
382             msg_print(_("こんなに多くのペットを制御できない!", "Too many pets to control at once!"));
383             msg_print(NULL);
384             do_cmd_pet_dismiss(creature_ptr);
385
386             upkeep_factor = calculate_upkeep(creature_ptr);
387
388             msg_format(_("維持MPは %d%%", "Upkeep: %d%% mana."), upkeep_factor);
389             msg_print(NULL);
390         }
391     }
392
393     if (creature_ptr->poisoned)
394         regen_amount = 0;
395     if (creature_ptr->cut)
396         regen_amount = 0;
397     if (cave_no_regen)
398         regen_amount = 0;
399
400     regen_amount = (regen_amount * creature_ptr->mutant_regenerate_mod) / 100;
401     if ((creature_ptr->chp < creature_ptr->mhp) && !cave_no_regen) {
402         regenhp(creature_ptr, regen_amount);
403     }
404 }
405
406 /*
407  * Increase players hit points, notice effects
408  */
409 bool hp_player(player_type *creature_ptr, int num)
410 {
411     int vir;
412     vir = virtue_number(creature_ptr, V_VITALITY);
413
414     if (num <= 0)
415         return FALSE;
416
417     if (vir) {
418         num = num * (creature_ptr->virtues[vir - 1] + 1250) / 1250;
419     }
420
421     if (creature_ptr->chp < creature_ptr->mhp) {
422         if ((num > 0) && (creature_ptr->chp < (creature_ptr->mhp / 3)))
423             chg_virtue(creature_ptr, V_TEMPERANCE, 1);
424
425         creature_ptr->chp += num;
426         if (creature_ptr->chp >= creature_ptr->mhp) {
427             creature_ptr->chp = creature_ptr->mhp;
428             creature_ptr->chp_frac = 0;
429         }
430
431         creature_ptr->redraw |= (PR_HP);
432         creature_ptr->window |= (PW_PLAYER);
433         if (num < 5) {
434             msg_print(_("少し気分が良くなった。", "You feel a little better."));
435         } else if (num < 15) {
436             msg_print(_("気分が良くなった。", "You feel better."));
437         } else if (num < 35) {
438             msg_print(_("とても気分が良くなった。", "You feel much better."));
439         } else {
440             msg_print(_("ひじょうに気分が良くなった。", "You feel very good."));
441         }
442
443         return TRUE;
444     }
445
446     return FALSE;
447 }