2 #include "player-damage.h"
4 #include "object-hook.h"
5 #include "object-broken.h"
6 #include "player-status.h"
10 * @brief アイテムが酸で破損するかどうかを判定する
11 * @param o_ptr アイテムの情報参照ポインタ
12 * @return 破損するならばTRUEを返す
13 * Note that amulets, rods, and high-level spell books are immune
14 * to "inventory damage" of any kind. Also sling ammo and shovels.
15 * Does a given class of objects (usually) hate acid?
16 * Note that acid can either melt or corrode something.
18 bool hates_acid(object_type *o_ptr)
20 /* Analyze the type */
43 /* Staffs/Scrolls are wood/paper */
70 * @brief アイテムが電撃で破損するかどうかを判定する /
71 * Does a given object (usually) hate electricity?
72 * @param o_ptr アイテムの情報参照ポインタ
73 * @return 破損するならばTRUEを返す
75 bool hates_elec(object_type *o_ptr)
91 * @brief アイテムが火炎で破損するかどうかを判定する /
92 * Does a given object (usually) hate fire?
93 * @param o_ptr アイテムの情報参照ポインタ
94 * @return 破損するならばTRUEを返す
96 * Hafted/Polearm weapons have wooden shafts.
97 * Arrows/Bows are mostly wooden.
99 bool hates_fire(object_type *o_ptr)
101 /* Analyze the type */
120 case TV_SORCERY_BOOK:
128 case TV_CRUSADE_BOOK:
130 case TV_HISSATSU_BOOK:
142 /* Staffs/Scrolls burn */
155 * @brief アイテムが冷気で破損するかどうかを判定する /
156 * Does a given object (usually) hate cold?
157 * @param o_ptr アイテムの情報参照ポインタ
158 * @return 破損するならばTRUEを返す
160 bool hates_cold(object_type *o_ptr)
177 * @brief アイテムが酸で破損するかどうかを判定する(メインルーチン) /
179 * @param o_ptr アイテムの情報参照ポインタ
180 * @return 破損するならばTRUEを返す
183 int set_acid_destroy(object_type *o_ptr)
185 BIT_FLAGS flgs[TR_FLAG_SIZE];
186 if (!hates_acid(o_ptr)) return (FALSE);
187 object_flags(o_ptr, flgs);
188 if (have_flag(flgs, TR_IGNORE_ACID)) return (FALSE);
194 * @brief アイテムが電撃で破損するかどうかを判定する(メインルーチン) /
196 * @param o_ptr アイテムの情報参照ポインタ
197 * @return 破損するならばTRUEを返す
200 int set_elec_destroy(object_type *o_ptr)
202 BIT_FLAGS flgs[TR_FLAG_SIZE];
203 if (!hates_elec(o_ptr)) return (FALSE);
204 object_flags(o_ptr, flgs);
205 if (have_flag(flgs, TR_IGNORE_ELEC)) return (FALSE);
211 * @brief アイテムが火炎で破損するかどうかを判定する(メインルーチン) /
213 * @param o_ptr アイテムの情報参照ポインタ
214 * @return 破損するならばTRUEを返す
217 int set_fire_destroy(object_type *o_ptr)
219 BIT_FLAGS flgs[TR_FLAG_SIZE];
220 if (!hates_fire(o_ptr)) return (FALSE);
221 object_flags(o_ptr, flgs);
222 if (have_flag(flgs, TR_IGNORE_FIRE)) return (FALSE);
228 * @brief アイテムが冷気で破損するかどうかを判定する(メインルーチン) /
230 * @param o_ptr アイテムの情報参照ポインタ
231 * @return 破損するならばTRUEを返す
234 int set_cold_destroy(object_type *o_ptr)
236 BIT_FLAGS flgs[TR_FLAG_SIZE];
237 if (!hates_cold(o_ptr)) return (FALSE);
238 object_flags(o_ptr, flgs);
239 if (have_flag(flgs, TR_IGNORE_COLD)) return (FALSE);
245 * @brief アイテムが指定確率で破損するかどうかを判定する /
246 * Destroys a type of item on a given percent chance
247 * @param typ 破損判定関数ポインタ
251 * Note that missiles are no longer necessarily all destroyed
252 * Destruction taken from "melee.c" code for "stealing".
253 * New-style wands and rods handled correctly. -LM-
254 * Returns number of items destroyed.
256 int inven_damage(inven_func typ, int perc)
261 GAME_TEXT o_name[MAX_NLEN];
263 if (CHECK_MULTISHADOW()) return 0;
265 if (p_ptr->inside_arena) return 0;
267 /* Count the casualties */
270 /* Scan through the slots backwards */
271 for (i = 0; i < INVEN_PACK; i++)
273 o_ptr = &inventory[i];
275 /* Skip non-objects */
276 if (!o_ptr->k_idx) continue;
278 /* Hack -- for now, skip artifacts */
279 if (object_is_artifact(o_ptr)) continue;
281 /* Give this item slot a shot at death */
284 /* Count the casualties */
285 for (amt = j = 0; j < o_ptr->number; ++j)
287 if (randint0(100) < perc) amt++;
290 /* Some casualities */
293 object_desc(o_name, o_ptr, OD_OMIT_PREFIX);
295 msg_format(_("%s(%c)が%s壊れてしまった!", "%sour %s (%c) %s destroyed!"),
297 o_name, index_to_label(i), ((o_ptr->number > 1) ?
298 ((amt == o_ptr->number) ? "全部" : (amt > 1 ? "何個か" : "一個")) : ""));
300 ((o_ptr->number > 1) ? ((amt == o_ptr->number) ? "All of y" :
301 (amt > 1 ? "Some of y" : "One of y")) : "Y"), o_name, index_to_label(i), ((amt > 1) ? "were" : "was"));
305 if ((p_ptr->pseikaku == SEIKAKU_COMBAT) || (inventory[INVEN_BOW].name1 == ART_CRIMSON))
306 msg_print("やりやがったな!");
307 else if ((p_ptr->pseikaku == SEIKAKU_CHARGEMAN))
309 if (randint0(2) == 0) msg_print(_("ジュラル星人め!", ""));
310 else msg_print(_("弱い者いじめは止めるんだ!", ""));
314 /* Potions smash open */
315 if (object_is_potion(o_ptr))
317 (void)potion_smash_effect(0, p_ptr->y, p_ptr->x, o_ptr->k_idx);
320 /* Reduce the charges of rods/wands */
321 reduce_charges(o_ptr, amt);
323 /* Destroy "amt" items */
324 inven_item_increase(i, -amt);
325 inven_item_optimize(i);
327 /* Count the casualties */
333 /* Return the casualty count */
339 * @brief 酸攻撃による装備のAC劣化処理 /
340 * Acid has hit the player, attempt to affect some armor.
341 * @return 装備による軽減があったならTRUEを返す
343 * Note that the "base armor" of an object never changes.
344 * If any armor is damaged (or resists), the player takes less damage.
346 static bool acid_minus_ac(void)
348 object_type *o_ptr = NULL;
349 BIT_FLAGS flgs[TR_FLAG_SIZE];
350 GAME_TEXT o_name[MAX_NLEN];
352 /* Pick a (possibly empty) inventory slot */
355 case 1: o_ptr = &inventory[INVEN_RARM]; break;
356 case 2: o_ptr = &inventory[INVEN_LARM]; break;
357 case 3: o_ptr = &inventory[INVEN_BODY]; break;
358 case 4: o_ptr = &inventory[INVEN_OUTER]; break;
359 case 5: o_ptr = &inventory[INVEN_HANDS]; break;
360 case 6: o_ptr = &inventory[INVEN_HEAD]; break;
361 case 7: o_ptr = &inventory[INVEN_FEET]; break;
364 if (!o_ptr->k_idx) return (FALSE);
365 if (!object_is_armour(o_ptr)) return (FALSE);
367 object_desc(o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
368 object_flags(o_ptr, flgs);
369 /* No damage left to be done */
370 if (o_ptr->ac + o_ptr->to_a <= 0)
372 msg_format(_("%sは既にボロボロだ!", "Your %s is already crumble!"), o_name);
377 if (have_flag(flgs, TR_IGNORE_ACID))
379 msg_format(_("しかし%sには効果がなかった!", "Your %s is unaffected!"), o_name);
383 msg_format(_("%sが酸で腐食した!", "Your %s is corroded!"), o_name);
385 /* Damage the item */
388 /* Calculate bonuses */
389 p_ptr->update |= (PU_BONUS);
390 p_ptr->window |= (PW_EQUIP | PW_PLAYER);
394 /* Item was damaged */
400 * @brief 酸属性によるプレイヤー損害処理 /
401 * Hurt the player with Acid
403 * @param kb_str ダメージ原因記述
404 * @param monspell 原因となったモンスター特殊攻撃ID
405 * @param aura オーラよるダメージが原因ならばTRUE
408 HIT_POINT acid_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura)
410 HIT_POINT get_damage;
411 int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
412 bool double_resist = IS_OPPOSE_ACID();
415 if (p_ptr->immune_acid || (dam <= 0))
417 learn_spell(monspell);
421 /* Vulnerability (Ouch!) */
422 if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
423 if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
425 /* Resist the damage */
426 if (p_ptr->resist_acid) dam = (dam + 2) / 3;
427 if (double_resist) dam = (dam + 2) / 3;
429 if (aura || !CHECK_MULTISHADOW())
431 if ((!(double_resist || p_ptr->resist_acid)) &&
432 one_in_(HURT_CHANCE))
433 (void)do_dec_stat(A_CHR);
435 /* If any armor gets hit, defend the player */
436 if (acid_minus_ac()) dam = (dam + 1) / 2;
439 get_damage = take_hit(aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str, monspell);
441 /* Inventory damage */
442 if (!aura && !(double_resist && p_ptr->resist_acid))
443 inven_damage(set_acid_destroy, inv);
449 * @brief 電撃属性によるプレイヤー損害処理 /
450 * Hurt the player with electricity
452 * @param kb_str ダメージ原因記述
453 * @param monspell 原因となったモンスター特殊攻撃ID
454 * @param aura オーラよるダメージが原因ならばTRUE
457 HIT_POINT elec_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura)
459 HIT_POINT get_damage;
460 int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
461 bool double_resist = IS_OPPOSE_ELEC();
464 if (p_ptr->immune_elec || (dam <= 0))
466 learn_spell(monspell);
470 /* Vulnerability (Ouch!) */
471 if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
472 if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
473 if (prace_is_(RACE_ANDROID)) dam += dam / 3;
475 /* Resist the damage */
476 if (p_ptr->resist_elec) dam = (dam + 2) / 3;
477 if (double_resist) dam = (dam + 2) / 3;
479 if (aura || !CHECK_MULTISHADOW())
481 if ((!(double_resist || p_ptr->resist_elec)) &&
482 one_in_(HURT_CHANCE))
483 (void)do_dec_stat(A_DEX);
486 get_damage = take_hit(aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str, monspell);
488 /* Inventory damage */
489 if (!aura && !(double_resist && p_ptr->resist_elec))
490 inven_damage(set_elec_destroy, inv);
497 * @brief 火炎属性によるプレイヤー損害処理 /
498 * Hurt the player with Fire
500 * @param kb_str ダメージ原因記述
501 * @param monspell 原因となったモンスター特殊攻撃ID
502 * @param aura オーラよるダメージが原因ならばTRUE
505 HIT_POINT fire_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura)
507 HIT_POINT get_damage;
508 int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
509 bool double_resist = IS_OPPOSE_FIRE();
512 if (p_ptr->immune_fire || (dam <= 0))
514 learn_spell(monspell);
518 /* Vulnerability (Ouch!) */
519 if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
520 if (prace_is_(RACE_ENT)) dam += dam / 3;
521 if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
523 /* Resist the damage */
524 if (p_ptr->resist_fire) dam = (dam + 2) / 3;
525 if (double_resist) dam = (dam + 2) / 3;
527 if (aura || !CHECK_MULTISHADOW())
529 if ((!(double_resist || p_ptr->resist_fire)) &&
530 one_in_(HURT_CHANCE))
531 (void)do_dec_stat(A_STR);
534 get_damage = take_hit(aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str, monspell);
536 /* Inventory damage */
537 if (!aura && !(double_resist && p_ptr->resist_fire))
538 inven_damage(set_fire_destroy, inv);
545 * @brief 冷気属性によるプレイヤー損害処理 /
546 * Hurt the player with Cold
548 * @param kb_str ダメージ原因記述
549 * @param monspell 原因となったモンスター特殊攻撃ID
550 * @param aura オーラよるダメージが原因ならばTRUE
553 HIT_POINT cold_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura)
555 HIT_POINT get_damage;
556 int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
557 bool double_resist = IS_OPPOSE_COLD();
560 if (p_ptr->immune_cold || (dam <= 0))
562 learn_spell(monspell);
566 /* Vulnerability (Ouch!) */
567 if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
568 if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
570 /* Resist the damage */
571 if (p_ptr->resist_cold) dam = (dam + 2) / 3;
572 if (double_resist) dam = (dam + 2) / 3;
574 if (aura || !CHECK_MULTISHADOW())
576 if ((!(double_resist || p_ptr->resist_cold)) &&
577 one_in_(HURT_CHANCE))
578 (void)do_dec_stat(A_STR);
581 get_damage = take_hit(aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str, monspell);
583 /* Inventory damage */
584 if (!aura && !(double_resist && p_ptr->resist_cold))
585 inven_damage(set_cold_destroy, inv);