OSDN Git Service

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