OSDN Git Service

v3.0.0 Alpha5 OSDN最終版
[hengband/hengband.git] / src / spells-object.c
1 
2 #include "angband.h"
3 #include "spells-object.h"
4 #include "object-hook.h"
5 #include "player-status.h"
6
7
8 typedef struct
9 {
10         OBJECT_TYPE_VALUE tval;
11         OBJECT_SUBTYPE_VALUE sval;
12         PERCENTAGE prob;
13         byte flag;
14 } amuse_type;
15
16 /*
17  * Scatter some "amusing" objects near the player
18  */
19
20 #define AMS_NOTHING   0x00 /* No restriction */
21 #define AMS_NO_UNIQUE 0x01 /* Don't make the amusing object of uniques */
22 #define AMS_FIXED_ART 0x02 /* Make a fixed artifact based on the amusing object */
23 #define AMS_MULTIPLE  0x04 /* Drop 1-3 objects for one type */
24 #define AMS_PILE      0x08 /* Drop 1-99 pile objects for one type */
25
26 static amuse_type amuse_info[] =
27 {
28         { TV_BOTTLE, SV_ANY, 5, AMS_NOTHING },
29         { TV_JUNK, SV_ANY, 3, AMS_MULTIPLE },
30         { TV_SPIKE, SV_ANY, 10, AMS_PILE },
31         { TV_STATUE, SV_ANY, 15, AMS_NOTHING },
32         { TV_CORPSE, SV_ANY, 15, AMS_NO_UNIQUE },
33         { TV_SKELETON, SV_ANY, 10, AMS_NO_UNIQUE },
34         { TV_FIGURINE, SV_ANY, 10, AMS_NO_UNIQUE },
35         { TV_PARCHMENT, SV_ANY, 1, AMS_NOTHING },
36         { TV_POLEARM, SV_TSURIZAO, 3, AMS_NOTHING }, //Fishing Pole of Taikobo
37         { TV_SWORD, SV_BROKEN_DAGGER, 3, AMS_FIXED_ART }, //Broken Dagger of Magician
38         { TV_SWORD, SV_BROKEN_DAGGER, 10, AMS_NOTHING },
39         { TV_SWORD, SV_BROKEN_SWORD, 5, AMS_NOTHING },
40         { TV_SCROLL, SV_SCROLL_AMUSEMENT, 10, AMS_NOTHING },
41
42         { 0, 0, 0 }
43 };
44
45 /*!
46  * @brief「弾/矢の製造」処理 / do_cmd_cast calls this function if the player's class is 'archer'.
47  * Hook to determine if an object is contertible in an arrow/bolt
48  * @return 製造を実際に行ったらTRUE、キャンセルしたらFALSEを返す
49  */
50 bool create_ammo(void)
51 {
52         int ext = 0;
53         char ch;
54
55         object_type     forge;
56         object_type *q_ptr;
57
58         char com[80];
59         GAME_TEXT o_name[MAX_NLEN];
60
61         q_ptr = &forge;
62
63         if (p_ptr->lev >= 20)
64                 sprintf(com, _("[S]弾, [A]矢, [B]クロスボウの矢 :", "Create [S]hots, Create [A]rrow or Create [B]olt ?"));
65         else if (p_ptr->lev >= 10)
66                 sprintf(com, _("[S]弾, [A]矢:", "Create [S]hots or Create [A]rrow ?"));
67         else
68                 sprintf(com, _("[S]弾:", "Create [S]hots ?"));
69
70         if (p_ptr->confused)
71         {
72                 msg_print(_("混乱してる!", "You are too confused!"));
73                 return FALSE;
74         }
75
76         if (p_ptr->blind)
77         {
78                 msg_print(_("目が見えない!", "You are blind!"));
79                 return FALSE;
80         }
81
82         while (TRUE)
83         {
84                 if (!get_com(com, &ch, TRUE))
85                 {
86                         return FALSE;
87                 }
88                 if (ch == 'S' || ch == 's')
89                 {
90                         ext = 1;
91                         break;
92                 }
93                 if ((ch == 'A' || ch == 'a') && (p_ptr->lev >= 10))
94                 {
95                         ext = 2;
96                         break;
97                 }
98                 if ((ch == 'B' || ch == 'b') && (p_ptr->lev >= 20))
99                 {
100                         ext = 3;
101                         break;
102                 }
103         }
104
105         /**********Create shots*********/
106         if (ext == 1)
107         {
108                 POSITION x, y;
109                 DIRECTION dir;
110                 cave_type *c_ptr;
111
112                 if (!get_rep_dir(&dir, FALSE)) return FALSE;
113                 y = p_ptr->y + ddy[dir];
114                 x = p_ptr->x + ddx[dir];
115                 c_ptr = &cave[y][x];
116
117                 if (!have_flag(f_info[get_feat_mimic(c_ptr)].flags, FF_CAN_DIG))
118                 {
119                         msg_print(_("そこには岩石がない。", "You need pile of rubble."));
120                         return FALSE;
121                 }
122                 else if (!cave_have_flag_grid(c_ptr, FF_CAN_DIG) || !cave_have_flag_grid(c_ptr, FF_HURT_ROCK))
123                 {
124                         msg_print(_("硬すぎて崩せなかった。", "You failed to make ammo."));
125                 }
126                 else
127                 {
128                         s16b slot;
129                         q_ptr = &forge;
130
131                         /* Hack -- Give the player some small firestones */
132                         object_prep(q_ptr, lookup_kind(TV_SHOT, (OBJECT_SUBTYPE_VALUE)m_bonus(1, p_ptr->lev) + 1));
133                         q_ptr->number = (byte)rand_range(15, 30);
134                         object_aware(q_ptr);
135                         object_known(q_ptr);
136                         apply_magic(q_ptr, p_ptr->lev, AM_NO_FIXED_ART);
137                         q_ptr->discount = 99;
138
139                         slot = inven_carry(q_ptr);
140
141                         object_desc(o_name, q_ptr, 0);
142                         msg_format(_("%sを作った。", "You make some ammo."), o_name);
143
144                         /* Auto-inscription */
145                         if (slot >= 0) autopick_alter_item(slot, FALSE);
146
147                         /* Destroy the wall */
148                         cave_alter_feat(y, x, FF_HURT_ROCK);
149
150                         p_ptr->update |= (PU_FLOW);
151                 }
152         }
153         /**********Create arrows*********/
154         else if (ext == 2)
155         {
156                 OBJECT_IDX item;
157                 concptr q, s;
158                 s16b slot;
159
160                 item_tester_hook = item_tester_hook_convertible;
161
162                 q = _("どのアイテムから作りますか? ", "Convert which item? ");
163                 s = _("材料を持っていない。", "You have no item to convert.");
164                 q_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR));
165                 if (!q_ptr) return FALSE;
166
167                 q_ptr = &forge;
168
169                 /* Hack -- Give the player some small firestones */
170                 object_prep(q_ptr, lookup_kind(TV_ARROW, (OBJECT_SUBTYPE_VALUE)m_bonus(1, p_ptr->lev) + 1));
171                 q_ptr->number = (byte)rand_range(5, 10);
172                 object_aware(q_ptr);
173                 object_known(q_ptr);
174                 apply_magic(q_ptr, p_ptr->lev, AM_NO_FIXED_ART);
175
176                 q_ptr->discount = 99;
177
178                 object_desc(o_name, q_ptr, 0);
179                 msg_format(_("%sを作った。", "You make some ammo."), o_name);
180
181                 if (item >= 0)
182                 {
183                         inven_item_increase(item, -1);
184                         inven_item_describe(item);
185                         inven_item_optimize(item);
186                 }
187                 else
188                 {
189                         floor_item_increase(0 - item, -1);
190                         floor_item_describe(0 - item);
191                         floor_item_optimize(0 - item);
192                 }
193
194                 slot = inven_carry(q_ptr);
195
196                 /* Auto-inscription */
197                 if (slot >= 0) autopick_alter_item(slot, FALSE);
198         }
199         /**********Create bolts*********/
200         else if (ext == 3)
201         {
202                 OBJECT_IDX item;
203                 concptr q, s;
204                 s16b slot;
205
206                 item_tester_hook = item_tester_hook_convertible;
207
208                 q = _("どのアイテムから作りますか? ", "Convert which item? ");
209                 s = _("材料を持っていない。", "You have no item to convert.");
210
211                 q_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR));
212                 if (!q_ptr) return FALSE;
213
214                 q_ptr = &forge;
215
216                 /* Hack -- Give the player some small firestones */
217                 object_prep(q_ptr, lookup_kind(TV_BOLT, (OBJECT_SUBTYPE_VALUE)m_bonus(1, p_ptr->lev) + 1));
218                 q_ptr->number = (byte)rand_range(4, 8);
219                 object_aware(q_ptr);
220                 object_known(q_ptr);
221                 apply_magic(q_ptr, p_ptr->lev, AM_NO_FIXED_ART);
222
223                 q_ptr->discount = 99;
224
225                 object_desc(o_name, q_ptr, 0);
226                 msg_format(_("%sを作った。", "You make some ammo."), o_name);
227
228                 if (item >= 0)
229                 {
230                         inven_item_increase(item, -1);
231                         inven_item_describe(item);
232                         inven_item_optimize(item);
233                 }
234                 else
235                 {
236                         floor_item_increase(0 - item, -1);
237                         floor_item_describe(0 - item);
238                         floor_item_optimize(0 - item);
239                 }
240
241                 slot = inven_carry(q_ptr);
242
243                 /* Auto-inscription */
244                 if (slot >= 0) autopick_alter_item(slot, FALSE);
245         }
246         return TRUE;
247 }
248
249 /*!
250  * @brief 魔道具術師の魔力取り込み処理
251  * @return 取り込みを実行したらTRUE、キャンセルしたらFALSEを返す
252  */
253 bool import_magic_device(void)
254 {
255         OBJECT_IDX item;
256         PARAMETER_VALUE pval;
257         int ext = 0;
258         concptr q, s;
259         object_type *o_ptr;
260         GAME_TEXT o_name[MAX_NLEN];
261
262         /* Only accept legal items */
263         item_tester_hook = item_tester_hook_recharge;
264
265         q = _("どのアイテムの魔力を取り込みますか? ", "Gain power of which item? ");
266         s = _("魔力を取り込めるアイテムがない。", "You have nothing to gain power.");
267
268         o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR));
269         if (!o_ptr) return (FALSE);
270
271         if (o_ptr->tval == TV_STAFF && o_ptr->sval == SV_STAFF_NOTHING)
272         {
273                 msg_print(_("この杖には発動の為の能力は何も備わっていないようだ。", "This staff doesn't have any magical ability."));
274                 return FALSE;
275         }
276
277         if (!object_is_known(o_ptr))
278         {
279                 msg_print(_("鑑定されていないと取り込めない。", "You need to identify before absorbing."));
280                 return FALSE;
281         }
282
283         if (o_ptr->timeout)
284         {
285                 msg_print(_("充填中のアイテムは取り込めない。", "This item is still charging."));
286                 return FALSE;
287         }
288
289         pval = o_ptr->pval;
290         if (o_ptr->tval == TV_ROD)
291                 ext = 72;
292         else if (o_ptr->tval == TV_WAND)
293                 ext = 36;
294
295         if (o_ptr->tval == TV_ROD)
296         {
297                 p_ptr->magic_num2[o_ptr->sval + ext] += (MAGIC_NUM2)o_ptr->number;
298                 if (p_ptr->magic_num2[o_ptr->sval + ext] > 99) p_ptr->magic_num2[o_ptr->sval + ext] = 99;
299         }
300         else
301         {
302                 int num;
303                 for (num = o_ptr->number; num; num--)
304                 {
305                         int gain_num = pval;
306                         if (o_ptr->tval == TV_WAND) gain_num = (pval + num - 1) / num;
307                         if (p_ptr->magic_num2[o_ptr->sval + ext])
308                         {
309                                 gain_num *= 256;
310                                 gain_num = (gain_num / 3 + randint0(gain_num / 3)) / 256;
311                                 if (gain_num < 1) gain_num = 1;
312                         }
313                         p_ptr->magic_num2[o_ptr->sval + ext] += (MAGIC_NUM2)gain_num;
314                         if (p_ptr->magic_num2[o_ptr->sval + ext] > 99) p_ptr->magic_num2[o_ptr->sval + ext] = 99;
315                         p_ptr->magic_num1[o_ptr->sval + ext] += pval * 0x10000;
316                         if (p_ptr->magic_num1[o_ptr->sval + ext] > 99 * 0x10000) p_ptr->magic_num1[o_ptr->sval + ext] = 99 * 0x10000;
317                         if (p_ptr->magic_num1[o_ptr->sval + ext] > p_ptr->magic_num2[o_ptr->sval + ext] * 0x10000) p_ptr->magic_num1[o_ptr->sval + ext] = p_ptr->magic_num2[o_ptr->sval + ext] * 0x10000;
318                         if (o_ptr->tval == TV_WAND) pval -= (pval + num - 1) / num;
319                 }
320         }
321
322         object_desc(o_name, o_ptr, 0);
323         msg_format(_("%sの魔力を取り込んだ。", "You absorb magic of %s."), o_name);
324
325         /* Eliminate the item (from the pack) */
326         if (item >= 0)
327         {
328                 inven_item_increase(item, -999);
329                 inven_item_describe(item);
330                 inven_item_optimize(item);
331         }
332
333         /* Eliminate the item (from the floor) */
334         else
335         {
336                 floor_item_increase(0 - item, -999);
337                 floor_item_describe(0 - item);
338                 floor_item_optimize(0 - item);
339         }
340         take_turn(p_ptr, 100);;
341         return TRUE;
342 }
343
344 /*!
345  * @brief 誰得ドロップを行う。
346  * @param y1 配置したいフロアのY座標
347  * @param x1 配置したいフロアのX座標
348  * @param num 誰得の処理回数
349  * @param known TRUEならばオブジェクトが必ず*鑑定*済になる
350  * @return なし
351  */
352 void amusement(POSITION y1, POSITION x1, int num, bool known)
353 {
354         object_type *i_ptr;
355         object_type object_type_body;
356         int n, t = 0;
357
358         for (n = 0; amuse_info[n].tval != 0; n++)
359         {
360                 t += amuse_info[n].prob;
361         }
362
363         /* Acquirement */
364         while (num)
365         {
366                 int i;
367                 KIND_OBJECT_IDX k_idx;
368                 ARTIFACT_IDX a_idx = 0;
369                 int r = randint0(t);
370                 bool insta_art, fixed_art;
371
372                 for (i = 0; ; i++)
373                 {
374                         r -= amuse_info[i].prob;
375                         if (r <= 0) break;
376                 }
377                 i_ptr = &object_type_body;
378                 object_wipe(i_ptr);
379                 k_idx = lookup_kind(amuse_info[i].tval, amuse_info[i].sval);
380
381                 /* Paranoia - reroll if nothing */
382                 if (!k_idx) continue;
383
384                 /* Search an artifact index if need */
385                 insta_art = (k_info[k_idx].gen_flags & TRG_INSTA_ART);
386                 fixed_art = (amuse_info[i].flag & AMS_FIXED_ART);
387
388                 if (insta_art || fixed_art)
389                 {
390                         for (a_idx = 1; a_idx < max_a_idx; a_idx++)
391                         {
392                                 if (insta_art && !(a_info[a_idx].gen_flags & TRG_INSTA_ART)) continue;
393                                 if (a_info[a_idx].tval != k_info[k_idx].tval) continue;
394                                 if (a_info[a_idx].sval != k_info[k_idx].sval) continue;
395                                 if (a_info[a_idx].cur_num > 0) continue;
396                                 break;
397                         }
398
399                         if (a_idx >= max_a_idx) continue;
400                 }
401
402                 /* Make an object (if possible) */
403                 object_prep(i_ptr, k_idx);
404                 if (a_idx) i_ptr->name1 = a_idx;
405                 apply_magic(i_ptr, 1, AM_NO_FIXED_ART);
406
407                 if (amuse_info[i].flag & AMS_NO_UNIQUE)
408                 {
409                         if (r_info[i_ptr->pval].flags1 & RF1_UNIQUE) continue;
410                 }
411
412                 if (amuse_info[i].flag & AMS_MULTIPLE) i_ptr->number = randint1(3);
413                 if (amuse_info[i].flag & AMS_PILE) i_ptr->number = randint1(99);
414
415                 if (known)
416                 {
417                         object_aware(i_ptr);
418                         object_known(i_ptr);
419                 }
420
421                 /* Paranoia - reroll if nothing */
422                 if (!(i_ptr->k_idx)) continue;
423
424                 /* Drop the object */
425                 (void)drop_near(i_ptr, -1, y1, x1);
426
427                 num--;
428         }
429 }
430
431
432
433 /*!
434  * @brief 獲得ドロップを行う。
435  * Scatter some "great" objects near the player
436  * @param y1 配置したいフロアのY座標
437  * @param x1 配置したいフロアのX座標
438  * @param num 獲得の処理回数
439  * @param great TRUEならば必ず高級品以上を落とす
440  * @param special TRUEならば必ず特別品を落とす
441  * @param known TRUEならばオブジェクトが必ず*鑑定*済になる
442  * @return なし
443  */
444 void acquirement(POSITION y1, POSITION x1, int num, bool great, bool special, bool known)
445 {
446         object_type *i_ptr;
447         object_type object_type_body;
448         BIT_FLAGS mode = AM_GOOD | (great || special ? AM_GREAT : 0L) | (special ? AM_SPECIAL : 0L);
449
450         /* Acquirement */
451         while (num--)
452         {
453                 i_ptr = &object_type_body;
454                 object_wipe(i_ptr);
455
456                 /* Make a good (or great) object (if possible) */
457                 if (!make_object(i_ptr, mode)) continue;
458
459                 if (known)
460                 {
461                         object_aware(i_ptr);
462                         object_known(i_ptr);
463                 }
464
465                 /* Drop the object */
466                 (void)drop_near(i_ptr, -1, y1, x1);
467         }
468 }