+++ /dev/null
-/*!
- * @file snipe.c
- * @brief スナイパー技能の実装 / Sniping
- * @date 2014/01/18
- * @author
- * 2014 Deskull rearranged comment for Doxygen.\n
- */
-
-#include "angband.h"
-#include "core.h"
-#include "util.h"
-#include "term.h"
-
-#include "player-status.h"
-#include "cmd-basic.h"
-#include "snipe.h"
-#include "monsterrace.h"
-#include "view-mainwindow.h"
-
-#define MAX_SNIPE_POWERS 16
-
-/*! スナイパー技能情報の構造体 */
-typedef struct snipe_power
-{
- PLAYER_LEVEL min_lev;
- MANA_POINT mana_cost;
- concptr name;
-} snipe_power;
-
-/*! スナイパー技能の解説メッセージ */
-static concptr const snipe_tips[MAX_SNIPE_POWERS] =
-{
-#ifdef JP
- "精神を集中する。射撃の威力、精度が上がり、高度な射撃術が使用できるようになる。",
- "光る矢を放つ。光に弱いモンスターに威力を発揮する。",
- "射撃を行った後、短距離の瞬間移動を行う。",
- "軌道上の罠をすべて無効にする低空飛行の矢を放つ。",
- "火炎属性の矢を放つ。",
- "壁を粉砕する矢を放つ。岩でできたモンスターと無生物のモンスターに威力を発揮する。",
- "冷気属性の矢を放つ。",
- "敵を突き飛ばす矢を放つ。",
- "複数の敵を貫通する矢を放つ。",
- "善良なモンスターに威力を発揮する矢を放つ。",
- "邪悪なモンスターに威力を発揮する矢を放つ。",
- "当たると爆発する矢を放つ。",
- "2回射撃を行う。",
- "電撃属性の矢を放つ。",
- "敵の急所にめがけて矢を放つ。成功すると敵を一撃死させる。失敗すると1ダメージ。",
- "全てのモンスターに高威力を発揮する矢を放つ。反動による副次効果を受ける。",
-#else
- "Concentrate your mind fot shooting.",
- "Shot an allow with brightness.",
- "Blink after shooting.",
- "Shot an allow able to shatter traps.",
- "Deals extra damege of fire.",
- "Shot an allow able to shatter rocks.",
- "Deals extra damege of ice.",
- "An allow rushes away a target.",
- "An allow pierces some monsters.",
- "Deals more damage to good monsters.",
- "Deals more damage to evil monsters.",
- "An allow explodes when it hits a monster.",
- "Shot allows twice.",
- "Deals extra damege of lightning.",
- "Deals quick death or 1 damage.",
- "Deals great damage to all monsters, and some side effects to you.",
-#endif
-};
-
-/*! スナイパー技能テーブル */
-static snipe_power const snipe_powers[MAX_SNIPE_POWERS] =
-{
- /* Level gained, cost, name */
-#ifdef JP
- { 1, 0, "精神集中" },
- { 2, 1, "フラッシュアロー" },
- { 3, 1, "シュート&アウェイ" },
- { 5, 1, "解除の矢" },
- { 8, 2, "火炎の矢" },
- { 10, 2, "岩砕き" },
- { 13, 2, "冷気の矢" },
- { 18, 2, "烈風弾"},
- { 22, 3, "貫通弾" },
- { 25, 4, "邪念弾"},
- { 26, 4, "破魔矢" },
- { 30, 3, "爆発の矢"},
- { 32, 4, "ダブルショット" },
- { 36, 3, "プラズマボルト" },
- { 40, 3, "ニードルショット" },
- { 48, 7, "セイントスターアロー" },
-#else
- { 1, 0, "Concentration" },
- { 2, 1, "Flush Arrow" },
- { 3, 1, "Shoot & Away" },
- { 5, 1, "Disarm Shot" },
- { 8, 2, "Fire Shot" },
- { 10, 2, "Shatter Arrow" },
- { 13, 2, "Ice Shot" },
- { 18, 2, "Rushing Arrow"},
- { 22, 3, "Piercing Shot" },
- { 25, 4, "Evil Shot"},
- { 26, 4, "Holy Shot" },
- { 30, 3, "Missile"},
- { 32, 4, "Double Shot" },
- { 36, 3, "Plasma Bolt" },
- { 40, 3, "Needle Shot" },
- { 48, 7, "Saint Stars Arrow" },
-#endif
-};
-
-/*!
- * @brief スナイパーの集中度加算
- * @return 常にTRUEを返す
- */
-static bool snipe_concentrate(player_type *creature_ptr)
-{
- if ((int)creature_ptr->concent < (2 + (creature_ptr->lev + 5) / 10)) creature_ptr->concent++;
-
- msg_format(_("集中した。(集中度 %d)", "You concentrate deeply. (lvl %d)"), creature_ptr->concent);
- creature_ptr->reset_concent = FALSE;
-
- creature_ptr->update |= (PU_BONUS | PU_MONSTERS);
- creature_ptr->redraw |= (PR_STATUS);
- return TRUE;
-}
-
-/*!
- * @brief スナイパーの集中度リセット
- * @param msg TRUEならばメッセージを表示する
- * @return なし
- */
-void reset_concentration(player_type *creature_ptr, bool msg)
-{
- if (msg)
- {
- msg_print(_("集中力が途切れてしまった。", "Stop concentrating."));
- }
-
- creature_ptr->concent = 0;
- creature_ptr->reset_concent = FALSE;
-
- creature_ptr->update |= (PU_BONUS | PU_MONSTERS);
- creature_ptr->redraw |= (PR_STATUS);
-}
-
-/*!
- * @brief スナイパーの集中度によるダメージボーナスを加算する
- * @param tdam 算出中のダメージ
- * @return 集中度修正を加えたダメージ
- */
-int boost_concentration_damage(player_type *creature_ptr, int tdam)
-{
- tdam *= (10 + creature_ptr->concent);
- tdam /= 10;
-
- return (tdam);
-}
-
-/*!
- * @brief スナイパーの技能リストを表示する
- * @return なし
- */
-void display_snipe_list(player_type *sniper_ptr)
-{
- int i;
- TERM_LEN y = 1;
- TERM_LEN x = 1;
- PLAYER_LEVEL plev = sniper_ptr->lev;
- snipe_power spell;
- char psi_desc[80];
-
- /* Display a list of spells */
- prt("", y, x);
- put_str(_("名前", "Name"), y, x + 5);
- put_str(_("Lv MP", "Lv Mana"), y, x + 35);
-
- for (i = 0; i < MAX_SNIPE_POWERS; i++)
- {
- /* Access the available spell */
- spell = snipe_powers[i];
- if (spell.min_lev > plev) continue;
- if (spell.mana_cost > (int)sniper_ptr->concent) continue;
-
- sprintf(psi_desc, " %c) %-30s%2d %4d",
- I2A(i), spell.name, spell.min_lev, spell.mana_cost);
-
- Term_putstr(x, y + i + 1, -1, TERM_WHITE, psi_desc);
- }
- return;
-}
-
-
-/*!
- * @brief スナイパー技能を選択する
- * @param sn 選択した特殊技能ID、キャンセルの場合-1、不正な選択の場合-2を返す
- * @param only_browse 一覧を見るだけの場合TRUEを返す
- * @return 発動可能な魔法を選択した場合TRUE、キャンセル処理か不正な選択が行われた場合FALSEを返す。
- * Allow user to choose a mindcrafter power.\n
- *\n
- * If a valid spell is chosen, saves it in '*sn' and returns TRUE\n
- * If the user hits escape, returns FALSE, and set '*sn' to -1\n
- * If there are no legal choices, returns FALSE, and sets '*sn' to -2\n
- *\n
- * The "prompt" should be "cast", "recite", or "study"\n
- * The "known" should be TRUE for cast/pray, FALSE for study\n
- *\n
- * nb: This function has a (trivial) display bug which will be obvious\n
- * when you run it. It's probably easy to fix but I haven't tried,\n
- * sorry.\n
- */
-static int get_snipe_power(player_type *sniper_ptr, COMMAND_CODE *sn, bool only_browse)
-{
- COMMAND_CODE i;
- int num = 0;
- TERM_LEN y = 1;
- TERM_LEN x = 20;
- PLAYER_LEVEL plev = sniper_ptr->lev;
- int ask;
- char choice;
- char out_val[160];
- concptr p = _("射撃術", "power");
- snipe_power spell;
- bool flag, redraw;
-
- repeat_push(*sn);
-
- /* Assume cancelled */
- *sn = (-1);
-
- /* Repeat previous command */
- /* Get the spell, if available */
- if (repeat_pull(sn))
- {
- /* Verify the spell */
- if ((snipe_powers[*sn].min_lev <= plev) && (snipe_powers[*sn].mana_cost <= (int)sniper_ptr->concent))
- {
- /* Success */
- return TRUE;
- }
- }
-
- flag = FALSE;
- redraw = FALSE;
-
- for (i = 0; i < MAX_SNIPE_POWERS; i++)
- {
- if ((snipe_powers[i].min_lev <= plev) &&
- ((only_browse) || (snipe_powers[i].mana_cost <= (int)sniper_ptr->concent)))
- {
- num = i;
- }
- }
-
- /* Build a prompt (accept all spells) */
- if (only_browse)
- {
- (void)strnfmt(out_val, 78,
- _("(%^s %c-%c, '*'で一覧, ESC) どの%sについて知りますか?", "(%^ss %c-%c, *=List, ESC=exit) Use which %s? "),
- p, I2A(0), I2A(num), p);
- }
- else
- {
- (void)strnfmt(out_val, 78,
- _("(%^s %c-%c, '*'で一覧, ESC) どの%sを使いますか?", "(%^ss %c-%c, *=List, ESC=exit) Use which %s? "),
- p, I2A(0), I2A(num), p);
- }
-
- choice = always_show_list ? ESCAPE : 1;
- while (!flag)
- {
- if(choice == ESCAPE) choice = ' ';
- else if( !get_com(out_val, &choice, FALSE) )break;
-
- /* Request redraw */
- if ((choice == ' ') || (choice == '*') || (choice == '?'))
- {
- /* Show the list */
- if (!redraw)
- {
- char psi_desc[80];
- redraw = TRUE;
- if (!only_browse) screen_save();
-
- /* Display a list of spells */
- prt("", y, x);
- put_str(_("名前", "Name"), y, x + 5);
- if (only_browse) put_str(_("Lv 集中度", "Lv Pow"), y, x + 35);
-
- /* Dump the spells */
- for (i = 0; i < MAX_SNIPE_POWERS; i++)
- {
- Term_erase(x, y + i + 1, 255);
-
- /* Access the spell */
- spell = snipe_powers[i];
- if (spell.min_lev > plev) continue;
- if (!only_browse && (spell.mana_cost > (int)sniper_ptr->concent)) continue;
-
- /* Dump the spell --(-- */
- if (only_browse)
- sprintf(psi_desc, " %c) %-30s%2d %4d",
- I2A(i), spell.name, spell.min_lev, spell.mana_cost);
- else
- sprintf(psi_desc, " %c) %-30s", I2A(i), spell.name);
- prt(psi_desc, y + i + 1, x);
- }
-
- /* Clear the bottom line */
- prt("", y + i + 1, x);
- }
-
- /* Hide the list */
- else
- {
- /* Hide list */
- redraw = FALSE;
- if (!only_browse) screen_load();
- }
-
- /* Redo asking */
- continue;
- }
-
- /* Note verify */
- ask = isupper(choice);
-
- /* Lowercase */
- if (ask) choice = (char)tolower(choice);
-
- /* Extract request */
- i = (islower(choice) ? A2I(choice) : -1);
-
- /* Totally Illegal */
- if ((i < 0) || (i > num) ||
- (!only_browse &&(snipe_powers[i].mana_cost > (int)sniper_ptr->concent)))
- {
- bell();
- continue;
- }
-
- /* Save the spell index */
- spell = snipe_powers[i];
-
- /* Verify it */
- if (ask)
- {
- char tmp_val[160];
-
- /* Prompt */
- (void) strnfmt(tmp_val, 78, _("%sを使いますか?", "Use %s? "), snipe_powers[i].name);
-
- /* Belay that order */
- if (!get_check(tmp_val)) continue;
- }
-
- /* Stop the loop */
- flag = TRUE;
- }
- if (redraw && !only_browse) screen_load();
-
- sniper_ptr->window |= (PW_SPELL);
- handle_stuff(sniper_ptr);
-
- /* Abort if needed */
- if (!flag) return FALSE;
-
- /* Save the choice */
- (*sn) = i;
-
- repeat_push(*sn);
-
- /* Success */
- return TRUE;
-}
-
-
-/*!
- * @brief スナイバー技能のスレイ倍率計算を行う /
- * Calcurate magnification of snipe technics
- * @param mult スナイバー技能のスレイ効果以前に算出している多要素の倍率(/10倍)
- * @param m_ptr 目標となるモンスターの構造体参照ポインタ
- * @return スレイの倍率(/10倍)
- */
-MULTIPLY tot_dam_aux_snipe(player_type *sniper_ptr, MULTIPLY mult, monster_type *m_ptr, SPELL_IDX snipe_type)
-{
- monster_race *r_ptr = &r_info[m_ptr->r_idx];
- bool seen = is_seen(m_ptr);
-
- switch (snipe_type)
- {
- case SP_LITE:
- if (r_ptr->flags3 & (RF3_HURT_LITE))
- {
- MULTIPLY n = 20 + sniper_ptr->concent;
- if (seen) r_ptr->r_flags3 |= (RF3_HURT_LITE);
- if (mult < n) mult = n;
- }
- break;
- case SP_FIRE:
- if (r_ptr->flagsr & RFR_IM_FIRE)
- {
- if (seen) r_ptr->r_flagsr |= RFR_IM_FIRE;
- }
- else
- {
- MULTIPLY n = 15 + (sniper_ptr->concent * 3);
- if (mult < n) mult = n;
- }
- break;
- case SP_COLD:
- if (r_ptr->flagsr & RFR_IM_COLD)
- {
- if (seen) r_ptr->r_flagsr |= RFR_IM_COLD;
- }
- else
- {
- MULTIPLY n = 15 + (sniper_ptr->concent * 3);
- if (mult < n) mult = n;
- }
- break;
- case SP_ELEC:
- if (r_ptr->flagsr & RFR_IM_ELEC)
- {
- if (seen) r_ptr->r_flagsr |= RFR_IM_ELEC;
- }
- else
- {
- MULTIPLY n = 18 + (sniper_ptr->concent * 4);
- if (mult < n) mult = n;
- }
- break;
- case SP_KILL_WALL:
- if (r_ptr->flags3 & RF3_HURT_ROCK)
- {
- MULTIPLY n = 15 + (sniper_ptr->concent * 2);
- if (seen) r_ptr->r_flags3 |= RF3_HURT_ROCK;
- if (mult < n) mult = n;
- }
- else if (r_ptr->flags3 & RF3_NONLIVING)
- {
- MULTIPLY n = 15 + (sniper_ptr->concent * 2);
- if (seen) r_ptr->r_flags3 |= RF3_NONLIVING;
- if (mult < n) mult = n;
- }
- break;
- case SP_EVILNESS:
- if (r_ptr->flags3 & RF3_GOOD)
- {
- MULTIPLY n = 15 + (sniper_ptr->concent * 4);
- if (seen) r_ptr->r_flags3 |= RF3_GOOD;
- if (mult < n) mult = n;
- }
- break;
- case SP_HOLYNESS:
- if (r_ptr->flags3 & RF3_EVIL)
- {
- MULTIPLY n = 12 + (sniper_ptr->concent * 3);
- if (seen) r_ptr->r_flags3 |= RF3_EVIL;
- if (r_ptr->flags3 & (RF3_HURT_LITE))
- {
- n += (sniper_ptr->concent * 3);
- if (seen) r_ptr->r_flags3 |= (RF3_HURT_LITE);
- }
- if (mult < n) mult = n;
- }
- break;
- case SP_FINAL:
- if (mult < 50) mult = 50;
- break;
- }
-
- return (mult);
-}
-
-
-/*!
- * @brief スナイパー技能の発動 /
- * do_cmd_cast calls this function if the player's class is 'snipe'.
- * @param spell 発動する特殊技能のID
- * @return 処理を実行したらTRUE、キャンセルした場合FALSEを返す。
- */
-static bool cast_sniper_spell(player_type *sniper_ptr, int spell)
-{
- object_type *o_ptr = &sniper_ptr->inventory_list[INVEN_BOW];
- SPELL_IDX snipe_type = SP_NONE;
-
- if (o_ptr->tval != TV_BOW)
- {
- msg_print(_("弓を装備していない!", "You wield no bow!"));
- return FALSE;
- }
-
- /* spell code */
- switch (spell)
- {
- case 0: /* Concentration */
- if (!snipe_concentrate(sniper_ptr)) return FALSE;
- take_turn(sniper_ptr, 100);
- return TRUE;
- case 1: snipe_type = SP_LITE; break;
- case 2: snipe_type = SP_AWAY; break;
- case 3: snipe_type = SP_KILL_TRAP; break;
- case 4: snipe_type = SP_FIRE; break;
- case 5: snipe_type = SP_KILL_WALL; break;
- case 6: snipe_type = SP_COLD; break;
- case 7: snipe_type = SP_RUSH; break;
- case 8: snipe_type = SP_PIERCE; break;
- case 9: snipe_type = SP_EVILNESS; break;
- case 10: snipe_type = SP_HOLYNESS; break;
- case 11: snipe_type = SP_EXPLODE; break;
- case 12: snipe_type = SP_DOUBLE; break;
- case 13: snipe_type = SP_ELEC; break;
- case 14: snipe_type = SP_NEEDLE; break;
- case 15: snipe_type = SP_FINAL; break;
- default:
- msg_print(_("なに?", "Zap?"));
- }
-
- command_cmd = 'f';
- do_cmd_fire(sniper_ptr, snipe_type);
-
- return (sniper_ptr->is_fired);
-}
-
-/*!
- * @brief スナイパー技能コマンドのメインルーチン /
- * @return なし
- */
-void do_cmd_snipe(player_type *sniper_ptr)
-{
- COMMAND_CODE n = 0;
- bool cast;
-
- if(cmd_limit_confused(sniper_ptr)) return;
- if(cmd_limit_image(sniper_ptr)) return;
- if(cmd_limit_stun(sniper_ptr)) return;
-
- if (!get_snipe_power(sniper_ptr, &n, FALSE)) return;
-
- sound(SOUND_SHOOT);
- cast = cast_sniper_spell(sniper_ptr, n);
-
- if (!cast) return;
- sniper_ptr->redraw |= (PR_HP | PR_MANA);
- sniper_ptr->window |= (PW_PLAYER);
- sniper_ptr->window |= (PW_SPELL);
-}
-
-/*!
- * @brief スナイパー技能コマンドの表示 /
- * @return なし
- */
-void do_cmd_snipe_browse(player_type *sniper_ptr)
-{
- COMMAND_CODE n = 0;
- int j, line;
- char temp[62 * 4];
-
- screen_save();
-
- while (TRUE)
- {
- if (!get_snipe_power(sniper_ptr, &n, TRUE))
- {
- screen_load();
- return;
- }
-
- /* Clear lines, position cursor (really should use strlen here) */
- Term_erase(12, 22, 255);
- Term_erase(12, 21, 255);
- Term_erase(12, 20, 255);
- Term_erase(12, 19, 255);
- Term_erase(12, 18, 255);
-
- roff_to_buf(snipe_tips[n], 62, temp, sizeof(temp));
- for(j = 0, line = 19; temp[j]; j += (1 + strlen(&temp[j])))
- {
- prt(&temp[j], line, 15);
- line++;
- }
- }
-}