4 #include "player-damage.h"
6 #include "object-flavor.h"
7 #include "object-hook.h"
8 #include "object-broken.h"
9 #include "player-status.h"
10 #include "player-effects.h"
11 #include "monster-spell.h"
15 * @brief アイテムが酸で破損するかどうかを判定する
16 * @param o_ptr アイテムの情報参照ポインタ
17 * @return 破損するならばTRUEを返す
18 * Note that amulets, rods, and high-level spell books are immune
19 * to "inventory damage" of any kind. Also sling ammo and shovels.
20 * Does a given class of objects (usually) hate acid?
21 * Note that acid can either melt or corrode something.
23 bool hates_acid(object_type *o_ptr)
25 /* Analyze the type */
48 /* Staffs/Scrolls are wood/paper */
75 * @brief アイテムが電撃で破損するかどうかを判定する /
76 * Does a given object (usually) hate electricity?
77 * @param o_ptr アイテムの情報参照ポインタ
78 * @return 破損するならばTRUEを返す
80 bool hates_elec(object_type *o_ptr)
96 * @brief アイテムが火炎で破損するかどうかを判定する /
97 * Does a given object (usually) hate fire?
98 * @param o_ptr アイテムの情報参照ポインタ
99 * @return 破損するならばTRUEを返す
101 * Hafted/Polearm weapons have wooden shafts.
102 * Arrows/Bows are mostly wooden.
104 bool hates_fire(object_type *o_ptr)
106 /* Analyze the type */
125 case TV_SORCERY_BOOK:
133 case TV_CRUSADE_BOOK:
135 case TV_HISSATSU_BOOK:
147 /* Staffs/Scrolls burn */
160 * @brief アイテムが冷気で破損するかどうかを判定する /
161 * Does a given object (usually) hate cold?
162 * @param o_ptr アイテムの情報参照ポインタ
163 * @return 破損するならばTRUEを返す
165 bool hates_cold(object_type *o_ptr)
182 * @brief アイテムが酸で破損するかどうかを判定する(メインルーチン) /
184 * @param o_ptr アイテムの情報参照ポインタ
185 * @return 破損するならばTRUEを返す
188 int set_acid_destroy(object_type *o_ptr)
190 BIT_FLAGS flgs[TR_FLAG_SIZE];
191 if (!hates_acid(o_ptr)) return (FALSE);
192 object_flags(o_ptr, flgs);
193 if (have_flag(flgs, TR_IGNORE_ACID)) return (FALSE);
199 * @brief アイテムが電撃で破損するかどうかを判定する(メインルーチン) /
201 * @param o_ptr アイテムの情報参照ポインタ
202 * @return 破損するならばTRUEを返す
205 int set_elec_destroy(object_type *o_ptr)
207 BIT_FLAGS flgs[TR_FLAG_SIZE];
208 if (!hates_elec(o_ptr)) return (FALSE);
209 object_flags(o_ptr, flgs);
210 if (have_flag(flgs, TR_IGNORE_ELEC)) return (FALSE);
216 * @brief アイテムが火炎で破損するかどうかを判定する(メインルーチン) /
218 * @param o_ptr アイテムの情報参照ポインタ
219 * @return 破損するならばTRUEを返す
222 int set_fire_destroy(object_type *o_ptr)
224 BIT_FLAGS flgs[TR_FLAG_SIZE];
225 if (!hates_fire(o_ptr)) return (FALSE);
226 object_flags(o_ptr, flgs);
227 if (have_flag(flgs, TR_IGNORE_FIRE)) return (FALSE);
233 * @brief アイテムが冷気で破損するかどうかを判定する(メインルーチン) /
235 * @param o_ptr アイテムの情報参照ポインタ
236 * @return 破損するならばTRUEを返す
239 int set_cold_destroy(object_type *o_ptr)
241 BIT_FLAGS flgs[TR_FLAG_SIZE];
242 if (!hates_cold(o_ptr)) return (FALSE);
243 object_flags(o_ptr, flgs);
244 if (have_flag(flgs, TR_IGNORE_COLD)) return (FALSE);
250 * @brief アイテムが指定確率で破損するかどうかを判定する /
251 * Destroys a type of item on a given percent chance
252 * @param typ 破損判定関数ポインタ
256 * Note that missiles are no longer necessarily all destroyed
257 * Destruction taken from "melee.c" code for "stealing".
258 * New-style wands and rods handled correctly. -LM-
259 * Returns number of items destroyed.
261 int inven_damage(inven_func typ, int perc)
266 GAME_TEXT o_name[MAX_NLEN];
268 if (CHECK_MULTISHADOW()) return 0;
270 if (p_ptr->inside_arena) return 0;
272 /* Count the casualties */
275 /* Scan through the slots backwards */
276 for (i = 0; i < INVEN_PACK; i++)
278 o_ptr = &inventory[i];
279 if (!o_ptr->k_idx) continue;
281 /* Hack -- for now, skip artifacts */
282 if (object_is_artifact(o_ptr)) continue;
284 /* Give this item slot a shot at death */
287 /* Count the casualties */
288 for (amt = j = 0; j < o_ptr->number; ++j)
290 if (randint0(100) < perc) amt++;
293 /* Some casualities */
296 object_desc(o_name, o_ptr, OD_OMIT_PREFIX);
298 msg_format(_("%s(%c)が%s壊れてしまった!", "%sour %s (%c) %s destroyed!"),
300 o_name, index_to_label(i), ((o_ptr->number > 1) ?
301 ((amt == o_ptr->number) ? "全部" : (amt > 1 ? "何個か" : "一個")) : ""));
303 ((o_ptr->number > 1) ? ((amt == o_ptr->number) ? "All of y" :
304 (amt > 1 ? "Some of y" : "One of y")) : "Y"), o_name, index_to_label(i), ((amt > 1) ? "were" : "was"));
308 if ((p_ptr->pseikaku == SEIKAKU_COMBAT) || (inventory[INVEN_BOW].name1 == ART_CRIMSON))
309 msg_print("やりやがったな!");
310 else if ((p_ptr->pseikaku == SEIKAKU_CHARGEMAN))
312 if (randint0(2) == 0) msg_print(_("ジュラル星人め!", ""));
313 else msg_print(_("弱い者いじめは止めるんだ!", ""));
317 /* Potions smash open */
318 if (object_is_potion(o_ptr))
320 (void)potion_smash_effect(0, p_ptr->y, p_ptr->x, o_ptr->k_idx);
323 /* Reduce the charges of rods/wands */
324 reduce_charges(o_ptr, amt);
326 /* Destroy "amt" items */
327 inven_item_increase(i, -amt);
328 inven_item_optimize(i);
330 /* Count the casualties */
336 /* Return the casualty count */
342 * @brief 酸攻撃による装備のAC劣化処理 /
343 * Acid has hit the player, attempt to affect some armor.
344 * @return 装備による軽減があったならTRUEを返す
346 * Note that the "base armor" of an object never changes.
347 * If any armor is damaged (or resists), the player takes less damage.
349 static bool acid_minus_ac(void)
351 object_type *o_ptr = NULL;
352 BIT_FLAGS flgs[TR_FLAG_SIZE];
353 GAME_TEXT o_name[MAX_NLEN];
355 /* Pick a (possibly empty) inventory slot */
358 case 1: o_ptr = &inventory[INVEN_RARM]; break;
359 case 2: o_ptr = &inventory[INVEN_LARM]; break;
360 case 3: o_ptr = &inventory[INVEN_BODY]; break;
361 case 4: o_ptr = &inventory[INVEN_OUTER]; break;
362 case 5: o_ptr = &inventory[INVEN_HANDS]; break;
363 case 6: o_ptr = &inventory[INVEN_HEAD]; break;
364 case 7: o_ptr = &inventory[INVEN_FEET]; break;
367 if (!o_ptr->k_idx) return (FALSE);
368 if (!object_is_armour(o_ptr)) return (FALSE);
370 object_desc(o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
371 object_flags(o_ptr, flgs);
372 /* No damage left to be done */
373 if (o_ptr->ac + o_ptr->to_a <= 0)
375 msg_format(_("%sは既にボロボロだ!", "Your %s is already crumble!"), o_name);
380 if (have_flag(flgs, TR_IGNORE_ACID))
382 msg_format(_("しかし%sには効果がなかった!", "Your %s is unaffected!"), o_name);
386 msg_format(_("%sが酸で腐食した!", "Your %s is corroded!"), o_name);
388 /* Damage the item */
391 /* Calculate bonuses */
392 p_ptr->update |= (PU_BONUS);
393 p_ptr->window |= (PW_EQUIP | PW_PLAYER);
397 /* Item was damaged */
403 * @brief 酸属性によるプレイヤー損害処理 /
404 * Hurt the player with Acid
406 * @param kb_str ダメージ原因記述
407 * @param monspell 原因となったモンスター特殊攻撃ID
408 * @param aura オーラよるダメージが原因ならばTRUE
411 HIT_POINT acid_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura)
413 HIT_POINT get_damage;
414 int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
415 bool double_resist = IS_OPPOSE_ACID();
418 if (p_ptr->immune_acid || (dam <= 0))
420 learn_spell(monspell);
424 /* Vulnerability (Ouch!) */
425 if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
426 if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
428 /* Resist the damage */
429 if (p_ptr->resist_acid) dam = (dam + 2) / 3;
430 if (double_resist) dam = (dam + 2) / 3;
432 if (aura || !CHECK_MULTISHADOW())
434 if ((!(double_resist || p_ptr->resist_acid)) &&
435 one_in_(HURT_CHANCE))
436 (void)do_dec_stat(A_CHR);
438 /* If any armor gets hit, defend the player */
439 if (acid_minus_ac()) dam = (dam + 1) / 2;
442 get_damage = take_hit(aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str, monspell);
444 /* Inventory damage */
445 if (!aura && !(double_resist && p_ptr->resist_acid))
446 inven_damage(set_acid_destroy, inv);
452 * @brief 電撃属性によるプレイヤー損害処理 /
453 * Hurt the player with electricity
455 * @param kb_str ダメージ原因記述
456 * @param monspell 原因となったモンスター特殊攻撃ID
457 * @param aura オーラよるダメージが原因ならばTRUE
460 HIT_POINT elec_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura)
462 HIT_POINT get_damage;
463 int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
464 bool double_resist = IS_OPPOSE_ELEC();
467 if (p_ptr->immune_elec || (dam <= 0))
469 learn_spell(monspell);
473 /* Vulnerability (Ouch!) */
474 if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
475 if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
476 if (prace_is_(RACE_ANDROID)) dam += dam / 3;
478 /* Resist the damage */
479 if (p_ptr->resist_elec) dam = (dam + 2) / 3;
480 if (double_resist) dam = (dam + 2) / 3;
482 if (aura || !CHECK_MULTISHADOW())
484 if ((!(double_resist || p_ptr->resist_elec)) &&
485 one_in_(HURT_CHANCE))
486 (void)do_dec_stat(A_DEX);
489 get_damage = take_hit(aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str, monspell);
491 /* Inventory damage */
492 if (!aura && !(double_resist && p_ptr->resist_elec))
493 inven_damage(set_elec_destroy, inv);
500 * @brief 火炎属性によるプレイヤー損害処理 /
501 * Hurt the player with Fire
503 * @param kb_str ダメージ原因記述
504 * @param monspell 原因となったモンスター特殊攻撃ID
505 * @param aura オーラよるダメージが原因ならばTRUE
508 HIT_POINT fire_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura)
510 HIT_POINT get_damage;
511 int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
512 bool double_resist = IS_OPPOSE_FIRE();
515 if (p_ptr->immune_fire || (dam <= 0))
517 learn_spell(monspell);
521 /* Vulnerability (Ouch!) */
522 if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
523 if (prace_is_(RACE_ENT)) dam += dam / 3;
524 if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
526 /* Resist the damage */
527 if (p_ptr->resist_fire) dam = (dam + 2) / 3;
528 if (double_resist) dam = (dam + 2) / 3;
530 if (aura || !CHECK_MULTISHADOW())
532 if ((!(double_resist || p_ptr->resist_fire)) &&
533 one_in_(HURT_CHANCE))
534 (void)do_dec_stat(A_STR);
537 get_damage = take_hit(aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str, monspell);
539 /* Inventory damage */
540 if (!aura && !(double_resist && p_ptr->resist_fire))
541 inven_damage(set_fire_destroy, inv);
548 * @brief 冷気属性によるプレイヤー損害処理 /
549 * Hurt the player with Cold
551 * @param kb_str ダメージ原因記述
552 * @param monspell 原因となったモンスター特殊攻撃ID
553 * @param aura オーラよるダメージが原因ならばTRUE
556 HIT_POINT cold_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura)
558 HIT_POINT get_damage;
559 int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
560 bool double_resist = IS_OPPOSE_COLD();
563 if (p_ptr->immune_cold || (dam <= 0))
565 learn_spell(monspell);
569 /* Vulnerability (Ouch!) */
570 if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
571 if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
573 /* Resist the damage */
574 if (p_ptr->resist_cold) dam = (dam + 2) / 3;
575 if (double_resist) dam = (dam + 2) / 3;
577 if (aura || !CHECK_MULTISHADOW())
579 if ((!(double_resist || p_ptr->resist_cold)) &&
580 one_in_(HURT_CHANCE))
581 (void)do_dec_stat(A_STR);
584 get_damage = take_hit(aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str, monspell);
586 /* Inventory damage */
587 if (!aura && !(double_resist && p_ptr->resist_cold))
588 inven_damage(set_cold_destroy, inv);