OSDN Git Service

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