1 #include "mspell/mspell-attack/mspell-breath.h"
2 #include "core/disturbance.h"
3 #include "effect/attribute-types.h"
4 #include "effect/effect-processor.h"
5 #include "main/sound-definitions-table.h"
6 #include "main/sound-of-music.h"
7 #include "mind/drs-types.h"
8 #include "monster-race/race-ability-flags.h"
9 #include "monster-race/race-indice-types.h"
10 #include "monster/monster-info.h"
11 #include "monster/monster-update.h"
12 #include "mspell/mspell-checker.h"
13 #include "mspell/mspell-damage-calculator.h"
14 #include "mspell/mspell-data.h"
15 #include "mspell/mspell-result.h"
16 #include "mspell/mspell-util.h"
17 #include "system/floor-type-definition.h"
18 #include "system/monster-entity.h"
19 #include "system/player-type-definition.h"
20 #include "timed-effect/player-blindness.h"
21 #include "timed-effect/timed-effects.h"
22 #include "view/display-messages.h"
25 * @brief ブレスを吐くときにモンスター固有のセリフを表示する
26 * @param r_idx モンスター種族番号
28 * @return 表示したらTRUE、しなかったらFALSE
30 static bool spell_RF4_BREATH_special_message(MonsterRaceId r_idx, AttributeType GF_TYPE, concptr m_name)
32 if (r_idx == MonsterRaceId::JAIAN && GF_TYPE == AttributeType::SOUND) {
33 msg_format(_("%s^「ボォエ~~~~~~」", "%s^ sings, 'Booooeeeeee'"), m_name);
36 if (r_idx == MonsterRaceId::BOTEI && GF_TYPE == AttributeType::SHARDS) {
37 msg_format(_("%s^「ボ帝ビルカッター!!!」", "%s^ shouts, 'Boty-Build cutter!!!'"), m_name);
40 if (r_idx == MonsterRaceId::RAOU && (GF_TYPE == AttributeType::FORCE)) {
42 msg_format(_("%s^「北斗剛掌波!!」", "%s^ says, 'Hokuto Goh-Sho-Ha!!'"), m_name);
44 msg_format(_("%s^「受けてみい!!天将奔烈!!!」", "%s^ says, 'Tensho-Honretsu!!'"), m_name);
51 static void message_breath(PlayerType *player_ptr, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type, std::string_view type_s, AttributeType GF_TYPE)
53 auto *floor_ptr = player_ptr->current_floor_ptr;
54 auto *m_ptr = &floor_ptr->m_list[m_idx];
55 auto see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
56 auto known = monster_near_player(floor_ptr, m_idx, t_idx);
57 auto mon_to_mon = (target_type == MONSTER_TO_MONSTER);
58 auto mon_to_player = (target_type == MONSTER_TO_PLAYER);
59 const auto m_name = monster_name(player_ptr, m_idx);
60 const auto t_name = monster_name(player_ptr, t_idx);
62 if (!spell_RF4_BREATH_special_message(m_ptr->r_idx, GF_TYPE, m_name.data())) {
63 if (player_ptr->effects()->blindness()->is_blind()) {
64 if (mon_to_player || (mon_to_mon && known && see_either)) {
65 msg_format(_("%s^が何かのブレスを吐いた。", "%s^ breathes."), m_name.data());
69 msg_format(_("%s^が%s^のブレスを吐いた。", "%s^ breathes %s^."), m_name.data(), type_s.data());
70 } else if (mon_to_mon && known && see_either) {
71 _(msg_format("%s^が%s^に%s^のブレスを吐いた。", m_name.data(), t_name.data(), type_s.data()), msg_format("%s^ breathes %s^ at %s^.", m_name.data(), type_s.data(), t_name.data()));
76 if (mon_to_mon && known && !see_either) {
77 floor_ptr->monster_noise = true;
80 if (known || see_either) {
85 static std::pair<MonsterAbilityType, MSpellData> make_breath_elemental(MonsterAbilityType ms_type, AttributeType GF_TYPE, std::string_view type_s)
87 return { ms_type, { [type_s, GF_TYPE](auto *player_ptr, auto m_idx, auto t_idx, int target_type) {
88 message_breath(player_ptr, m_idx, t_idx, target_type, type_s, GF_TYPE);
94 static std::pair<MonsterAbilityType, MSpellData> make_breath_elemental(MonsterAbilityType ms_type, AttributeType GF_TYPE, std::string_view type_s, MSpellDrsData drs)
96 return { ms_type, { [type_s, GF_TYPE](auto *player_ptr, auto m_idx, auto t_idx, int target_type) {
97 message_breath(player_ptr, m_idx, t_idx, target_type, type_s, GF_TYPE);
103 const std::unordered_map<MonsterAbilityType, MSpellData> breath_list = {
104 make_breath_elemental(MonsterAbilityType::BR_ACID, AttributeType::ACID, _("酸", "acid"), DRS_ACID),
105 make_breath_elemental(MonsterAbilityType::BR_ELEC, AttributeType::ELEC, _("稲妻", "lightning"), DRS_ELEC),
106 make_breath_elemental(MonsterAbilityType::BR_FIRE, AttributeType::FIRE, _("火炎", "fire"), DRS_FIRE),
107 make_breath_elemental(MonsterAbilityType::BR_COLD, AttributeType::COLD, _("冷気", "frost"), DRS_COLD),
108 make_breath_elemental(MonsterAbilityType::BR_POIS, AttributeType::POIS, _("ガス", "gas"), DRS_POIS),
109 make_breath_elemental(MonsterAbilityType::BR_NETH, AttributeType::NETHER, _("地獄", "nether"), DRS_NETH),
110 make_breath_elemental(MonsterAbilityType::BR_LITE, AttributeType::LITE, _("閃光", "light"), DRS_LITE),
111 make_breath_elemental(MonsterAbilityType::BR_DARK, AttributeType::DARK, _("暗黒", "darkness"), DRS_DARK),
112 make_breath_elemental(MonsterAbilityType::BR_CONF, AttributeType::CONFUSION, _("混乱", "confusion"), DRS_CONF),
113 make_breath_elemental(MonsterAbilityType::BR_SOUN, AttributeType::SOUND, _("轟音", "sound"), DRS_SOUND),
114 make_breath_elemental(MonsterAbilityType::BR_CHAO, AttributeType::CHAOS, _("カオス", "chaos"), DRS_CHAOS),
115 make_breath_elemental(MonsterAbilityType::BR_DISE, AttributeType::DISENCHANT, _("劣化", "disenchantment"), DRS_DISEN),
116 make_breath_elemental(MonsterAbilityType::BR_NEXU, AttributeType::NEXUS, _("因果混乱", "nexus"), DRS_NEXUS),
117 make_breath_elemental(MonsterAbilityType::BR_TIME, AttributeType::TIME, _("時間逆転", "time")),
118 make_breath_elemental(MonsterAbilityType::BR_INER, AttributeType::INERTIAL, _("遅鈍", "inertia")),
119 make_breath_elemental(MonsterAbilityType::BR_GRAV, AttributeType::GRAVITY, _("重力", "gravity")),
120 make_breath_elemental(MonsterAbilityType::BR_SHAR, AttributeType::SHARDS, _("破片", "shards"), DRS_SHARD),
121 make_breath_elemental(MonsterAbilityType::BR_PLAS, AttributeType::PLASMA, _("プラズマ", "plasma")),
122 make_breath_elemental(MonsterAbilityType::BR_FORC, AttributeType::FORCE, _("フォース", "force")),
123 make_breath_elemental(MonsterAbilityType::BR_MANA, AttributeType::MANA, _("魔力", "mana")),
124 make_breath_elemental(MonsterAbilityType::BR_NUKE, AttributeType::NUKE, _("放射性廃棄物", "toxic waste"), DRS_POIS),
125 make_breath_elemental(MonsterAbilityType::BR_DISI, AttributeType::DISINTEGRATE, _("分解", "disintegration")),
126 make_breath_elemental(MonsterAbilityType::BR_VOID, AttributeType::VOID_MAGIC, _("虚無", "void")),
127 make_breath_elemental(MonsterAbilityType::BR_ABYSS, AttributeType::ABYSS, _("深淵", "abyss")),
131 * @brief RF4_BR_*の処理。各種ブレス。 /
132 * @param player_ptr プレイヤーへの参照ポインタ
133 * @param GF_TYPE ブレスの属性
136 * @param m_idx 呪文を唱えるモンスターID
137 * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
138 * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
142 MonsterSpellResult spell_RF4_BREATH(PlayerType *player_ptr, MonsterAbilityType ms_type, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type)
145 auto mon_to_player = (target_type == MONSTER_TO_PLAYER);
146 std::unique_ptr<MSpellData> data;
148 if (breath_list.find(ms_type) != breath_list.end()) {
149 dam = monspell_damage(player_ptr, ms_type, m_idx, DAM_ROLL);
150 data = std::make_unique<MSpellData>(breath_list.at(ms_type));
153 data = std::make_unique<MSpellData>([](auto *player_ptr, auto m_idx, auto t_idx, int target_type) {
154 message_breath(player_ptr, m_idx, t_idx, target_type, _("不明", "Unknown"), AttributeType::NONE);
157 AttributeType::NONE);
160 data->msg.output(player_ptr, m_idx, t_idx, target_type);
162 const auto proj_res = breath(player_ptr, y, x, m_idx, data->type, dam, 0, target_type);
165 data->drs.execute(player_ptr, m_idx);
168 auto res = MonsterSpellResult::make_valid(dam);
169 res.learnable = proj_res.affected_player;