OSDN Git Service

[Refactor] #40399 Separated object-mark-types.h from object.h
[hengband/hengband.git] / src / effect / effect-item.c
1 #include "system/angband.h"
2 #include "effect-item.h"
3 #include "object/object-flavor.h"
4 #include "object/object-hook.h"
5 #include "object/object-broken.h"
6 #include "autopick/autopick.h"
7 #include "spell/spells-type.h"
8 #include "spell/spells3.h"
9 #include "object/tr-types.h"
10 #include "object/object-mark-types.h"
11
12 /*!
13  * @brief 汎用的なビーム/ボルト/ボール系によるアイテムオブジェクトへの効果処理 / Handle a beam/bolt/ball causing damage to a monster.
14  * @param caster_ptr プレーヤーへの参照ポインタ
15  * @param who 魔法を発動したモンスター(0ならばプレイヤー) / Index of "source" monster (zero for "player")
16  * @param r 効果半径(ビーム/ボルト = 0 / ボール = 1以上) / Radius of explosion (0 = beam/bolt, 1 to 9 = ball)
17  * @param y 目標Y座標 / Target y location (or location to travel "towards")
18  * @param x 目標X座標 / Target x location (or location to travel "towards")
19  * @param dam 基本威力 / Base damage roll to apply to affected monsters (or player)
20  * @param typ 効果属性 / Type of damage to apply to monsters (and objects)
21  * @return 何か一つでも効力があればTRUEを返す / TRUE if any "effects" of the projection were observed, else FALSE
22  */
23 bool affect_item(player_type *caster_ptr, MONSTER_IDX who, POSITION r, POSITION y, POSITION x, HIT_POINT dam, EFFECT_ID typ)
24 {
25         grid_type *g_ptr = &caster_ptr->current_floor_ptr->grid_array[y][x];
26
27         bool is_item_affected = FALSE;
28         bool known = player_has_los_bold(caster_ptr, y, x);
29         who = who ? who : 0;
30         dam = (dam + r) / (r + 1);
31         OBJECT_IDX next_o_idx = 0;
32         for (OBJECT_IDX this_o_idx = g_ptr->o_idx; this_o_idx != 0; this_o_idx = next_o_idx)
33         {
34                 object_type *o_ptr = &caster_ptr->current_floor_ptr->o_list[this_o_idx];
35                 bool ignore = FALSE;
36                 bool do_kill = FALSE;
37                 concptr note_kill = NULL;
38
39 #ifdef JP
40 #else
41                 bool plural = (o_ptr->number > 1);
42 #endif
43                 next_o_idx = o_ptr->next_o_idx;
44                 BIT_FLAGS flags[TR_FLAG_SIZE];
45                 object_flags(o_ptr, flags);
46                 bool is_artifact = object_is_artifact(o_ptr);
47                 switch (typ)
48                 {
49                 case GF_ACID:
50                 {
51                         if (hates_acid(o_ptr))
52                         {
53                                 do_kill = TRUE;
54                                 note_kill = _("融けてしまった!", (plural ? " melt!" : " melts!"));
55                                 if (have_flag(flags, TR_IGNORE_ACID)) ignore = TRUE;
56                         }
57
58                         break;
59                 }
60                 case GF_ELEC:
61                 {
62                         if (hates_elec(o_ptr))
63                         {
64                                 do_kill = TRUE;
65                                 note_kill = _("壊れてしまった!", (plural ? " are destroyed!" : " is destroyed!"));
66                                 if (have_flag(flags, TR_IGNORE_ELEC)) ignore = TRUE;
67                         }
68
69                         break;
70                 }
71                 case GF_FIRE:
72                 {
73                         if (hates_fire(o_ptr))
74                         {
75                                 do_kill = TRUE;
76                                 note_kill = _("燃えてしまった!", (plural ? " burn up!" : " burns up!"));
77                                 if (have_flag(flags, TR_IGNORE_FIRE)) ignore = TRUE;
78                         }
79
80                         break;
81                 }
82                 case GF_COLD:
83                 {
84                         if (hates_cold(o_ptr))
85                         {
86                                 note_kill = _("砕け散ってしまった!", (plural ? " shatter!" : " shatters!"));
87                                 do_kill = TRUE;
88                                 if (have_flag(flags, TR_IGNORE_COLD)) ignore = TRUE;
89                         }
90
91                         break;
92                 }
93                 case GF_PLASMA:
94                 {
95                         if (hates_fire(o_ptr))
96                         {
97                                 do_kill = TRUE;
98                                 note_kill = _("燃えてしまった!", (plural ? " burn up!" : " burns up!"));
99                                 if (have_flag(flags, TR_IGNORE_FIRE)) ignore = TRUE;
100                         }
101
102                         if (hates_elec(o_ptr))
103                         {
104                                 ignore = FALSE;
105                                 do_kill = TRUE;
106                                 note_kill = _("壊れてしまった!", (plural ? " are destroyed!" : " is destroyed!"));
107                                 if (have_flag(flags, TR_IGNORE_ELEC)) ignore = TRUE;
108                         }
109
110                         break;
111                 }
112                 case GF_METEOR:
113                 {
114                         if (hates_fire(o_ptr))
115                         {
116                                 do_kill = TRUE;
117                                 note_kill = _("燃えてしまった!", (plural ? " burn up!" : " burns up!"));
118                                 if (have_flag(flags, TR_IGNORE_FIRE)) ignore = TRUE;
119                         }
120
121                         if (hates_cold(o_ptr))
122                         {
123                                 ignore = FALSE;
124                                 do_kill = TRUE;
125                                 note_kill = _("砕け散ってしまった!", (plural ? " shatter!" : " shatters!"));
126                                 if (have_flag(flags, TR_IGNORE_COLD)) ignore = TRUE;
127                         }
128
129                         break;
130                 }
131                 case GF_ICE:
132                 case GF_SHARDS:
133                 case GF_FORCE:
134                 case GF_SOUND:
135                 {
136                         if (hates_cold(o_ptr))
137                         {
138                                 note_kill = _("砕け散ってしまった!", (plural ? " shatter!" : " shatters!"));
139                                 do_kill = TRUE;
140                         }
141
142                         break;
143                 }
144                 case GF_MANA:
145                 case GF_SEEKER:
146                 case GF_SUPER_RAY:
147                 {
148                         do_kill = TRUE;
149                         note_kill = _("壊れてしまった!", (plural ? " are destroyed!" : " is destroyed!"));
150                         break;
151                 }
152                 case GF_DISINTEGRATE:
153                 {
154                         do_kill = TRUE;
155                         note_kill = _("蒸発してしまった!", (plural ? " evaporate!" : " evaporates!"));
156                         break;
157                 }
158                 case GF_CHAOS:
159                 {
160                         do_kill = TRUE;
161                         note_kill = _("壊れてしまった!", (plural ? " are destroyed!" : " is destroyed!"));
162                         if (have_flag(flags, TR_RES_CHAOS)) ignore = TRUE;
163                         else if ((o_ptr->tval == TV_SCROLL) && (o_ptr->sval == SV_SCROLL_CHAOS)) ignore = TRUE;
164                         break;
165                 }
166                 case GF_HOLY_FIRE:
167                 case GF_HELL_FIRE:
168                 {
169                         if (object_is_cursed(o_ptr))
170                         {
171                                 do_kill = TRUE;
172                                 note_kill = _("壊れてしまった!", (plural ? " are destroyed!" : " is destroyed!"));
173                         }
174
175                         break;
176                 }
177                 case GF_IDENTIFY:
178                 {
179                         identify_item(caster_ptr, o_ptr);
180                         autopick_alter_item(caster_ptr, (-this_o_idx), FALSE);
181                         break;
182                 }
183                 case GF_KILL_TRAP:
184                 case GF_KILL_DOOR:
185                 {
186                         if (o_ptr->tval != TV_CHEST) break;
187                         if (o_ptr->pval <= 0) break;
188
189                         o_ptr->pval = (0 - o_ptr->pval);
190                         object_known(o_ptr);
191                         if (known && (o_ptr->marked & OM_FOUND))
192                         {
193                                 msg_print(_("カチッと音がした!", "Click!"));
194                                 is_item_affected = TRUE;
195                         }
196
197                         break;
198                 }
199                 case GF_ANIM_DEAD:
200                 {
201                         if (o_ptr->tval != TV_CORPSE) break;
202
203                         BIT_FLAGS mode = 0L;
204                         if (!who || is_pet(&caster_ptr->current_floor_ptr->m_list[who]))
205                                 mode |= PM_FORCE_PET;
206
207                         for (int i = 0; i < o_ptr->number; i++)
208                         {
209                                 if (((o_ptr->sval == SV_CORPSE) && (randint1(100) > 80)) || 
210                                         ((o_ptr->sval == SV_SKELETON) && (randint1(100) > 60)))
211                                 {
212                                         if (!note_kill)
213                                         {
214                                                 note_kill = _("灰になった。", (plural ? " become dust." : " becomes dust."));
215                                         }
216
217                                         continue;
218                                 }
219                                 else if (summon_named_creature(caster_ptr, who, y, x, o_ptr->pval, mode))
220                                 {
221                                         note_kill = _("生き返った。", " revived.");
222                                 }
223                                 else if (!note_kill)
224                                 {
225                                         note_kill = _("灰になった。", (plural ? " become dust." : " becomes dust."));
226                                 }
227                         }
228
229                         do_kill = TRUE;
230                         is_item_affected = TRUE;
231                         break;
232                 }
233                 }
234
235                 if (!do_kill) continue;
236
237                 GAME_TEXT o_name[MAX_NLEN];
238                 if (known && (o_ptr->marked & OM_FOUND))
239                 {
240                         is_item_affected = TRUE;
241                         object_desc(caster_ptr, o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
242                 }
243
244                 if ((is_artifact || ignore))
245                 {
246                         if (known && (o_ptr->marked & OM_FOUND))
247                                 msg_format(_("%sは影響を受けない!", (plural ? "The %s are unaffected!" : "The %s is unaffected!")), o_name);
248
249                         continue;
250                 }
251
252                 if (known && (o_ptr->marked & OM_FOUND) && note_kill)
253                         msg_format(_("%sは%s", "The %s%s"), o_name, note_kill);
254
255                 KIND_OBJECT_IDX k_idx = o_ptr->k_idx;
256                 bool is_potion = object_is_potion(o_ptr);
257                 delete_object_idx(caster_ptr, this_o_idx);
258                 if (is_potion)
259                         (void)potion_smash_effect(caster_ptr, who, y, x, k_idx);
260
261                 lite_spot(caster_ptr, y, x);
262         }
263
264         return is_item_affected;
265 }