4 #include "realm-song.h"
5 #include "player-damage.h"
7 #include "object-flavor.h"
8 #include "object-hook.h"
9 #include "object-broken.h"
10 #include "player-status.h"
11 #include "player-effects.h"
12 #include "player-class.h"
13 #include "monster-spell.h"
15 #include "view-mainwindow.h"
19 * @brief アイテムが酸で破損するかどうかを判定する
20 * @param o_ptr アイテムの情報参照ポインタ
21 * @return 破損するならばTRUEを返す
22 * Note that amulets, rods, and high-level spell books are immune
23 * to "p_ptr->inventory_list damage" of any kind. Also sling ammo and shovels.
24 * Does a given class of objects (usually) hate acid?
25 * Note that acid can either melt or corrode something.
27 bool hates_acid(object_type *o_ptr)
29 /* Analyze the type */
52 /* Staffs/Scrolls are wood/paper */
79 * @brief アイテムが電撃で破損するかどうかを判定する /
80 * Does a given object (usually) hate electricity?
81 * @param o_ptr アイテムの情報参照ポインタ
82 * @return 破損するならばTRUEを返す
84 bool hates_elec(object_type *o_ptr)
100 * @brief アイテムが火炎で破損するかどうかを判定する /
101 * Does a given object (usually) hate fire?
102 * @param o_ptr アイテムの情報参照ポインタ
103 * @return 破損するならばTRUEを返す
105 * Hafted/Polearm weapons have wooden shafts.
106 * Arrows/Bows are mostly wooden.
108 bool hates_fire(object_type *o_ptr)
110 /* Analyze the type */
129 case TV_SORCERY_BOOK:
137 case TV_CRUSADE_BOOK:
139 case TV_HISSATSU_BOOK:
151 /* Staffs/Scrolls burn */
164 * @brief アイテムが冷気で破損するかどうかを判定する /
165 * Does a given object (usually) hate cold?
166 * @param o_ptr アイテムの情報参照ポインタ
167 * @return 破損するならばTRUEを返す
169 bool hates_cold(object_type *o_ptr)
186 * @brief アイテムが酸で破損するかどうかを判定する(メインルーチン) /
188 * @param o_ptr アイテムの情報参照ポインタ
189 * @return 破損するならばTRUEを返す
192 int set_acid_destroy(object_type *o_ptr)
194 BIT_FLAGS flgs[TR_FLAG_SIZE];
195 if (!hates_acid(o_ptr)) return (FALSE);
196 object_flags(o_ptr, flgs);
197 if (have_flag(flgs, TR_IGNORE_ACID)) return (FALSE);
203 * @brief アイテムが電撃で破損するかどうかを判定する(メインルーチン) /
205 * @param o_ptr アイテムの情報参照ポインタ
206 * @return 破損するならばTRUEを返す
209 int set_elec_destroy(object_type *o_ptr)
211 BIT_FLAGS flgs[TR_FLAG_SIZE];
212 if (!hates_elec(o_ptr)) return (FALSE);
213 object_flags(o_ptr, flgs);
214 if (have_flag(flgs, TR_IGNORE_ELEC)) return (FALSE);
220 * @brief アイテムが火炎で破損するかどうかを判定する(メインルーチン) /
222 * @param o_ptr アイテムの情報参照ポインタ
223 * @return 破損するならばTRUEを返す
226 int set_fire_destroy(object_type *o_ptr)
228 BIT_FLAGS flgs[TR_FLAG_SIZE];
229 if (!hates_fire(o_ptr)) return (FALSE);
230 object_flags(o_ptr, flgs);
231 if (have_flag(flgs, TR_IGNORE_FIRE)) return (FALSE);
237 * @brief アイテムが冷気で破損するかどうかを判定する(メインルーチン) /
239 * @param o_ptr アイテムの情報参照ポインタ
240 * @return 破損するならばTRUEを返す
243 int set_cold_destroy(object_type *o_ptr)
245 BIT_FLAGS flgs[TR_FLAG_SIZE];
246 if (!hates_cold(o_ptr)) return (FALSE);
247 object_flags(o_ptr, flgs);
248 if (have_flag(flgs, TR_IGNORE_COLD)) return (FALSE);
254 * @brief アイテムが指定確率で破損するかどうかを判定する /
255 * Destroys a type of item on a given percent chance
256 * @param typ 破損判定関数ポインタ
260 * Note that missiles are no longer necessarily all destroyed
261 * Destruction taken from "melee.c" code for "stealing".
262 * New-style wands and rods handled correctly. -LM-
263 * Returns number of items destroyed.
265 int inven_damage(inven_func typ, int perc)
270 GAME_TEXT o_name[MAX_NLEN];
272 if (CHECK_MULTISHADOW()) return 0;
274 if (p_ptr->inside_arena) return 0;
276 /* Count the casualties */
279 /* Scan through the slots backwards */
280 for (i = 0; i < INVEN_PACK; i++)
282 o_ptr = &p_ptr->inventory_list[i];
283 if (!o_ptr->k_idx) continue;
285 /* Hack -- for now, skip artifacts */
286 if (object_is_artifact(o_ptr)) continue;
288 /* Give this item slot a shot at death */
291 /* Count the casualties */
292 for (amt = j = 0; j < o_ptr->number; ++j)
294 if (randint0(100) < perc) amt++;
297 /* Some casualities */
300 object_desc(o_name, o_ptr, OD_OMIT_PREFIX);
302 msg_format(_("%s(%c)が%s壊れてしまった!", "%sour %s (%c) %s destroyed!"),
304 o_name, index_to_label(i), ((o_ptr->number > 1) ?
305 ((amt == o_ptr->number) ? "全部" : (amt > 1 ? "何個か" : "一個")) : ""));
307 ((o_ptr->number > 1) ? ((amt == o_ptr->number) ? "All of y" :
308 (amt > 1 ? "Some of y" : "One of y")) : "Y"), o_name, index_to_label(i), ((amt > 1) ? "were" : "was"));
312 if ((p_ptr->pseikaku == SEIKAKU_COMBAT) || (p_ptr->inventory_list[INVEN_BOW].name1 == ART_CRIMSON))
313 msg_print("やりやがったな!");
314 else if ((p_ptr->pseikaku == SEIKAKU_CHARGEMAN))
316 if (randint0(2) == 0) msg_print(_("ジュラル星人め!", ""));
317 else msg_print(_("弱い者いじめは止めるんだ!", ""));
321 /* Potions smash open */
322 if (object_is_potion(o_ptr))
324 (void)potion_smash_effect(0, p_ptr->y, p_ptr->x, o_ptr->k_idx);
327 /* Reduce the charges of rods/wands */
328 reduce_charges(o_ptr, amt);
330 /* Destroy "amt" items */
331 inven_item_increase(i, -amt);
332 inven_item_optimize(i);
334 /* Count the casualties */
340 /* Return the casualty count */
346 * @brief 酸攻撃による装備のAC劣化処理 /
347 * Acid has hit the player, attempt to affect some armor.
348 * @return 装備による軽減があったならTRUEを返す
350 * Note that the "base armor" of an object never changes.
351 * If any armor is damaged (or resists), the player takes less damage.
353 static bool acid_minus_ac(void)
355 object_type *o_ptr = NULL;
356 BIT_FLAGS flgs[TR_FLAG_SIZE];
357 GAME_TEXT o_name[MAX_NLEN];
359 /* Pick a (possibly empty) p_ptr->inventory_list slot */
362 case 1: o_ptr = &p_ptr->inventory_list[INVEN_RARM]; break;
363 case 2: o_ptr = &p_ptr->inventory_list[INVEN_LARM]; break;
364 case 3: o_ptr = &p_ptr->inventory_list[INVEN_BODY]; break;
365 case 4: o_ptr = &p_ptr->inventory_list[INVEN_OUTER]; break;
366 case 5: o_ptr = &p_ptr->inventory_list[INVEN_HANDS]; break;
367 case 6: o_ptr = &p_ptr->inventory_list[INVEN_HEAD]; break;
368 case 7: o_ptr = &p_ptr->inventory_list[INVEN_FEET]; break;
371 if (!o_ptr->k_idx) return (FALSE);
372 if (!object_is_armour(o_ptr)) return (FALSE);
374 object_desc(o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
375 object_flags(o_ptr, flgs);
376 /* No damage left to be done */
377 if (o_ptr->ac + o_ptr->to_a <= 0)
379 msg_format(_("%sは既にボロボロだ!", "Your %s is already crumble!"), o_name);
384 if (have_flag(flgs, TR_IGNORE_ACID))
386 msg_format(_("しかし%sには効果がなかった!", "Your %s is unaffected!"), o_name);
390 msg_format(_("%sが酸で腐食した!", "Your %s is corroded!"), o_name);
392 /* Damage the item */
395 /* Calculate bonuses */
396 p_ptr->update |= (PU_BONUS);
397 p_ptr->window |= (PW_EQUIP | PW_PLAYER);
401 /* Item was damaged */
407 * @brief 酸属性によるプレイヤー損害処理 /
408 * Hurt the player with Acid
410 * @param kb_str ダメージ原因記述
411 * @param monspell 原因となったモンスター特殊攻撃ID
412 * @param aura オーラよるダメージが原因ならばTRUE
415 HIT_POINT acid_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura)
417 HIT_POINT get_damage;
418 int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
419 bool double_resist = IS_OPPOSE_ACID();
422 if (p_ptr->immune_acid || (dam <= 0))
424 learn_spell(monspell);
428 /* Vulnerability (Ouch!) */
429 if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
430 if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
432 /* Resist the damage */
433 if (p_ptr->resist_acid) dam = (dam + 2) / 3;
434 if (double_resist) dam = (dam + 2) / 3;
436 if (aura || !CHECK_MULTISHADOW())
438 if ((!(double_resist || p_ptr->resist_acid)) &&
439 one_in_(HURT_CHANCE))
440 (void)do_dec_stat(A_CHR);
442 /* If any armor gets hit, defend the player */
443 if (acid_minus_ac()) dam = (dam + 1) / 2;
446 get_damage = take_hit(aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str, monspell);
448 /* Inventory damage */
449 if (!aura && !(double_resist && p_ptr->resist_acid))
450 inven_damage(set_acid_destroy, inv);
456 * @brief 電撃属性によるプレイヤー損害処理 /
457 * Hurt the player with electricity
459 * @param kb_str ダメージ原因記述
460 * @param monspell 原因となったモンスター特殊攻撃ID
461 * @param aura オーラよるダメージが原因ならばTRUE
464 HIT_POINT elec_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura)
466 HIT_POINT get_damage;
467 int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
468 bool double_resist = IS_OPPOSE_ELEC();
471 if (p_ptr->immune_elec || (dam <= 0))
473 learn_spell(monspell);
477 /* Vulnerability (Ouch!) */
478 if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
479 if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
480 if (prace_is_(RACE_ANDROID)) dam += dam / 3;
482 /* Resist the damage */
483 if (p_ptr->resist_elec) dam = (dam + 2) / 3;
484 if (double_resist) dam = (dam + 2) / 3;
486 if (aura || !CHECK_MULTISHADOW())
488 if ((!(double_resist || p_ptr->resist_elec)) &&
489 one_in_(HURT_CHANCE))
490 (void)do_dec_stat(A_DEX);
493 get_damage = take_hit(aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str, monspell);
495 /* Inventory damage */
496 if (!aura && !(double_resist && p_ptr->resist_elec))
497 inven_damage(set_elec_destroy, inv);
504 * @brief 火炎属性によるプレイヤー損害処理 /
505 * Hurt the player with Fire
507 * @param kb_str ダメージ原因記述
508 * @param monspell 原因となったモンスター特殊攻撃ID
509 * @param aura オーラよるダメージが原因ならばTRUE
512 HIT_POINT fire_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura)
514 HIT_POINT get_damage;
515 int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
516 bool double_resist = IS_OPPOSE_FIRE();
519 if (p_ptr->immune_fire || (dam <= 0))
521 learn_spell(monspell);
525 /* Vulnerability (Ouch!) */
526 if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
527 if (prace_is_(RACE_ENT)) dam += dam / 3;
528 if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
530 /* Resist the damage */
531 if (p_ptr->resist_fire) dam = (dam + 2) / 3;
532 if (double_resist) dam = (dam + 2) / 3;
534 if (aura || !CHECK_MULTISHADOW())
536 if ((!(double_resist || p_ptr->resist_fire)) &&
537 one_in_(HURT_CHANCE))
538 (void)do_dec_stat(A_STR);
541 get_damage = take_hit(aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str, monspell);
543 /* Inventory damage */
544 if (!aura && !(double_resist && p_ptr->resist_fire))
545 inven_damage(set_fire_destroy, inv);
552 * @brief 冷気属性によるプレイヤー損害処理 /
553 * Hurt the player with Cold
555 * @param kb_str ダメージ原因記述
556 * @param monspell 原因となったモンスター特殊攻撃ID
557 * @param aura オーラよるダメージが原因ならばTRUE
560 HIT_POINT cold_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura)
562 HIT_POINT get_damage;
563 int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
564 bool double_resist = IS_OPPOSE_COLD();
567 if (p_ptr->immune_cold || (dam <= 0))
569 learn_spell(monspell);
573 /* Vulnerability (Ouch!) */
574 if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
575 if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
577 /* Resist the damage */
578 if (p_ptr->resist_cold) dam = (dam + 2) / 3;
579 if (double_resist) dam = (dam + 2) / 3;
581 if (aura || !CHECK_MULTISHADOW())
583 if ((!(double_resist || p_ptr->resist_cold)) &&
584 one_in_(HURT_CHANCE))
585 (void)do_dec_stat(A_STR);
588 get_damage = take_hit(aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str, monspell);
590 /* Inventory damage */
591 if (!aura && !(double_resist && p_ptr->resist_cold))
592 inven_damage(set_cold_destroy, inv);