OSDN Git Service

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