OSDN Git Service

[Refactor] #37353 cmd6.cをcmd-magiceat.cに改名しつつ整理。 / Refactor to rename cmd6.c to cmd...
[hengbandforosx/hengbandosx.git] / src / cmd-activate.c
1 /*!
2 * @file cmd-activate.c
3 * @brief プレイヤーの発動コマンド実装
4 * @date 2018/09/07
5 * @details
6 * cmd6.cより分離。
7 */
8
9 #include "angband.h"
10
11 /*!
12 * @brief ペット入りモンスターボールをソートするための比較関数
13 * @param u 所持品配列の参照ポインタ
14 * @param v 未使用
15 * @param a 所持品ID1
16 * @param b 所持品ID2
17 * @return 1の方が大であればTRUE
18 */
19 static bool ang_sort_comp_pet(vptr u, vptr v, int a, int b)
20 {
21         u16b *who = (u16b*)(u);
22
23         int w1 = who[a];
24         int w2 = who[b];
25
26         monster_type *m_ptr1 = &m_list[w1];
27         monster_type *m_ptr2 = &m_list[w2];
28         monster_race *r_ptr1 = &r_info[m_ptr1->r_idx];
29         monster_race *r_ptr2 = &r_info[m_ptr2->r_idx];
30
31         /* Unused */
32         (void)v;
33
34         if (m_ptr1->nickname && !m_ptr2->nickname) return TRUE;
35         if (m_ptr2->nickname && !m_ptr1->nickname) return FALSE;
36
37         if ((r_ptr1->flags1 & RF1_UNIQUE) && !(r_ptr2->flags1 & RF1_UNIQUE)) return TRUE;
38         if ((r_ptr2->flags1 & RF1_UNIQUE) && !(r_ptr1->flags1 & RF1_UNIQUE)) return FALSE;
39
40         if (r_ptr1->level > r_ptr2->level) return TRUE;
41         if (r_ptr2->level > r_ptr1->level) return FALSE;
42
43         if (m_ptr1->hp > m_ptr2->hp) return TRUE;
44         if (m_ptr2->hp > m_ptr1->hp) return FALSE;
45
46         return w1 <= w2;
47 }
48
49 /*!
50 * @brief オブジェクトをプレイヤーが魔道具として発動できるかを判定する /
51 * Hook to determine if an object is activatable
52 * @param o_ptr 判定したいオブジェクトの構造体参照ポインタ
53 * @return 魔道具として発動可能ならばTRUEを返す
54 */
55 static bool item_tester_hook_activate(object_type *o_ptr)
56 {
57         u32b flgs[TR_FLAG_SIZE];
58
59         /* Not known */
60         if (!object_is_known(o_ptr)) return (FALSE);
61
62         /* Extract the flags */
63         object_flags(o_ptr, flgs);
64
65         /* Check activation flag */
66         if (have_flag(flgs, TR_ACTIVATE)) return (TRUE);
67
68         /* Assume not */
69         return (FALSE);
70 }
71
72 /*!
73  * @brief 装備を発動するコマンドのサブルーチン /
74  * Activate a wielded object.  Wielded objects never stack.
75  * And even if they did, activatable objects never stack.
76  * @param item 発動するオブジェクトの所持品ID
77  * @return なし
78  * @details
79  * <pre>
80  * Currently, only (some) artifacts, and Dragon Scale Mail, can be activated.
81  * But one could, for example, easily make an activatable "Ring of Plasma".
82  * Note that it always takes a turn to activate an artifact, even if
83  * the user hits "escape" at the "direction" prompt.
84  * </pre>
85  */
86 void do_cmd_activate_aux(int item)
87 {
88         int         dir, lev, chance, fail;
89         object_type *o_ptr;
90         bool success;
91
92
93         /* Get the item (in the pack) */
94         if (item >= 0)
95         {
96                 o_ptr = &inventory[item];
97         }
98
99         /* Get the item (on the floor) */
100         else
101         {
102                 o_ptr = &o_list[0 - item];
103         }
104
105         /* Take a turn */
106         p_ptr->energy_use = 100;
107
108         /* Extract the item level */
109         lev = k_info[o_ptr->k_idx].level;
110
111         /* Hack -- use artifact level instead */
112         if (object_is_fixed_artifact(o_ptr)) lev = a_info[o_ptr->name1].level;
113         else if (object_is_random_artifact(o_ptr))
114         {
115                 const activation_type* const act_ptr = find_activation_info(o_ptr);
116                 if (act_ptr) {
117                         lev = act_ptr->level;
118                 }
119         }
120         else if (((o_ptr->tval == TV_RING) || (o_ptr->tval == TV_AMULET)) && o_ptr->name2) lev = e_info[o_ptr->name2].level;
121
122         /* Base chance of success */
123         chance = p_ptr->skill_dev;
124
125         /* Confusion hurts skill */
126         if (p_ptr->confused) chance = chance / 2;
127
128         fail = lev+5;
129         if (chance > fail) fail -= (chance - fail)*2;
130         else chance -= (fail - chance)*2;
131         if (fail < USE_DEVICE) fail = USE_DEVICE;
132         if (chance < USE_DEVICE) chance = USE_DEVICE;
133
134         if (world_player)
135         {
136                 if (flush_failure) flush();
137                 msg_print(_("止まった時の中ではうまく働かないようだ。", "It shows no reaction."));
138                 sound(SOUND_FAIL);
139                 return;
140         }
141
142         if (p_ptr->pclass == CLASS_BERSERKER) success = FALSE;
143         else if (chance > fail)
144         {
145                 if (randint0(chance*2) < fail) success = FALSE;
146                 else success = TRUE;
147         }
148         else
149         {
150                 if (randint0(fail*2) < chance) success = TRUE;
151                 else success = FALSE;
152         }
153
154         /* Roll for usage */
155         if (!success)
156         {
157                 if (flush_failure) flush();
158                 msg_print(_("うまく始動させることができなかった。", "You failed to activate it properly."));
159                 sound(SOUND_FAIL);
160                 return;
161         }
162
163         /* Check the recharge */
164         if (o_ptr->timeout)
165         {
166                 msg_print(_("それは微かに音を立て、輝き、消えた...", "It whines, glows and fades..."));
167                 return;
168         }
169
170         /* Some lights need enough fuel for activation */
171         if (!o_ptr->xtra4 && (o_ptr->tval == TV_FLASK) &&
172                 ((o_ptr->sval == SV_LITE_TORCH) || (o_ptr->sval == SV_LITE_LANTERN)))
173         {
174                 msg_print(_("燃料がない。", "It has no fuel."));
175                 p_ptr->energy_use = 0;
176                 return;
177         }
178
179         /* Activate the artifact */
180         msg_print(_("始動させた...", "You activate it..."));
181
182         /* Sound */
183         sound(SOUND_ZAP);
184
185         /* Activate object */
186         if (activation_index(o_ptr))
187         {
188                 (void)activate_random_artifact(o_ptr);
189
190                 /* Window stuff */
191                 p_ptr->window |= (PW_INVEN | PW_EQUIP);
192
193                 /* Success */
194                 return;
195         }
196
197         /* Special items */
198         else if (o_ptr->tval == TV_WHISTLE)
199         {
200                 if (music_singing_any()) stop_singing();
201                 if (hex_spelling_any()) stop_hex_spell_all();
202
203 #if 0
204                 if (object_is_cursed(o_ptr))
205                 {
206                         msg_print(_("カン高い音が響き渡った。", "You produce a shrill whistling sound."));
207                         aggravate_monsters(0);
208                 }
209                 else
210 #endif
211                 {
212                         IDX pet_ctr, i;
213                         IDX *who;
214                         int max_pet = 0;
215                         u16b dummy_why;
216
217                         /* Allocate the "who" array */
218                         C_MAKE(who, max_m_idx, IDX);
219
220                         /* Process the monsters (backwards) */
221                         for (pet_ctr = m_max - 1; pet_ctr >= 1; pet_ctr--)
222                         {
223                                 if (is_pet(&m_list[pet_ctr]) && (p_ptr->riding != pet_ctr))
224                                   who[max_pet++] = pet_ctr;
225                         }
226
227                         /* Select the sort method */
228                         ang_sort_comp = ang_sort_comp_pet;
229                         ang_sort_swap = ang_sort_swap_hook;
230
231                         ang_sort(who, &dummy_why, max_pet);
232
233                         /* Process the monsters (backwards) */
234                         for (i = 0; i < max_pet; i++)
235                         {
236                                 pet_ctr = who[i];
237                                 teleport_monster_to(pet_ctr, p_ptr->y, p_ptr->x, 100, TELEPORT_PASSIVE);
238                         }
239
240                         /* Free the "who" array */
241                         C_KILL(who, max_m_idx, IDX);
242                 }
243                 o_ptr->timeout = 100+randint1(100);
244                 return;
245         }
246         else if (o_ptr->tval == TV_CAPTURE)
247         {
248                 if(!o_ptr->pval)
249                 {
250                         bool old_target_pet = target_pet;
251                         target_pet = TRUE;
252                         if (!get_aim_dir(&dir))
253                         {
254                                 target_pet = old_target_pet;
255                                 return;
256                         }
257                         target_pet = old_target_pet;
258
259                         if(fire_ball(GF_CAPTURE, dir, 0, 0))
260                         {
261                                 o_ptr->pval = (PARAMETER_VALUE)cap_mon;
262                                 o_ptr->xtra3 = (XTRA8)cap_mspeed;
263                                 o_ptr->xtra4 = (XTRA16)cap_hp;
264                                 o_ptr->xtra5 = (XTRA16)cap_maxhp;
265                                 if (cap_nickname)
266                                 {
267                                         cptr t;
268                                         char *s;
269                                         char buf[80] = "";
270
271                                         if (o_ptr->inscription)
272                                                 strcpy(buf, quark_str(o_ptr->inscription));
273                                         s = buf;
274                                         for (s = buf;*s && (*s != '#'); s++)
275                                         {
276 #ifdef JP
277                                                 if (iskanji(*s)) s++;
278 #endif
279                                         }
280                                         *s = '#';
281                                         s++;
282 #ifdef JP
283  /*nothing*/
284 #else
285                                         *s++ = '\'';
286 #endif
287                                         t = quark_str(cap_nickname);
288                                         while (*t)
289                                         {
290                                                 *s = *t;
291                                                 s++;
292                                                 t++;
293                                         }
294 #ifdef JP
295  /*nothing*/
296 #else
297                                         *s++ = '\'';
298 #endif
299                                         *s = '\0';
300                                         o_ptr->inscription = quark_add(buf);
301                                 }
302                         }
303                 }
304                 else
305                 {
306                         success = FALSE;
307                         if (!get_rep_dir2(&dir)) return;
308                         if (monster_can_enter(p_ptr->y + ddy[dir], p_ptr->x + ddx[dir], &r_info[o_ptr->pval], 0))
309                         {
310                                 if (place_monster_aux(0, p_ptr->y + ddy[dir], p_ptr->x + ddx[dir], o_ptr->pval, (PM_FORCE_PET | PM_NO_KAGE)))
311                                 {
312                                         if (o_ptr->xtra3) m_list[hack_m_idx_ii].mspeed = o_ptr->xtra3;
313                                         if (o_ptr->xtra5) m_list[hack_m_idx_ii].max_maxhp = o_ptr->xtra5;
314                                         if (o_ptr->xtra4) m_list[hack_m_idx_ii].hp = o_ptr->xtra4;
315                                         m_list[hack_m_idx_ii].maxhp = m_list[hack_m_idx_ii].max_maxhp;
316                                         if (o_ptr->inscription)
317                                         {
318                                                 char buf[80];
319                                                 cptr t;
320 #ifndef JP
321                                                 bool quote = FALSE;
322 #endif
323
324                                                 t = quark_str(o_ptr->inscription);
325                                                 for (t = quark_str(o_ptr->inscription);*t && (*t != '#'); t++)
326                                                 {
327 #ifdef JP
328                                                         if (iskanji(*t)) t++;
329 #endif
330                                                 }
331                                                 if (*t)
332                                                 {
333                                                         char *s = buf;
334                                                         t++;
335 #ifdef JP
336                                                         /* nothing */
337 #else
338                                                         if (*t =='\'')
339                                                         {
340                                                                 t++;
341                                                                 quote = TRUE;
342                                                         }
343 #endif
344                                                         while(*t)
345                                                         {
346                                                                 *s = *t;
347                                                                 t++;
348                                                                 s++;
349                                                         }
350 #ifdef JP
351                                                         /* nothing */
352 #else
353                                                         if (quote && *(s-1) =='\'')
354                                                                 s--;
355 #endif
356                                                         *s = '\0';
357                                                         m_list[hack_m_idx_ii].nickname = quark_add(buf);
358                                                         t = quark_str(o_ptr->inscription);
359                                                         s = buf;
360                                                         while(*t && (*t != '#'))
361                                                         {
362                                                                 *s = *t;
363                                                                 t++;
364                                                                 s++;
365                                                         }
366                                                         *s = '\0';
367                                                         o_ptr->inscription = quark_add(buf);
368                                                 }
369                                         }
370                                         o_ptr->pval = 0;
371                                         o_ptr->xtra3 = 0;
372                                         o_ptr->xtra4 = 0;
373                                         o_ptr->xtra5 = 0;
374                                         success = TRUE;
375                                 }
376                         }
377                         if (!success)
378                                 msg_print(_("おっと、解放に失敗した。", "Oops.  You failed to release your pet."));
379                 }
380                 calc_android_exp();
381                 return;
382         }
383
384         /* Mistake */
385         msg_print(_("おっと、このアイテムは始動できない。", "Oops.  That object cannot be activated."));
386 }
387
388 /*!
389  * @brief 装備を発動するコマンドのメインルーチン /
390  * @return なし
391  */
392 void do_cmd_activate(void)
393 {
394         OBJECT_IDX item;
395         cptr    q, s;
396
397
398         if (p_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN))
399         {
400                 set_action(ACTION_NONE);
401         }
402
403         item_tester_no_ryoute = TRUE;
404         /* Prepare the hook */
405         item_tester_hook = item_tester_hook_activate;
406
407         /* Get an item */
408         q = _("どのアイテムを始動させますか? ", "Activate which item? ");
409         s = _("始動できるアイテムを装備していない。", "You have nothing to activate.");
410
411         if (!get_item(&item, q, s, (USE_EQUIP))) return;
412
413         /* Activate the item */
414         do_cmd_activate_aux(item);
415 }
416
417
418