OSDN Git Service

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