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 "monster-spell.h"
17 * @brief アイテムが酸で破損するかどうかを判定する
18 * @param o_ptr アイテムの情報参照ポインタ
19 * @return 破損するならばTRUEを返す
20 * Note that amulets, rods, and high-level spell books are immune
21 * to "p_ptr->inventory_list damage" of any kind. Also sling ammo and shovels.
22 * Does a given class of objects (usually) hate acid?
23 * Note that acid can either melt or corrode something.
25 bool hates_acid(object_type *o_ptr)
27 /* Analyze the type */
50 /* Staffs/Scrolls are wood/paper */
77 * @brief アイテムが電撃で破損するかどうかを判定する /
78 * Does a given object (usually) hate electricity?
79 * @param o_ptr アイテムの情報参照ポインタ
80 * @return 破損するならばTRUEを返す
82 bool hates_elec(object_type *o_ptr)
98 * @brief アイテムが火炎で破損するかどうかを判定する /
99 * Does a given object (usually) hate fire?
100 * @param o_ptr アイテムの情報参照ポインタ
101 * @return 破損するならばTRUEを返す
103 * Hafted/Polearm weapons have wooden shafts.
104 * Arrows/Bows are mostly wooden.
106 bool hates_fire(object_type *o_ptr)
108 /* Analyze the type */
127 case TV_SORCERY_BOOK:
135 case TV_CRUSADE_BOOK:
137 case TV_HISSATSU_BOOK:
149 /* Staffs/Scrolls burn */
162 * @brief アイテムが冷気で破損するかどうかを判定する /
163 * Does a given object (usually) hate cold?
164 * @param o_ptr アイテムの情報参照ポインタ
165 * @return 破損するならばTRUEを返す
167 bool hates_cold(object_type *o_ptr)
184 * @brief アイテムが酸で破損するかどうかを判定する(メインルーチン) /
186 * @param o_ptr アイテムの情報参照ポインタ
187 * @return 破損するならばTRUEを返す
190 int set_acid_destroy(object_type *o_ptr)
192 BIT_FLAGS flgs[TR_FLAG_SIZE];
193 if (!hates_acid(o_ptr)) return (FALSE);
194 object_flags(o_ptr, flgs);
195 if (have_flag(flgs, TR_IGNORE_ACID)) return (FALSE);
201 * @brief アイテムが電撃で破損するかどうかを判定する(メインルーチン) /
203 * @param o_ptr アイテムの情報参照ポインタ
204 * @return 破損するならばTRUEを返す
207 int set_elec_destroy(object_type *o_ptr)
209 BIT_FLAGS flgs[TR_FLAG_SIZE];
210 if (!hates_elec(o_ptr)) return (FALSE);
211 object_flags(o_ptr, flgs);
212 if (have_flag(flgs, TR_IGNORE_ELEC)) return (FALSE);
218 * @brief アイテムが火炎で破損するかどうかを判定する(メインルーチン) /
220 * @param o_ptr アイテムの情報参照ポインタ
221 * @return 破損するならばTRUEを返す
224 int set_fire_destroy(object_type *o_ptr)
226 BIT_FLAGS flgs[TR_FLAG_SIZE];
227 if (!hates_fire(o_ptr)) return (FALSE);
228 object_flags(o_ptr, flgs);
229 if (have_flag(flgs, TR_IGNORE_FIRE)) return (FALSE);
235 * @brief アイテムが冷気で破損するかどうかを判定する(メインルーチン) /
237 * @param o_ptr アイテムの情報参照ポインタ
238 * @return 破損するならばTRUEを返す
241 int set_cold_destroy(object_type *o_ptr)
243 BIT_FLAGS flgs[TR_FLAG_SIZE];
244 if (!hates_cold(o_ptr)) return (FALSE);
245 object_flags(o_ptr, flgs);
246 if (have_flag(flgs, TR_IGNORE_COLD)) return (FALSE);
252 * @brief アイテムが指定確率で破損するかどうかを判定する /
253 * Destroys a type of item on a given percent chance
254 * @param typ 破損判定関数ポインタ
258 * Note that missiles are no longer necessarily all destroyed
259 * Destruction taken from "melee.c" code for "stealing".
260 * New-style wands and rods handled correctly. -LM-
261 * Returns number of items destroyed.
263 int inven_damage(inven_func typ, int perc)
268 GAME_TEXT o_name[MAX_NLEN];
270 if (CHECK_MULTISHADOW()) return 0;
272 if (p_ptr->inside_arena) return 0;
274 /* Count the casualties */
277 /* Scan through the slots backwards */
278 for (i = 0; i < INVEN_PACK; i++)
280 o_ptr = &p_ptr->inventory_list[i];
281 if (!o_ptr->k_idx) continue;
283 /* Hack -- for now, skip artifacts */
284 if (object_is_artifact(o_ptr)) continue;
286 /* Give this item slot a shot at death */
289 /* Count the casualties */
290 for (amt = j = 0; j < o_ptr->number; ++j)
292 if (randint0(100) < perc) amt++;
295 /* Some casualities */
298 object_desc(o_name, o_ptr, OD_OMIT_PREFIX);
300 msg_format(_("%s(%c)が%s壊れてしまった!", "%sour %s (%c) %s destroyed!"),
302 o_name, index_to_label(i), ((o_ptr->number > 1) ?
303 ((amt == o_ptr->number) ? "全部" : (amt > 1 ? "何個か" : "一個")) : ""));
305 ((o_ptr->number > 1) ? ((amt == o_ptr->number) ? "All of y" :
306 (amt > 1 ? "Some of y" : "One of y")) : "Y"), o_name, index_to_label(i), ((amt > 1) ? "were" : "was"));
310 if ((p_ptr->pseikaku == SEIKAKU_COMBAT) || (p_ptr->inventory_list[INVEN_BOW].name1 == ART_CRIMSON))
311 msg_print("やりやがったな!");
312 else if ((p_ptr->pseikaku == SEIKAKU_CHARGEMAN))
314 if (randint0(2) == 0) msg_print(_("ジュラル星人め!", ""));
315 else msg_print(_("弱い者いじめは止めるんだ!", ""));
319 /* Potions smash open */
320 if (object_is_potion(o_ptr))
322 (void)potion_smash_effect(0, p_ptr->y, p_ptr->x, o_ptr->k_idx);
325 /* Reduce the charges of rods/wands */
326 reduce_charges(o_ptr, amt);
328 /* Destroy "amt" items */
329 inven_item_increase(i, -amt);
330 inven_item_optimize(i);
332 /* Count the casualties */
338 /* Return the casualty count */
344 * @brief 酸攻撃による装備のAC劣化処理 /
345 * Acid has hit the player, attempt to affect some armor.
346 * @return 装備による軽減があったならTRUEを返す
348 * Note that the "base armor" of an object never changes.
349 * If any armor is damaged (or resists), the player takes less damage.
351 static bool acid_minus_ac(void)
353 object_type *o_ptr = NULL;
354 BIT_FLAGS flgs[TR_FLAG_SIZE];
355 GAME_TEXT o_name[MAX_NLEN];
357 /* Pick a (possibly empty) p_ptr->inventory_list slot */
360 case 1: o_ptr = &p_ptr->inventory_list[INVEN_RARM]; break;
361 case 2: o_ptr = &p_ptr->inventory_list[INVEN_LARM]; break;
362 case 3: o_ptr = &p_ptr->inventory_list[INVEN_BODY]; break;
363 case 4: o_ptr = &p_ptr->inventory_list[INVEN_OUTER]; break;
364 case 5: o_ptr = &p_ptr->inventory_list[INVEN_HANDS]; break;
365 case 6: o_ptr = &p_ptr->inventory_list[INVEN_HEAD]; break;
366 case 7: o_ptr = &p_ptr->inventory_list[INVEN_FEET]; break;
369 if (!o_ptr->k_idx) return (FALSE);
370 if (!object_is_armour(o_ptr)) return (FALSE);
372 object_desc(o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
373 object_flags(o_ptr, flgs);
374 /* No damage left to be done */
375 if (o_ptr->ac + o_ptr->to_a <= 0)
377 msg_format(_("%sは既にボロボロだ!", "Your %s is already crumble!"), o_name);
382 if (have_flag(flgs, TR_IGNORE_ACID))
384 msg_format(_("しかし%sには効果がなかった!", "Your %s is unaffected!"), o_name);
388 msg_format(_("%sが酸で腐食した!", "Your %s is corroded!"), o_name);
390 /* Damage the item */
393 /* Calculate bonuses */
394 p_ptr->update |= (PU_BONUS);
395 p_ptr->window |= (PW_EQUIP | PW_PLAYER);
399 /* Item was damaged */
405 * @brief 酸属性によるプレイヤー損害処理 /
406 * Hurt the player with Acid
408 * @param kb_str ダメージ原因記述
409 * @param monspell 原因となったモンスター特殊攻撃ID
410 * @param aura オーラよるダメージが原因ならばTRUE
413 HIT_POINT acid_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura)
415 HIT_POINT get_damage;
416 int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
417 bool double_resist = IS_OPPOSE_ACID();
420 if (p_ptr->immune_acid || (dam <= 0))
422 learn_spell(monspell);
426 /* Vulnerability (Ouch!) */
427 if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
428 if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
430 /* Resist the damage */
431 if (p_ptr->resist_acid) dam = (dam + 2) / 3;
432 if (double_resist) dam = (dam + 2) / 3;
434 if (aura || !CHECK_MULTISHADOW())
436 if ((!(double_resist || p_ptr->resist_acid)) &&
437 one_in_(HURT_CHANCE))
438 (void)do_dec_stat(A_CHR);
440 /* If any armor gets hit, defend the player */
441 if (acid_minus_ac()) dam = (dam + 1) / 2;
444 get_damage = take_hit(aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str, monspell);
446 /* Inventory damage */
447 if (!aura && !(double_resist && p_ptr->resist_acid))
448 inven_damage(set_acid_destroy, inv);
454 * @brief 電撃属性によるプレイヤー損害処理 /
455 * Hurt the player with electricity
457 * @param kb_str ダメージ原因記述
458 * @param monspell 原因となったモンスター特殊攻撃ID
459 * @param aura オーラよるダメージが原因ならばTRUE
462 HIT_POINT elec_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura)
464 HIT_POINT get_damage;
465 int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
466 bool double_resist = IS_OPPOSE_ELEC();
469 if (p_ptr->immune_elec || (dam <= 0))
471 learn_spell(monspell);
475 /* Vulnerability (Ouch!) */
476 if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
477 if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
478 if (prace_is_(RACE_ANDROID)) dam += dam / 3;
480 /* Resist the damage */
481 if (p_ptr->resist_elec) dam = (dam + 2) / 3;
482 if (double_resist) dam = (dam + 2) / 3;
484 if (aura || !CHECK_MULTISHADOW())
486 if ((!(double_resist || p_ptr->resist_elec)) &&
487 one_in_(HURT_CHANCE))
488 (void)do_dec_stat(A_DEX);
491 get_damage = take_hit(aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str, monspell);
493 /* Inventory damage */
494 if (!aura && !(double_resist && p_ptr->resist_elec))
495 inven_damage(set_elec_destroy, inv);
502 * @brief 火炎属性によるプレイヤー損害処理 /
503 * Hurt the player with Fire
505 * @param kb_str ダメージ原因記述
506 * @param monspell 原因となったモンスター特殊攻撃ID
507 * @param aura オーラよるダメージが原因ならばTRUE
510 HIT_POINT fire_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura)
512 HIT_POINT get_damage;
513 int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
514 bool double_resist = IS_OPPOSE_FIRE();
517 if (p_ptr->immune_fire || (dam <= 0))
519 learn_spell(monspell);
523 /* Vulnerability (Ouch!) */
524 if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
525 if (prace_is_(RACE_ENT)) dam += dam / 3;
526 if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
528 /* Resist the damage */
529 if (p_ptr->resist_fire) dam = (dam + 2) / 3;
530 if (double_resist) dam = (dam + 2) / 3;
532 if (aura || !CHECK_MULTISHADOW())
534 if ((!(double_resist || p_ptr->resist_fire)) &&
535 one_in_(HURT_CHANCE))
536 (void)do_dec_stat(A_STR);
539 get_damage = take_hit(aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str, monspell);
541 /* Inventory damage */
542 if (!aura && !(double_resist && p_ptr->resist_fire))
543 inven_damage(set_fire_destroy, inv);
550 * @brief 冷気属性によるプレイヤー損害処理 /
551 * Hurt the player with Cold
553 * @param kb_str ダメージ原因記述
554 * @param monspell 原因となったモンスター特殊攻撃ID
555 * @param aura オーラよるダメージが原因ならばTRUE
558 HIT_POINT cold_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura)
560 HIT_POINT get_damage;
561 int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
562 bool double_resist = IS_OPPOSE_COLD();
565 if (p_ptr->immune_cold || (dam <= 0))
567 learn_spell(monspell);
571 /* Vulnerability (Ouch!) */
572 if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
573 if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
575 /* Resist the damage */
576 if (p_ptr->resist_cold) dam = (dam + 2) / 3;
577 if (double_resist) dam = (dam + 2) / 3;
579 if (aura || !CHECK_MULTISHADOW())
581 if ((!(double_resist || p_ptr->resist_cold)) &&
582 one_in_(HURT_CHANCE))
583 (void)do_dec_stat(A_STR);
586 get_damage = take_hit(aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str, monspell);
588 /* Inventory damage */
589 if (!aura && !(double_resist && p_ptr->resist_cold))
590 inven_damage(set_cold_destroy, inv);