3 * @brief ¥¹¥Ê¥¤¥Ñ¡¼µ»Ç½¤Î¼ÂÁõ / Sniping
6 * 2014 Deskull rearranged comment for Doxygen.\n
11 #define MAX_SNIPE_POWERS 16
13 /*! ¥¹¥Ê¥¤¥Ñ¡¼µ»Ç½¾ðÊó¤Îtypedef */
14 typedef struct snipe_power snipe_power;
16 /*! ¥¹¥Ê¥¤¥Ñ¡¼µ»Ç½¾ðÊó¤Î¹½Â¤ÂÎ */
24 /*! ¥¹¥Ê¥¤¥Ñ¡¼µ»Ç½¤Î²òÀâ¥á¥Ã¥»¡¼¥¸ */
25 static const char *snipe_tips[MAX_SNIPE_POWERS] =
28 "Àº¿À¤ò½¸Ã椹¤ë¡£¼Í·â¤Î°ÒÎÏ¡¢ÀºÅÙ¤¬¾å¤¬¤ê¡¢¹âÅ٤ʼͷâ½Ñ¤¬»ÈÍѤǤ¤ë¤è¤¦¤Ë¤Ê¤ë¡£",
29 "¸÷¤ëÌð¤òÊü¤Ä¡£¸÷¤Ë¼å¤¤¥â¥ó¥¹¥¿¡¼¤Ë°ÒÎϤòȯ´ø¤¹¤ë¡£",
30 "¼Í·â¤ò¹Ô¤Ã¤¿¸å¡¢Ã»µ÷Î¥¤Î½Ö´Ö°ÜÆ°¤ò¹Ô¤¦¡£",
31 "µ°Æ»¾å¤Î櫤ò¤¹¤Ù¤Æ̵¸ú¤Ë¤¹¤ëÄã¶õÈô¹Ô¤ÎÌð¤òÊü¤Ä¡£",
32 "²Ð±ê°À¤ÎÌð¤òÊü¤Ä¡£",
33 "ÊɤòÊ´ºÕ¤¹¤ëÌð¤òÊü¤Ä¡£´ä¤Ç¤Ç¤¤¿¥â¥ó¥¹¥¿¡¼¤È̵À¸Êª¤Î¥â¥ó¥¹¥¿¡¼¤Ë°ÒÎϤòȯ´ø¤¹¤ë¡£",
34 "Î䵤°À¤ÎÌð¤òÊü¤Ä¡£",
35 "Ũ¤òÆͤÈô¤Ð¤¹Ìð¤òÊü¤Ä¡£",
36 "Ê£¿ô¤ÎŨ¤ò´ÓÄ̤¹¤ëÌð¤òÊü¤Ä¡£",
37 "Á±Îɤʥâ¥ó¥¹¥¿¡¼¤Ë°ÒÎϤòȯ´ø¤¹¤ëÌð¤òÊü¤Ä¡£",
38 "¼Ù°¤Ê¥â¥ó¥¹¥¿¡¼¤Ë°ÒÎϤòȯ´ø¤¹¤ëÌð¤òÊü¤Ä¡£",
39 "Åö¤¿¤ë¤ÈÇúȯ¤¹¤ëÌð¤òÊü¤Ä¡£",
41 "ÅÅ·â°À¤ÎÌð¤òÊü¤Ä¡£",
42 "Ũ¤ÎµÞ½ê¤Ë¤á¤¬¤±¤ÆÌð¤òÊü¤Ä¡£À®¸ù¤¹¤ë¤ÈŨ¤ò°ì·â»à¤µ¤»¤ë¡£¼ºÇÔ¤¹¤ë¤È1¥À¥á¡¼¥¸¡£",
43 "Á´¤Æ¤Î¥â¥ó¥¹¥¿¡¼¤Ë¹â°ÒÎϤòȯ´ø¤¹¤ëÌð¤òÊü¤Ä¡£È¿Æ°¤Ë¤è¤ëÉû¼¡¸ú²Ì¤ò¼õ¤±¤ë¡£",
45 "Concentrate your mind fot shooting.",
46 "Shot an allow with brightness.",
47 "Blink after shooting.",
48 "Shot an allow able to shatter traps.",
49 "Deals extra damege of fire.",
50 "Shot an allow able to shatter rocks.",
51 "Deals extra damege of ice.",
52 "An allow rushes away a target.",
53 "An allow pierces some monsters.",
54 "Deals more damage to good monsters.",
55 "Deals more damage to evil monsters.",
56 "An allow explodes when it hits a monster.",
58 "Deals extra damege of lightning.",
59 "Deals quick death or 1 damage.",
60 "Deals great damage to all monsters, and some side effects to you.",
64 /*! ¥¹¥Ê¥¤¥Ñ¡¼µ»Ç½¥Æ¡¼¥Ö¥ë */
65 snipe_power snipe_powers[MAX_SNIPE_POWERS] =
67 /* Level gained, cost, name */
70 { 2, 1, "¥Õ¥é¥Ã¥·¥å¥¢¥í¡¼" },
71 { 3, 1, "¥·¥å¡¼¥È¡õ¥¢¥¦¥§¥¤" },
75 { 13, 2, "Î䵤¤ÎÌð" },
81 { 32, 4, "¥À¥Ö¥ë¥·¥ç¥Ã¥È" },
82 { 36, 3, "¥×¥é¥º¥Þ¥Ü¥ë¥È" },
83 { 40, 3, "¥Ë¡¼¥É¥ë¥·¥ç¥Ã¥È" },
84 { 48, 7, "¥»¥¤¥ó¥È¥¹¥¿¡¼¥¢¥í¡¼" },
86 { 1, 0, "Concentration" },
87 { 2, 1, "Flush Arrow" },
88 { 3, 1, "Shoot & Away" },
89 { 5, 1, "Disarm Shot" },
90 { 8, 2, "Fire Shot" },
91 { 10, 2, "Shatter Arrow" },
92 { 13, 2, "Ice Shot" },
93 { 18, 2, "Rushing Arrow"},
94 { 22, 3, "Piercing Shot" },
95 { 25, 4, "Evil Shot"},
96 { 26, 4, "Holy Shot" },
98 { 32, 4, "Double Shot" },
99 { 36, 3, "Plasma Bolt" },
100 { 40, 3, "Needle Shot" },
101 { 48, 7, "Saint Stars Arrow" },
106 * @brief ¥¹¥Ê¥¤¥Ñ¡¼¤Î½¸ÃæÅٲû»
107 * @return ¾ï¤ËTRUE¤òÊÖ¤¹
109 static bool snipe_concentrate(void)
111 if ((int)p_ptr->concent < (2 + (p_ptr->lev + 5) / 10)) p_ptr->concent++;
114 msg_format("½¸Ã椷¤¿¡£(½¸ÃæÅÙ %d)", p_ptr->concent);
116 msg_format("You concentrate deeply. (lvl %d)", p_ptr->concent);
119 reset_concent = FALSE;
121 /* Recalculate bonuses */
122 p_ptr->update |= (PU_BONUS);
124 p_ptr->redraw |= (PR_STATUS);
126 /* Update the monsters */
127 p_ptr->update |= (PU_MONSTERS);
133 * @brief ¥¹¥Ê¥¤¥Ñ¡¼¤Î½¸ÃæÅ٥ꥻ¥Ã¥È
134 * @param msg TRUE¤Ê¤é¤Ð¥á¥Ã¥»¡¼¥¸¤òɽ¼¨¤¹¤ë
137 void reset_concentration(bool msg)
142 msg_print("½¸ÃæÎϤ¬ÅÓÀÚ¤ì¤Æ¤·¤Þ¤Ã¤¿¡£");
144 msg_print("Stop concentrating.");
149 reset_concent = FALSE;
151 /* Recalculate bonuses */
152 p_ptr->update |= (PU_BONUS);
154 p_ptr->redraw |= (PR_STATUS);
156 /* Update the monsters */
157 p_ptr->update |= (PU_MONSTERS);
161 * @brief ¥¹¥Ê¥¤¥Ñ¡¼¤Î½¸ÃæÅ٤ˤè¤ë¥À¥á¡¼¥¸¥Ü¡¼¥Ê¥¹¤ò²Ã»»¤¹¤ë
162 * @param tdam »»½ÐÃæ¤Î¥À¥á¡¼¥¸
163 * @return ½¸ÃæÅÙ½¤Àµ¤ò²Ã¤¨¤¿¥À¥á¡¼¥¸
165 int boost_concentration_damage(int tdam)
167 tdam *= (10 + p_ptr->concent);
174 * @brief ¥¹¥Ê¥¤¥Ñ¡¼¤Îµ»Ç½¥ê¥¹¥È¤òɽ¼¨¤¹¤ë
177 void display_snipe_list(void)
182 int plev = p_ptr->lev;
186 /* Display a list of spells */
189 put_str("̾Á°", y, x + 5);
190 put_str("Lv MP", y, x + 35);
192 put_str("Name", y, x + 5);
193 put_str("Lv Mana", y, x + 35);
196 /* Dump the spells */
197 for (i = 0; i < MAX_SNIPE_POWERS; i++)
199 /* Access the available spell */
200 spell = snipe_powers[i];
201 if (spell.min_lev > plev) continue;
202 if (spell.mana_cost > (int)p_ptr->concent) continue;
205 sprintf(psi_desc, " %c) %-30s%2d %4d",
206 I2A(i), spell.name, spell.min_lev, spell.mana_cost);
208 Term_putstr(x, y + i + 1, -1, TERM_WHITE, psi_desc);
215 * @brief ¥¹¥Ê¥¤¥Ñ¡¼µ»Ç½¤òÁªÂò¤¹¤ë
216 * @param sn ÁªÂò¤·¤¿Æü쵻ǽID¡¢¥¥ã¥ó¥»¥ë¤Î¾ì¹ç-1¡¢ÉÔÀµ¤ÊÁªÂò¤Î¾ì¹ç-2¤òÊÖ¤¹
217 * @param only_browse °ìÍ÷¤ò¸«¤ë¤À¤±¤Î¾ì¹çTRUE¤òÊÖ¤¹
218 * @return ȯư²Äǽ¤ÊËâË¡¤òÁªÂò¤·¤¿¾ì¹çTRUE¡¢¥¥ã¥ó¥»¥ë½èÍý¤«ÉÔÀµ¤ÊÁªÂò¤¬¹Ô¤ï¤ì¤¿¾ì¹çFALSE¤òÊÖ¤¹¡£
219 * Allow user to choose a mindcrafter power.\n
221 * If a valid spell is chosen, saves it in '*sn' and returns TRUE\n
222 * If the user hits escape, returns FALSE, and set '*sn' to -1\n
223 * If there are no legal choices, returns FALSE, and sets '*sn' to -2\n
225 * The "prompt" should be "cast", "recite", or "study"\n
226 * The "known" should be TRUE for cast/pray, FALSE for study\n
228 * nb: This function has a (trivial) display bug which will be obvious\n
229 * when you run it. It's probably easy to fix but I haven't tried,\n
232 static int get_snipe_power(int *sn, bool only_browse)
238 int plev = p_ptr->lev;
250 #ifdef ALLOW_REPEAT /* TNB */
254 /* Assume cancelled */
257 /* Repeat previous command */
258 /* Get the spell, if available */
261 /* Verify the spell */
262 if ((snipe_powers[*sn].min_lev <= plev) && (snipe_powers[*sn].mana_cost <= (int)p_ptr->concent))
269 #endif /* ALLOW_REPEAT -- TNB */
271 /* Nothing chosen yet */
277 for (i = 0; i < MAX_SNIPE_POWERS; i++)
279 if ((snipe_powers[i].min_lev <= plev) &&
280 ((only_browse) || (snipe_powers[i].mana_cost <= (int)p_ptr->concent)))
286 /* Build a prompt (accept all spells) */
290 (void)strnfmt(out_val, 78, "(%^s %c-%c, '*'¤Ç°ìÍ÷, ESC) ¤É¤Î%s¤Ë¤Ä¤¤¤ÆÃΤê¤Þ¤¹¤«¡©",
292 (void)strnfmt(out_val, 78, "(%^ss %c-%c, *=List, ESC=exit) Use which %s? ",
294 p, I2A(0), I2A(num), p);
299 (void)strnfmt(out_val, 78, "(%^s %c-%c, '*'¤Ç°ìÍ÷, ESC) ¤É¤Î%s¤ò»È¤¤¤Þ¤¹¤«¡©",
301 (void)strnfmt(out_val, 78, "(%^ss %c-%c, *=List, ESC=exit) Use which %s? ",
303 p, I2A(0), I2A(num), p);
306 /* Get a spell from the user */
307 choice = always_show_list ? ESCAPE : 1;
310 if(choice == ESCAPE) choice = ' ';
311 else if( !get_com(out_val, &choice, FALSE) )break;
314 if ((choice == ' ') || (choice == '*') || (choice == '?'))
324 /* Save the screen */
325 if (!only_browse) screen_save();
327 /* Display a list of spells */
330 put_str("̾Á°", y, x + 5);
331 if (only_browse) put_str("Lv ½¸ÃæÅÙ", y, x + 35);
333 put_str("Name", y, x + 5);
334 if (only_browse) put_str("Lv Pow", y, x + 35);
337 /* Dump the spells */
338 for (i = 0; i < MAX_SNIPE_POWERS; i++)
340 Term_erase(x, y + i + 1, 255);
342 /* Access the spell */
343 spell = snipe_powers[i];
344 if (spell.min_lev > plev) continue;
345 if (!only_browse && (spell.mana_cost > (int)p_ptr->concent)) continue;
347 /* Dump the spell --(-- */
349 sprintf(psi_desc, " %c) %-30s%2d %4d",
350 I2A(i), spell.name, spell.min_lev, spell.mana_cost);
352 sprintf(psi_desc, " %c) %-30s", I2A(i), spell.name);
353 prt(psi_desc, y + i + 1, x);
356 /* Clear the bottom line */
357 prt("", y + i + 1, x);
366 /* Restore the screen */
367 if (!only_browse) screen_load();
375 ask = isupper(choice);
378 if (ask) choice = tolower(choice);
380 /* Extract request */
381 i = (islower(choice) ? A2I(choice) : -1);
383 /* Totally Illegal */
384 if ((i < 0) || (i > num) ||
385 (!only_browse &&(snipe_powers[i].mana_cost > (int)p_ptr->concent)))
391 /* Save the spell index */
392 spell = snipe_powers[i];
401 (void) strnfmt(tmp_val, 78, "%s¤ò»È¤¤¤Þ¤¹¤«¡©", snipe_powers[i].name);
403 (void)strnfmt(tmp_val, 78, "Use %s? ", snipe_powers[i].name);
406 /* Belay that order */
407 if (!get_check(tmp_val)) continue;
414 /* Restore the screen */
415 if (redraw && !only_browse) screen_load();
418 p_ptr->window |= (PW_SPELL);
423 /* Abort if needed */
424 if (!flag) return (FALSE);
426 /* Save the choice */
429 #ifdef ALLOW_REPEAT /* TNB */
433 #endif /* ALLOW_REPEAT -- TNB */
440 * @brief ¥¹¥Ê¥¤¥Ð¡¼µ»Ç½¤Î¥¹¥ì¥¤ÇÜΨ·×»»¤ò¹Ô¤¦ /
441 * Calcurate magnification of snipe technics
442 * @param mult ¥¹¥Ê¥¤¥Ð¡¼µ»Ç½¤Î¥¹¥ì¥¤¸ú²Ì°ÊÁ°¤Ë»»½Ð¤·¤Æ¤¤¤ë¿Í×ÁǤÎÇÜΨ(/10ÇÜ)
443 * @param m_ptr ÌÜɸ¤È¤Ê¤ë¥â¥ó¥¹¥¿¡¼¤Î¹½Â¤Âλ²¾È¥Ý¥¤¥ó¥¿
444 * @return ¥¹¥ì¥¤¤ÎÇÜΨ(/10ÇÜ)
446 int tot_dam_aux_snipe(int mult, monster_type *m_ptr)
448 monster_race *r_ptr = &r_info[m_ptr->r_idx];
449 bool seen = is_seen(m_ptr);
454 if (r_ptr->flags3 & (RF3_HURT_LITE))
456 int n = 20 + p_ptr->concent;
457 if (seen) r_ptr->r_flags3 |= (RF3_HURT_LITE);
458 if (mult < n) mult = n;
462 if (r_ptr->flagsr & RFR_IM_FIRE)
464 if (seen) r_ptr->r_flagsr |= RFR_IM_FIRE;
468 int n = 15 + (p_ptr->concent * 3);
469 if (mult < n) mult = n;
473 if (r_ptr->flagsr & RFR_IM_COLD)
475 if (seen) r_ptr->r_flagsr |= RFR_IM_COLD;
479 int n = 15 + (p_ptr->concent * 3);
480 if (mult < n) mult = n;
484 if (r_ptr->flagsr & RFR_IM_ELEC)
486 if (seen) r_ptr->r_flagsr |= RFR_IM_ELEC;
490 int n = 18 + (p_ptr->concent * 4);
491 if (mult < n) mult = n;
495 if (r_ptr->flags3 & RF3_HURT_ROCK)
497 int n = 15 + (p_ptr->concent * 2);
498 if (seen) r_ptr->r_flags3 |= RF3_HURT_ROCK;
499 if (mult < n) mult = n;
501 else if (r_ptr->flags3 & RF3_NONLIVING)
503 int n = 15 + (p_ptr->concent * 2);
504 if (seen) r_ptr->r_flags3 |= RF3_NONLIVING;
505 if (mult < n) mult = n;
509 if (r_ptr->flags3 & RF3_GOOD)
511 int n = 15 + (p_ptr->concent * 4);
512 if (seen) r_ptr->r_flags3 |= RF3_GOOD;
513 if (mult < n) mult = n;
517 if (r_ptr->flags3 & RF3_EVIL)
519 int n = 12 + (p_ptr->concent * 3);
520 if (seen) r_ptr->r_flags3 |= RF3_EVIL;
521 if (r_ptr->flags3 & (RF3_HURT_LITE))
523 n += (p_ptr->concent * 3);
524 if (seen) r_ptr->r_flags3 |= (RF3_HURT_LITE);
526 if (mult < n) mult = n;
530 if (mult < 50) mult = 50;
539 * @brief ¥¹¥Ê¥¤¥Ñ¡¼µ»Ç½¤Îȯư /
540 * do_cmd_cast calls this function if the player's class is 'snipe'.
541 * @param spell ȯư¤¹¤ëÆü쵻ǽ¤ÎID
542 * @return ½èÍý¤ò¼Â¹Ô¤·¤¿¤éTRUE¡¢¥¥ã¥ó¥»¥ë¤·¤¿¾ì¹çFALSE¤òÊÖ¤¹¡£
544 static bool cast_sniper_spell(int spell)
546 object_type *o_ptr = &inventory[INVEN_BOW];
548 if (o_ptr->tval != TV_BOW)
551 msg_print("µÝ¤òÁõÈ÷¤·¤Æ¤¤¤Ê¤¤¡ª");
553 msg_print("You wield no bow!");
561 case 0: /* Concentration */
562 if (!snipe_concentrate()) return (FALSE);
565 case 1: snipe_type = SP_LITE; break;
566 case 2: snipe_type = SP_AWAY; break;
567 case 3: snipe_type = SP_KILL_TRAP; break;
568 case 4: snipe_type = SP_FIRE; break;
569 case 5: snipe_type = SP_KILL_WALL; break;
570 case 6: snipe_type = SP_COLD; break;
571 case 7: snipe_type = SP_RUSH; break;
572 case 8: snipe_type = SP_PIERCE; break;
573 case 9: snipe_type = SP_EVILNESS; break;
574 case 10: snipe_type = SP_HOLYNESS; break;
575 case 11: snipe_type = SP_EXPLODE; break;
576 case 12: snipe_type = SP_DOUBLE; break;
577 case 13: snipe_type = SP_ELEC; break;
578 case 14: snipe_type = SP_NEEDLE; break;
579 case 15: snipe_type = SP_FINAL; break;
596 * @brief ¥¹¥Ê¥¤¥Ñ¡¼µ»Ç½¥³¥Þ¥ó¥É¤Î¥á¥¤¥ó¥ë¡¼¥Á¥ó /
599 void do_cmd_snipe(void)
605 /* not if confused */
609 msg_print("º®Í𤷤Ƥ¤¤Æ½¸Ãæ¤Ç¤¤Ê¤¤¡ª");
611 msg_print("You are too confused!");
616 /* not if hullucinated */
620 msg_print("¸¸³Ð¤¬¸«¤¨¤Æ½¸Ãæ¤Ç¤¤Ê¤¤¡ª");
622 msg_print("You are too hallucinated!");
631 msg_print("Ƭ¤¬Û¯Û°¤È¤·¤Æ¤¤¤Æ½¸Ãæ¤Ç¤¤Ê¤¤¡ª");
633 msg_print("You are too stuned!");
639 if (!get_snipe_power(&n, FALSE)) return;
644 cast = cast_sniper_spell(n);
652 p_ptr->redraw |= (PR_HP | PR_MANA);
655 p_ptr->window |= (PW_PLAYER);
656 p_ptr->window |= (PW_SPELL);
660 * @brief ¥¹¥Ê¥¤¥Ñ¡¼µ»Ç½¥³¥Þ¥ó¥É¤Îɽ¼¨ /
663 void do_cmd_snipe_browse(void)
674 if (!get_snipe_power(&n, TRUE))
680 /* Clear lines, position cursor (really should use strlen here) */
681 Term_erase(12, 22, 255);
682 Term_erase(12, 21, 255);
683 Term_erase(12, 20, 255);
684 Term_erase(12, 19, 255);
685 Term_erase(12, 18, 255);
687 roff_to_buf(snipe_tips[n], 62, temp, sizeof(temp));
688 for(j = 0, line = 19; temp[j]; j += (1 + strlen(&temp[j])))
690 prt(&temp[j], line, 15);