OSDN Git Service

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