OSDN Git Service

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