OSDN Git Service

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