OSDN Git Service

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