#include "angband.h"
-#include "projection.h"
+#include "util.h"
+
+#include "monster.h"
#include "monster-status.h"
+#include "monster-spell.h"
#include "artifact.h"
#include "avatar.h"
#include "player-status.h"
+#include "player-skill.h"
+#include "object-hook.h"
+#include "floor.h"
+#include "grid.h"
+#include "spells.h"
+#include "object-flavor.h"
#include "shoot.h"
+#include "snipe.h"
+#include "view-mainwindow.h"
+
/*!
* @brief 矢弾を射撃した際のスレイ倍率をかけた結果を返す /
* Determines the odds of an object breaking when thrown at a monster
* @param m_ptr 目標モンスターの構造体参照ポインタ
* @return スレイ倍率をかけたダメージ量
*/
-static s16b tot_dam_aux_shot(object_type *o_ptr, int tdam, monster_type *m_ptr)
+static MULTIPLY tot_dam_aux_shot(object_type *o_ptr, HIT_POINT tdam, monster_type *m_ptr, SPELL_IDX snipe_type)
{
- int mult = 10;
+ MULTIPLY mult = 10;
monster_race *r_ptr = &r_info[m_ptr->r_idx];
}
/* Sniper */
- if (snipe_type) mult = tot_dam_aux_snipe(mult, m_ptr);
+ if (snipe_type) mult = tot_dam_aux_snipe(mult, m_ptr, snipe_type);
/* Return the total damage */
return (tdam * mult / 10);
* Note that Bows of "Extra Shots" give an extra shot.
* </pre>
*/
-void exe_fire(INVENTORY_IDX item, object_type *j_ptr)
+void exe_fire(INVENTORY_IDX item, object_type *j_ptr, SPELL_IDX snipe_type)
{
DIRECTION dir;
int i;
}
- /* Take a (partial) turn */
+ /* Take a (partial) current_world_ptr->game_turn */
p_ptr->energy_use = (p_ptr->energy_use / thits);
is_fired = TRUE;
- /* Sniper - Difficult to shot twice at 1 turn */
+ /* Sniper - Difficult to shot twice at 1 current_world_ptr->game_turn */
if (snipe_type == SP_DOUBLE) p_ptr->concent = (p_ptr->concent + 1) / 2;
/* Sniper - Repeat shooting when double shots */
else
{
/* Apply special damage */
- tdam = tot_dam_aux_shot(q_ptr, tdam, m_ptr);
+ tdam = tot_dam_aux_shot(q_ptr, tdam, m_ptr, snipe_type);
tdam = critical_shot(q_ptr->weight, q_ptr->to_h, j_ptr->to_h, tdam);
/* No negative damage */
}
/* Chance of breakage (during attacks) */
- j = (hit_body ? breakage_chance(q_ptr) : 0);
+ j = (hit_body ? breakage_chance(q_ptr, snipe_type) : 0);
if (stick_to)
{
}
+/*!
+ * @brief 射撃時クリティカルによるダメージ期待値修正計算(スナイパーの集中処理と武器経験値) / critical happens at i / 10000
+ * @param plus_ammo 矢弾のダメージ修正
+ * @param plus_bow 弓のダメージ修正
+ * @return ダメージ期待値
+ * @note 基本ダメージ量と重量はこの部位では計算に加わらない。
+ */
+HIT_POINT calc_crit_ratio_shot(HIT_POINT plus_ammo, HIT_POINT plus_bow)
+{
+ HIT_POINT i;
+ object_type *j_ptr = &inventory[INVEN_BOW];
+
+ /* Extract "shot" power */
+ i = p_ptr->to_h_b + plus_ammo;
+
+ if (p_ptr->tval_ammo == TV_BOLT)
+ i = (p_ptr->skill_thb + (p_ptr->weapon_exp[0][j_ptr->sval] / 400 + i) * BTH_PLUS_ADJ);
+ else
+ i = (p_ptr->skill_thb + ((p_ptr->weapon_exp[0][j_ptr->sval] - (WEAPON_EXP_MASTER / 2)) / 200 + i) * BTH_PLUS_ADJ);
+
+ /* Snipers can shot more critically with crossbows */
+ if (p_ptr->concent) i += ((i * p_ptr->concent) / 5);
+ if ((p_ptr->pclass == CLASS_SNIPER) && (p_ptr->tval_ammo == TV_BOLT)) i *= 2;
+
+ /* Good bow makes more critical */
+ i += plus_bow * 8 * (p_ptr->concent ? p_ptr->concent + 5 : 5);
+
+ if (i < 0) i = 0;
+
+ return i;
+}
+
+/*!
+ * @brief 射撃時クリティカルによるダメージ期待値修正計算(重量依存部分) / critical happens at i / 10000
+ * @param weight 武器の重量
+ * @param plus_ammo 矢弾のダメージ修正
+ * @param plus_bow 弓のダメージ修正
+ * @param dam 基本ダメージ量
+ * @return ダメージ期待値
+ */
+HIT_POINT calc_expect_crit_shot(WEIGHT weight, int plus_ammo, int plus_bow, HIT_POINT dam)
+{
+ u32b num;
+ int i, k, crit;
+ i = calc_crit_ratio_shot(plus_ammo, plus_bow);
+
+ k = 0;
+ num = 0;
+
+ crit = MIN(500, 900 / weight);
+ num += dam * 3 / 2 * crit;
+ k = crit;
+
+ crit = MIN(500, 1350 / weight);
+ crit -= k;
+ num += dam * 2 * crit;
+ k += crit;
+
+ if (k < 500)
+ {
+ crit = 500 - k;
+ num += dam * 3 * crit;
+ }
+
+ num /= 500;
+
+ num *= i;
+ num += (10000 - i) * dam;
+ num /= 10000;
+
+ return num;
+}
+
+/*!
+ * @brief 攻撃時クリティカルによるダメージ期待値修正計算(重量と毒針処理) / critical happens at i / 10000
+ * @param weight 武器の重量
+ * @param plus 武器のダメージ修正
+ * @param dam 基本ダメージ
+ * @param meichuu 命中値
+ * @param dokubari 毒針処理か否か
+ * @return ダメージ期待値
+ */
+HIT_POINT calc_expect_crit(WEIGHT weight, int plus, HIT_POINT dam, s16b meichuu, bool dokubari)
+{
+ u32b k, num;
+ int i;
+
+ if (dokubari) return dam;
+
+ i = (weight + (meichuu * 3 + plus * 5) + p_ptr->skill_thn);
+ if (i < 0) i = 0;
+
+ k = weight;
+ num = 0;
+
+ if (k < 400) num += (2 * dam + 5) * (400 - k);
+ if (k < 700) num += (2 * dam + 10) * (MIN(700, k + 650) - MAX(400, k));
+ if (k > (700 - 650) && k < 900) num += (3 * dam + 15) * (MIN(900, k + 650) - MAX(700, k));
+ if (k > (900 - 650) && k < 1300) num += (3 * dam + 20) * (MIN(1300, k + 650) - MAX(900, k));
+ if (k > (1300 - 650)) num += (7 * dam / 2 + 25) * MIN(650, k - (1300 - 650));
+
+ num /= 650;
+ if (p_ptr->pclass == CLASS_NINJA)
+ {
+ num *= i;
+ num += (4444 - i) * dam;
+ num /= 4444;
+ }
+ else
+ {
+ num *= i;
+ num += (5000 - i) * dam;
+ num /= 5000;
+ }
+
+ return num;
+}
+