1 #include "core/hp-mp-processor.h"
2 #include "cmd-action/cmd-pet.h"
3 #include "core/hp-mp-regenerator.h"
4 #include "core/player-redraw-types.h"
5 #include "core/window-redrawer.h"
6 #include "flavor/flavor-describer.h"
7 #include "flavor/object-flavor-types.h"
8 #include "floor/pattern-walk.h"
9 #include "grid/feature.h"
10 #include "grid/grid.h"
11 #include "inventory/inventory-slot-types.h"
12 #include "monster-race/monster-race.h"
13 #include "monster-race/race-flags2.h"
14 #include "monster-race/race-flags3.h"
15 #include "object-enchant/object-ego.h"
16 #include "object-enchant/trc-types.h"
17 #include "player/attack-defense-types.h"
18 #include "player-info/avatar.h"
19 #include "player/player-damage.h"
20 #include "player/player-race-types.h"
21 #include "player/player-race.h"
22 #include "player/special-defense-types.h"
23 #include "player/player-status-flags.h"
24 #include "status/bad-status-setter.h"
25 #include "status/element-resistance.h"
26 #include "system/floor-type-definition.h"
27 #include "util/bit-flags-calculator.h"
28 #include "view/display-messages.h"
29 #include "world/world.h"
30 #include "player/player-status-resist.h"
31 #include "util/bit-flags-calculator.h"
32 #include "object/object-flags.h"
33 #include "object-enchant/tr-types.h"
37 * @brief 10ゲームターンが進行するごとにプレイヤーのHPとMPの増減処理を行う。
38 * / Handle timed damage and regeneration every 10 game turns
41 void process_player_hp_mp(player_type *creature_ptr)
43 feature_type *f_ptr = &f_info[creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x].feat];
44 bool cave_no_regen = FALSE;
45 int upkeep_factor = 0;
46 int regen_amount = PY_REGEN_NORMAL;
47 if (creature_ptr->poisoned && !is_invuln(creature_ptr)) {
48 take_hit(creature_ptr, DAMAGE_NOESCAPE, 1, _("毒", "poison"), -1);
51 if (creature_ptr->cut && !is_invuln(creature_ptr)) {
53 if (creature_ptr->cut > 1000) {
55 } else if (creature_ptr->cut > 200) {
57 } else if (creature_ptr->cut > 100) {
59 } else if (creature_ptr->cut > 50) {
61 } else if (creature_ptr->cut > 25) {
63 } else if (creature_ptr->cut > 10) {
69 take_hit(creature_ptr, DAMAGE_NOESCAPE, dam, _("致命傷", "a fatal wound"), -1);
72 if (is_specific_player_race(creature_ptr, RACE_VAMPIRE) || (creature_ptr->mimic_form == MIMIC_VAMPIRE)) {
73 if (!creature_ptr->current_floor_ptr->dun_level && !has_resist_lite(creature_ptr) && !is_invuln(creature_ptr) && is_daytime()) {
74 if ((creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x].info & (CAVE_GLOW | CAVE_MNDK)) == CAVE_GLOW) {
75 msg_print(_("日光があなたのアンデッドの肉体を焼き焦がした!", "The sun's rays scorch your undead flesh!"));
76 take_hit(creature_ptr, DAMAGE_NOESCAPE, 1, _("日光", "sunlight"), -1);
82 o_ptr = &creature_ptr->inventory_list[INVEN_LITE];
83 BIT_FLAGS flgs[TR_FLAG_SIZE];
84 object_flags(creature_ptr, o_ptr, flgs);
86 if (creature_ptr->inventory_list[INVEN_LITE].tval && !has_flag(flgs, TR_DARK_SOURCE) && !has_resist_lite(creature_ptr)) {
87 GAME_TEXT o_name[MAX_NLEN];
88 char ouch[MAX_NLEN + 40];
89 describe_flavor(creature_ptr, o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
90 msg_format(_("%sがあなたのアンデッドの肉体を焼き焦がした!", "The %s scorches your undead flesh!"), o_name);
93 describe_flavor(creature_ptr, o_name, o_ptr, OD_NAME_ONLY);
94 sprintf(ouch, _("%sを装備したダメージ", "wielding %s"), o_name);
96 if (!is_invuln(creature_ptr))
97 take_hit(creature_ptr, DAMAGE_NOESCAPE, 1, ouch, -1);
101 if (has_flag(f_ptr->flags, FF_LAVA) && !is_invuln(creature_ptr) && !has_immune_fire(creature_ptr)) {
104 if (has_flag(f_ptr->flags, FF_DEEP)) {
105 damage = 6000 + randint0(4000);
106 } else if (!creature_ptr->levitation) {
107 damage = 3000 + randint0(2000);
111 if (is_specific_player_race(creature_ptr, RACE_ENT))
112 damage += damage / 3;
113 if (has_resist_fire(creature_ptr))
115 if (is_oppose_fire(creature_ptr))
119 if (creature_ptr->levitation)
122 damage = damage / 100 + (randint0(100) < (damage % 100));
124 if (creature_ptr->levitation) {
125 msg_print(_("熱で火傷した!", "The heat burns you!"));
126 take_hit(creature_ptr, DAMAGE_NOESCAPE, damage,
127 format(_("%sの上に浮遊したダメージ", "flying over %s"),
128 f_name + f_info[get_feat_mimic(&creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x])].name),
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 burns you!"), name);
133 take_hit(creature_ptr, DAMAGE_NOESCAPE, damage, name, -1);
136 cave_no_regen = TRUE;
140 if (has_flag(f_ptr->flags, FF_COLD_PUDDLE) && !is_invuln(creature_ptr) && !has_immune_cold(creature_ptr)) {
143 if (has_flag(f_ptr->flags, FF_DEEP)) {
144 damage = 6000 + randint0(4000);
145 } else if (!creature_ptr->levitation) {
146 damage = 3000 + randint0(2000);
150 if (has_resist_cold(creature_ptr))
152 if (is_oppose_cold(creature_ptr))
154 if (creature_ptr->levitation)
157 damage = damage / 100 + (randint0(100) < (damage % 100));
159 if (creature_ptr->levitation) {
160 msg_print(_("冷気に覆われた!", "The cold engulfs you!"));
161 take_hit(creature_ptr, DAMAGE_NOESCAPE, damage,
162 format(_("%sの上に浮遊したダメージ", "flying over %s"),
163 f_name + f_info[get_feat_mimic(&creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x])].name),
166 concptr name = f_name + f_info[get_feat_mimic(&creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x])].name;
167 msg_format(_("%sに凍えた!", "The %s frostbites you!"), name);
168 take_hit(creature_ptr, DAMAGE_NOESCAPE, damage, name, -1);
171 cave_no_regen = TRUE;
175 if (has_flag(f_ptr->flags, FF_ELEC_PUDDLE) && !is_invuln(creature_ptr) && !has_immune_elec(creature_ptr)) {
178 if (has_flag(f_ptr->flags, FF_DEEP)) {
179 damage = 6000 + randint0(4000);
180 } else if (!creature_ptr->levitation) {
181 damage = 3000 + randint0(2000);
185 if (has_resist_elec(creature_ptr))
187 if (is_oppose_elec(creature_ptr))
189 if (creature_ptr->levitation)
192 damage = damage / 100 + (randint0(100) < (damage % 100));
194 if (creature_ptr->levitation) {
195 msg_print(_("電撃を受けた!", "The electricity shocks you!"));
196 take_hit(creature_ptr, DAMAGE_NOESCAPE, damage,
197 format(_("%sの上に浮遊したダメージ", "flying over %s"),
198 f_name + f_info[get_feat_mimic(&creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x])].name),
201 concptr name = f_name + f_info[get_feat_mimic(&creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x])].name;
202 msg_format(_("%sに感電した!", "The %s shocks you!"), name);
203 take_hit(creature_ptr, DAMAGE_NOESCAPE, damage, name, -1);
206 cave_no_regen = TRUE;
210 if (has_flag(f_ptr->flags, FF_ACID_PUDDLE) && !is_invuln(creature_ptr) && !has_immune_acid(creature_ptr)) {
213 if (has_flag(f_ptr->flags, FF_DEEP)) {
214 damage = 6000 + randint0(4000);
215 } else if (!creature_ptr->levitation) {
216 damage = 3000 + randint0(2000);
220 if (has_resist_acid(creature_ptr))
222 if (is_oppose_acid(creature_ptr))
224 if (creature_ptr->levitation)
227 damage = damage / 100 + (randint0(100) < (damage % 100));
229 if (creature_ptr->levitation) {
230 msg_print(_("酸が飛び散った!", "The acid melts you!"));
231 take_hit(creature_ptr, DAMAGE_NOESCAPE, damage,
232 format(_("%sの上に浮遊したダメージ", "flying over %s"),
233 f_name + f_info[get_feat_mimic(&creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x])].name),
236 concptr name = f_name + f_info[get_feat_mimic(&creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x])].name;
237 msg_format(_("%sに溶かされた!", "The %s melts you!"), name);
238 take_hit(creature_ptr, DAMAGE_NOESCAPE, damage, name, -1);
241 cave_no_regen = TRUE;
245 if (has_flag(f_ptr->flags, FF_POISON_PUDDLE) && !is_invuln(creature_ptr)) {
248 if (has_flag(f_ptr->flags, FF_DEEP)) {
249 damage = 6000 + randint0(4000);
250 } else if (!creature_ptr->levitation) {
251 damage = 3000 + randint0(2000);
255 damage = calc_pois_damage_rate(creature_ptr) / 100;
256 if (creature_ptr->levitation)
259 damage = damage / 100 + (randint0(100) < (damage % 100));
261 if (creature_ptr->levitation) {
262 msg_print(_("毒気を吸い込んだ!", "The gas poisons you!"));
263 take_hit(creature_ptr, DAMAGE_NOESCAPE, damage,
264 format(_("%sの上に浮遊したダメージ", "flying over %s"),
265 f_name + f_info[get_feat_mimic(&creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x])].name),
267 if (has_resist_pois(creature_ptr))
268 (void)set_poisoned(creature_ptr, creature_ptr->poisoned + 1);
270 concptr name = f_name + f_info[get_feat_mimic(&creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x])].name;
271 msg_format(_("%sに毒された!", "The %s poisons you!"), name);
272 take_hit(creature_ptr, DAMAGE_NOESCAPE, damage, name, -1);
273 if (has_resist_pois(creature_ptr))
274 (void)set_poisoned(creature_ptr, creature_ptr->poisoned + 3);
277 cave_no_regen = TRUE;
281 if (has_flag(f_ptr->flags, FF_WATER) && has_flag(f_ptr->flags, FF_DEEP) && !creature_ptr->levitation && !creature_ptr->can_swim
282 && !creature_ptr->resist_water) {
283 if (calc_inventory_weight(creature_ptr) > calc_weight_limit(creature_ptr)) {
284 msg_print(_("溺れている!", "You are drowning!"));
285 take_hit(creature_ptr, DAMAGE_NOESCAPE, randint1(creature_ptr->lev), _("溺れ", "drowning"), -1);
286 cave_no_regen = TRUE;
290 if (creature_ptr->riding) {
292 if ((r_info[creature_ptr->current_floor_ptr->m_list[creature_ptr->riding].r_idx].flags2 & RF2_AURA_FIRE) && !has_immune_fire(creature_ptr)) {
293 damage = r_info[creature_ptr->current_floor_ptr->m_list[creature_ptr->riding].r_idx].level / 2;
294 if (is_specific_player_race(creature_ptr, RACE_ENT))
295 damage += damage / 3;
296 if (has_resist_fire(creature_ptr))
298 if (is_oppose_fire(creature_ptr))
300 msg_print(_("熱い!", "It's hot!"));
301 take_hit(creature_ptr, DAMAGE_NOESCAPE, damage, _("炎のオーラ", "Fire aura"), -1);
303 if ((r_info[creature_ptr->current_floor_ptr->m_list[creature_ptr->riding].r_idx].flags2 & RF2_AURA_ELEC) && !has_immune_elec(creature_ptr)) {
304 damage = r_info[creature_ptr->current_floor_ptr->m_list[creature_ptr->riding].r_idx].level / 2;
305 if (is_specific_player_race(creature_ptr, RACE_ANDROID))
306 damage += damage / 3;
307 if (has_resist_elec(creature_ptr))
309 if (is_oppose_elec(creature_ptr))
311 msg_print(_("痛い!", "It hurts!"));
312 take_hit(creature_ptr, DAMAGE_NOESCAPE, damage, _("電気のオーラ", "Elec aura"), -1);
314 if ((r_info[creature_ptr->current_floor_ptr->m_list[creature_ptr->riding].r_idx].flags3 & RF3_AURA_COLD) && !has_immune_cold(creature_ptr)) {
315 damage = r_info[creature_ptr->current_floor_ptr->m_list[creature_ptr->riding].r_idx].level / 2;
316 if (has_resist_cold(creature_ptr))
318 if (is_oppose_cold(creature_ptr))
320 msg_print(_("冷たい!", "It's cold!"));
321 take_hit(creature_ptr, DAMAGE_NOESCAPE, damage, _("冷気のオーラ", "Cold aura"), -1);
325 /* Spectres -- take damage when moving through walls */
327 * Added: ANYBODY takes damage if inside through walls
328 * without wraith form -- NOTE: Spectres will never be
329 * reduced below 0 hp by being inside a stone wall; others
332 if (!has_flag(f_ptr->flags, FF_MOVE) && !has_flag(f_ptr->flags, FF_CAN_FLY)) {
333 if (!is_invuln(creature_ptr) && !creature_ptr->wraith_form && !creature_ptr->tim_pass_wall
334 && ((creature_ptr->chp > (creature_ptr->lev / 5)) || !creature_ptr->pass_wall)) {
336 cave_no_regen = TRUE;
338 if (creature_ptr->pass_wall) {
339 msg_print(_("体の分子が分解した気がする!", "Your molecules feel disrupted!"));
340 dam_desc = _("密度", "density");
342 msg_print(_("崩れた岩に押し潰された!", "You are being crushed!"));
343 dam_desc = _("硬い岩", "solid rock");
346 take_hit(creature_ptr, DAMAGE_NOESCAPE, 1 + (creature_ptr->lev / 5), dam_desc, -1);
350 if (creature_ptr->food < PY_FOOD_WEAK) {
351 if (creature_ptr->food < PY_FOOD_STARVE) {
353 } else if (creature_ptr->food < PY_FOOD_FAINT) {
354 regen_amount = PY_REGEN_FAINT;
356 regen_amount = PY_REGEN_WEAK;
360 if (pattern_effect(creature_ptr)) {
361 cave_no_regen = TRUE;
363 if (creature_ptr->regenerate) {
364 regen_amount = regen_amount * 2;
366 if (creature_ptr->special_defense & (KAMAE_MASK | KATA_MASK)) {
369 if (creature_ptr->cursed & TRC_SLOW_REGEN) {
374 if ((creature_ptr->action == ACTION_SEARCH) || (creature_ptr->action == ACTION_REST)) {
375 regen_amount = regen_amount * 2;
378 upkeep_factor = calculate_upkeep(creature_ptr);
379 if ((creature_ptr->action == ACTION_LEARN) || (creature_ptr->action == ACTION_HAYAGAKE) || (creature_ptr->special_defense & KATA_KOUKIJIN)) {
380 upkeep_factor += 100;
383 regenmana(creature_ptr, upkeep_factor, regen_amount);
384 if (creature_ptr->pclass == CLASS_MAGIC_EATER) {
385 regenmagic(creature_ptr, regen_amount);
388 if ((creature_ptr->csp == 0) && (creature_ptr->csp_frac == 0)) {
389 while (upkeep_factor > 100) {
390 msg_print(_("こんなに多くのペットを制御できない!", "Too many pets to control at once!"));
392 do_cmd_pet_dismiss(creature_ptr);
394 upkeep_factor = calculate_upkeep(creature_ptr);
396 msg_format(_("維持MPは %d%%", "Upkeep: %d%% mana."), upkeep_factor);
401 if (creature_ptr->poisoned)
403 if (creature_ptr->cut)
408 regen_amount = (regen_amount * creature_ptr->mutant_regenerate_mod) / 100;
409 if ((creature_ptr->chp < creature_ptr->mhp) && !cave_no_regen) {
410 regenhp(creature_ptr, regen_amount);
415 * Increase players hit points, notice effects
417 bool hp_player(player_type *creature_ptr, int num)
420 vir = virtue_number(creature_ptr, V_VITALITY);
426 num = num * (creature_ptr->virtues[vir - 1] + 1250) / 1250;
429 if (creature_ptr->chp < creature_ptr->mhp) {
430 if ((num > 0) && (creature_ptr->chp < (creature_ptr->mhp / 3)))
431 chg_virtue(creature_ptr, V_TEMPERANCE, 1);
433 creature_ptr->chp += num;
434 if (creature_ptr->chp >= creature_ptr->mhp) {
435 creature_ptr->chp = creature_ptr->mhp;
436 creature_ptr->chp_frac = 0;
439 creature_ptr->redraw |= (PR_HP);
440 creature_ptr->window |= (PW_PLAYER);
442 msg_print(_("少し気分が良くなった。", "You feel a little better."));
443 } else if (num < 15) {
444 msg_print(_("気分が良くなった。", "You feel better."));
445 } else if (num < 35) {
446 msg_print(_("とても気分が良くなった。", "You feel much better."));
448 msg_print(_("ひじょうに気分が良くなった。", "You feel very good."));