OSDN Git Service

snipe_concentrate および reset_concentration 関数で PU_BONUS フラグを立てていなかったため、集中が途切れた後も一時テレパシ...
[hengband/hengband.git] / src / snipe.c
1 #include "angband.h"
2
3 #define MAX_SNIPE_POWERS 16
4
5 typedef struct snipe_power snipe_power;
6 struct snipe_power
7 {
8         int     min_lev;
9         int     mana_cost;
10         const char *name;
11 };
12
13 static const char *snipe_tips[MAX_SNIPE_POWERS] =
14 {
15 #ifdef JP
16         "Àº¿À¤ò½¸Ã椹¤ë¡£¼Í·â¤Î°ÒÎÏ¡¢ÀºÅÙ¤¬¾å¤¬¤ê¡¢¹âÅ٤ʼͷâ½Ñ¤¬»ÈÍѤǤ­¤ë¤è¤¦¤Ë¤Ê¤ë¡£",
17         "¸÷¤ëÌð¤òÊü¤Ä¡£¸÷¤Ë¼å¤¤¥â¥ó¥¹¥¿¡¼¤Ë°ÒÎϤòȯ´ø¤¹¤ë¡£",
18         "¼Í·â¤ò¹Ô¤Ã¤¿¸å¡¢Ã»µ÷Î¥¤Î½Ö´Ö°ÜÆ°¤ò¹Ô¤¦¡£",
19         "µ°Æ»¾å¤Î櫤ò¤¹¤Ù¤Æ̵¸ú¤Ë¤¹¤ëÄã¶õÈô¹Ô¤ÎÌð¤òÊü¤Ä¡£",
20         "²Ð±ê°À­¤ÎÌð¤òÊü¤Ä¡£",
21         "ÊɤòÊ´ºÕ¤¹¤ëÌð¤òÊü¤Ä¡£´ä¤Ç¤Ç¤­¤¿¥â¥ó¥¹¥¿¡¼¤È̵À¸Êª¤Î¥â¥ó¥¹¥¿¡¼¤Ë°ÒÎϤòȯ´ø¤¹¤ë¡£",
22         "Î䵤°À­¤ÎÌð¤òÊü¤Ä¡£",
23         "Ũ¤òÆͤ­Èô¤Ð¤¹Ìð¤òÊü¤Ä¡£",
24         "Ê£¿ô¤ÎŨ¤ò´ÓÄ̤¹¤ëÌð¤òÊü¤Ä¡£",
25         "Á±Îɤʥâ¥ó¥¹¥¿¡¼¤Ë°ÒÎϤòȯ´ø¤¹¤ëÌð¤òÊü¤Ä¡£",
26         "¼Ù°­¤Ê¥â¥ó¥¹¥¿¡¼¤Ë°ÒÎϤòȯ´ø¤¹¤ëÌð¤òÊü¤Ä¡£",
27         "Åö¤¿¤ë¤ÈÇúȯ¤¹¤ëÌð¤òÊü¤Ä¡£",
28         "2²ó¼Í·â¤ò¹Ô¤¦¡£",
29         "ÅÅ·â°À­¤ÎÌð¤òÊü¤Ä¡£",
30         "Ũ¤ÎµÞ½ê¤Ë¤á¤¬¤±¤ÆÌð¤òÊü¤Ä¡£À®¸ù¤¹¤ë¤ÈŨ¤ò°ì·â»à¤µ¤»¤ë¡£¼ºÇÔ¤¹¤ë¤È1¥À¥á¡¼¥¸¡£",
31         "Á´¤Æ¤Î¥â¥ó¥¹¥¿¡¼¤Ë¹â°ÒÎϤòȯ´ø¤¹¤ëÌð¤òÊü¤Ä¡£È¿Æ°¤Ë¤è¤ëÉû¼¡¸ú²Ì¤ò¼õ¤±¤ë¡£",
32 #else
33         "Concentrate your mind fot shooting.",
34         "Shot an allow with brightness.",
35         "Blink after shooting.",
36         "Shot an allow able to shatter traps.",
37         "Deals extra damege of fire.",
38         "Shot an allow able to shatter rocks.",
39         "Deals extra damege of ice.",
40         "An allow rushes away a target.",
41         "An allow pierces some monsters.",
42         "Deals more damage to good monsters.",
43         "Deals more damage to evil monsters.",
44         "An allow explodes when it hits a monster.",
45         "Shot allows twice.",
46         "Deals extra damege of lightning.",
47         "Deals quick death or 1 damage.",
48         "Deals great damage to all monsters, and some side effects to you.",
49 #endif
50 };
51
52 snipe_power snipe_powers[MAX_SNIPE_POWERS] =
53 {
54         /* Level gained,  cost,  name */
55 #ifdef JP
56         {  1,  0,  "Àº¿À½¸Ãæ" },
57         {  2,  1,  "¥Õ¥é¥Ã¥·¥å¥¢¥í¡¼" },
58         {  3,  1,  "¥·¥å¡¼¥È¡õ¥¢¥¦¥§¥¤" },
59         {  5,  1,  "²ò½ü¤ÎÌð" },
60         {  8,  2,  "²Ð±ê¤ÎÌð" },
61         { 10,  2,  "´äºÕ¤­" },
62         { 13,  2,  "Î䵤¤ÎÌð" },
63         { 18,  2,  "ÎõÉ÷ÃÆ"},
64         { 22,  3,  "´ÓÄÌÃÆ" },
65         { 25,  4,  "¼ÙÇ°ÃÆ"},
66         { 26,  4,  "ÇËËâÌð" },
67         { 30,  3,  "Çúȯ¤ÎÌð"},
68         { 32,  4,  "¥À¥Ö¥ë¥·¥ç¥Ã¥È" },
69         { 36,  3,  "¥×¥é¥º¥Þ¥Ü¥ë¥È" },
70         { 40,  3,  "¥Ë¡¼¥É¥ë¥·¥ç¥Ã¥È" },
71         { 48,  7,  "¥»¥¤¥ó¥È¥¹¥¿¡¼¥¢¥í¡¼" },
72 #else
73         {  1,  0,  "Concentration" },
74         {  2,  1,  "Flush Arrow" },
75         {  3,  1,  "Shoot & Away" },
76         {  5,  1,  "Disarm Shot" },
77         {  8,  2,  "Fire Shot" },
78         { 10,  2,  "Shatter Arrow" },
79         { 13,  2,  "Ice Shot" },
80         { 18,  2,  "Rushing Arrow"},
81         { 22,  3,  "Piercing Shot" },
82         { 25,  4,  "Evil Shot"},
83         { 26,  4,  "Holy Shot" },
84         { 30,  3,  "Missile"},
85         { 32,  4,  "Double Shot" },
86         { 36,  3,  "Plasma Bolt" },
87         { 40,  3,  "Needle Shot" },
88         { 48,  7,  "Saint Stars Arrow" },
89 #endif
90 };
91
92
93 static bool snipe_concentrate(void)
94 {
95         if ((int)p_ptr->concent < (2 + (p_ptr->lev + 5) / 10)) p_ptr->concent++;
96
97 #ifdef JP
98         msg_format("½¸Ã椷¤¿¡£(½¸ÃæÅÙ %d)", p_ptr->concent);
99 #else
100         msg_format("You concentrate deeply. (lvl %d)", p_ptr->concent);
101 #endif
102
103         reset_concent = FALSE;
104
105         /* Recalculate bonuses */
106         p_ptr->update |= (PU_BONUS);
107
108         p_ptr->redraw |= (PR_STATUS);
109
110         /* Update the monsters */
111         p_ptr->update |= (PU_MONSTERS);
112
113         return (TRUE);
114 }
115
116 void reset_concentration(bool msg)
117 {
118         if (msg)
119         {
120 #ifdef JP
121                 msg_print("½¸ÃæÎϤ¬ÅÓÀÚ¤ì¤Æ¤·¤Þ¤Ã¤¿¡£");
122 #else
123                 msg_print("Stop concentrating.");
124 #endif
125         }
126
127         p_ptr->concent = 0;
128         reset_concent = FALSE;
129
130         /* Recalculate bonuses */
131         p_ptr->update |= (PU_BONUS);
132
133         p_ptr->redraw |= (PR_STATUS);
134
135         /* Update the monsters */
136         p_ptr->update |= (PU_MONSTERS);
137 }
138
139 int boost_concentration_damage(int tdam)
140 {
141         tdam *= (10 + p_ptr->concent);
142         tdam /= 10;
143
144         return (tdam);
145 }
146
147 void display_snipe_list(void)
148 {
149         int             i;
150         int             y = 1;
151         int             x = 1;
152         int             plev = p_ptr->lev;
153         snipe_power     spell;
154         char            psi_desc[80];
155
156         /* Display a list of spells */
157         prt("", y, x);
158 #ifdef JP
159         put_str("̾Á°", y, x + 5);
160         put_str("Lv   MP", y, x + 35);
161 #else
162         put_str("Name", y, x + 5);
163         put_str("Lv Mana", y, x + 35);
164 #endif
165
166         /* Dump the spells */
167         for (i = 0; i < MAX_SNIPE_POWERS; i++)
168         {
169                 /* Access the available spell */
170                 spell = snipe_powers[i];
171                 if (spell.min_lev > plev) continue;
172                 if (spell.mana_cost > (int)p_ptr->concent) continue;
173
174                 /* Dump the spell */
175                 sprintf(psi_desc, "  %c) %-30s%2d %4d",
176                         I2A(i), spell.name, spell.min_lev, spell.mana_cost);
177
178                 Term_putstr(x, y + i + 1, -1, TERM_WHITE, psi_desc);
179         }
180         return;
181 }
182
183
184 /*
185  * Allow user to choose a mindcrafter power.
186  *
187  * If a valid spell is chosen, saves it in '*sn' and returns TRUE
188  * If the user hits escape, returns FALSE, and set '*sn' to -1
189  * If there are no legal choices, returns FALSE, and sets '*sn' to -2
190  *
191  * The "prompt" should be "cast", "recite", or "study"
192  * The "known" should be TRUE for cast/pray, FALSE for study
193  *
194  * nb: This function has a (trivial) display bug which will be obvious
195  * when you run it. It's probably easy to fix but I haven't tried,
196  * sorry.
197  */
198 static int get_snipe_power(int *sn, bool only_browse)
199 {
200         int             i;
201         int             num = 0;
202         int             y = 1;
203         int             x = 20;
204         int             plev = p_ptr->lev;
205         int             ask;
206         char            choice;
207         char            out_val[160];
208 #ifdef JP
209         cptr            p = "¼Í·â½Ñ";
210 #else
211         cptr            p = "power";
212 #endif
213         snipe_power     spell;
214         bool            flag, redraw;
215
216 #ifdef ALLOW_REPEAT /* TNB */
217
218         repeat_push(*sn);
219
220         /* Assume cancelled */
221         *sn = (-1);
222
223         /* Repeat previous command */
224         /* Get the spell, if available */
225         if (repeat_pull(sn))
226         {
227                 /* Verify the spell */
228                 if ((snipe_powers[*sn].min_lev <= plev) && (snipe_powers[*sn].mana_cost <= (int)p_ptr->concent))
229                 {
230                         /* Success */
231                         return (TRUE);
232                 }
233         }
234
235 #endif /* ALLOW_REPEAT -- TNB */
236
237         /* Nothing chosen yet */
238         flag = FALSE;
239
240         /* No redraw yet */
241         redraw = FALSE;
242
243         for (i = 0; i < MAX_SNIPE_POWERS; i++)
244         {
245                 if ((snipe_powers[i].min_lev <= plev) &&
246                         ((only_browse) || (snipe_powers[i].mana_cost <= (int)p_ptr->concent)))
247                 {
248                         num = i;
249                 }
250         }
251
252         /* Build a prompt (accept all spells) */
253         if (only_browse)
254         {
255 #ifdef JP
256                 (void)strnfmt(out_val, 78, "(%^s %c-%c, '*'¤Ç°ìÍ÷, ESC) ¤É¤Î%s¤Ë¤Ä¤¤¤ÆÃΤê¤Þ¤¹¤«¡©",
257 #else
258                 (void)strnfmt(out_val, 78, "(%^ss %c-%c, *=List, ESC=exit) Use which %s? ",
259 #endif
260                               p, I2A(0), I2A(num), p);
261         }
262         else
263         {
264 #ifdef JP
265                 (void)strnfmt(out_val, 78, "(%^s %c-%c, '*'¤Ç°ìÍ÷, ESC) ¤É¤Î%s¤ò»È¤¤¤Þ¤¹¤«¡©",
266 #else
267                 (void)strnfmt(out_val, 78, "(%^ss %c-%c, *=List, ESC=exit) Use which %s? ",
268 #endif
269                           p, I2A(0), I2A(num), p);
270         }
271
272         /* Get a spell from the user */
273         choice = always_show_list ? ESCAPE : 1;
274         while (!flag)
275         {
276                 if(choice == ESCAPE) choice = ' ';
277                 else if( !get_com(out_val, &choice, FALSE) )break; 
278
279                 /* Request redraw */
280                 if ((choice == ' ') || (choice == '*') || (choice == '?'))
281                 {
282                         /* Show the list */
283                         if (!redraw)
284                         {
285                                 char psi_desc[80];
286
287                                 /* Show list */
288                                 redraw = TRUE;
289
290                                 /* Save the screen */
291                                 if (!only_browse) screen_save();
292
293                                 /* Display a list of spells */
294                                 prt("", y, x);
295 #ifdef JP
296                                 put_str("̾Á°", y, x + 5);
297                                 if (only_browse) put_str("Lv   ½¸ÃæÅÙ", y, x + 35);
298 #else
299                                 put_str("Name", y, x + 5);
300                                 if (only_browse) put_str("Lv Pow", y, x + 35);
301 #endif
302
303                                 /* Dump the spells */
304                                 for (i = 0; i < MAX_SNIPE_POWERS; i++)
305                                 {
306                                         Term_erase(x, y + i + 1, 255);
307
308                                         /* Access the spell */
309                                         spell = snipe_powers[i];
310                                         if (spell.min_lev > plev) continue;
311                                         if (!only_browse && (spell.mana_cost > (int)p_ptr->concent)) continue;
312
313                                         /* Dump the spell --(-- */
314                                         if (only_browse)
315                                                 sprintf(psi_desc, "  %c) %-30s%2d %4d",
316                                                         I2A(i), spell.name,     spell.min_lev, spell.mana_cost);
317                                         else
318                                                 sprintf(psi_desc, "  %c) %-30s", I2A(i), spell.name);
319                                         prt(psi_desc, y + i + 1, x);
320                                 }
321
322                                 /* Clear the bottom line */
323                                 prt("", y + i + 1, x);
324                         }
325
326                         /* Hide the list */
327                         else
328                         {
329                                 /* Hide list */
330                                 redraw = FALSE;
331
332                                 /* Restore the screen */
333                                 if (!only_browse) screen_load();
334                         }
335
336                         /* Redo asking */
337                         continue;
338                 }
339
340                 /* Note verify */
341                 ask = isupper(choice);
342
343                 /* Lowercase */
344                 if (ask) choice = tolower(choice);
345
346                 /* Extract request */
347                 i = (islower(choice) ? A2I(choice) : -1);
348
349                 /* Totally Illegal */
350                 if ((i < 0) || (i > num) || 
351                         (!only_browse &&(snipe_powers[i].mana_cost > (int)p_ptr->concent)))
352                 {
353                         bell();
354                         continue;
355                 }
356
357                 /* Save the spell index */
358                 spell = snipe_powers[i];
359
360                 /* Verify it */
361                 if (ask)
362                 {
363                         char tmp_val[160];
364
365                         /* Prompt */
366 #ifdef JP
367                         (void) strnfmt(tmp_val, 78, "%s¤ò»È¤¤¤Þ¤¹¤«¡©", snipe_powers[i].name);
368 #else
369                         (void)strnfmt(tmp_val, 78, "Use %s? ", snipe_powers[i].name);
370 #endif
371
372                         /* Belay that order */
373                         if (!get_check(tmp_val)) continue;
374                 }
375
376                 /* Stop the loop */
377                 flag = TRUE;
378         }
379
380         /* Restore the screen */
381         if (redraw && !only_browse) screen_load();
382
383         /* Show choices */
384         p_ptr->window |= (PW_SPELL);
385
386         /* Window stuff */
387         window_stuff();
388
389         /* Abort if needed */
390         if (!flag) return (FALSE);
391
392         /* Save the choice */
393         (*sn) = i;
394
395 #ifdef ALLOW_REPEAT /* TNB */
396
397         repeat_push(*sn);
398
399 #endif /* ALLOW_REPEAT -- TNB */
400
401         /* Success */
402         return (TRUE);
403 }
404
405
406 int tot_dam_aux_snipe (int mult, monster_type *m_ptr)
407 {
408         monster_race *r_ptr = &r_info[m_ptr->r_idx];
409         bool seen = is_seen(m_ptr);
410
411         switch (snipe_type)
412         {
413         case SP_LITE:
414                 if (r_ptr->flags3 & (RF3_HURT_LITE))
415                 {
416                         int n = 20 + p_ptr->concent;
417                         if (seen) r_ptr->r_flags3 |= (RF3_HURT_LITE);
418                         if (mult < n) mult = n;
419                 }
420                 break;
421         case SP_FIRE:
422                 if (r_ptr->flagsr & RFR_IM_FIRE)
423                 {
424                         if (seen) r_ptr->r_flagsr |= RFR_IM_FIRE;
425                 }
426                 else
427                 {
428                         int n = 15 + (p_ptr->concent * 3);
429                         if (mult < n) mult = n;
430                 }
431                 break;
432         case SP_COLD:
433                 if (r_ptr->flagsr & RFR_IM_COLD)
434                 {
435                         if (seen) r_ptr->r_flagsr |= RFR_IM_COLD;
436                 }
437                 else
438                 {
439                         int n = 15 + (p_ptr->concent * 3);
440                         if (mult < n) mult = n;
441                 }
442                 break;
443         case SP_ELEC:
444                 if (r_ptr->flagsr & RFR_IM_ELEC)
445                 {
446                         if (seen) r_ptr->r_flagsr |= RFR_IM_ELEC;
447                 }
448                 else
449                 {
450                         int n = 18 + (p_ptr->concent * 4);
451                         if (mult < n) mult = n;
452                 }
453                 break;
454         case SP_KILL_WALL:
455                 if (r_ptr->flags3 & RF3_HURT_ROCK)
456                 {
457                         int n = 15 + (p_ptr->concent * 2);
458                         if (seen) r_ptr->r_flags3 |= RF3_HURT_ROCK;
459                         if (mult < n) mult = n;
460                 }
461                 else if (r_ptr->flags3 & RF3_NONLIVING)
462                 {
463                         int n = 15 + (p_ptr->concent * 2);
464                         if (seen) r_ptr->r_flags3 |= RF3_NONLIVING;
465                         if (mult < n) mult = n;
466                 }
467                 break;
468         case SP_EVILNESS:
469                 if (r_ptr->flags3 & RF3_GOOD)
470                 {
471                         int n = 15 + (p_ptr->concent * 4);
472                         if (seen) r_ptr->r_flags3 |= RF3_GOOD;
473                         if (mult < n) mult = n;
474                 }
475                 break;
476         case SP_HOLYNESS:
477                 if (r_ptr->flags3 & RF3_EVIL)
478                 {
479                         int n = 12 + (p_ptr->concent * 3);
480                         if (seen) r_ptr->r_flags3 |= RF3_EVIL;
481                         if (r_ptr->flags3 & (RF3_HURT_LITE))
482                         {
483                                 n += (p_ptr->concent * 3);
484                                 if (seen) r_ptr->r_flags3 |= (RF3_HURT_LITE);
485                         }
486                         if (mult < n) mult = n;
487                 }
488                 break;
489         case SP_FINAL:
490                 if (mult < 50) mult = 50;
491                 break;
492         }
493
494         return (mult);
495 }
496
497 /*
498  * do_cmd_cast calls this function if the player's class
499  * is 'mindcrafter'.
500  */
501 static bool cast_sniper_spell(int spell)
502 {
503         bool flag = FALSE;
504         object_type *o_ptr = &inventory[INVEN_BOW];
505
506         if (o_ptr->tval != TV_BOW)
507         {
508 #ifdef JP
509                 msg_print("µÝ¤òÁõÈ÷¤·¤Æ¤¤¤Ê¤¤¡ª");
510 #else
511                 msg_print("You wield no bow!");
512 #endif
513                 return (FALSE);
514         }
515
516         /* spell code */
517         switch (spell)
518         {
519         case 0: /* Concentration */
520                 if (!snipe_concentrate()) return (FALSE);
521                 energy_use = 100;
522                 return (TRUE);
523         case 1: snipe_type = SP_LITE; break;
524         case 2: snipe_type = SP_AWAY; break;
525         case 3: snipe_type = SP_KILL_TRAP; break;
526         case 4: snipe_type = SP_FIRE; break;
527         case 5: snipe_type = SP_KILL_WALL; break;
528         case 6: snipe_type = SP_COLD; break;
529         case 7: snipe_type = SP_RUSH; break;
530         case 8: snipe_type = SP_PIERCE; break;
531         case 9: snipe_type = SP_EVILNESS; break;
532         case 10: snipe_type = SP_HOLYNESS; break;
533         case 11: snipe_type = SP_EXPLODE; break;
534         case 12: snipe_type = SP_DOUBLE; break;
535         case 13: snipe_type = SP_ELEC; break;
536         case 14: snipe_type = SP_NEEDLE; break;
537         case 15: snipe_type = SP_FINAL; break;
538         default:
539 #ifdef JP
540                 msg_print("¤Ê¤Ë¡©");
541 #else
542                 msg_print("Zap?");
543 #endif
544         }
545
546         command_cmd = 'f';
547         do_cmd_fire();
548         snipe_type = 0;
549
550         return (is_fired);
551 }
552
553
554 /*
555  * do_cmd_cast calls this function if the player's class
556  * is 'mindcrafter'.
557  */
558 void do_cmd_snipe(void)
559 {
560         int             n = 0;
561         int             plev = p_ptr->lev;
562         int             old_chp = p_ptr->chp;
563         snipe_power     spell;
564         bool            cast;
565
566
567         /* not if confused */
568         if (p_ptr->confused)
569         {
570 #ifdef JP
571                 msg_print("º®Í𤷤Ƥ¤¤Æ½¸Ãæ¤Ç¤­¤Ê¤¤¡ª");
572 #else
573                 msg_print("You are too confused!");
574 #endif
575                 return;
576         }
577
578         /* not if hullucinated */
579         if (p_ptr->image)
580         {
581 #ifdef JP
582                 msg_print("¸¸³Ð¤¬¸«¤¨¤Æ½¸Ãæ¤Ç¤­¤Ê¤¤¡ª");
583 #else
584                 msg_print("You are too hallucinated!");
585 #endif
586                 return;
587         }
588
589         /* not if stuned */
590         if (p_ptr->stun)
591         {
592 #ifdef JP
593                 msg_print("Ƭ¤¬Û¯Û°¤È¤·¤Æ¤¤¤Æ½¸Ãæ¤Ç¤­¤Ê¤¤¡ª");
594 #else
595                 msg_print("You are too stuned!");
596 #endif
597                 return;
598         }
599
600         /* get power */
601         if (!get_snipe_power(&n, FALSE)) return;
602
603         spell = snipe_powers[n];
604
605         sound(SOUND_SHOOT);
606
607         /* Cast the spell */
608         cast = cast_sniper_spell(n);
609
610         if (!cast) return;
611 #if 0
612         /* Take a turn */
613         energy_use = 100;
614 #endif
615         /* Redraw mana */
616         p_ptr->redraw |= (PR_HP | PR_MANA);
617
618         /* Window stuff */
619         p_ptr->window |= (PW_PLAYER);
620         p_ptr->window |= (PW_SPELL);
621 }
622
623 /*
624  * do_cmd_cast calls this function if the player's class
625  * is 'mindcrafter'.
626  */
627 void do_cmd_snipe_browse(void)
628 {
629         int n = 0;
630         int j, line;
631         char temp[62 * 4];
632
633         screen_save();
634
635         while(1)
636         {
637                 /* get power */
638                 if (!get_snipe_power(&n, TRUE))
639                 {
640                         screen_load();
641                         return;
642                 }
643
644                 /* Clear lines, position cursor  (really should use strlen here) */
645                 Term_erase(12, 22, 255);
646                 Term_erase(12, 21, 255);
647                 Term_erase(12, 20, 255);
648                 Term_erase(12, 19, 255);
649                 Term_erase(12, 18, 255);
650
651                 roff_to_buf(snipe_tips[n], 62, temp, sizeof(temp));
652                 for(j = 0, line = 19; temp[j]; j += (1 + strlen(&temp[j])))
653                 {
654                         prt(&temp[j], line, 15);
655                         line++;
656                 }
657         }
658 }