X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=src%2Fmelee1.c;h=2ec4458512ead9d57fc3bd700c5411141e8d520e;hb=9751a5949c847a3777da5ce04bc585a9da88af1b;hp=74a6e38dfdece2b1fe9454934d0751c0a2f0c33a;hpb=dde770ef16ff93c895d1d69a888cd61172a29452;p=hengband%2Fhengband.git diff --git a/src/melee1.c b/src/melee1.c index 74a6e38df..2ec445851 100644 --- a/src/melee1.c +++ b/src/melee1.c @@ -12,8 +12,100 @@ */ #include "angband.h" +#include "cmd-pet.h" +#include "player-damage.h" +#include "monsterrace-hook.h" +#include "melee.h" + + /*! + * @brief プレイヤーからモンスターへの打撃命中判定 / + * Determine if the player "hits" a monster (normal combat). + * @param chance 基本命中値 + * @param ac モンスターのAC + * @param visible 目標を視界に捕らえているならばTRUEを指定 + * @return 命中と判定された場合TRUEを返す + * @note Always miss 5%, always hit 5%, otherwise random. + */ +bool test_hit_norm(HIT_RELIABILITY chance, ARMOUR_CLASS ac, bool visible) +{ + if (!visible) chance = (chance + 1) / 2; + return hit_chance(chance, ac) >= randint1(100); +} + +/*! + * @brief モンスターへの命中率の計算 + * @param to_h 命中値 + * @param ac 敵AC + * @return 命中確率 + */ +PERCENTAGE hit_chance(HIT_RELIABILITY reli, ARMOUR_CLASS ac) +{ + PERCENTAGE chance = 5, chance_left = 90; + + if (p_ptr->pseikaku == SEIKAKU_NAMAKE) chance_left = (chance_left * 19 + 9) / 20; + chance += (100 - ((ac * 75) / reli)) * chance_left / 100; + + return chance; +} + + + +/*! +* @brief プレイヤーからモンスターへの打撃クリティカル判定 / +* Critical hits (by player) Factor in weapon weight, total plusses, player melee bonus +* @param weight 矢弾の重量 +* @param plus 武器の命中修正 +* @param dam 現在算出中のダメージ値 +* @param meichuu 打撃の基本命中力 +* @param mode オプションフラグ +* @return クリティカル修正が入ったダメージ値 +*/ +HIT_POINT critical_norm(WEIGHT weight, int plus, HIT_POINT dam, s16b meichuu, BIT_FLAGS mode) +{ + int i, k; + + /* Extract "blow" power */ + i = (weight + (meichuu * 3 + plus * 5) + p_ptr->skill_thn); + + /* Chance */ + if ((randint1((p_ptr->pclass == CLASS_NINJA) ? 4444 : 5000) <= i) || (mode == HISSATSU_MAJIN) || (mode == HISSATSU_3DAN)) + { + k = weight + randint1(650); + if ((mode == HISSATSU_MAJIN) || (mode == HISSATSU_3DAN)) k += randint1(650); + + if (k < 400) + { + msg_print(_("手ごたえがあった!", "It was a good hit!")); + + dam = 2 * dam + 5; + } + else if (k < 700) + { + msg_print(_("かなりの手ごたえがあった!", "It was a great hit!")); + dam = 2 * dam + 10; + } + else if (k < 900) + { + msg_print(_("会心の一撃だ!", "It was a superb hit!")); + dam = 3 * dam + 15; + } + else if (k < 1300) + { + msg_print(_("最高の会心の一撃だ!", "It was a *GREAT* hit!")); + dam = 3 * dam + 20; + } + else + { + msg_print(_("比類なき最高の会心の一撃だ!", "It was a *SUPERB* hit!")); + dam = ((7 * dam) / 2) + 25; + } + } + + return (dam); +} + /*! * @brief モンスター打撃のクリティカルランクを返す / * Critical blow. All hits that do 95% of total possible damage, @@ -24,121 +116,1385 @@ * and which also do at least 20 damage, or, sometimes, N damage. * This is used only to determine "cuts" and "stuns". */ -static int monster_critical(int dice, int sides, HIT_POINT dam) +static int monster_critical(DICE_NUMBER dice, DICE_SID sides, HIT_POINT dam) { int max = 0; int total = dice * sides; - /* Must do at least 95% of perfect */ - if (dam < total * 19 / 20) return (0); + /* Must do at least 95% of perfect */ + if (dam < total * 19 / 20) return (0); + + /* Weak blows rarely work */ + if ((dam < 20) && (randint0(100) >= dam)) return (0); + + /* Perfect damage */ + if ((dam >= total) && (dam >= 40)) max++; + + /* Super-charge */ + if (dam >= 20) + { + while (randint0(100) < 2) max++; + } + + /* Critical damage */ + if (dam > 45) return (6 + max); + if (dam > 33) return (5 + max); + if (dam > 25) return (4 + max); + if (dam > 18) return (3 + max); + if (dam > 11) return (2 + max); + return (1 + max); +} + +/*! + * @brief モンスター打撃の命中を判定する / + * Determine if a monster attack against the player succeeds. + * @param power 打撃属性毎の基本命中値 + * @param level モンスターのレベル + * @param stun モンスターの朦朧値 + * @return TRUEならば命中判定 + * @details + * Always miss 5% of the time, Always hit 5% of the time. + * Otherwise, match monster power against player armor. + */ +static int check_hit(int power, DEPTH level, int stun) +{ + int i, k, ac; + + /* Percentile dice */ + k = randint0(100); + + if (stun && one_in_(2)) return FALSE; + + /* Hack -- Always miss or hit */ + if (k < 10) return (k < 5); + + /* Calculate the "attack quality" */ + i = (power + (level * 3)); + + /* Total armor */ + ac = p_ptr->ac + p_ptr->to_a; + if (p_ptr->special_attack & ATTACK_SUIKEN) ac += (p_ptr->lev * 2); + + /* Power and Level compete against Armor */ + if ((i > 0) && (randint1(i) > ((ac * 3) / 4))) return (TRUE); + + /* Assume miss */ + return (FALSE); +} + +/*! モンスターの侮辱行為メッセージテーブル / Hack -- possible "insult" messages */ +static concptr desc_insult[] = +{ +#ifdef JP + "があなたを侮辱した!", + "があなたの母を侮辱した!", + "があなたを軽蔑した!", + "があなたを辱めた!", + "があなたを汚した!", + "があなたの回りで踊った!", + "が猥褻な身ぶりをした!", + "があなたをぼんやりと見た!!!", + "があなたをパラサイト呼ばわりした!", + "があなたをサイボーグ扱いした!" +#else + "insults you!", + "insults your mother!", + "gives you the finger!", + "humiliates you!", + "defiles you!", + "dances around you!", + "makes obscene gestures!", + "moons you!!!" + "calls you a parasite!", + "calls you a cyborg!" +#endif + +}; + +/*! マゴットのぼやきメッセージテーブル / Hack -- possible "insult" messages */ +static concptr desc_moan[] = +{ +#ifdef JP + "は何かを悲しんでいるようだ。", + "が彼の飼い犬を見なかったかと尋ねている。", + "が縄張りから出て行けと言っている。", + "はキノコがどうとか呟いている。" +#else + "seems sad about something.", + "asks if you have seen his dogs.", + "tells you to get off his land.", + "mumbles something about mushrooms." +#endif + +}; + +/*! +* @brief 敵オーラによるプレイヤーのダメージ処理(補助) +* @param m_ptr オーラを持つモンスターの構造体参照ポインタ +* @param immune ダメージを回避できる免疫フラグ +* @param flags_offset オーラフラグ配列の参照オフセット +* @param r_flags_offset モンスターの耐性配列の参照オフセット +* @param aura_flag オーラフラグ配列 +* @param dam_func ダメージ処理を行う関数の参照ポインタ +* @param message オーラダメージを受けた際のメッセージ +* @return なし +*/ +static void touch_zap_player_aux(monster_type *m_ptr, bool immune, int flags_offset, int r_flags_offset, u32b aura_flag, + HIT_POINT(*dam_func)(HIT_POINT dam, concptr kb_str, int monspell, bool aura), concptr message) +{ + monster_race *r_ptr = &r_info[m_ptr->r_idx]; + + if ((atoffset(u32b, r_ptr, flags_offset) & aura_flag) && !immune) + { + GAME_TEXT mon_name[MAX_NLEN]; + int aura_damage = damroll(1 + (r_ptr->level / 26), 1 + (r_ptr->level / 17)); + + /* Hack -- Get the "died from" name */ + monster_desc(mon_name, m_ptr, MD_IGNORE_HALLU | MD_ASSUME_VISIBLE | MD_INDEF_VISIBLE); + + msg_print(message); + + dam_func(aura_damage, mon_name, -1, TRUE); + + if (is_original_ap_and_seen(m_ptr)) + { + atoffset(u32b, r_ptr, r_flags_offset) |= aura_flag; + } + + handle_stuff(); + } +} + +/*! +* @brief 敵オーラによるプレイヤーのダメージ処理(メイン) +* @param m_ptr オーラを持つモンスターの構造体参照ポインタ +* @return なし +*/ +static void touch_zap_player(monster_type *m_ptr) +{ + touch_zap_player_aux(m_ptr, p_ptr->immune_fire, offsetof(monster_race, flags2), offsetof(monster_race, r_flags2), RF2_AURA_FIRE, + fire_dam, _("突然とても熱くなった!", "You are suddenly very hot!")); + touch_zap_player_aux(m_ptr, p_ptr->immune_cold, offsetof(monster_race, flags3), offsetof(monster_race, r_flags3), RF3_AURA_COLD, + cold_dam, _("突然とても寒くなった!", "You are suddenly very cold!")); + touch_zap_player_aux(m_ptr, p_ptr->immune_elec, offsetof(monster_race, flags2), offsetof(monster_race, r_flags2), RF2_AURA_ELEC, + elec_dam, _("電撃をくらった!", "You get zapped!")); +} + +/*! +* @brief プレイヤーの変異要素による打撃処理 +* @param m_idx 攻撃目標となったモンスターの参照ID +* @param attack 変異要素による攻撃要素の種類 +* @param fear 攻撃を受けたモンスターが恐慌状態に陥ったかを返す参照ポインタ +* @param mdeath 攻撃を受けたモンスターが死亡したかを返す参照ポインタ +* @return なし +*/ +static void natural_attack(s16b m_idx, int attack, bool *fear, bool *mdeath) +{ + HIT_POINT k; + int bonus, chance; + int n_weight = 0; + monster_type *m_ptr = &m_list[m_idx]; + monster_race *r_ptr = &r_info[m_ptr->r_idx]; + GAME_TEXT m_name[MAX_NLEN]; + + int dice_num, dice_side; + + concptr atk_desc; + + switch (attack) + { + case MUT2_SCOR_TAIL: + dice_num = 3; + dice_side = 7; + n_weight = 5; + atk_desc = _("尻尾", "tail"); + + break; + case MUT2_HORNS: + dice_num = 2; + dice_side = 6; + n_weight = 15; + atk_desc = _("角", "horns"); + + break; + case MUT2_BEAK: + dice_num = 2; + dice_side = 4; + n_weight = 5; + atk_desc = _("クチバシ", "beak"); + + break; + case MUT2_TRUNK: + dice_num = 1; + dice_side = 4; + n_weight = 35; + atk_desc = _("象の鼻", "trunk"); + + break; + case MUT2_TENTACLES: + dice_num = 2; + dice_side = 5; + n_weight = 5; + atk_desc = _("触手", "tentacles"); + + break; + default: + dice_num = dice_side = n_weight = 1; + atk_desc = _("未定義の部位", "undefined body part"); + + } + + /* Extract monster name (or "it") */ + monster_desc(m_name, m_ptr, 0); + + /* Calculate the "attack quality" */ + bonus = p_ptr->to_h_m + (p_ptr->lev * 6 / 5); + chance = (p_ptr->skill_thn + (bonus * BTH_PLUS_ADJ)); + + /* Test for hit */ + if ((!(r_ptr->flags2 & RF2_QUANTUM) || !randint0(2)) && test_hit_norm(chance, r_ptr->ac, m_ptr->ml)) + { + sound(SOUND_HIT); + msg_format(_("%sを%sで攻撃した。", "You hit %s with your %s."), m_name, atk_desc); + + k = damroll(dice_num, dice_side); + k = critical_norm(n_weight, bonus, k, (s16b)bonus, 0); + + /* Apply the player damage bonuses */ + k += p_ptr->to_d_m; + + /* No negative damage */ + if (k < 0) k = 0; + + /* Modify the damage */ + k = mon_damage_mod(m_ptr, k, FALSE); + + /* Complex message */ + msg_format_wizard(CHEAT_MONSTER, + _("%dのダメージを与えた。(残りHP %d/%d(%d))", "You do %d damage. (left HP %d/%d(%d))"), + k, m_ptr->hp - k, m_ptr->maxhp, m_ptr->max_maxhp); + + /* Anger the monster */ + if (k > 0) anger_monster(m_ptr); + + /* Damage, check for fear and mdeath */ + switch (attack) + { + case MUT2_SCOR_TAIL: + project(0, 0, m_ptr->fy, m_ptr->fx, k, GF_POIS, PROJECT_KILL, -1); + *mdeath = (m_ptr->r_idx == 0); + break; + case MUT2_HORNS: + *mdeath = mon_take_hit(m_idx, k, fear, NULL); + break; + case MUT2_BEAK: + *mdeath = mon_take_hit(m_idx, k, fear, NULL); + break; + case MUT2_TRUNK: + *mdeath = mon_take_hit(m_idx, k, fear, NULL); + break; + case MUT2_TENTACLES: + *mdeath = mon_take_hit(m_idx, k, fear, NULL); + break; + default: + *mdeath = mon_take_hit(m_idx, k, fear, NULL); + } + + touch_zap_player(m_ptr); + } + /* Player misses */ + else + { + sound(SOUND_MISS); + msg_format(_("ミス! %sにかわされた。", "You miss %s."), m_name); + } +} + +/*! +* @brief プレイヤーの打撃処理サブルーチン / +* Player attacks a (poor, defenseless) creature -RAK- +* @param y 攻撃目標のY座標 +* @param x 攻撃目標のX座標 +* @param fear 攻撃を受けたモンスターが恐慌状態に陥ったかを返す参照ポインタ +* @param mdeath 攻撃を受けたモンスターが死亡したかを返す参照ポインタ +* @param hand 攻撃を行うための武器を持つ手 +* @param mode 発動中の剣術ID +* @return なし +* @details +* If no "weapon" is available, then "punch" the monster one time. +*/ +static void py_attack_aux(POSITION y, POSITION x, bool *fear, bool *mdeath, s16b hand, BIT_FLAGS mode) +{ + int num = 0, bonus, chance, vir; + HIT_POINT k; + + cave_type *c_ptr = &cave[y][x]; + + monster_type *m_ptr = &m_list[c_ptr->m_idx]; + monster_race *r_ptr = &r_info[m_ptr->r_idx]; + + /* Access the weapon */ + object_type *o_ptr = &inventory[INVEN_RARM + hand]; + + GAME_TEXT m_name[MAX_NLEN]; + + bool success_hit = FALSE; + bool backstab = FALSE; + bool vorpal_cut = FALSE; + int chaos_effect = 0; + bool stab_fleeing = FALSE; + bool fuiuchi = FALSE; + bool monk_attack = FALSE; + bool do_quake = FALSE; + bool weak = FALSE; + bool drain_msg = TRUE; + int drain_result = 0, drain_heal = 0; + bool can_drain = FALSE; + int num_blow; + int drain_left = MAX_VAMPIRIC_DRAIN; + BIT_FLAGS flgs[TR_FLAG_SIZE]; /* A massive hack -- life-draining weapons */ + bool is_human = (r_ptr->d_char == 'p'); + bool is_lowlevel = (r_ptr->level < (p_ptr->lev - 15)); + bool zantetsu_mukou, e_j_mukou; + + switch (p_ptr->pclass) + { + case CLASS_ROGUE: + case CLASS_NINJA: + if (buki_motteruka(INVEN_RARM + hand) && !p_ptr->icky_wield[hand]) + { + int tmp = p_ptr->lev * 6 + (p_ptr->skill_stl + 10) * 4; + if (p_ptr->monlite && (mode != HISSATSU_NYUSIN)) tmp /= 3; + if (p_ptr->cursed & TRC_AGGRAVATE) tmp /= 2; + if (r_ptr->level > (p_ptr->lev * p_ptr->lev / 20 + 10)) tmp /= 3; + if (MON_CSLEEP(m_ptr) && m_ptr->ml) + { + /* Can't backstab creatures that we can't see, right? */ + backstab = TRUE; + } + else if ((p_ptr->special_defense & NINJA_S_STEALTH) && (randint0(tmp) > (r_ptr->level + 20)) && m_ptr->ml && !(r_ptr->flagsr & RFR_RES_ALL)) + { + fuiuchi = TRUE; + } + else if (MON_MONFEAR(m_ptr) && m_ptr->ml) + { + stab_fleeing = TRUE; + } + } + break; + + case CLASS_MONK: + case CLASS_FORCETRAINER: + case CLASS_BERSERKER: + if ((empty_hands(TRUE) & EMPTY_HAND_RARM) && !p_ptr->riding) monk_attack = TRUE; + break; + } + + if (!o_ptr->k_idx) /* Empty hand */ + { + if ((r_ptr->level + 10) > p_ptr->lev) + { + if (p_ptr->skill_exp[GINOU_SUDE] < s_info[p_ptr->pclass].s_max[GINOU_SUDE]) + { + if (p_ptr->skill_exp[GINOU_SUDE] < WEAPON_EXP_BEGINNER) + p_ptr->skill_exp[GINOU_SUDE] += 40; + else if ((p_ptr->skill_exp[GINOU_SUDE] < WEAPON_EXP_SKILLED)) + p_ptr->skill_exp[GINOU_SUDE] += 5; + else if ((p_ptr->skill_exp[GINOU_SUDE] < WEAPON_EXP_EXPERT) && (p_ptr->lev > 19)) + p_ptr->skill_exp[GINOU_SUDE] += 1; + else if ((p_ptr->lev > 34)) + if (one_in_(3)) p_ptr->skill_exp[GINOU_SUDE] += 1; + p_ptr->update |= (PU_BONUS); + } + } + } + else if (object_is_melee_weapon(o_ptr)) + { + if ((r_ptr->level + 10) > p_ptr->lev) + { + OBJECT_TYPE_VALUE tval = inventory[INVEN_RARM + hand].tval - TV_WEAPON_BEGIN; + OBJECT_SUBTYPE_VALUE sval = inventory[INVEN_RARM + hand].sval; + int now_exp = p_ptr->weapon_exp[tval][sval]; + if (now_exp < s_info[p_ptr->pclass].w_max[tval][sval]) + { + SUB_EXP amount = 0; + if (now_exp < WEAPON_EXP_BEGINNER) amount = 80; + else if (now_exp < WEAPON_EXP_SKILLED) amount = 10; + else if ((now_exp < WEAPON_EXP_EXPERT) && (p_ptr->lev > 19)) amount = 1; + else if ((p_ptr->lev > 34) && one_in_(2)) amount = 1; + p_ptr->weapon_exp[tval][sval] += amount; + p_ptr->update |= (PU_BONUS); + } + } + } + + /* Disturb the monster */ + (void)set_monster_csleep(c_ptr->m_idx, 0); + + /* Extract monster name (or "it") */ + monster_desc(m_name, m_ptr, 0); + + /* Calculate the "attack quality" */ + bonus = p_ptr->to_h[hand] + o_ptr->to_h; + chance = (p_ptr->skill_thn + (bonus * BTH_PLUS_ADJ)); + if (mode == HISSATSU_IAI) chance += 60; + if (p_ptr->special_defense & KATA_KOUKIJIN) chance += 150; + if (p_ptr->sutemi) chance = MAX(chance * 3 / 2, chance + 60); + + vir = virtue_number(V_VALOUR); + if (vir) + { + chance += (p_ptr->virtues[vir - 1] / 10); + } + + zantetsu_mukou = ((o_ptr->name1 == ART_ZANTETSU) && (r_ptr->d_char == 'j')); + e_j_mukou = ((o_ptr->name1 == ART_EXCALIBUR_J) && (r_ptr->d_char == 'S')); + + if ((mode == HISSATSU_KYUSHO) || (mode == HISSATSU_MINEUCHI) || (mode == HISSATSU_3DAN) || (mode == HISSATSU_IAI)) num_blow = 1; + else if (mode == HISSATSU_COLD) num_blow = p_ptr->num_blow[hand] + 2; + else num_blow = p_ptr->num_blow[hand]; + + /* Hack -- DOKUBARI always hit once */ + if ((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_DOKUBARI)) num_blow = 1; + + /* Attack once for each legal blow */ + while ((num++ < num_blow) && !p_ptr->is_dead) + { + if (((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_DOKUBARI)) || (mode == HISSATSU_KYUSHO)) + { + int n = 1; + + if (p_ptr->migite && p_ptr->hidarite) + { + n *= 2; + } + if (mode == HISSATSU_3DAN) + { + n *= 2; + } + + success_hit = one_in_(n); + } + else if ((p_ptr->pclass == CLASS_NINJA) && ((backstab || fuiuchi) && !(r_ptr->flagsr & RFR_RES_ALL))) success_hit = TRUE; + else success_hit = test_hit_norm(chance, r_ptr->ac, m_ptr->ml); + + if (mode == HISSATSU_MAJIN) + { + if (one_in_(2)) + success_hit = FALSE; + } + + /* Test for hit */ + if (success_hit) + { + int vorpal_chance = ((o_ptr->name1 == ART_VORPAL_BLADE) || (o_ptr->name1 == ART_CHAINSWORD)) ? 2 : 4; + + sound(SOUND_HIT); + + if (backstab) msg_format(_("あなたは冷酷にも眠っている無力な%sを突き刺した!", "You cruelly stab the helpless, sleeping %s!"), m_name); + else if (fuiuchi) msg_format(_("不意を突いて%sに強烈な一撃を喰らわせた!", "You make surprise attack, and hit %s with a powerful blow!"), m_name); + else if (stab_fleeing) msg_format(_("逃げる%sを背中から突き刺した!", "You backstab the fleeing %s!"), m_name); + else if (!monk_attack) msg_format(_("%sを攻撃した。", "You hit %s."), m_name); + + /* Hack -- bare hands do one damage */ + k = 1; + + object_flags(o_ptr, flgs); + + /* Select a chaotic effect (50% chance) */ + if ((have_flag(flgs, TR_CHAOTIC)) && one_in_(2)) + { + if (one_in_(10)) + chg_virtue(V_CHANCE, 1); + + if (randint1(5) < 3) + { + /* Vampiric (20%) */ + chaos_effect = 1; + } + else if (one_in_(250)) + { + /* Quake (0.12%) */ + chaos_effect = 2; + } + else if (!one_in_(10)) + { + /* Confusion (26.892%) */ + chaos_effect = 3; + } + else if (one_in_(2)) + { + /* Teleport away (1.494%) */ + chaos_effect = 4; + } + else + { + /* Polymorph (1.494%) */ + chaos_effect = 5; + } + } + + /* Vampiric drain */ + if ((have_flag(flgs, TR_VAMPIRIC)) || (chaos_effect == 1) || (mode == HISSATSU_DRAIN) || hex_spelling(HEX_VAMP_BLADE)) + { + /* Only drain "living" monsters */ + if (monster_living(m_ptr->r_idx)) + can_drain = TRUE; + else + can_drain = FALSE; + } + + if ((have_flag(flgs, TR_VORPAL) || hex_spelling(HEX_RUNESWORD)) && (randint1(vorpal_chance * 3 / 2) == 1) && !zantetsu_mukou) + vorpal_cut = TRUE; + else vorpal_cut = FALSE; + + if (monk_attack) + { + int special_effect = 0, stun_effect = 0, times = 0, max_times; + int min_level = 1; + const martial_arts *ma_ptr = &ma_blows[0], *old_ptr = &ma_blows[0]; + int resist_stun = 0; + WEIGHT weight = 8; + + if (r_ptr->flags1 & RF1_UNIQUE) resist_stun += 88; + if (r_ptr->flags3 & RF3_NO_STUN) resist_stun += 66; + if (r_ptr->flags3 & RF3_NO_CONF) resist_stun += 33; + if (r_ptr->flags3 & RF3_NO_SLEEP) resist_stun += 33; + if ((r_ptr->flags3 & RF3_UNDEAD) || (r_ptr->flags3 & RF3_NONLIVING)) + resist_stun += 66; + + if (p_ptr->special_defense & KAMAE_BYAKKO) + max_times = (p_ptr->lev < 3 ? 1 : p_ptr->lev / 3); + else if (p_ptr->special_defense & KAMAE_SUZAKU) + max_times = 1; + else if (p_ptr->special_defense & KAMAE_GENBU) + max_times = 1; + else + max_times = (p_ptr->lev < 7 ? 1 : p_ptr->lev / 7); + /* Attempt 'times' */ + for (times = 0; times < max_times; times++) + { + do + { + ma_ptr = &ma_blows[randint0(MAX_MA)]; + if ((p_ptr->pclass == CLASS_FORCETRAINER) && (ma_ptr->min_level > 1)) min_level = ma_ptr->min_level + 3; + else min_level = ma_ptr->min_level; + } while ((min_level > p_ptr->lev) || + (randint1(p_ptr->lev) < ma_ptr->chance)); + + /* keep the highest level attack available we found */ + if ((ma_ptr->min_level > old_ptr->min_level) && + !p_ptr->stun && !p_ptr->confused) + { + old_ptr = ma_ptr; + + if (p_ptr->wizard && cheat_xtra) + { + msg_print(_("攻撃を再選択しました。", "Attack re-selected.")); + } + } + else + { + ma_ptr = old_ptr; + } + } + + if (p_ptr->pclass == CLASS_FORCETRAINER) min_level = MAX(1, ma_ptr->min_level - 3); + else min_level = ma_ptr->min_level; + k = damroll(ma_ptr->dd + p_ptr->to_dd[hand], ma_ptr->ds + p_ptr->to_ds[hand]); + if (p_ptr->special_attack & ATTACK_SUIKEN) k *= 2; + + if (ma_ptr->effect == MA_KNEE) + { + if (r_ptr->flags1 & RF1_MALE) + { + msg_format(_("%sに金的膝蹴りをくらわした!", "You hit %s in the groin with your knee!"), m_name); + sound(SOUND_PAIN); + special_effect = MA_KNEE; + } + else + msg_format(ma_ptr->desc, m_name); + } + + else if (ma_ptr->effect == MA_SLOW) + { + if (!((r_ptr->flags1 & RF1_NEVER_MOVE) || + my_strchr("~#{}.UjmeEv$,DdsbBFIJQSXclnw!=?", r_ptr->d_char))) + { + msg_format(_("%sの足首に関節蹴りをくらわした!", "You kick %s in the ankle."), m_name); + special_effect = MA_SLOW; + } + else msg_format(ma_ptr->desc, m_name); + } + else + { + if (ma_ptr->effect) + { + stun_effect = (ma_ptr->effect / 2) + randint1(ma_ptr->effect / 2); + } + + msg_format(ma_ptr->desc, m_name); + } + + if (p_ptr->special_defense & KAMAE_SUZAKU) weight = 4; + if ((p_ptr->pclass == CLASS_FORCETRAINER) && P_PTR_KI) + { + weight += (P_PTR_KI / 30); + if (weight > 20) weight = 20; + } + + k = critical_norm(p_ptr->lev * weight, min_level, k, p_ptr->to_h[0], 0); + + if ((special_effect == MA_KNEE) && ((k + p_ptr->to_d[hand]) < m_ptr->hp)) + { + msg_format(_("%^sは苦痛にうめいている!", "%^s moans in agony!"), m_name); + stun_effect = 7 + randint1(13); + resist_stun /= 3; + } + + else if ((special_effect == MA_SLOW) && ((k + p_ptr->to_d[hand]) < m_ptr->hp)) + { + if (!(r_ptr->flags1 & RF1_UNIQUE) && + (randint1(p_ptr->lev) > r_ptr->level) && + m_ptr->mspeed > 60) + { + msg_format(_("%^sは足をひきずり始めた。", "%^s starts limping slower."), m_name); + m_ptr->mspeed -= 10; + } + } + + if (stun_effect && ((k + p_ptr->to_d[hand]) < m_ptr->hp)) + { + if (p_ptr->lev > randint1(r_ptr->level + resist_stun + 10)) + { + if (set_monster_stunned(c_ptr->m_idx, stun_effect + MON_STUNNED(m_ptr))) + { + msg_format(_("%^sはフラフラになった。", "%^s is stunned."), m_name); + } + else + { + msg_format(_("%^sはさらにフラフラになった。", "%^s is more stunned."), m_name); + } + } + } + } + + /* Handle normal weapon */ + else if (o_ptr->k_idx) + { + k = damroll(o_ptr->dd + p_ptr->to_dd[hand], o_ptr->ds + p_ptr->to_ds[hand]); + k = tot_dam_aux(o_ptr, k, m_ptr, mode, FALSE); + + if (backstab) + { + k *= (3 + (p_ptr->lev / 20)); + } + else if (fuiuchi) + { + k = k*(5 + (p_ptr->lev * 2 / 25)) / 2; + } + else if (stab_fleeing) + { + k = (3 * k) / 2; + } + + if ((p_ptr->impact[hand] && ((k > 50) || one_in_(7))) || + (chaos_effect == 2) || (mode == HISSATSU_QUAKE)) + { + do_quake = TRUE; + } + + if ((!(o_ptr->tval == TV_SWORD) || !(o_ptr->sval == SV_DOKUBARI)) && !(mode == HISSATSU_KYUSHO)) + k = critical_norm(o_ptr->weight, o_ptr->to_h, k, p_ptr->to_h[hand], mode); + + drain_result = k; + + if (vorpal_cut) + { + int mult = 2; + + if ((o_ptr->name1 == ART_CHAINSWORD) && !one_in_(2)) + { + char chainsword_noise[1024]; + if (!get_rnd_line(_("chainswd_j.txt", "chainswd.txt"), 0, chainsword_noise)) + { + msg_print(chainsword_noise); + } + } + + if (o_ptr->name1 == ART_VORPAL_BLADE) + { + msg_print(_("目にも止まらぬヴォーパルブレード、手錬の早業!", "Your Vorpal Blade goes snicker-snack!")); + } + else + { + msg_format(_("%sをグッサリ切り裂いた!", "Your weapon cuts deep into %s!"), m_name); + } + + /* Try to increase the damage */ + while (one_in_(vorpal_chance)) + { + mult++; + } + + k *= (HIT_POINT)mult; + + /* Ouch! */ + if (((r_ptr->flagsr & RFR_RES_ALL) ? k / 100 : k) > m_ptr->hp) + { + msg_format(_("%sを真っ二つにした!", "You cut %s in half!"), m_name); + } + else + { + switch (mult) + { + case 2: msg_format(_("%sを斬った!", "You gouge %s!"), m_name); break; + case 3: msg_format(_("%sをぶった斬った!", "You maim %s!"), m_name); break; + case 4: msg_format(_("%sをメッタ斬りにした!", "You carve %s!"), m_name); break; + case 5: msg_format(_("%sをメッタメタに斬った!", "You cleave %s!"), m_name); break; + case 6: msg_format(_("%sを刺身にした!", "You smite %s!"), m_name); break; + case 7: msg_format(_("%sを斬って斬って斬りまくった!", "You eviscerate %s!"), m_name); break; + default: msg_format(_("%sを細切れにした!", "You shred %s!"), m_name); break; + } + } + drain_result = drain_result * 3 / 2; + } + + k += o_ptr->to_d; + drain_result += o_ptr->to_d; + } + + /* Apply the player damage bonuses */ + k += p_ptr->to_d[hand]; + drain_result += p_ptr->to_d[hand]; + + if ((mode == HISSATSU_SUTEMI) || (mode == HISSATSU_3DAN)) k *= 2; + if ((mode == HISSATSU_SEKIRYUKA) && !monster_living(m_ptr->r_idx)) k = 0; + if ((mode == HISSATSU_SEKIRYUKA) && !p_ptr->cut) k /= 2; + + /* No negative damage */ + if (k < 0) k = 0; + + if ((mode == HISSATSU_ZANMA) && !(!monster_living(m_ptr->r_idx) && (r_ptr->flags3 & RF3_EVIL))) + { + k = 0; + } + + if (zantetsu_mukou) + { + msg_print(_("こんな軟らかいものは切れん!", "You cannot cut such a elastic thing!")); + k = 0; + } + + if (e_j_mukou) + { + msg_print(_("蜘蛛は苦手だ!", "Spiders are difficult for you to deal with!")); + k /= 2; + } + + if (mode == HISSATSU_MINEUCHI) + { + int tmp = (10 + randint1(15) + p_ptr->lev / 5); + + k = 0; + anger_monster(m_ptr); + + if (!(r_ptr->flags3 & (RF3_NO_STUN))) + { + /* Get stunned */ + if (MON_STUNNED(m_ptr)) + { + msg_format(_("%sはひどくもうろうとした。", "%s is more dazed."), m_name); + tmp /= 2; + } + else + { + msg_format(_("%s はもうろうとした。", "%s is dazed."), m_name); + } + + /* Apply stun */ + (void)set_monster_stunned(c_ptr->m_idx, MON_STUNNED(m_ptr) + tmp); + } + else + { + msg_format(_("%s には効果がなかった。", "%s is not effected."), m_name); + } + } + + /* Modify the damage */ + k = mon_damage_mod(m_ptr, k, (bool)(((o_ptr->tval == TV_POLEARM) && (o_ptr->sval == SV_DEATH_SCYTHE)) || ((p_ptr->pclass == CLASS_BERSERKER) && one_in_(2)))); + if (((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_DOKUBARI)) || (mode == HISSATSU_KYUSHO)) + { + if ((randint1(randint1(r_ptr->level / 7) + 5) == 1) && !(r_ptr->flags1 & RF1_UNIQUE) && !(r_ptr->flags7 & RF7_UNIQUE2)) + { + k = m_ptr->hp + 1; + msg_format(_("%sの急所を突き刺した!", "You hit %s on a fatal spot!"), m_name); + } + else k = 1; + } + else if ((p_ptr->pclass == CLASS_NINJA) && buki_motteruka(INVEN_RARM + hand) && !p_ptr->icky_wield[hand] && ((p_ptr->cur_lite <= 0) || one_in_(7))) + { + int maxhp = maxroll(r_ptr->hdice, r_ptr->hside); + if (one_in_(backstab ? 13 : (stab_fleeing || fuiuchi) ? 15 : 27)) + { + k *= 5; + drain_result *= 2; + msg_format(_("刃が%sに深々と突き刺さった!", "You critically injured %s!"), m_name); + } + else if (((m_ptr->hp < maxhp / 2) && one_in_((p_ptr->num_blow[0] + p_ptr->num_blow[1] + 1) * 10)) || ((one_in_(666) || ((backstab || fuiuchi) && one_in_(11))) && !(r_ptr->flags1 & RF1_UNIQUE) && !(r_ptr->flags7 & RF7_UNIQUE2))) + { + if ((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->flags7 & RF7_UNIQUE2) || (m_ptr->hp >= maxhp / 2)) + { + k = MAX(k * 5, m_ptr->hp / 2); + drain_result *= 2; + msg_format(_("%sに致命傷を負わせた!", "You fatally injured %s!"), m_name); + } + else + { + k = m_ptr->hp + 1; + msg_format(_("刃が%sの急所を貫いた!", "You hit %s on a fatal spot!"), m_name); + } + } + } + + msg_format_wizard(CHEAT_MONSTER, + _("%dのダメージを与えた。(残りHP %d/%d(%d))", "You do %d damage. (left HP %d/%d(%d))"), k, + m_ptr->hp - k, m_ptr->maxhp, m_ptr->max_maxhp); + + if (k <= 0) can_drain = FALSE; + + if (drain_result > m_ptr->hp) + drain_result = m_ptr->hp; + + /* Damage, check for fear and death */ + if (mon_take_hit(c_ptr->m_idx, k, fear, NULL)) + { + *mdeath = TRUE; + if ((p_ptr->pclass == CLASS_BERSERKER) && p_ptr->energy_use) + { + if (p_ptr->migite && p_ptr->hidarite) + { + if (hand) p_ptr->energy_use = p_ptr->energy_use * 3 / 5 + p_ptr->energy_use*num * 2 / (p_ptr->num_blow[hand] * 5); + else p_ptr->energy_use = p_ptr->energy_use*num * 3 / (p_ptr->num_blow[hand] * 5); + } + else + { + p_ptr->energy_use = p_ptr->energy_use*num / p_ptr->num_blow[hand]; + } + } + if ((o_ptr->name1 == ART_ZANTETSU) && is_lowlevel) + msg_print(_("またつまらぬものを斬ってしまった...", "Sigh... Another trifling thing I've cut....")); + break; + } + + /* Anger the monster */ + if (k > 0) anger_monster(m_ptr); + + touch_zap_player(m_ptr); + + /* Are we draining it? A little note: If the monster is + dead, the drain does not work... */ + + if (can_drain && (drain_result > 0)) + { + if (o_ptr->name1 == ART_MURAMASA) + { + if (is_human) + { + HIT_PROB to_h = o_ptr->to_h; + HIT_POINT to_d = o_ptr->to_d; + int i, flag; + + flag = 1; + for (i = 0; i < to_h + 3; i++) if (one_in_(4)) flag = 0; + if (flag) to_h++; + + flag = 1; + for (i = 0; i < to_d + 3; i++) if (one_in_(4)) flag = 0; + if (flag) to_d++; + + if (o_ptr->to_h != to_h || o_ptr->to_d != to_d) + { + msg_print(_("妖刀は血を吸って強くなった!", "Muramasa sucked blood, and became more powerful!")); + o_ptr->to_h = to_h; + o_ptr->to_d = to_d; + } + } + } + else + { + if (drain_result > 5) /* Did we really hurt it? */ + { + drain_heal = damroll(2, drain_result / 6); + + /* Hex */ + if (hex_spelling(HEX_VAMP_BLADE)) drain_heal *= 2; + + if (cheat_xtra) + { + msg_format(_("Draining left: %d", "Draining left: %d"), drain_left); + } + + if (drain_left) + { + if (drain_heal < drain_left) + { + drain_left -= drain_heal; + } + else + { + drain_heal = drain_left; + drain_left = 0; + } + + if (drain_msg) + { + msg_format(_("刃が%sから生命力を吸い取った!", "Your weapon drains life from %s!"), m_name); + drain_msg = FALSE; + } + + drain_heal = (drain_heal * mutant_regenerate_mod) / 100; + + hp_player(drain_heal); + /* We get to keep some of it! */ + } + } + } + m_ptr->maxhp -= (k + 7) / 8; + if (m_ptr->hp > m_ptr->maxhp) m_ptr->hp = m_ptr->maxhp; + if (m_ptr->maxhp < 1) m_ptr->maxhp = 1; + weak = TRUE; + } + can_drain = FALSE; + drain_result = 0; + + /* Confusion attack */ + if ((p_ptr->special_attack & ATTACK_CONFUSE) || (chaos_effect == 3) || (mode == HISSATSU_CONF) || hex_spelling(HEX_CONFUSION)) + { + /* Cancel glowing hands */ + if (p_ptr->special_attack & ATTACK_CONFUSE) + { + p_ptr->special_attack &= ~(ATTACK_CONFUSE); + msg_print(_("手の輝きがなくなった。", "Your hands stop glowing.")); + p_ptr->redraw |= (PR_STATUS); + + } + + /* Confuse the monster */ + if (r_ptr->flags3 & RF3_NO_CONF) + { + if (is_original_ap_and_seen(m_ptr)) r_ptr->r_flags3 |= RF3_NO_CONF; + msg_format(_("%^sには効果がなかった。", "%^s is unaffected."), m_name); + + } + else if (randint0(100) < r_ptr->level) + { + msg_format(_("%^sには効果がなかった。", "%^s is unaffected."), m_name); + } + else + { + msg_format(_("%^sは混乱したようだ。", "%^s appears confused."), m_name); + (void)set_monster_confused(c_ptr->m_idx, MON_CONFUSED(m_ptr) + 10 + randint0(p_ptr->lev) / 5); + } + } + + else if (chaos_effect == 4) + { + bool resists_tele = FALSE; + + if (r_ptr->flagsr & RFR_RES_TELE) + { + if (r_ptr->flags1 & RF1_UNIQUE) + { + if (is_original_ap_and_seen(m_ptr)) r_ptr->r_flagsr |= RFR_RES_TELE; + msg_format(_("%^sには効果がなかった。", "%^s is unaffected!"), m_name); + resists_tele = TRUE; + } + else if (r_ptr->level > randint1(100)) + { + if (is_original_ap_and_seen(m_ptr)) r_ptr->r_flagsr |= RFR_RES_TELE; + msg_format(_("%^sは抵抗力を持っている!", "%^s resists!"), m_name); + resists_tele = TRUE; + } + } + + if (!resists_tele) + { + msg_format(_("%^sは消えた!", "%^s disappears!"), m_name); + teleport_away(c_ptr->m_idx, 50, TELEPORT_PASSIVE); + num = num_blow + 1; /* Can't hit it anymore! */ + *mdeath = TRUE; + } + } + + else if ((chaos_effect == 5) && (randint1(90) > r_ptr->level)) + { + if (!(r_ptr->flags1 & (RF1_UNIQUE | RF1_QUESTOR)) && + !(r_ptr->flagsr & RFR_EFF_RES_CHAO_MASK)) + { + if (polymorph_monster(y, x)) + { + msg_format(_("%^sは変化した!", "%^s changes!"), m_name); + *fear = FALSE; + weak = FALSE; + } + else + { + msg_format(_("%^sには効果がなかった。", "%^s is unaffected."), m_name); + } + + /* Hack -- Get new monster */ + m_ptr = &m_list[c_ptr->m_idx]; - /* Weak blows rarely work */ - if ((dam < 20) && (randint0(100) >= dam)) return (0); + /* Oops, we need a different name... */ + monster_desc(m_name, m_ptr, 0); - /* Perfect damage */ - if ((dam >= total) && (dam >= 40)) max++; + /* Hack -- Get new race */ + r_ptr = &r_info[m_ptr->r_idx]; + } + } + else if (o_ptr->name1 == ART_G_HAMMER) + { + monster_type *target_ptr = &m_list[c_ptr->m_idx]; - /* Super-charge */ - if (dam >= 20) - { - while (randint0(100) < 2) max++; + if (target_ptr->hold_o_idx) + { + object_type *q_ptr = &o_list[target_ptr->hold_o_idx]; + GAME_TEXT o_name[MAX_NLEN]; + + object_desc(o_name, q_ptr, OD_NAME_ONLY); + q_ptr->held_m_idx = 0; + q_ptr->marked = OM_TOUCHED; + target_ptr->hold_o_idx = q_ptr->next_o_idx; + q_ptr->next_o_idx = 0; + msg_format(_("%sを奪った。", "You snatched %s."), o_name); + inven_carry(q_ptr); + } + } + } + + /* Player misses */ + else + { + backstab = FALSE; /* Clumsy! */ + fuiuchi = FALSE; /* Clumsy! */ + + if ((o_ptr->tval == TV_POLEARM) && (o_ptr->sval == SV_DEATH_SCYTHE) && one_in_(3)) + { + BIT_FLAGS flgs_aux[TR_FLAG_SIZE]; + + sound(SOUND_HIT); + + msg_format(_("ミス! %sにかわされた。", "You miss %s."), m_name); + msg_print(_("振り回した大鎌が自分自身に返ってきた!", "Your scythe returns to you!")); + object_flags(o_ptr, flgs_aux); + + k = damroll(o_ptr->dd + p_ptr->to_dd[hand], o_ptr->ds + p_ptr->to_ds[hand]); + { + int mult; + switch (p_ptr->mimic_form) + { + case MIMIC_NONE: + switch (p_ptr->prace) + { + case RACE_YEEK: + case RACE_KLACKON: + case RACE_HUMAN: + case RACE_AMBERITE: + case RACE_DUNADAN: + case RACE_BARBARIAN: + case RACE_BEASTMAN: + mult = 25; break; + case RACE_HALF_ORC: + case RACE_HALF_TROLL: + case RACE_HALF_OGRE: + case RACE_HALF_GIANT: + case RACE_HALF_TITAN: + case RACE_CYCLOPS: + case RACE_IMP: + case RACE_SKELETON: + case RACE_ZOMBIE: + case RACE_VAMPIRE: + case RACE_SPECTRE: + case RACE_DEMON: + case RACE_DRACONIAN: + mult = 30; break; + default: + mult = 10; break; + } + break; + case MIMIC_DEMON: + case MIMIC_DEMON_LORD: + case MIMIC_VAMPIRE: + mult = 30; break; + default: + mult = 10; break; + } + + if (p_ptr->align < 0 && mult < 20) + mult = 20; + if (!(p_ptr->resist_acid || IS_OPPOSE_ACID() || p_ptr->immune_acid) && (mult < 25)) + mult = 25; + if (!(p_ptr->resist_elec || IS_OPPOSE_ELEC() || p_ptr->immune_elec) && (mult < 25)) + mult = 25; + if (!(p_ptr->resist_fire || IS_OPPOSE_FIRE() || p_ptr->immune_fire) && (mult < 25)) + mult = 25; + if (!(p_ptr->resist_cold || IS_OPPOSE_COLD() || p_ptr->immune_cold) && (mult < 25)) + mult = 25; + if (!(p_ptr->resist_pois || IS_OPPOSE_POIS()) && (mult < 25)) + mult = 25; + + if ((p_ptr->pclass != CLASS_SAMURAI) && (have_flag(flgs_aux, TR_FORCE_WEAPON)) && (p_ptr->csp >(p_ptr->msp / 30))) + { + p_ptr->csp -= (1 + (p_ptr->msp / 30)); + p_ptr->redraw |= (PR_MANA); + mult = mult * 3 / 2 + 20; + } + k *= (HIT_POINT)mult; + k /= 10; + } + + k = critical_norm(o_ptr->weight, o_ptr->to_h, k, p_ptr->to_h[hand], mode); + if (one_in_(6)) + { + int mult = 2; + msg_format(_("グッサリ切り裂かれた!", "Your weapon cuts deep into yourself!")); + /* Try to increase the damage */ + while (one_in_(4)) + { + mult++; + } + + k *= (HIT_POINT)mult; + } + k += (p_ptr->to_d[hand] + o_ptr->to_d); + if (k < 0) k = 0; + + take_hit(DAMAGE_FORCE, k, _("死の大鎌", "Death scythe"), -1); + handle_stuff(); + } + else + { + sound(SOUND_MISS); + msg_format(_("ミス! %sにかわされた。", "You miss %s."), m_name); + } + } + backstab = FALSE; + fuiuchi = FALSE; } - /* Critical damage */ - if (dam > 45) return (6 + max); - if (dam > 33) return (5 + max); - if (dam > 25) return (4 + max); - if (dam > 18) return (3 + max); - if (dam > 11) return (2 + max); - return (1 + max); + + if (weak && !(*mdeath)) + { + msg_format(_("%sは弱くなったようだ。", "%^s seems weakened."), m_name); + } + if (drain_left != MAX_VAMPIRIC_DRAIN) + { + if (one_in_(4)) + { + chg_virtue(V_UNLIFE, 1); + } + } + /* Mega-Hack -- apply earthquake brand */ + if (do_quake) + { + earthquake(p_ptr->y, p_ptr->x, 10); + if (!cave[y][x].m_idx) *mdeath = TRUE; + } } /*! - * @brief モンスター打撃の命中を判定する / - * Determine if a monster attack against the player succeeds. - * @param power 打撃属性毎の基本命中値 - * @param level モンスターのレベル - * @param stun モンスターの朦朧値 - * @return TRUEならば命中判定 - * @details - * Always miss 5% of the time, Always hit 5% of the time. - * Otherwise, match monster power against player armor. - */ -static int check_hit(int power, int level, int stun) +* @brief プレイヤーの打撃処理メインルーチン +* @param y 攻撃目標のY座標 +* @param x 攻撃目標のX座標 +* @param mode 発動中の剣術ID +* @return 実際に攻撃処理が行われた場合TRUEを返す。 +* @details +* If no "weapon" is available, then "punch" the monster one time. +*/ +bool py_attack(POSITION y, POSITION x, BIT_FLAGS mode) { - int i, k, ac; + bool fear = FALSE; + bool mdeath = FALSE; + bool stormbringer = FALSE; - /* Percentile dice */ - k = randint0(100); + cave_type *c_ptr = &cave[y][x]; + monster_type *m_ptr = &m_list[c_ptr->m_idx]; + monster_race *r_ptr = &r_info[m_ptr->r_idx]; + GAME_TEXT m_name[MAX_NLEN]; - if (stun && one_in_(2)) return FALSE; + disturb(FALSE, TRUE); - /* Hack -- Always miss or hit */ - if (k < 10) return (k < 5); + p_ptr->energy_use = 100; - /* Calculate the "attack quality" */ - i = (power + (level * 3)); + if (!p_ptr->migite && !p_ptr->hidarite && + !(p_ptr->muta2 & (MUT2_HORNS | MUT2_BEAK | MUT2_SCOR_TAIL | MUT2_TRUNK | MUT2_TENTACLES))) + { + msg_format(_("%s攻撃できない。", "You cannot do attacking."), + (empty_hands(FALSE) == EMPTY_HAND_NONE) ? _("両手がふさがって", "") : ""); + return FALSE; + } - /* Total armor */ - ac = p_ptr->ac + p_ptr->to_a; - if (p_ptr->special_attack & ATTACK_SUIKEN) ac += (p_ptr->lev * 2); + /* Extract monster name (or "it") */ + monster_desc(m_name, m_ptr, 0); - /* Power and Level compete against Armor */ - if ((i > 0) && (randint1(i) > ((ac * 3) / 4))) return (TRUE); + if (m_ptr->ml) + { + /* Auto-Recall if possible and visible */ + if (!p_ptr->image) monster_race_track(m_ptr->ap_r_idx); - /* Assume miss */ - return (FALSE); -} + /* Track a new monster */ + health_track(c_ptr->m_idx); + } + if ((r_ptr->flags1 & RF1_FEMALE) && + !(p_ptr->stun || p_ptr->confused || p_ptr->image || !m_ptr->ml)) + { + if ((inventory[INVEN_RARM].name1 == ART_ZANTETSU) || (inventory[INVEN_LARM].name1 == ART_ZANTETSU)) + { + msg_print(_("拙者、おなごは斬れぬ!", "I can not attack women!")); + return FALSE; + } + } + if (d_info[dungeon_type].flags1 & DF1_NO_MELEE) + { + msg_print(_("なぜか攻撃することができない。", "Something prevent you from attacking.")); + return FALSE; + } -/*! モンスターの侮辱行為メッセージテーブル / Hack -- possible "insult" messages */ -static cptr desc_insult[] = -{ -#ifdef JP - "があなたを侮辱した!", - "があなたの母を侮辱した!", - "があなたを軽蔑した!", - "があなたを辱めた!", - "があなたを汚した!", - "があなたの回りで踊った!", - "が猥褻な身ぶりをした!", - "があなたをぼんやりと見た!!!", - "があなたをパラサイト呼ばわりした!", - "があなたをサイボーグ扱いした!" -#else - "insults you!", - "insults your mother!", - "gives you the finger!", - "humiliates you!", - "defiles you!", - "dances around you!", - "makes obscene gestures!", - "moons you!!!" - "calls you a parasite!", - "calls you a cyborg!" -#endif + /* Stop if friendly */ + if (!is_hostile(m_ptr) && + !(p_ptr->stun || p_ptr->confused || p_ptr->image || + p_ptr->shero || !m_ptr->ml)) + { + if (inventory[INVEN_RARM].name1 == ART_STORMBRINGER) stormbringer = TRUE; + if (inventory[INVEN_LARM].name1 == ART_STORMBRINGER) stormbringer = TRUE; + if (stormbringer) + { + msg_format(_("黒い刃は強欲に%sを攻撃した!", "Your black blade greedily attacks %s!"), m_name); + chg_virtue(V_INDIVIDUALISM, 1); + chg_virtue(V_HONOUR, -1); + chg_virtue(V_JUSTICE, -1); + chg_virtue(V_COMPASSION, -1); + } + else if (p_ptr->pclass != CLASS_BERSERKER) + { + if (get_check(_("本当に攻撃しますか?", "Really hit it? "))) + { + chg_virtue(V_INDIVIDUALISM, 1); + chg_virtue(V_HONOUR, -1); + chg_virtue(V_JUSTICE, -1); + chg_virtue(V_COMPASSION, -1); + } + else + { + msg_format(_("%sを攻撃するのを止めた。", "You stop to avoid hitting %s."), m_name); + return FALSE; + } + } + } -}; + /* Handle player fear */ + if (p_ptr->afraid) + { + if (m_ptr->ml) + msg_format(_("恐くて%sを攻撃できない!", "You are too afraid to attack %s!"), m_name); + else + msg_format(_("そっちには何か恐いものがいる!", "There is something scary in your way!")); -/*! マゴットのぼやきメッセージテーブル / Hack -- possible "insult" messages */ -static cptr desc_moan[] = -{ -#ifdef JP - "は何かを悲しんでいるようだ。", - "が彼の飼い犬を見なかったかと尋ねている。", - "が縄張りから出て行けと言っている。", - "はキノコがどうとか呟いている。" -#else - "seems sad about something.", - "asks if you have seen his dogs.", - "tells you to get off his land.", - "mumbles something about mushrooms." -#endif + /* Disturb the monster */ + (void)set_monster_csleep(c_ptr->m_idx, 0); -}; + return FALSE; + } + + if (MON_CSLEEP(m_ptr)) /* It is not honorable etc to attack helpless victims */ + { + if (!(r_ptr->flags3 & RF3_EVIL) || one_in_(5)) chg_virtue(V_COMPASSION, -1); + if (!(r_ptr->flags3 & RF3_EVIL) || one_in_(5)) chg_virtue(V_HONOUR, -1); + } + + if (p_ptr->migite && p_ptr->hidarite) + { + if ((p_ptr->skill_exp[GINOU_NITOURYU] < s_info[p_ptr->pclass].s_max[GINOU_NITOURYU]) && ((p_ptr->skill_exp[GINOU_NITOURYU] - 1000) / 200 < r_ptr->level)) + { + if (p_ptr->skill_exp[GINOU_NITOURYU] < WEAPON_EXP_BEGINNER) + p_ptr->skill_exp[GINOU_NITOURYU] += 80; + else if (p_ptr->skill_exp[GINOU_NITOURYU] < WEAPON_EXP_SKILLED) + p_ptr->skill_exp[GINOU_NITOURYU] += 4; + else if (p_ptr->skill_exp[GINOU_NITOURYU] < WEAPON_EXP_EXPERT) + p_ptr->skill_exp[GINOU_NITOURYU] += 1; + else if (p_ptr->skill_exp[GINOU_NITOURYU] < WEAPON_EXP_MASTER) + if (one_in_(3)) p_ptr->skill_exp[GINOU_NITOURYU] += 1; + p_ptr->update |= (PU_BONUS); + } + } + + /* Gain riding experience */ + if (p_ptr->riding) + { + int cur = p_ptr->skill_exp[GINOU_RIDING]; + int max = s_info[p_ptr->pclass].s_max[GINOU_RIDING]; + + if (cur < max) + { + DEPTH ridinglevel = r_info[m_list[p_ptr->riding].r_idx].level; + DEPTH targetlevel = r_ptr->level; + int inc = 0; + + if ((cur / 200 - 5) < targetlevel) + inc += 1; + + /* Extra experience */ + if ((cur / 100) < ridinglevel) + { + if ((cur / 100 + 15) < ridinglevel) + inc += 1 + (ridinglevel - (cur / 100 + 15)); + else + inc += 1; + } + + p_ptr->skill_exp[GINOU_RIDING] = MIN(max, cur + inc); + p_ptr->update |= (PU_BONUS); + } + } + + riding_t_m_idx = c_ptr->m_idx; + if (p_ptr->migite) py_attack_aux(y, x, &fear, &mdeath, 0, mode); + if (p_ptr->hidarite && !mdeath) py_attack_aux(y, x, &fear, &mdeath, 1, mode); + + /* Mutations which yield extra 'natural' attacks */ + if (!mdeath) + { + if ((p_ptr->muta2 & MUT2_HORNS) && !mdeath) + natural_attack(c_ptr->m_idx, MUT2_HORNS, &fear, &mdeath); + if ((p_ptr->muta2 & MUT2_BEAK) && !mdeath) + natural_attack(c_ptr->m_idx, MUT2_BEAK, &fear, &mdeath); + if ((p_ptr->muta2 & MUT2_SCOR_TAIL) && !mdeath) + natural_attack(c_ptr->m_idx, MUT2_SCOR_TAIL, &fear, &mdeath); + if ((p_ptr->muta2 & MUT2_TRUNK) && !mdeath) + natural_attack(c_ptr->m_idx, MUT2_TRUNK, &fear, &mdeath); + if ((p_ptr->muta2 & MUT2_TENTACLES) && !mdeath) + natural_attack(c_ptr->m_idx, MUT2_TENTACLES, &fear, &mdeath); + } + + /* Hack -- delay fear messages */ + if (fear && m_ptr->ml && !mdeath) + { + sound(SOUND_FLEE); + + msg_format(_("%^sは恐怖して逃げ出した!", "%^s flees in terror!"), m_name); + } + + if ((p_ptr->special_defense & KATA_IAI) && ((mode != HISSATSU_IAI) || mdeath)) + { + set_action(ACTION_NONE); + } + return mdeath; +} /*! * @brief モンスターからプレイヤーへの打撃処理 / Attack the player via physical attacks. @@ -152,16 +1508,17 @@ bool make_attack_normal(MONSTER_IDX m_idx) int ap_cnt; - int i, k, tmp, ac, rlev; + INVENTORY_IDX i; + int k, tmp, ac, rlev; int do_cut, do_stun; s32b gold; object_type *o_ptr; - char o_name[MAX_NLEN]; + GAME_TEXT o_name[MAX_NLEN]; - char m_name[80]; + GAME_TEXT m_name[MAX_NLEN]; char ddesc[80]; @@ -170,7 +1527,7 @@ bool make_attack_normal(MONSTER_IDX m_idx) bool explode = FALSE; bool do_silly_attack = (one_in_(2) && p_ptr->image); HIT_POINT get_damage = 0; - int abbreviate = 0; + int abbreviate = 0; // 2回目以降の省略表現フラグ /* Not allowed to attack */ if (r_ptr->flags1 & (RF1_NEVER_BLOW)) return (FALSE); @@ -212,7 +1569,7 @@ bool make_attack_normal(MONSTER_IDX m_idx) HIT_POINT power = 0; HIT_POINT damage = 0; - cptr act = NULL; + concptr act = NULL; /* Extract the attack infomation */ int effect = r_ptr->blow[ap_cnt].effect; @@ -251,7 +1608,7 @@ bool make_attack_normal(MONSTER_IDX m_idx) if (!effect || check_hit(power, rlev, MON_STUNNED(m_ptr))) { /* Always disturbing */ - disturb(1, 1); + disturb(TRUE, TRUE); /* Hack -- Apply "protection from evil" */ @@ -263,13 +1620,10 @@ bool make_attack_normal(MONSTER_IDX m_idx) /* Remember the Evil-ness */ if (is_original_ap_and_seen(m_ptr)) r_ptr->r_flags3 |= RF3_EVIL; - /* Message */ #ifdef JP - if (abbreviate) - msg_format("撃退した。"); - else - msg_format("%^sは撃退された。", m_name); - abbreviate = 1;/*2回目以降は省略 */ + if (abbreviate) msg_format("撃退した。"); + else msg_format("%^sは撃退された。", m_name); + abbreviate = 1; /*2回目以降は省略 */ #else msg_format("%^s is repelled.", m_name); #endif @@ -535,15 +1889,9 @@ bool make_attack_normal(MONSTER_IDX m_idx) else { if (one_in_(3)) -#ifdef JP - act = "は♪僕らは楽しい家族♪と歌っている。"; - else - act = "は♪アイ ラブ ユー、ユー ラブ ミー♪と歌っている。"; -#else - act = "sings 'We are a happy family.'"; + act = _("は♪僕らは楽しい家族♪と歌っている。", "sings 'We are a happy family.'"); else - act = "sings 'I love you, you love me.'"; -#endif + act = _("は♪アイ ラブ ユー、ユー ラブ ミー♪と歌っている。", "sings 'I love you, you love me.'"); } sound(SOUND_SHOW); @@ -551,7 +1899,6 @@ bool make_attack_normal(MONSTER_IDX m_idx) } } - /* Message */ if (act) { if (do_silly_attack) @@ -563,11 +1910,11 @@ bool make_attack_normal(MONSTER_IDX m_idx) } #ifdef JP if (abbreviate == 0) - msg_format("%^sに%s", m_name, act); + msg_format("%^sに%s", m_name, act); else if (abbreviate == 1) - msg_format("%s", act); + msg_format("%s", act); else /* if (abbreviate == -1) */ - msg_format("%^s%s", m_name, act); + msg_format("%^s%s", m_name, act); abbreviate = 1;/*2回目以降は省略 */ #else msg_format("%^s %s%s", m_name, act, do_silly_attack ? " you." : ""); @@ -584,23 +1931,18 @@ bool make_attack_normal(MONSTER_IDX m_idx) * Skip the effect when exploding, since the explosion * already causes the effect. */ - if (explode) - damage = 0; + if(explode) damage = 0; /* Apply appropriate damage */ switch (effect) { case 0: { - /* Hack -- Assume obvious */ obvious = TRUE; - - /* Hack -- No damage */ damage = 0; - break; } - case RBE_SUPERHURT: + case RBE_SUPERHURT: /* AC軽減あり / Player armor reduces total damage */ { if (((randint1(rlev*2+300) > (ac+200)) || one_in_(13)) && !CHECK_MULTISHADOW()) { @@ -608,22 +1950,15 @@ bool make_attack_normal(MONSTER_IDX m_idx) msg_print(_("痛恨の一撃!", "It was a critical hit!")); tmp_damage = MAX(damage, tmp_damage*2); - /* Take damage */ get_damage += take_hit(DAMAGE_ATTACK, tmp_damage, ddesc, -1); break; } } - case RBE_HURT: + case RBE_HURT: /* AC軽減あり / Player armor reduces total damage */ { - /* Obvious */ obvious = TRUE; - - /* Hack -- Player armor reduces total damage */ damage -= (damage * ((ac < 150) ? ac : 150) / 250); - - /* Take damage */ get_damage += take_hit(DAMAGE_ATTACK, damage, ddesc, -1); - break; } @@ -640,7 +1975,6 @@ bool make_attack_normal(MONSTER_IDX m_idx) } } - /* Take some damage */ get_damage += take_hit(DAMAGE_ATTACK, damage, ddesc, -1); /* Learn about the player */ @@ -660,12 +1994,11 @@ bool make_attack_normal(MONSTER_IDX m_idx) if (apply_disenchant(0)) { /* Hack -- Update AC */ - update_stuff(); + update_creature(p_ptr); obvious = TRUE; } } - /* Take some damage */ get_damage += take_hit(DAMAGE_ATTACK, damage, ddesc, -1); /* Learn about the player */ @@ -676,7 +2009,6 @@ bool make_attack_normal(MONSTER_IDX m_idx) case RBE_UN_POWER: { - /* Take some damage */ get_damage += take_hit(DAMAGE_ATTACK, damage, ddesc, -1); if (p_ptr->is_dead || CHECK_MULTISHADOW()) break; @@ -685,7 +2017,7 @@ bool make_attack_normal(MONSTER_IDX m_idx) for (k = 0; k < 10; k++) { /* Pick an item */ - i = randint0(INVEN_PACK); + i = (INVENTORY_IDX)randint0(INVEN_PACK); /* Obtain the item */ o_ptr = &inventory[i]; @@ -706,10 +2038,8 @@ bool make_attack_normal(MONSTER_IDX m_idx) /* Don't heal more than max hp */ heal = MIN(heal, m_ptr->maxhp - m_ptr->hp); - /* Message */ msg_print(_("ザックからエネルギーが吸い取られた!", "Energy drains from your pack!")); - /* Obvious */ obvious = TRUE; /* Heal the monster */ @@ -723,12 +2053,9 @@ bool make_attack_normal(MONSTER_IDX m_idx) o_ptr->pval = 0; /* Combine / Reorder the pack */ - p_ptr->notice |= (PN_COMBINE | PN_REORDER); - - /* Window stuff */ + p_ptr->update |= (PU_COMBINE | PU_REORDER); p_ptr->window |= (PW_INVEN); - /* Done */ break; } } @@ -738,7 +2065,6 @@ bool make_attack_normal(MONSTER_IDX m_idx) case RBE_EAT_GOLD: { - /* Take some damage */ get_damage += take_hit(DAMAGE_ATTACK, damage, ddesc, -1); /* Confused monsters cannot steal successfully. -LM-*/ @@ -746,7 +2072,6 @@ bool make_attack_normal(MONSTER_IDX m_idx) if (p_ptr->is_dead || CHECK_MULTISHADOW()) break; - /* Obvious */ obvious = TRUE; /* Saving throw (unless paralyzed) based on dex and level */ @@ -789,7 +2114,6 @@ bool make_attack_normal(MONSTER_IDX m_idx) /* Redraw gold */ p_ptr->redraw |= (PR_GOLD); - /* Window stuff */ p_ptr->window |= (PW_PLAYER); /* Blink away */ @@ -801,7 +2125,6 @@ bool make_attack_normal(MONSTER_IDX m_idx) case RBE_EAT_ITEM: { - /* Take some damage */ get_damage += take_hit(DAMAGE_ATTACK, damage, ddesc, -1); /* Confused monsters cannot steal successfully. -LM-*/ @@ -819,21 +2142,17 @@ bool make_attack_normal(MONSTER_IDX m_idx) /* Occasional "blink" anyway */ blinked = TRUE; - - /* Obvious */ obvious = TRUE; - - /* Done */ break; } /* Find an item */ for (k = 0; k < 10; k++) { - s16b o_idx; + OBJECT_IDX o_idx; /* Pick an item */ - i = randint0(INVEN_PACK); + i = (INVENTORY_IDX)randint0(INVEN_PACK); /* Obtain the item */ o_ptr = &inventory[i]; @@ -844,18 +2163,12 @@ bool make_attack_normal(MONSTER_IDX m_idx) /* Skip artifacts */ if (object_is_artifact(o_ptr)) continue; - /* Get a description */ object_desc(o_name, o_ptr, OD_OMIT_PREFIX); - /* Message */ #ifdef JP - msg_format("%s(%c)を%s盗まれた!", - o_name, index_to_label(i), - ((o_ptr->number > 1) ? "一つ" : "")); + msg_format("%s(%c)を%s盗まれた!", o_name, index_to_label(i), ((o_ptr->number > 1) ? "一つ" : "")); #else - msg_format("%sour %s (%c) was stolen!", - ((o_ptr->number > 1) ? "One of y" : "Y"), - o_name, index_to_label(i)); + msg_format("%sour %s (%c) was stolen!", ((o_ptr->number > 1) ? "One of y" : "Y"), o_name, index_to_label(i)); #endif chg_virtue(V_SACRIFICE, 1); @@ -868,11 +2181,7 @@ bool make_attack_normal(MONSTER_IDX m_idx) if (o_idx) { object_type *j_ptr; - - /* Get new object */ j_ptr = &o_list[o_idx]; - - /* Copy object */ object_copy(j_ptr, o_ptr); /* Modify number */ @@ -905,13 +2214,11 @@ bool make_attack_normal(MONSTER_IDX m_idx) inven_item_increase(i, -1); inven_item_optimize(i); - /* Obvious */ obvious = TRUE; /* Blink away */ blinked = TRUE; - /* Done */ break; } @@ -920,7 +2227,6 @@ bool make_attack_normal(MONSTER_IDX m_idx) case RBE_EAT_FOOD: { - /* Take some damage */ get_damage += take_hit(DAMAGE_ATTACK, damage, ddesc, -1); if (p_ptr->is_dead || CHECK_MULTISHADOW()) break; @@ -929,9 +2235,8 @@ bool make_attack_normal(MONSTER_IDX m_idx) for (k = 0; k < 10; k++) { /* Pick an item from the pack */ - i = randint0(INVEN_PACK); + i = (INVENTORY_IDX)randint0(INVEN_PACK); - /* Get the item */ o_ptr = &inventory[i]; /* Skip non-objects */ @@ -940,29 +2245,20 @@ bool make_attack_normal(MONSTER_IDX m_idx) /* Skip non-food objects */ if ((o_ptr->tval != TV_FOOD) && !((o_ptr->tval == TV_CORPSE) && (o_ptr->sval))) continue; - /* Get a description */ object_desc(o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY)); - /* Message */ #ifdef JP - msg_format("%s(%c)を%s食べられてしまった!", - o_name, index_to_label(i), - ((o_ptr->number > 1) ? "一つ" : "")); + msg_format("%s(%c)を%s食べられてしまった!", o_name, index_to_label(i), ((o_ptr->number > 1) ? "一つ" : "")); #else - msg_format("%sour %s (%c) was eaten!", - ((o_ptr->number > 1) ? "One of y" : "Y"), - o_name, index_to_label(i)); + msg_format("%sour %s (%c) was eaten!", ((o_ptr->number > 1) ? "One of y" : "Y"), o_name, index_to_label(i)); #endif - /* Steal the items */ inven_item_increase(i, -1); inven_item_optimize(i); - /* Obvious */ obvious = TRUE; - /* Done */ break; } @@ -973,8 +2269,6 @@ bool make_attack_normal(MONSTER_IDX m_idx) { /* Access the lite */ o_ptr = &inventory[INVEN_LITE]; - - /* Take some damage */ get_damage += take_hit(DAMAGE_ATTACK, damage, ddesc, -1); if (p_ptr->is_dead || CHECK_MULTISHADOW()) break; @@ -986,14 +2280,12 @@ bool make_attack_normal(MONSTER_IDX m_idx) o_ptr->xtra4 -= (s16b)(250 + randint1(250)); if (o_ptr->xtra4 < 1) o_ptr->xtra4 = 1; - /* Notice */ if (!p_ptr->blind) { msg_print(_("明かりが暗くなってしまった。", "Your light dims.")); obvious = TRUE; } - /* Window stuff */ p_ptr->window |= (PW_EQUIP); } @@ -1003,83 +2295,47 @@ bool make_attack_normal(MONSTER_IDX m_idx) case RBE_ACID: { if (explode) break; - /* Obvious */ obvious = TRUE; - - /* Message */ msg_print(_("酸を浴びせられた!", "You are covered in acid!")); - - /* Special damage */ get_damage += acid_dam(damage, ddesc, -1, FALSE); - - /* Hack -- Update AC */ - update_stuff(); - - /* Learn about the player */ + update_creature(p_ptr); update_smart_learn(m_idx, DRS_ACID); - break; } case RBE_ELEC: { if (explode) break; - /* Obvious */ obvious = TRUE; - - /* Message */ msg_print(_("電撃を浴びせられた!", "You are struck by electricity!")); - - /* Special damage */ get_damage += elec_dam(damage, ddesc, -1, FALSE); - - /* Learn about the player */ update_smart_learn(m_idx, DRS_ELEC); - break; } case RBE_FIRE: { if (explode) break; - /* Obvious */ obvious = TRUE; - - /* Message */ msg_print(_("全身が炎に包まれた!", "You are enveloped in flames!")); - - /* Special damage */ get_damage += fire_dam(damage, ddesc, -1, FALSE); - - /* Learn about the player */ update_smart_learn(m_idx, DRS_FIRE); - break; } case RBE_COLD: { if (explode) break; - /* Obvious */ obvious = TRUE; - - /* Message */ msg_print(_("全身が冷気で覆われた!", "You are covered with frost!")); - - /* Special damage */ get_damage += cold_dam(damage, ddesc, -1, FALSE); - - /* Learn about the player */ update_smart_learn(m_idx, DRS_COLD); - break; } case RBE_BLIND: { - /* Take damage */ get_damage += take_hit(DAMAGE_ATTACK, damage, ddesc, -1); - if (p_ptr->is_dead) break; /* Increase "blind" */ @@ -1105,7 +2361,6 @@ bool make_attack_normal(MONSTER_IDX m_idx) case RBE_CONFUSE: { if (explode) break; - /* Take damage */ get_damage += take_hit(DAMAGE_ATTACK, damage, ddesc, -1); if (p_ptr->is_dead) break; @@ -1127,7 +2382,6 @@ bool make_attack_normal(MONSTER_IDX m_idx) case RBE_TERRIFY: { - /* Take damage */ get_damage += take_hit(DAMAGE_ATTACK, damage, ddesc, -1); if (p_ptr->is_dead) break; @@ -1163,7 +2417,6 @@ bool make_attack_normal(MONSTER_IDX m_idx) case RBE_PARALYZE: { - /* Take damage */ get_damage += take_hit(DAMAGE_ATTACK, damage, ddesc, -1); if (p_ptr->is_dead) break; @@ -1202,12 +2455,9 @@ bool make_attack_normal(MONSTER_IDX m_idx) case RBE_LOSE_STR: { - /* Damage (physical) */ get_damage += take_hit(DAMAGE_ATTACK, damage, ddesc, -1); if (p_ptr->is_dead || CHECK_MULTISHADOW()) break; - - /* Damage (stat) */ if (do_dec_stat(A_STR)) obvious = TRUE; break; @@ -1215,12 +2465,9 @@ bool make_attack_normal(MONSTER_IDX m_idx) case RBE_LOSE_INT: { - /* Damage (physical) */ get_damage += take_hit(DAMAGE_ATTACK, damage, ddesc, -1); if (p_ptr->is_dead || CHECK_MULTISHADOW()) break; - - /* Damage (stat) */ if (do_dec_stat(A_INT)) obvious = TRUE; break; @@ -1228,12 +2475,9 @@ bool make_attack_normal(MONSTER_IDX m_idx) case RBE_LOSE_WIS: { - /* Damage (physical) */ get_damage += take_hit(DAMAGE_ATTACK, damage, ddesc, -1); if (p_ptr->is_dead || CHECK_MULTISHADOW()) break; - - /* Damage (stat) */ if (do_dec_stat(A_WIS)) obvious = TRUE; break; @@ -1241,12 +2485,9 @@ bool make_attack_normal(MONSTER_IDX m_idx) case RBE_LOSE_DEX: { - /* Damage (physical) */ get_damage += take_hit(DAMAGE_ATTACK, damage, ddesc, -1); if (p_ptr->is_dead || CHECK_MULTISHADOW()) break; - - /* Damage (stat) */ if (do_dec_stat(A_DEX)) obvious = TRUE; break; @@ -1254,12 +2495,9 @@ bool make_attack_normal(MONSTER_IDX m_idx) case RBE_LOSE_CON: { - /* Damage (physical) */ get_damage += take_hit(DAMAGE_ATTACK, damage, ddesc, -1); if (p_ptr->is_dead || CHECK_MULTISHADOW()) break; - - /* Damage (stat) */ if (do_dec_stat(A_CON)) obvious = TRUE; break; @@ -1267,12 +2505,9 @@ bool make_attack_normal(MONSTER_IDX m_idx) case RBE_LOSE_CHR: { - /* Damage (physical) */ get_damage += take_hit(DAMAGE_ATTACK, damage, ddesc, -1); if (p_ptr->is_dead || CHECK_MULTISHADOW()) break; - - /* Damage (stat) */ if (do_dec_stat(A_CHR)) obvious = TRUE; break; @@ -1280,7 +2515,6 @@ bool make_attack_normal(MONSTER_IDX m_idx) case RBE_LOSE_ALL: { - /* Damage (physical) */ get_damage += take_hit(DAMAGE_ATTACK, damage, ddesc, -1); if (p_ptr->is_dead || CHECK_MULTISHADOW()) break; @@ -1298,13 +2532,11 @@ bool make_attack_normal(MONSTER_IDX m_idx) case RBE_SHATTER: { - /* Obvious */ obvious = TRUE; /* Hack -- Reduce damage based on the player armor class */ damage -= (damage * ((ac < 150) ? ac : 150) / 250); - /* Take damage */ get_damage += take_hit(DAMAGE_ATTACK, damage, ddesc, -1); /* Radius 8 earthquake centered at the monster */ @@ -1320,10 +2552,8 @@ bool make_attack_normal(MONSTER_IDX m_idx) { s32b d = damroll(10, 6) + (p_ptr->exp / 100) * MON_DRAIN_LIFE; - /* Obvious */ obvious = TRUE; - /* Take damage */ get_damage += take_hit(DAMAGE_ATTACK, damage, ddesc, -1); if (p_ptr->is_dead || CHECK_MULTISHADOW()) break; @@ -1336,10 +2566,8 @@ bool make_attack_normal(MONSTER_IDX m_idx) { s32b d = damroll(20, 6) + (p_ptr->exp / 100) * MON_DRAIN_LIFE; - /* Obvious */ obvious = TRUE; - /* Take damage */ get_damage += take_hit(DAMAGE_ATTACK, damage, ddesc, -1); if (p_ptr->is_dead || CHECK_MULTISHADOW()) break; @@ -1352,10 +2580,8 @@ bool make_attack_normal(MONSTER_IDX m_idx) { s32b d = damroll(40, 6) + (p_ptr->exp / 100) * MON_DRAIN_LIFE; - /* Obvious */ obvious = TRUE; - /* Take damage */ get_damage += take_hit(DAMAGE_ATTACK, damage, ddesc, -1); if (p_ptr->is_dead || CHECK_MULTISHADOW()) break; @@ -1368,10 +2594,8 @@ bool make_attack_normal(MONSTER_IDX m_idx) { s32b d = damroll(80, 6) + (p_ptr->exp / 100) * MON_DRAIN_LIFE; - /* Obvious */ obvious = TRUE; - /* Take damage */ get_damage += take_hit(DAMAGE_ATTACK, damage, ddesc, -1); if (p_ptr->is_dead || CHECK_MULTISHADOW()) break; @@ -1382,7 +2606,6 @@ bool make_attack_normal(MONSTER_IDX m_idx) case RBE_DISEASE: { - /* Take some damage */ get_damage += take_hit(DAMAGE_ATTACK, damage, ddesc, -1); if (p_ptr->is_dead || CHECK_MULTISHADOW()) break; @@ -1460,7 +2683,7 @@ bool make_attack_normal(MONSTER_IDX m_idx) { msg_print(_("あなたは以前ほど力強くなくなってしまった...。", "You're not as powerful as you used to be...")); - for (k = 0; k < 6; k++) + for (k = 0; k < A_MAX; k++) { p_ptr->stat_cur[k] = (p_ptr->stat_cur[k] * 7) / 8; if (p_ptr->stat_cur[k] < 3) p_ptr->stat_cur[k] = 3; @@ -1479,10 +2702,8 @@ bool make_attack_normal(MONSTER_IDX m_idx) s32b d = damroll(60, 6) + (p_ptr->exp / 100) * MON_DRAIN_LIFE; bool resist_drain; - /* Obvious */ obvious = TRUE; - /* Take damage */ get_damage += take_hit(DAMAGE_ATTACK, damage, ddesc, -1); if (p_ptr->is_dead || CHECK_MULTISHADOW()) break; @@ -1536,7 +2757,6 @@ bool make_attack_normal(MONSTER_IDX m_idx) } case RBE_DR_MANA: { - /* Obvious */ obvious = TRUE; if (CHECK_MULTISHADOW()) @@ -1547,7 +2767,6 @@ bool make_attack_normal(MONSTER_IDX m_idx) { do_cut = 0; - /* Take damage */ p_ptr->csp -= damage; if (p_ptr->csp < 0) { @@ -1565,7 +2784,6 @@ bool make_attack_normal(MONSTER_IDX m_idx) } case RBE_INERTIA: { - /* Take damage */ get_damage += take_hit(DAMAGE_ATTACK, damage, ddesc, -1); if (p_ptr->is_dead) break; @@ -1587,7 +2805,6 @@ bool make_attack_normal(MONSTER_IDX m_idx) } case RBE_STUN: { - /* Take damage */ get_damage += take_hit(DAMAGE_ATTACK, damage, ddesc, -1); if (p_ptr->is_dead) break; @@ -1925,7 +3142,7 @@ bool make_attack_normal(MONSTER_IDX m_idx) { int j; BIT_FLAGS flg = PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL; - int typ[4][2] = { + EFFECT_ID typ[4][2] = { { INVEN_HEAD, GF_OLD_CONF }, { INVEN_LARM, GF_OLD_SLEEP }, { INVEN_HANDS, GF_TURN_ALL }, @@ -1973,9 +3190,8 @@ bool make_attack_normal(MONSTER_IDX m_idx) if (m_ptr->ml) { /* Disturbing */ - disturb(1, 1); + disturb(TRUE, TRUE); - /* Message */ #ifdef JP if (abbreviate) msg_format("%sかわした。", (p_ptr->special_attack & ATTACK_SUIKEN) ? "奇妙な動きで" : ""); @@ -1987,6 +3203,33 @@ bool make_attack_normal(MONSTER_IDX m_idx) #endif } + + /* Gain shield experience */ + if (object_is_armour(&inventory[INVEN_RARM]) || object_is_armour(&inventory[INVEN_LARM])) + { + int cur = p_ptr->skill_exp[GINOU_SHIELD]; + int max = s_info[p_ptr->pclass].s_max[GINOU_SHIELD]; + + if (cur < max) + { + DEPTH targetlevel = r_ptr->level; + int inc = 0; + + + /* Extra experience */ + if ((cur / 100) < targetlevel) + { + if ((cur / 100 + 15) < targetlevel) + inc += 1 + (targetlevel - (cur / 100 + 15)); + else + inc += 1; + } + + p_ptr->skill_exp[GINOU_SHIELD] = MIN(max, cur + inc); + p_ptr->update |= (PU_BONUS); + } + } + damage = 0; break; @@ -2010,7 +3253,7 @@ bool make_attack_normal(MONSTER_IDX m_idx) if (p_ptr->riding && damage) { - char m_steed_name[80]; + char m_steed_name[MAX_NLEN]; monster_desc(m_steed_name, &m_list[p_ptr->riding], 0); if (rakuba((damage > 200) ? 200 : damage, FALSE)) { @@ -2033,7 +3276,7 @@ bool make_attack_normal(MONSTER_IDX m_idx) #ifdef JP msg_format("攻撃が%s自身を傷つけた!", m_name); #else - char m_name_self[80]; + GAME_TEXT m_name_self[80]; /* hisself */ monster_desc(m_name_self, m_ptr, MD_PRON_VISIBLE | MD_POSSESSIVE | MD_OBJECTIVE); @@ -2046,15 +3289,13 @@ bool make_attack_normal(MONSTER_IDX m_idx) if ((p_ptr->counter || (p_ptr->special_defense & KATA_MUSOU)) && alive && !p_ptr->is_dead && m_ptr->ml && (p_ptr->csp > 7)) { - char m_target_name[80]; + char m_target_name[MAX_NLEN]; monster_desc(m_target_name, m_ptr, 0); p_ptr->csp -= 7; msg_format(_("%^sに反撃した!", "Your counterattack to %s!"), m_target_name); py_attack(m_ptr->fy, m_ptr->fx, HISSATSU_COUNTER); fear = FALSE; - - /* Redraw mana */ p_ptr->redraw |= (PR_MANA); }