OSDN Git Service

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