OSDN Git Service

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