OSDN Git Service

[Refactor] #37353 ULTRIX のプリプロを削除 / Removed preprocessor ULTRIX
[hengband/hengband.git] / src / object-broken.c
1 #include "angband.h"
2 #include "spells.h"
3 #include "objectkind.h"
4 #include "snipe.h"
5
6 /*!
7 * @brief アイテムが酸で破損するかどうかを判定する
8 * @param o_ptr アイテムの情報参照ポインタ
9 * @return 破損するならばTRUEを返す
10 * Note that amulets, rods, and high-level spell books are immune
11 * to "inventory damage" of any kind.  Also sling ammo and shovels.
12 * Does a given class of objects (usually) hate acid?
13 * Note that acid can either melt or corrode something.
14 */
15 bool hates_acid(object_type *o_ptr)
16 {
17         /* Analyze the type */
18         switch (o_ptr->tval)
19         {
20                 /* Wearable items */
21         case TV_ARROW:
22         case TV_BOLT:
23         case TV_BOW:
24         case TV_SWORD:
25         case TV_HAFTED:
26         case TV_POLEARM:
27         case TV_HELM:
28         case TV_CROWN:
29         case TV_SHIELD:
30         case TV_BOOTS:
31         case TV_GLOVES:
32         case TV_CLOAK:
33         case TV_SOFT_ARMOR:
34         case TV_HARD_ARMOR:
35         case TV_DRAG_ARMOR:
36         {
37                 return TRUE;
38         }
39
40         /* Staffs/Scrolls are wood/paper */
41         case TV_STAFF:
42         case TV_SCROLL:
43         {
44                 return TRUE;
45         }
46
47         /* Ouch */
48         case TV_CHEST:
49         {
50                 return TRUE;
51         }
52
53         /* Junk is useless */
54         case TV_SKELETON:
55         case TV_BOTTLE:
56         case TV_JUNK:
57         {
58                 return TRUE;
59         }
60         }
61
62         return FALSE;
63 }
64
65
66 /*!
67 * @brief アイテムが電撃で破損するかどうかを判定する /
68 * Does a given object (usually) hate electricity?
69 * @param o_ptr アイテムの情報参照ポインタ
70 * @return 破損するならばTRUEを返す
71 */
72 bool hates_elec(object_type *o_ptr)
73 {
74         switch (o_ptr->tval)
75         {
76         case TV_RING:
77         case TV_WAND:
78         {
79                 return TRUE;
80         }
81         }
82
83         return FALSE;
84 }
85
86
87 /*!
88 * @brief アイテムが火炎で破損するかどうかを判定する /
89 * Does a given object (usually) hate fire?
90 * @param o_ptr アイテムの情報参照ポインタ
91 * @return 破損するならばTRUEを返す
92 * @details
93 * Hafted/Polearm weapons have wooden shafts.
94 * Arrows/Bows are mostly wooden.
95 */
96 bool hates_fire(object_type *o_ptr)
97 {
98         /* Analyze the type */
99         switch (o_ptr->tval)
100         {
101                 /* Wearable */
102         case TV_LITE:
103         case TV_ARROW:
104         case TV_BOW:
105         case TV_HAFTED:
106         case TV_POLEARM:
107         case TV_BOOTS:
108         case TV_GLOVES:
109         case TV_CLOAK:
110         case TV_SOFT_ARMOR:
111         {
112                 return TRUE;
113         }
114
115         /* Books */
116         case TV_LIFE_BOOK:
117         case TV_SORCERY_BOOK:
118         case TV_NATURE_BOOK:
119         case TV_CHAOS_BOOK:
120         case TV_DEATH_BOOK:
121         case TV_TRUMP_BOOK:
122         case TV_ARCANE_BOOK:
123         case TV_CRAFT_BOOK:
124         case TV_DAEMON_BOOK:
125         case TV_CRUSADE_BOOK:
126         case TV_MUSIC_BOOK:
127         case TV_HISSATSU_BOOK:
128         case TV_HEX_BOOK:
129         {
130                 return TRUE;
131         }
132
133         /* Chests */
134         case TV_CHEST:
135         {
136                 return TRUE;
137         }
138
139         /* Staffs/Scrolls burn */
140         case TV_STAFF:
141         case TV_SCROLL:
142         {
143                 return TRUE;
144         }
145         }
146
147         return FALSE;
148 }
149
150
151 /*!
152 * @brief アイテムが冷気で破損するかどうかを判定する /
153 * Does a given object (usually) hate cold?
154 * @param o_ptr アイテムの情報参照ポインタ
155 * @return 破損するならばTRUEを返す
156 */
157 bool hates_cold(object_type *o_ptr)
158 {
159         switch (o_ptr->tval)
160         {
161         case TV_POTION:
162         case TV_FLASK:
163         case TV_BOTTLE:
164         {
165                 return TRUE;
166         }
167         }
168
169         return FALSE;
170 }
171
172
173 /*!
174 * @brief アイテムが酸で破損するかどうかを判定する(メインルーチン) /
175 * Melt something
176 * @param o_ptr アイテムの情報参照ポインタ
177 * @return 破損するならばTRUEを返す
178 * @todo 統合を検討
179 */
180 int set_acid_destroy(object_type *o_ptr)
181 {
182         BIT_FLAGS flgs[TR_FLAG_SIZE];
183         if (!hates_acid(o_ptr)) return FALSE;
184         object_flags(o_ptr, flgs);
185         if (have_flag(flgs, TR_IGNORE_ACID)) return FALSE;
186         return TRUE;
187 }
188
189
190 /*!
191 * @brief アイテムが電撃で破損するかどうかを判定する(メインルーチン) /
192 * Electrical damage
193 * @param o_ptr アイテムの情報参照ポインタ
194 * @return 破損するならばTRUEを返す
195 * @todo 統合を検討
196 */
197 int set_elec_destroy(object_type *o_ptr)
198 {
199         BIT_FLAGS flgs[TR_FLAG_SIZE];
200         if (!hates_elec(o_ptr)) return FALSE;
201         object_flags(o_ptr, flgs);
202         if (have_flag(flgs, TR_IGNORE_ELEC)) return FALSE;
203         return TRUE;
204 }
205
206
207 /*!
208 * @brief アイテムが火炎で破損するかどうかを判定する(メインルーチン) /
209 * Burn something
210 * @param o_ptr アイテムの情報参照ポインタ
211 * @return 破損するならばTRUEを返す
212 * @todo 統合を検討
213 */
214 int set_fire_destroy(object_type *o_ptr)
215 {
216         BIT_FLAGS flgs[TR_FLAG_SIZE];
217         if (!hates_fire(o_ptr)) return FALSE;
218         object_flags(o_ptr, flgs);
219         if (have_flag(flgs, TR_IGNORE_FIRE)) return FALSE;
220         return TRUE;
221 }
222
223
224 /*!
225 * @brief アイテムが冷気で破損するかどうかを判定する(メインルーチン) /
226 * Freeze things
227 * @param o_ptr アイテムの情報参照ポインタ
228 * @return 破損するならばTRUEを返す
229 * @todo 統合を検討
230 */
231 int set_cold_destroy(object_type *o_ptr)
232 {
233         BIT_FLAGS flgs[TR_FLAG_SIZE];
234         if (!hates_cold(o_ptr)) return FALSE;
235         object_flags(o_ptr, flgs);
236         if (have_flag(flgs, TR_IGNORE_COLD)) return FALSE;
237         return TRUE;
238 }
239
240
241 /*!
242  * @brief 薬の破損効果処理 /
243  * Potions "smash open" and cause an area effect when
244  * @param who 薬破損の主体ID(プレイヤー所持アイテムが壊れた場合0、床上のアイテムの場合モンスターID)
245  * @param y 破壊時のY座標
246  * @param x 破壊時のX座標
247  * @param k_idx 破損した薬のアイテムID
248  * @return 薬を浴びたモンスターが起こるならばTRUEを返す
249  * @details
250  * <pre>
251  * (1) they are shattered while in the player's p_ptr->inventory_list,
252  * due to cold (etc) attacks;
253  * (2) they are thrown at a monster, or obstacle;
254  * (3) they are shattered by a "cold ball" or other such spell
255  * while lying on the floor.
256  *
257  * Arguments:
258  *    who   ---  who caused the potion to shatter (0=player)
259  *          potions that smash on the floor are assumed to
260  *          be caused by no-one (who = 1), as are those that
261  *          shatter inside the player inventory.
262  *          (Not anymore -- I changed this; TY)
263  *    y, x  --- coordinates of the potion (or player if
264  *          the potion was in her inventory);
265  *    o_ptr --- pointer to the potion object.
266  * </pre>
267  */
268 bool potion_smash_effect(player_type *owner_ptr, MONSTER_IDX who, POSITION y, POSITION x, KIND_OBJECT_IDX k_idx)
269 {
270         int radius = 2;
271         int dt = 0;
272         int dam = 0;
273         bool angry = FALSE;
274         object_kind *k_ptr = &k_info[k_idx];
275         switch (k_ptr->sval)
276         {
277         case SV_POTION_SALT_WATER:
278         case SV_POTION_SLIME_MOLD:
279         case SV_POTION_LOSE_MEMORIES:
280         case SV_POTION_DEC_STR:
281         case SV_POTION_DEC_INT:
282         case SV_POTION_DEC_WIS:
283         case SV_POTION_DEC_DEX:
284         case SV_POTION_DEC_CON:
285         case SV_POTION_DEC_CHR:
286         case SV_POTION_WATER:   /* perhaps a 'water' attack? */
287         case SV_POTION_APPLE_JUICE:
288                 return TRUE;
289
290         case SV_POTION_INFRAVISION:
291         case SV_POTION_DETECT_INVIS:
292         case SV_POTION_SLOW_POISON:
293         case SV_POTION_CURE_POISON:
294         case SV_POTION_BOLDNESS:
295         case SV_POTION_RESIST_HEAT:
296         case SV_POTION_RESIST_COLD:
297         case SV_POTION_HEROISM:
298         case SV_POTION_BESERK_STRENGTH:
299         case SV_POTION_RES_STR:
300         case SV_POTION_RES_INT:
301         case SV_POTION_RES_WIS:
302         case SV_POTION_RES_DEX:
303         case SV_POTION_RES_CON:
304         case SV_POTION_RES_CHR:
305         case SV_POTION_INC_STR:
306         case SV_POTION_INC_INT:
307         case SV_POTION_INC_WIS:
308         case SV_POTION_INC_DEX:
309         case SV_POTION_INC_CON:
310         case SV_POTION_INC_CHR:
311         case SV_POTION_AUGMENTATION:
312         case SV_POTION_ENLIGHTENMENT:
313         case SV_POTION_STAR_ENLIGHTENMENT:
314         case SV_POTION_SELF_KNOWLEDGE:
315         case SV_POTION_EXPERIENCE:
316         case SV_POTION_RESISTANCE:
317         case SV_POTION_INVULNERABILITY:
318         case SV_POTION_NEW_LIFE:
319                 /* All of the above potions have no effect when shattered */
320                 return FALSE;
321         case SV_POTION_SLOWNESS:
322                 dt = GF_OLD_SLOW;
323                 dam = 5;
324                 angry = TRUE;
325                 break;
326         case SV_POTION_POISON:
327                 dt = GF_POIS;
328                 dam = 3;
329                 angry = TRUE;
330                 break;
331         case SV_POTION_BLINDNESS:
332                 dt = GF_DARK;
333                 angry = TRUE;
334                 break;
335         case SV_POTION_BOOZE:
336                 dt = GF_OLD_CONF;
337                 angry = TRUE;
338                 break;
339         case SV_POTION_SLEEP:
340                 dt = GF_OLD_SLEEP;
341                 angry = TRUE;
342                 break;
343         case SV_POTION_RUINATION:
344         case SV_POTION_DETONATIONS:
345                 dt = GF_SHARDS;
346                 dam = damroll(25, 25);
347                 angry = TRUE;
348                 break;
349         case SV_POTION_DEATH:
350                 dt = GF_DEATH_RAY;
351                 dam = k_ptr->level * 10;
352                 angry = TRUE;
353                 radius = 1;
354                 break;
355         case SV_POTION_SPEED:
356                 dt = GF_OLD_SPEED;
357                 break;
358         case SV_POTION_CURE_LIGHT:
359                 dt = GF_OLD_HEAL;
360                 dam = damroll(2, 3);
361                 break;
362         case SV_POTION_CURE_SERIOUS:
363                 dt = GF_OLD_HEAL;
364                 dam = damroll(4, 3);
365                 break;
366         case SV_POTION_CURE_CRITICAL:
367         case SV_POTION_CURING:
368                 dt = GF_OLD_HEAL;
369                 dam = damroll(6, 3);
370                 break;
371         case SV_POTION_HEALING:
372                 dt = GF_OLD_HEAL;
373                 dam = damroll(10, 10);
374                 break;
375         case SV_POTION_RESTORE_EXP:
376                 dt = GF_STAR_HEAL;
377                 dam = 0;
378                 radius = 1;
379                 break;
380         case SV_POTION_LIFE:
381                 dt = GF_STAR_HEAL;
382                 dam = damroll(50, 50);
383                 radius = 1;
384                 break;
385         case SV_POTION_STAR_HEALING:
386                 dt = GF_OLD_HEAL;
387                 dam = damroll(50, 50);
388                 radius = 1;
389                 break;
390         case SV_POTION_RESTORE_MANA:
391                 dt = GF_MANA;
392                 dam = damroll(10, 10);
393                 radius = 1;
394                 break;
395         default:
396                 break;
397         }
398
399         (void)project(owner_ptr, who, radius, y, x, dam, dt, (PROJECT_JUMP | PROJECT_ITEM | PROJECT_KILL), -1);
400         return angry;
401 }
402
403 /*!
404  * @brief 矢弾を射撃した場合の破損確率を返す /
405  * Determines the odds of an object breaking when thrown at a monster
406  * @param o_ptr 矢弾のオブジェクト構造体参照ポインタ
407  * @return 破損確率(%)
408  * @details
409  * Note that artifacts never break, see the "drop_near()" function.
410  */
411 PERCENTAGE breakage_chance(player_type *owner_ptr, object_type *o_ptr, bool has_archer_bonus, SPELL_IDX snipe_type)
412 {
413         /* Examine the snipe type */
414         if (snipe_type)
415         {
416                 if (snipe_type == SP_KILL_WALL) return 100;
417                 if (snipe_type == SP_EXPLODE) return 100;
418                 if (snipe_type == SP_PIERCE) return 100;
419                 if (snipe_type == SP_FINAL) return 100;
420                 if (snipe_type == SP_NEEDLE) return 100;
421                 if (snipe_type == SP_EVILNESS) return 40;
422                 if (snipe_type == SP_HOLYNESS) return 40;
423         }
424
425         /* Examine the item type */
426         PERCENTAGE archer_bonus = (has_archer_bonus ? (PERCENTAGE)(owner_ptr->lev - 1) / 7 + 4 : 0);
427         switch (o_ptr->tval)
428         {
429                 /* Always break */
430         case TV_FLASK:
431         case TV_POTION:
432         case TV_BOTTLE:
433         case TV_FOOD:
434         case TV_JUNK:
435                 return 100;
436
437                 /* Often break */
438         case TV_LITE:
439         case TV_SCROLL:
440         case TV_SKELETON:
441                 return 50;
442
443                 /* Sometimes break */
444         case TV_WAND:
445         case TV_SPIKE:
446                 return 25;
447         case TV_ARROW:
448                 return 20 - archer_bonus * 2;
449
450                 /* Rarely break */
451         case TV_SHOT:
452         case TV_BOLT:
453                 return 10 - archer_bonus;
454         default:
455                 return 10;
456         }
457 }