2 * @brief 特殊属性武器で攻撃した際の追加効果処理
9 #include "player-attack/attack-chaos-effect.h"
10 #include "artifact/fixed-art-types.h"
11 #include "flavor/flavor-describer.h"
12 #include "flavor/object-flavor-types.h"
13 #include "inventory/inventory-object.h"
14 #include "inventory/inventory-slot-types.h"
15 #include "lore/lore-store.h"
16 #include "monster-race//race-ability-mask.h"
17 #include "monster-race/monster-race.h"
18 #include "monster-race/race-flags-resistance.h"
19 #include "monster-race/race-flags1.h"
20 #include "monster-race/race-flags3.h"
21 #include "monster-race/race-resistance-mask.h"
22 #include "monster/monster-describer.h"
23 #include "monster/monster-info.h"
24 #include "monster/monster-status-setter.h"
25 #include "monster/monster-status.h"
26 #include "object/object-mark-types.h"
27 #include "player-attack/player-attack.h"
28 #include "player/attack-defense-types.h"
29 #include "realm/realm-hex-numbers.h"
30 #include "spell-kind/spells-polymorph.h"
31 #include "spell-kind/spells-sight.h"
32 #include "spell-kind/spells-teleport.h"
33 #include "spell-realm/spells-hex.h"
34 #include "system/floor-type-definition.h"
35 #include "system/item-entity.h"
36 #include "system/monster-entity.h"
37 #include "system/monster-race-info.h"
38 #include "system/player-type-definition.h"
39 #include "system/redrawing-flags-updater.h"
40 #include "util/bit-flags-calculator.h"
41 #include "util/string-processor.h"
42 #include "view/display-messages.h"
45 * @brief 打撃でモンスターを混乱させる処理
46 * @param player_ptr プレイヤーへの参照ポインタ
47 * @param pa_ptr 直接攻撃構造体への参照ポインタ
48 * @param can_resist レベルで抵抗可能ならTRUE、できないならFALSE
52 static void attack_confuse(PlayerType *player_ptr, player_attack_type *pa_ptr, bool can_resist = true)
54 if (player_ptr->special_attack & ATTACK_CONFUSE) {
55 player_ptr->special_attack &= ~(ATTACK_CONFUSE);
56 msg_print(_("手の輝きがなくなった。", "Your hands stop glowing."));
57 RedrawingFlagsUpdater::get_instance().set_flag(MainWindowRedrawingFlag::TIMED_EFFECT);
60 auto *r_ptr = pa_ptr->r_ptr;
61 if (r_ptr->flags3 & RF3_NO_CONF) {
62 if (is_original_ap_and_seen(player_ptr, pa_ptr->m_ptr)) {
63 r_ptr->r_flags3 |= RF3_NO_CONF;
65 msg_format(_("%s^には効果がなかった。", "%s^ is unaffected."), pa_ptr->m_name);
67 } else if (can_resist && randint0(100) < r_ptr->level) {
68 msg_format(_("%s^には効果がなかった。", "%s^ is unaffected."), pa_ptr->m_name);
70 msg_format(_("%s^は混乱したようだ。", "%s^ appears confused."), pa_ptr->m_name);
71 (void)set_monster_confused(player_ptr, pa_ptr->m_idx, pa_ptr->m_ptr->get_remaining_confusion() + 10 + randint0(player_ptr->lev) / 5);
76 * @brief 打撃でモンスターを朦朧とさせる処理
77 * @param player_ptr プレイヤーへの参照ポインタ
78 * @param pa_ptr 直接攻撃構造体への参照ポインタ
79 * @param can_resist レベルで抵抗可能ならTRUE、できないならFALSE
83 static void attack_stun(PlayerType *player_ptr, player_attack_type *pa_ptr, bool can_resist = true)
85 auto *r_ptr = pa_ptr->r_ptr;
86 if (any_bits(r_ptr->flags3, RF3_NO_STUN)) {
87 if (is_original_ap_and_seen(player_ptr, pa_ptr->m_ptr)) {
88 set_bits(r_ptr->flags3, RF3_NO_STUN);
90 msg_format(_("%s^には効果がなかった。", "%s^ is unaffected."), pa_ptr->m_name);
91 } else if (can_resist && randint0(100) < r_ptr->level) {
92 msg_format(_("%s^には効果がなかった。", "%s^ is unaffected."), pa_ptr->m_name);
94 msg_format(_("%s^は朦朧としたようだ。", "%s^ appears stunned."), pa_ptr->m_name);
95 (void)set_monster_stunned(player_ptr, pa_ptr->m_idx, pa_ptr->m_ptr->get_remaining_stun() + 10 + randint0(player_ptr->lev) / 5);
100 * @brief 打撃でモンスターを恐怖させる処理
101 * @param player_ptr プレイヤーへの参照ポインタ
102 * @param pa_ptr 直接攻撃構造体への参照ポインタ
103 * @param can_resist レベルで抵抗可能ならTRUE、できないならFALSE
107 static void attack_scare(PlayerType *player_ptr, player_attack_type *pa_ptr, bool can_resist = true)
109 auto *r_ptr = pa_ptr->r_ptr;
110 if (any_bits(r_ptr->flags3, RF3_NO_FEAR)) {
111 if (is_original_ap_and_seen(player_ptr, pa_ptr->m_ptr)) {
112 set_bits(r_ptr->flags3, RF3_NO_FEAR);
114 msg_format(_("%s^には効果がなかった。", "%s^ is unaffected."), pa_ptr->m_name);
115 } else if (can_resist && randint0(100) < r_ptr->level) {
116 msg_format(_("%s^には効果がなかった。", "%s^ is unaffected."), pa_ptr->m_name);
118 msg_format(_("%s^は恐怖して逃げ出した!", "%s^ flees in terror!"), pa_ptr->m_name);
119 (void)set_monster_monfear(player_ptr, pa_ptr->m_idx, pa_ptr->m_ptr->get_remaining_fear() + 10 + randint0(player_ptr->lev) / 5);
124 * @brief 打撃でモンスターを無力化する処理
125 * @param player_ptr プレイヤーへの参照ポインタ
126 * @param pa_ptr 直接攻撃構造体への参照ポインタ
130 static void attack_dispel(PlayerType *player_ptr, player_attack_type *pa_ptr)
132 if (pa_ptr->r_ptr->ability_flags.has_none_of(RF_ABILITY_ATTACK_MASK) && pa_ptr->r_ptr->ability_flags.has_none_of(RF_ABILITY_INDIRECT_MASK)) {
137 if (pa_ptr->m_ptr->mtimed[MTIMED_SLOW]) {
140 if (pa_ptr->m_ptr->mtimed[MTIMED_FAST]) {
143 if (pa_ptr->m_ptr->mtimed[MTIMED_INVULNER]) {
147 msg_print(_("武器が敵の魔力を吸い取った!", "The weapon drains mana from your enemy!"));
148 dispel_monster_status(player_ptr, pa_ptr->m_idx);
150 auto sp = damroll(dd, 8);
151 player_ptr->csp = std::min(player_ptr->msp, player_ptr->csp + sp);
152 RedrawingFlagsUpdater::get_instance().set_flag(MainWindowRedrawingFlag::MP);
156 * @brief 打撃でモンスターを調査する処理
157 * @param player_ptr プレイヤーへの参照ポインタ
158 * @param pa_ptr 直接攻撃構造体への参照ポインタ
162 static void attack_probe(PlayerType *player_ptr, player_attack_type *pa_ptr)
164 msg_print(_("刃が敵を調査した...", "The blade probed your enemy..."));
166 msg_print(probed_monster_info(player_ptr, pa_ptr->m_ptr, pa_ptr->r_ptr));
168 (void)lore_do_probe(player_ptr, pa_ptr->r_idx);
172 * @breif カオス武器でのテレポート・アウェイを行うか判定する (抵抗されたら無効)
173 * @param player_ptr プレイヤーへの参照ポインタ
174 * @param pa_ptr 直接攻撃構造体への参照ポインタ
175 * @return 抵抗されたらTRUE、アウェイされるならFALSE
177 static bool judge_tereprt_resistance(PlayerType *player_ptr, player_attack_type *pa_ptr)
179 auto *r_ptr = pa_ptr->r_ptr;
180 if (r_ptr->resistance_flags.has_not(MonsterResistanceType::RESIST_TELEPORT)) {
184 if (r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
185 if (is_original_ap_and_seen(player_ptr, pa_ptr->m_ptr)) {
186 r_ptr->r_resistance_flags.set(MonsterResistanceType::RESIST_TELEPORT);
189 msg_format(_("%s^には効果がなかった。", "%s^ is unaffected!"), pa_ptr->m_name);
193 if (r_ptr->level > randint1(100)) {
194 if (is_original_ap_and_seen(player_ptr, pa_ptr->m_ptr)) {
195 r_ptr->r_resistance_flags.set(MonsterResistanceType::RESIST_TELEPORT);
198 msg_format(_("%s^は抵抗力を持っている!", "%s^ resists!"), pa_ptr->m_name);
206 * @brief カオス武器でのテレポート・アウェイを実行する
207 * @param player_ptr プレイヤーへの参照ポインタ
208 * @param pa_ptr 直接攻撃構造体への参照ポインタ
209 * @param num 現在の攻撃回数 (テレポートしてしまったら追加攻撃できないのでその補正)
211 static void attack_teleport_away(PlayerType *player_ptr, player_attack_type *pa_ptr, int *num)
213 if (judge_tereprt_resistance(player_ptr, pa_ptr)) {
217 msg_format(_("%s^は消えた!", "%s^ disappears!"), pa_ptr->m_name);
218 teleport_away(player_ptr, pa_ptr->m_idx, 50, TELEPORT_PASSIVE);
219 *num = pa_ptr->num_blow + 1;
220 *(pa_ptr->mdeath) = true;
224 * @brief カオス武器でのテレポート・アウェイを実行する
225 * @param player_ptr プレイヤーへの参照ポインタ
226 * @param pa_ptr 直接攻撃構造体への参照ポインタ
230 static void attack_polymorph(PlayerType *player_ptr, player_attack_type *pa_ptr, POSITION y, POSITION x)
232 auto *r_ptr = pa_ptr->r_ptr;
233 if (r_ptr->kind_flags.has(MonsterKindType::UNIQUE) || any_bits(r_ptr->flags1, RF1_QUESTOR) || r_ptr->resistance_flags.has_any_of(RFR_EFF_RESIST_CHAOS_MASK)) {
237 if (polymorph_monster(player_ptr, y, x)) {
238 msg_format(_("%s^は変化した!", "%s^ changes!"), pa_ptr->m_name);
239 *(pa_ptr->fear) = false;
240 pa_ptr->weak = false;
242 msg_format(_("%s^には効果がなかった。", "%s^ is unaffected."), pa_ptr->m_name);
245 pa_ptr->m_ptr = &player_ptr->current_floor_ptr->m_list[pa_ptr->m_idx];
246 angband_strcpy(pa_ptr->m_name, monster_desc(player_ptr, pa_ptr->m_ptr, 0), sizeof(pa_ptr->m_name));
250 * @brief ゴールデンハンマーによるアイテム奪取処理
251 * @param player_ptr プレイヤーへの参照ポインタ
252 * @param pa_ptr 直接攻撃構造体への参照ポインタ
254 static void attack_golden_hammer(PlayerType *player_ptr, player_attack_type *pa_ptr)
256 auto *floor_ptr = player_ptr->current_floor_ptr;
257 auto *m_ptr = &floor_ptr->m_list[pa_ptr->m_idx];
258 if (m_ptr->hold_o_idx_list.empty()) {
262 auto *q_ptr = &floor_ptr->o_list[m_ptr->hold_o_idx_list.front()];
263 const auto item_name = describe_flavor(player_ptr, q_ptr, OD_NAME_ONLY);
264 q_ptr->held_m_idx = 0;
265 q_ptr->marked.clear().set(OmType::TOUCHED);
266 m_ptr->hold_o_idx_list.pop_front();
267 msg_format(_("%sを奪った。", "You snatched %s."), item_name.data());
268 store_item_to_inventory(player_ptr, q_ptr);
272 * @brief カオス武器その他でモンスターのステータスを変化させる
273 * @param player_ptr プレイヤーへの参照ポインタ
274 * @param pa_ptr 直接攻撃構造体への参照ポインタ
279 void change_monster_stat(PlayerType *player_ptr, player_attack_type *pa_ptr, const POSITION y, const POSITION x, int *num)
281 auto should_confuse = any_bits(player_ptr->special_attack, ATTACK_CONFUSE);
282 should_confuse |= pa_ptr->chaos_effect == CE_CONFUSION;
283 should_confuse |= pa_ptr->mode == HISSATSU_CONF;
284 should_confuse |= SpellHex(player_ptr).is_spelling_specific(HEX_CONFUSION);
285 if (should_confuse) {
286 attack_confuse(player_ptr, pa_ptr);
289 if (pa_ptr->magical_effect == MagicalBrandEffectType::STUN) {
290 attack_stun(player_ptr, pa_ptr, false);
293 if (pa_ptr->magical_effect == MagicalBrandEffectType::SCARE) {
294 attack_scare(player_ptr, pa_ptr, false);
297 if (pa_ptr->magical_effect == MagicalBrandEffectType::DISPELL) {
298 attack_dispel(player_ptr, pa_ptr);
301 if (pa_ptr->magical_effect == MagicalBrandEffectType::PROBE) {
302 attack_probe(player_ptr, pa_ptr);
305 if (pa_ptr->chaos_effect == CE_TELE_AWAY) {
306 attack_teleport_away(player_ptr, pa_ptr, num);
309 if (pa_ptr->chaos_effect == CE_POLYMORPH && (randint1(90) > monraces_info[pa_ptr->m_ptr->r_idx].level)) {
310 attack_polymorph(player_ptr, pa_ptr, y, x);
313 const auto &item = player_ptr->inventory_list[enum2i(INVEN_MAIN_HAND) + pa_ptr->hand];
314 if (item.is_specific_artifact(FixedArtifactId::G_HAMMER)) {
315 attack_golden_hammer(player_ptr, pa_ptr);