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"
16 * @brief アイテムが酸で破損するかどうかを判定する
17 * @param o_ptr アイテムの情報参照ポインタ
18 * @return 破損するならばTRUEを返す
19 * Note that amulets, rods, and high-level spell books are immune
20 * to "p_ptr->inventory_list damage" of any kind. Also sling ammo and shovels.
21 * Does a given class of objects (usually) hate acid?
22 * Note that acid can either melt or corrode something.
24 bool hates_acid(object_type *o_ptr)
26 /* Analyze the type */
49 /* Staffs/Scrolls are wood/paper */
76 * @brief アイテムが電撃で破損するかどうかを判定する /
77 * Does a given object (usually) hate electricity?
78 * @param o_ptr アイテムの情報参照ポインタ
79 * @return 破損するならばTRUEを返す
81 bool hates_elec(object_type *o_ptr)
97 * @brief アイテムが火炎で破損するかどうかを判定する /
98 * Does a given object (usually) hate fire?
99 * @param o_ptr アイテムの情報参照ポインタ
100 * @return 破損するならばTRUEを返す
102 * Hafted/Polearm weapons have wooden shafts.
103 * Arrows/Bows are mostly wooden.
105 bool hates_fire(object_type *o_ptr)
107 /* Analyze the type */
126 case TV_SORCERY_BOOK:
134 case TV_CRUSADE_BOOK:
136 case TV_HISSATSU_BOOK:
148 /* Staffs/Scrolls burn */
161 * @brief アイテムが冷気で破損するかどうかを判定する /
162 * Does a given object (usually) hate cold?
163 * @param o_ptr アイテムの情報参照ポインタ
164 * @return 破損するならばTRUEを返す
166 bool hates_cold(object_type *o_ptr)
183 * @brief アイテムが酸で破損するかどうかを判定する(メインルーチン) /
185 * @param o_ptr アイテムの情報参照ポインタ
186 * @return 破損するならばTRUEを返す
189 int set_acid_destroy(object_type *o_ptr)
191 BIT_FLAGS flgs[TR_FLAG_SIZE];
192 if (!hates_acid(o_ptr)) return (FALSE);
193 object_flags(o_ptr, flgs);
194 if (have_flag(flgs, TR_IGNORE_ACID)) return (FALSE);
200 * @brief アイテムが電撃で破損するかどうかを判定する(メインルーチン) /
202 * @param o_ptr アイテムの情報参照ポインタ
203 * @return 破損するならばTRUEを返す
206 int set_elec_destroy(object_type *o_ptr)
208 BIT_FLAGS flgs[TR_FLAG_SIZE];
209 if (!hates_elec(o_ptr)) return (FALSE);
210 object_flags(o_ptr, flgs);
211 if (have_flag(flgs, TR_IGNORE_ELEC)) return (FALSE);
217 * @brief アイテムが火炎で破損するかどうかを判定する(メインルーチン) /
219 * @param o_ptr アイテムの情報参照ポインタ
220 * @return 破損するならばTRUEを返す
223 int set_fire_destroy(object_type *o_ptr)
225 BIT_FLAGS flgs[TR_FLAG_SIZE];
226 if (!hates_fire(o_ptr)) return (FALSE);
227 object_flags(o_ptr, flgs);
228 if (have_flag(flgs, TR_IGNORE_FIRE)) return (FALSE);
234 * @brief アイテムが冷気で破損するかどうかを判定する(メインルーチン) /
236 * @param o_ptr アイテムの情報参照ポインタ
237 * @return 破損するならばTRUEを返す
240 int set_cold_destroy(object_type *o_ptr)
242 BIT_FLAGS flgs[TR_FLAG_SIZE];
243 if (!hates_cold(o_ptr)) return (FALSE);
244 object_flags(o_ptr, flgs);
245 if (have_flag(flgs, TR_IGNORE_COLD)) return (FALSE);
251 * @brief アイテムが指定確率で破損するかどうかを判定する /
252 * Destroys a type of item on a given percent chance
253 * @param typ 破損判定関数ポインタ
257 * Note that missiles are no longer necessarily all destroyed
258 * Destruction taken from "melee.c" code for "stealing".
259 * New-style wands and rods handled correctly. -LM-
260 * Returns number of items destroyed.
262 int inven_damage(inven_func typ, int perc)
267 GAME_TEXT o_name[MAX_NLEN];
269 if (CHECK_MULTISHADOW()) return 0;
271 if (p_ptr->inside_arena) return 0;
273 /* Count the casualties */
276 /* Scan through the slots backwards */
277 for (i = 0; i < INVEN_PACK; i++)
279 o_ptr = &p_ptr->inventory_list[i];
280 if (!o_ptr->k_idx) continue;
282 /* Hack -- for now, skip artifacts */
283 if (object_is_artifact(o_ptr)) continue;
285 /* Give this item slot a shot at death */
288 /* Count the casualties */
289 for (amt = j = 0; j < o_ptr->number; ++j)
291 if (randint0(100) < perc) amt++;
294 /* Some casualities */
297 object_desc(o_name, o_ptr, OD_OMIT_PREFIX);
299 msg_format(_("%s(%c)が%s壊れてしまった!", "%sour %s (%c) %s destroyed!"),
301 o_name, index_to_label(i), ((o_ptr->number > 1) ?
302 ((amt == o_ptr->number) ? "全部" : (amt > 1 ? "何個か" : "一個")) : ""));
304 ((o_ptr->number > 1) ? ((amt == o_ptr->number) ? "All of y" :
305 (amt > 1 ? "Some of y" : "One of y")) : "Y"), o_name, index_to_label(i), ((amt > 1) ? "were" : "was"));
309 if ((p_ptr->pseikaku == SEIKAKU_COMBAT) || (p_ptr->inventory_list[INVEN_BOW].name1 == ART_CRIMSON))
310 msg_print("やりやがったな!");
311 else if ((p_ptr->pseikaku == SEIKAKU_CHARGEMAN))
313 if (randint0(2) == 0) msg_print(_("ジュラル星人め!", ""));
314 else msg_print(_("弱い者いじめは止めるんだ!", ""));
318 /* Potions smash open */
319 if (object_is_potion(o_ptr))
321 (void)potion_smash_effect(0, p_ptr->y, p_ptr->x, o_ptr->k_idx);
324 /* Reduce the charges of rods/wands */
325 reduce_charges(o_ptr, amt);
327 /* Destroy "amt" items */
328 inven_item_increase(i, -amt);
329 inven_item_optimize(i);
331 /* Count the casualties */
337 /* Return the casualty count */
343 * @brief 酸攻撃による装備のAC劣化処理 /
344 * Acid has hit the player, attempt to affect some armor.
345 * @return 装備による軽減があったならTRUEを返す
347 * Note that the "base armor" of an object never changes.
348 * If any armor is damaged (or resists), the player takes less damage.
350 static bool acid_minus_ac(void)
352 object_type *o_ptr = NULL;
353 BIT_FLAGS flgs[TR_FLAG_SIZE];
354 GAME_TEXT o_name[MAX_NLEN];
356 /* Pick a (possibly empty) p_ptr->inventory_list slot */
359 case 1: o_ptr = &p_ptr->inventory_list[INVEN_RARM]; break;
360 case 2: o_ptr = &p_ptr->inventory_list[INVEN_LARM]; break;
361 case 3: o_ptr = &p_ptr->inventory_list[INVEN_BODY]; break;
362 case 4: o_ptr = &p_ptr->inventory_list[INVEN_OUTER]; break;
363 case 5: o_ptr = &p_ptr->inventory_list[INVEN_HANDS]; break;
364 case 6: o_ptr = &p_ptr->inventory_list[INVEN_HEAD]; break;
365 case 7: o_ptr = &p_ptr->inventory_list[INVEN_FEET]; break;
368 if (!o_ptr->k_idx) return (FALSE);
369 if (!object_is_armour(o_ptr)) return (FALSE);
371 object_desc(o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
372 object_flags(o_ptr, flgs);
373 /* No damage left to be done */
374 if (o_ptr->ac + o_ptr->to_a <= 0)
376 msg_format(_("%sは既にボロボロだ!", "Your %s is already crumble!"), o_name);
381 if (have_flag(flgs, TR_IGNORE_ACID))
383 msg_format(_("しかし%sには効果がなかった!", "Your %s is unaffected!"), o_name);
387 msg_format(_("%sが酸で腐食した!", "Your %s is corroded!"), o_name);
389 /* Damage the item */
392 /* Calculate bonuses */
393 p_ptr->update |= (PU_BONUS);
394 p_ptr->window |= (PW_EQUIP | PW_PLAYER);
398 /* Item was damaged */
404 * @brief 酸属性によるプレイヤー損害処理 /
405 * Hurt the player with Acid
407 * @param kb_str ダメージ原因記述
408 * @param monspell 原因となったモンスター特殊攻撃ID
409 * @param aura オーラよるダメージが原因ならばTRUE
412 HIT_POINT acid_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura)
414 HIT_POINT get_damage;
415 int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
416 bool double_resist = IS_OPPOSE_ACID();
419 if (p_ptr->immune_acid || (dam <= 0))
421 learn_spell(monspell);
425 /* Vulnerability (Ouch!) */
426 if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
427 if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
429 /* Resist the damage */
430 if (p_ptr->resist_acid) dam = (dam + 2) / 3;
431 if (double_resist) dam = (dam + 2) / 3;
433 if (aura || !CHECK_MULTISHADOW())
435 if ((!(double_resist || p_ptr->resist_acid)) &&
436 one_in_(HURT_CHANCE))
437 (void)do_dec_stat(A_CHR);
439 /* If any armor gets hit, defend the player */
440 if (acid_minus_ac()) dam = (dam + 1) / 2;
443 get_damage = take_hit(aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str, monspell);
445 /* Inventory damage */
446 if (!aura && !(double_resist && p_ptr->resist_acid))
447 inven_damage(set_acid_destroy, inv);
453 * @brief 電撃属性によるプレイヤー損害処理 /
454 * Hurt the player with electricity
456 * @param kb_str ダメージ原因記述
457 * @param monspell 原因となったモンスター特殊攻撃ID
458 * @param aura オーラよるダメージが原因ならばTRUE
461 HIT_POINT elec_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura)
463 HIT_POINT get_damage;
464 int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
465 bool double_resist = IS_OPPOSE_ELEC();
468 if (p_ptr->immune_elec || (dam <= 0))
470 learn_spell(monspell);
474 /* Vulnerability (Ouch!) */
475 if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
476 if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
477 if (prace_is_(RACE_ANDROID)) dam += dam / 3;
479 /* Resist the damage */
480 if (p_ptr->resist_elec) dam = (dam + 2) / 3;
481 if (double_resist) dam = (dam + 2) / 3;
483 if (aura || !CHECK_MULTISHADOW())
485 if ((!(double_resist || p_ptr->resist_elec)) &&
486 one_in_(HURT_CHANCE))
487 (void)do_dec_stat(A_DEX);
490 get_damage = take_hit(aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str, monspell);
492 /* Inventory damage */
493 if (!aura && !(double_resist && p_ptr->resist_elec))
494 inven_damage(set_elec_destroy, inv);
501 * @brief 火炎属性によるプレイヤー損害処理 /
502 * Hurt the player with Fire
504 * @param kb_str ダメージ原因記述
505 * @param monspell 原因となったモンスター特殊攻撃ID
506 * @param aura オーラよるダメージが原因ならばTRUE
509 HIT_POINT fire_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura)
511 HIT_POINT get_damage;
512 int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
513 bool double_resist = IS_OPPOSE_FIRE();
516 if (p_ptr->immune_fire || (dam <= 0))
518 learn_spell(monspell);
522 /* Vulnerability (Ouch!) */
523 if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
524 if (prace_is_(RACE_ENT)) dam += dam / 3;
525 if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
527 /* Resist the damage */
528 if (p_ptr->resist_fire) dam = (dam + 2) / 3;
529 if (double_resist) dam = (dam + 2) / 3;
531 if (aura || !CHECK_MULTISHADOW())
533 if ((!(double_resist || p_ptr->resist_fire)) &&
534 one_in_(HURT_CHANCE))
535 (void)do_dec_stat(A_STR);
538 get_damage = take_hit(aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str, monspell);
540 /* Inventory damage */
541 if (!aura && !(double_resist && p_ptr->resist_fire))
542 inven_damage(set_fire_destroy, inv);
549 * @brief 冷気属性によるプレイヤー損害処理 /
550 * Hurt the player with Cold
552 * @param kb_str ダメージ原因記述
553 * @param monspell 原因となったモンスター特殊攻撃ID
554 * @param aura オーラよるダメージが原因ならばTRUE
557 HIT_POINT cold_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura)
559 HIT_POINT get_damage;
560 int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
561 bool double_resist = IS_OPPOSE_COLD();
564 if (p_ptr->immune_cold || (dam <= 0))
566 learn_spell(monspell);
570 /* Vulnerability (Ouch!) */
571 if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
572 if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
574 /* Resist the damage */
575 if (p_ptr->resist_cold) dam = (dam + 2) / 3;
576 if (double_resist) dam = (dam + 2) / 3;
578 if (aura || !CHECK_MULTISHADOW())
580 if ((!(double_resist || p_ptr->resist_cold)) &&
581 one_in_(HURT_CHANCE))
582 (void)do_dec_stat(A_STR);
585 get_damage = take_hit(aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str, monspell);
587 /* Inventory damage */
588 if (!aura && !(double_resist && p_ptr->resist_cold))
589 inven_damage(set_cold_destroy, inv);