OSDN Git Service

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