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;
24 /*! スナイパー技能の解説メッセージ */
25 static concptr const snipe_tips[MAX_SNIPE_POWERS] =
28 "精神を集中する。射撃の威力、精度が上がり、高度な射撃術が使用できるようになる。",
29 "光る矢を放つ。光に弱いモンスターに威力を発揮する。",
30 "射撃を行った後、短距離の瞬間移動を行う。",
31 "軌道上の罠をすべて無効にする低空飛行の矢を放つ。",
33 "壁を粉砕する矢を放つ。岩でできたモンスターと無生物のモンスターに威力を発揮する。",
37 "善良なモンスターに威力を発揮する矢を放つ。",
38 "邪悪なモンスターに威力を発揮する矢を放つ。",
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.",
65 static snipe_power const snipe_powers[MAX_SNIPE_POWERS] =
67 /* Level gained, cost, name */
71 { 3, 1, "シュート&アウェイ" },
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" },
109 static bool snipe_concentrate(void)
111 if ((int)p_ptr->concent < (2 + (p_ptr->lev + 5) / 10)) p_ptr->concent++;
113 msg_format(_("集中した。(集中度 %d)", "You concentrate deeply. (lvl %d)"), p_ptr->concent);
114 reset_concent = FALSE;
116 p_ptr->update |= (PU_BONUS | PU_MONSTERS);
117 p_ptr->redraw |= (PR_STATUS);
122 * @brief スナイパーの集中度リセット
123 * @param msg TRUEならばメッセージを表示する
126 void reset_concentration(bool msg)
130 msg_print(_("集中力が途切れてしまった。", "Stop concentrating."));
134 reset_concent = FALSE;
136 p_ptr->update |= (PU_BONUS | PU_MONSTERS);
137 p_ptr->redraw |= (PR_STATUS);
141 * @brief スナイパーの集中度によるダメージボーナスを加算する
142 * @param tdam 算出中のダメージ
143 * @return 集中度修正を加えたダメージ
145 int boost_concentration_damage(int tdam)
147 tdam *= (10 + p_ptr->concent);
154 * @brief スナイパーの技能リストを表示する
157 void display_snipe_list(void)
162 PLAYER_LEVEL plev = p_ptr->lev;
166 /* Display a list of spells */
169 put_str("名前", y, x + 5);
170 put_str("Lv MP", y, x + 35);
172 put_str("Name", y, x + 5);
173 put_str("Lv Mana", y, x + 35);
176 /* Dump the spells */
177 for (i = 0; i < MAX_SNIPE_POWERS; i++)
179 /* Access the available spell */
180 spell = snipe_powers[i];
181 if (spell.min_lev > plev) continue;
182 if (spell.mana_cost > (int)p_ptr->concent) continue;
185 sprintf(psi_desc, " %c) %-30s%2d %4d",
186 I2A(i), spell.name, spell.min_lev, spell.mana_cost);
188 Term_putstr(x, y + i + 1, -1, TERM_WHITE, psi_desc);
195 * @brief スナイパー技能を選択する
196 * @param sn 選択した特殊技能ID、キャンセルの場合-1、不正な選択の場合-2を返す
197 * @param only_browse 一覧を見るだけの場合TRUEを返す
198 * @return 発動可能な魔法を選択した場合TRUE、キャンセル処理か不正な選択が行われた場合FALSEを返す。
199 * Allow user to choose a mindcrafter power.\n
201 * If a valid spell is chosen, saves it in '*sn' and returns TRUE\n
202 * If the user hits escape, returns FALSE, and set '*sn' to -1\n
203 * If there are no legal choices, returns FALSE, and sets '*sn' to -2\n
205 * The "prompt" should be "cast", "recite", or "study"\n
206 * The "known" should be TRUE for cast/pray, FALSE for study\n
208 * nb: This function has a (trivial) display bug which will be obvious\n
209 * when you run it. It's probably easy to fix but I haven't tried,\n
212 static int get_snipe_power(COMMAND_CODE *sn, bool only_browse)
218 PLAYER_LEVEL plev = p_ptr->lev;
222 concptr p = _("射撃術", "power");
228 /* Assume cancelled */
231 /* Repeat previous command */
232 /* Get the spell, if available */
235 /* Verify the spell */
236 if ((snipe_powers[*sn].min_lev <= plev) && (snipe_powers[*sn].mana_cost <= (int)p_ptr->concent))
243 /* Nothing chosen yet */
249 for (i = 0; i < MAX_SNIPE_POWERS; i++)
251 if ((snipe_powers[i].min_lev <= plev) &&
252 ((only_browse) || (snipe_powers[i].mana_cost <= (int)p_ptr->concent)))
258 /* Build a prompt (accept all spells) */
261 (void)strnfmt(out_val, 78,
262 _("(%^s %c-%c, '*'で一覧, ESC) どの%sについて知りますか?", "(%^ss %c-%c, *=List, ESC=exit) Use which %s? "),
263 p, I2A(0), I2A(num), p);
267 (void)strnfmt(out_val, 78,
268 _("(%^s %c-%c, '*'で一覧, ESC) どの%sを使いますか?", "(%^ss %c-%c, *=List, ESC=exit) Use which %s? "),
269 p, I2A(0), I2A(num), p);
272 /* Get a spell from the user */
273 choice = always_show_list ? ESCAPE : 1;
276 if(choice == ESCAPE) choice = ' ';
277 else if( !get_com(out_val, &choice, FALSE) )break;
280 if ((choice == ' ') || (choice == '*') || (choice == '?'))
289 if (!only_browse) screen_save();
291 /* Display a list of spells */
294 put_str("名前", y, x + 5);
295 if (only_browse) put_str("Lv 集中度", y, x + 35);
297 put_str("Name", y, x + 5);
298 if (only_browse) put_str("Lv Pow", y, x + 35);
301 /* Dump the spells */
302 for (i = 0; i < MAX_SNIPE_POWERS; i++)
304 Term_erase(x, y + i + 1, 255);
306 /* Access the spell */
307 spell = snipe_powers[i];
308 if (spell.min_lev > plev) continue;
309 if (!only_browse && (spell.mana_cost > (int)p_ptr->concent)) continue;
311 /* Dump the spell --(-- */
313 sprintf(psi_desc, " %c) %-30s%2d %4d",
314 I2A(i), spell.name, spell.min_lev, spell.mana_cost);
316 sprintf(psi_desc, " %c) %-30s", I2A(i), spell.name);
317 prt(psi_desc, y + i + 1, x);
320 /* Clear the bottom line */
321 prt("", y + i + 1, x);
329 if (!only_browse) screen_load();
337 ask = isupper(choice);
340 if (ask) choice = (char)tolower(choice);
342 /* Extract request */
343 i = (islower(choice) ? A2I(choice) : -1);
345 /* Totally Illegal */
346 if ((i < 0) || (i > num) ||
347 (!only_browse &&(snipe_powers[i].mana_cost > (int)p_ptr->concent)))
353 /* Save the spell index */
354 spell = snipe_powers[i];
362 (void) strnfmt(tmp_val, 78, _("%sを使いますか?", "Use %s? "), snipe_powers[i].name);
364 /* Belay that order */
365 if (!get_check(tmp_val)) continue;
371 if (redraw && !only_browse) screen_load();
373 p_ptr->window |= (PW_SPELL);
376 /* Abort if needed */
377 if (!flag) return (FALSE);
379 /* Save the choice */
389 * @brief スナイバー技能のスレイ倍率計算を行う /
390 * Calcurate magnification of snipe technics
391 * @param mult スナイバー技能のスレイ効果以前に算出している多要素の倍率(/10倍)
392 * @param m_ptr 目標となるモンスターの構造体参照ポインタ
393 * @return スレイの倍率(/10倍)
395 int tot_dam_aux_snipe(int mult, monster_type *m_ptr)
397 monster_race *r_ptr = &r_info[m_ptr->r_idx];
398 bool seen = is_seen(m_ptr);
403 if (r_ptr->flags3 & (RF3_HURT_LITE))
405 int n = 20 + p_ptr->concent;
406 if (seen) r_ptr->r_flags3 |= (RF3_HURT_LITE);
407 if (mult < n) mult = n;
411 if (r_ptr->flagsr & RFR_IM_FIRE)
413 if (seen) r_ptr->r_flagsr |= RFR_IM_FIRE;
417 int n = 15 + (p_ptr->concent * 3);
418 if (mult < n) mult = n;
422 if (r_ptr->flagsr & RFR_IM_COLD)
424 if (seen) r_ptr->r_flagsr |= RFR_IM_COLD;
428 int n = 15 + (p_ptr->concent * 3);
429 if (mult < n) mult = n;
433 if (r_ptr->flagsr & RFR_IM_ELEC)
435 if (seen) r_ptr->r_flagsr |= RFR_IM_ELEC;
439 int n = 18 + (p_ptr->concent * 4);
440 if (mult < n) mult = n;
444 if (r_ptr->flags3 & RF3_HURT_ROCK)
446 int n = 15 + (p_ptr->concent * 2);
447 if (seen) r_ptr->r_flags3 |= RF3_HURT_ROCK;
448 if (mult < n) mult = n;
450 else if (r_ptr->flags3 & RF3_NONLIVING)
452 int n = 15 + (p_ptr->concent * 2);
453 if (seen) r_ptr->r_flags3 |= RF3_NONLIVING;
454 if (mult < n) mult = n;
458 if (r_ptr->flags3 & RF3_GOOD)
460 int n = 15 + (p_ptr->concent * 4);
461 if (seen) r_ptr->r_flags3 |= RF3_GOOD;
462 if (mult < n) mult = n;
466 if (r_ptr->flags3 & RF3_EVIL)
468 int n = 12 + (p_ptr->concent * 3);
469 if (seen) r_ptr->r_flags3 |= RF3_EVIL;
470 if (r_ptr->flags3 & (RF3_HURT_LITE))
472 n += (p_ptr->concent * 3);
473 if (seen) r_ptr->r_flags3 |= (RF3_HURT_LITE);
475 if (mult < n) mult = n;
479 if (mult < 50) mult = 50;
488 * @brief スナイパー技能の発動 /
489 * do_cmd_cast calls this function if the player's class is 'snipe'.
490 * @param spell 発動する特殊技能のID
491 * @return 処理を実行したらTRUE、キャンセルした場合FALSEを返す。
493 static bool cast_sniper_spell(int spell)
495 object_type *o_ptr = &inventory[INVEN_BOW];
497 if (o_ptr->tval != TV_BOW)
499 msg_print(_("弓を装備していない!", "You wield no bow!"));
506 case 0: /* Concentration */
507 if (!snipe_concentrate()) return (FALSE);
508 p_ptr->energy_use = 100;
510 case 1: snipe_type = SP_LITE; break;
511 case 2: snipe_type = SP_AWAY; break;
512 case 3: snipe_type = SP_KILL_TRAP; break;
513 case 4: snipe_type = SP_FIRE; break;
514 case 5: snipe_type = SP_KILL_WALL; break;
515 case 6: snipe_type = SP_COLD; break;
516 case 7: snipe_type = SP_RUSH; break;
517 case 8: snipe_type = SP_PIERCE; break;
518 case 9: snipe_type = SP_EVILNESS; break;
519 case 10: snipe_type = SP_HOLYNESS; break;
520 case 11: snipe_type = SP_EXPLODE; break;
521 case 12: snipe_type = SP_DOUBLE; break;
522 case 13: snipe_type = SP_ELEC; break;
523 case 14: snipe_type = SP_NEEDLE; break;
524 case 15: snipe_type = SP_FINAL; break;
526 msg_print(_("なに?", "Zap?"));
537 * @brief スナイパー技能コマンドのメインルーチン /
540 void do_cmd_snipe(void)
545 if (cmd_limit_confused(p_ptr)) return;
547 /* not if hullucinated */
550 msg_print(_("幻覚が見えて集中できない!", "You are too hallucinated!"));
557 msg_print(_("頭が朦朧としていて集中できない!", "You are too stuned!"));
562 if (!get_snipe_power(&n, FALSE)) return;
567 cast = cast_sniper_spell(n);
570 p_ptr->redraw |= (PR_HP | PR_MANA);
572 p_ptr->window |= (PW_PLAYER);
573 p_ptr->window |= (PW_SPELL);
577 * @brief スナイパー技能コマンドの表示 /
580 void do_cmd_snipe_browse(void)
591 if (!get_snipe_power(&n, TRUE))
597 /* Clear lines, position cursor (really should use strlen here) */
598 Term_erase(12, 22, 255);
599 Term_erase(12, 21, 255);
600 Term_erase(12, 20, 255);
601 Term_erase(12, 19, 255);
602 Term_erase(12, 18, 255);
604 roff_to_buf(snipe_tips[n], 62, temp, sizeof(temp));
605 for(j = 0, line = 19; temp[j]; j += (1 + strlen(&temp[j])))
607 prt(&temp[j], line, 15);