OSDN Git Service

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