4 #include "realm-song.h"
5 #include "player-damage.h"
6 #include "player-personality.h"
8 #include "object-flavor.h"
9 #include "object-hook.h"
10 #include "object-broken.h"
11 #include "player-status.h"
12 #include "player-effects.h"
13 #include "player-class.h"
14 #include "monster-spell.h"
16 #include "view-mainwindow.h"
20 * @brief アイテムが酸で破損するかどうかを判定する
21 * @param o_ptr アイテムの情報参照ポインタ
22 * @return 破損するならばTRUEを返す
23 * Note that amulets, rods, and high-level spell books are immune
24 * to "p_ptr->inventory_list damage" of any kind. Also sling ammo and shovels.
25 * Does a given class of objects (usually) hate acid?
26 * Note that acid can either melt or corrode something.
28 bool hates_acid(object_type *o_ptr)
30 /* Analyze the type */
53 /* Staffs/Scrolls are wood/paper */
80 * @brief アイテムが電撃で破損するかどうかを判定する /
81 * Does a given object (usually) hate electricity?
82 * @param o_ptr アイテムの情報参照ポインタ
83 * @return 破損するならばTRUEを返す
85 bool hates_elec(object_type *o_ptr)
101 * @brief アイテムが火炎で破損するかどうかを判定する /
102 * Does a given object (usually) hate fire?
103 * @param o_ptr アイテムの情報参照ポインタ
104 * @return 破損するならばTRUEを返す
106 * Hafted/Polearm weapons have wooden shafts.
107 * Arrows/Bows are mostly wooden.
109 bool hates_fire(object_type *o_ptr)
111 /* Analyze the type */
130 case TV_SORCERY_BOOK:
138 case TV_CRUSADE_BOOK:
140 case TV_HISSATSU_BOOK:
152 /* Staffs/Scrolls burn */
165 * @brief アイテムが冷気で破損するかどうかを判定する /
166 * Does a given object (usually) hate cold?
167 * @param o_ptr アイテムの情報参照ポインタ
168 * @return 破損するならばTRUEを返す
170 bool hates_cold(object_type *o_ptr)
187 * @brief アイテムが酸で破損するかどうかを判定する(メインルーチン) /
189 * @param o_ptr アイテムの情報参照ポインタ
190 * @return 破損するならばTRUEを返す
193 int set_acid_destroy(object_type *o_ptr)
195 BIT_FLAGS flgs[TR_FLAG_SIZE];
196 if (!hates_acid(o_ptr)) return (FALSE);
197 object_flags(o_ptr, flgs);
198 if (have_flag(flgs, TR_IGNORE_ACID)) return (FALSE);
204 * @brief アイテムが電撃で破損するかどうかを判定する(メインルーチン) /
206 * @param o_ptr アイテムの情報参照ポインタ
207 * @return 破損するならばTRUEを返す
210 int set_elec_destroy(object_type *o_ptr)
212 BIT_FLAGS flgs[TR_FLAG_SIZE];
213 if (!hates_elec(o_ptr)) return (FALSE);
214 object_flags(o_ptr, flgs);
215 if (have_flag(flgs, TR_IGNORE_ELEC)) return (FALSE);
221 * @brief アイテムが火炎で破損するかどうかを判定する(メインルーチン) /
223 * @param o_ptr アイテムの情報参照ポインタ
224 * @return 破損するならばTRUEを返す
227 int set_fire_destroy(object_type *o_ptr)
229 BIT_FLAGS flgs[TR_FLAG_SIZE];
230 if (!hates_fire(o_ptr)) return (FALSE);
231 object_flags(o_ptr, flgs);
232 if (have_flag(flgs, TR_IGNORE_FIRE)) return (FALSE);
238 * @brief アイテムが冷気で破損するかどうかを判定する(メインルーチン) /
240 * @param o_ptr アイテムの情報参照ポインタ
241 * @return 破損するならばTRUEを返す
244 int set_cold_destroy(object_type *o_ptr)
246 BIT_FLAGS flgs[TR_FLAG_SIZE];
247 if (!hates_cold(o_ptr)) return (FALSE);
248 object_flags(o_ptr, flgs);
249 if (have_flag(flgs, TR_IGNORE_COLD)) return (FALSE);
255 * @brief アイテムが指定確率で破損するかどうかを判定する /
256 * Destroys a type of item on a given percent chance
257 * @param typ 破損判定関数ポインタ
261 * Note that missiles are no longer necessarily all destroyed
262 * Destruction taken from "melee.c" code for "stealing".
263 * New-style wands and rods handled correctly. -LM-
264 * Returns number of items destroyed.
266 int inven_damage(inven_func typ, int perc)
271 GAME_TEXT o_name[MAX_NLEN];
273 if (CHECK_MULTISHADOW()) return 0;
275 if (p_ptr->inside_arena) return 0;
277 /* Count the casualties */
280 /* Scan through the slots backwards */
281 for (i = 0; i < INVEN_PACK; i++)
283 o_ptr = &p_ptr->inventory_list[i];
284 if (!o_ptr->k_idx) continue;
286 /* Hack -- for now, skip artifacts */
287 if (object_is_artifact(o_ptr)) continue;
289 /* Give this item slot a shot at death */
292 /* Count the casualties */
293 for (amt = j = 0; j < o_ptr->number; ++j)
295 if (randint0(100) < perc) amt++;
298 /* Some casualities */
301 object_desc(o_name, o_ptr, OD_OMIT_PREFIX);
303 msg_format(_("%s(%c)が%s壊れてしまった!", "%sour %s (%c) %s destroyed!"),
305 o_name, index_to_label(i), ((o_ptr->number > 1) ?
306 ((amt == o_ptr->number) ? "全部" : (amt > 1 ? "何個か" : "一個")) : ""));
308 ((o_ptr->number > 1) ? ((amt == o_ptr->number) ? "All of y" :
309 (amt > 1 ? "Some of y" : "One of y")) : "Y"), o_name, index_to_label(i), ((amt > 1) ? "were" : "was"));
313 if ((p_ptr->pseikaku == SEIKAKU_COMBAT) || (p_ptr->inventory_list[INVEN_BOW].name1 == ART_CRIMSON))
314 msg_print("やりやがったな!");
315 else if ((p_ptr->pseikaku == SEIKAKU_CHARGEMAN))
317 if (randint0(2) == 0) msg_print(_("ジュラル星人め!", ""));
318 else msg_print(_("弱い者いじめは止めるんだ!", ""));
322 /* Potions smash open */
323 if (object_is_potion(o_ptr))
325 (void)potion_smash_effect(0, p_ptr->y, p_ptr->x, o_ptr->k_idx);
328 /* Reduce the charges of rods/wands */
329 reduce_charges(o_ptr, amt);
331 /* Destroy "amt" items */
332 inven_item_increase(i, -amt);
333 inven_item_optimize(i);
335 /* Count the casualties */
341 /* Return the casualty count */
347 * @brief 酸攻撃による装備のAC劣化処理 /
348 * Acid has hit the player, attempt to affect some armor.
349 * @return 装備による軽減があったならTRUEを返す
351 * Note that the "base armor" of an object never changes.
352 * If any armor is damaged (or resists), the player takes less damage.
354 static bool acid_minus_ac(void)
356 object_type *o_ptr = NULL;
357 BIT_FLAGS flgs[TR_FLAG_SIZE];
358 GAME_TEXT o_name[MAX_NLEN];
360 /* Pick a (possibly empty) p_ptr->inventory_list slot */
363 case 1: o_ptr = &p_ptr->inventory_list[INVEN_RARM]; break;
364 case 2: o_ptr = &p_ptr->inventory_list[INVEN_LARM]; break;
365 case 3: o_ptr = &p_ptr->inventory_list[INVEN_BODY]; break;
366 case 4: o_ptr = &p_ptr->inventory_list[INVEN_OUTER]; break;
367 case 5: o_ptr = &p_ptr->inventory_list[INVEN_HANDS]; break;
368 case 6: o_ptr = &p_ptr->inventory_list[INVEN_HEAD]; break;
369 case 7: o_ptr = &p_ptr->inventory_list[INVEN_FEET]; break;
372 if (!o_ptr->k_idx) return (FALSE);
373 if (!object_is_armour(o_ptr)) return (FALSE);
375 object_desc(o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
376 object_flags(o_ptr, flgs);
377 /* No damage left to be done */
378 if (o_ptr->ac + o_ptr->to_a <= 0)
380 msg_format(_("%sは既にボロボロだ!", "Your %s is already crumble!"), o_name);
385 if (have_flag(flgs, TR_IGNORE_ACID))
387 msg_format(_("しかし%sには効果がなかった!", "Your %s is unaffected!"), o_name);
391 msg_format(_("%sが酸で腐食した!", "Your %s is corroded!"), o_name);
393 /* Damage the item */
396 /* Calculate bonuses */
397 p_ptr->update |= (PU_BONUS);
398 p_ptr->window |= (PW_EQUIP | PW_PLAYER);
402 /* Item was damaged */
408 * @brief 酸属性によるプレイヤー損害処理 /
409 * Hurt the player with Acid
411 * @param kb_str ダメージ原因記述
412 * @param monspell 原因となったモンスター特殊攻撃ID
413 * @param aura オーラよるダメージが原因ならばTRUE
416 HIT_POINT acid_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura)
418 HIT_POINT get_damage;
419 int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
420 bool double_resist = IS_OPPOSE_ACID();
423 if (p_ptr->immune_acid || (dam <= 0))
425 learn_spell(monspell);
429 /* Vulnerability (Ouch!) */
430 if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
431 if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
433 /* Resist the damage */
434 if (p_ptr->resist_acid) dam = (dam + 2) / 3;
435 if (double_resist) dam = (dam + 2) / 3;
437 if (aura || !CHECK_MULTISHADOW())
439 if ((!(double_resist || p_ptr->resist_acid)) &&
440 one_in_(HURT_CHANCE))
441 (void)do_dec_stat(A_CHR);
443 /* If any armor gets hit, defend the player */
444 if (acid_minus_ac()) dam = (dam + 1) / 2;
447 get_damage = take_hit(aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str, monspell);
449 /* Inventory damage */
450 if (!aura && !(double_resist && p_ptr->resist_acid))
451 inven_damage(set_acid_destroy, inv);
457 * @brief 電撃属性によるプレイヤー損害処理 /
458 * Hurt the player with electricity
460 * @param kb_str ダメージ原因記述
461 * @param monspell 原因となったモンスター特殊攻撃ID
462 * @param aura オーラよるダメージが原因ならばTRUE
465 HIT_POINT elec_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura)
467 HIT_POINT get_damage;
468 int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
469 bool double_resist = IS_OPPOSE_ELEC();
472 if (p_ptr->immune_elec || (dam <= 0))
474 learn_spell(monspell);
478 /* Vulnerability (Ouch!) */
479 if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
480 if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
481 if (prace_is_(RACE_ANDROID)) dam += dam / 3;
483 /* Resist the damage */
484 if (p_ptr->resist_elec) dam = (dam + 2) / 3;
485 if (double_resist) dam = (dam + 2) / 3;
487 if (aura || !CHECK_MULTISHADOW())
489 if ((!(double_resist || p_ptr->resist_elec)) &&
490 one_in_(HURT_CHANCE))
491 (void)do_dec_stat(A_DEX);
494 get_damage = take_hit(aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str, monspell);
496 /* Inventory damage */
497 if (!aura && !(double_resist && p_ptr->resist_elec))
498 inven_damage(set_elec_destroy, inv);
505 * @brief 火炎属性によるプレイヤー損害処理 /
506 * Hurt the player with Fire
508 * @param kb_str ダメージ原因記述
509 * @param monspell 原因となったモンスター特殊攻撃ID
510 * @param aura オーラよるダメージが原因ならばTRUE
513 HIT_POINT fire_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura)
515 HIT_POINT get_damage;
516 int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
517 bool double_resist = IS_OPPOSE_FIRE();
520 if (p_ptr->immune_fire || (dam <= 0))
522 learn_spell(monspell);
526 /* Vulnerability (Ouch!) */
527 if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
528 if (prace_is_(RACE_ENT)) dam += dam / 3;
529 if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
531 /* Resist the damage */
532 if (p_ptr->resist_fire) dam = (dam + 2) / 3;
533 if (double_resist) dam = (dam + 2) / 3;
535 if (aura || !CHECK_MULTISHADOW())
537 if ((!(double_resist || p_ptr->resist_fire)) &&
538 one_in_(HURT_CHANCE))
539 (void)do_dec_stat(A_STR);
542 get_damage = take_hit(aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str, monspell);
544 /* Inventory damage */
545 if (!aura && !(double_resist && p_ptr->resist_fire))
546 inven_damage(set_fire_destroy, inv);
553 * @brief 冷気属性によるプレイヤー損害処理 /
554 * Hurt the player with Cold
556 * @param kb_str ダメージ原因記述
557 * @param monspell 原因となったモンスター特殊攻撃ID
558 * @param aura オーラよるダメージが原因ならばTRUE
561 HIT_POINT cold_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura)
563 HIT_POINT get_damage;
564 int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
565 bool double_resist = IS_OPPOSE_COLD();
568 if (p_ptr->immune_cold || (dam <= 0))
570 learn_spell(monspell);
574 /* Vulnerability (Ouch!) */
575 if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
576 if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
578 /* Resist the damage */
579 if (p_ptr->resist_cold) dam = (dam + 2) / 3;
580 if (double_resist) dam = (dam + 2) / 3;
582 if (aura || !CHECK_MULTISHADOW())
584 if ((!(double_resist || p_ptr->resist_cold)) &&
585 one_in_(HURT_CHANCE))
586 (void)do_dec_stat(A_STR);
589 get_damage = take_hit(aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str, monspell);
591 /* Inventory damage */
592 if (!aura && !(double_resist && p_ptr->resist_cold))
593 inven_damage(set_cold_destroy, inv);