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-type-definition.h"
19 #include "system/player-type-definition.h"
20 #include "view/display-messages.h"
23 * @brief ブレスを吐くときにモンスター固有のセリフを表示する
24 * @param r_idx モンスター種族番号
26 * @return 表示したらTRUE、しなかったらFALSE
28 static bool spell_RF4_BREATH_special_message(MonsterRaceId r_idx, AttributeType GF_TYPE, concptr m_name)
30 if (r_idx == MonsterRaceId::JAIAN && GF_TYPE == AttributeType::SOUND) {
31 msg_format(_("%^s「ボォエ~~~~~~」", "%^s sings, 'Booooeeeeee'"), m_name);
34 if (r_idx == MonsterRaceId::BOTEI && GF_TYPE == AttributeType::SHARDS) {
35 msg_format(_("%^s「ボ帝ビルカッター!!!」", "%^s shouts, 'Boty-Build cutter!!!'"), m_name);
38 if (r_idx == MonsterRaceId::RAOU && (GF_TYPE == AttributeType::FORCE)) {
40 msg_format(_("%^s「北斗剛掌波!!」", "%^s says, 'Hokuto Goh-Sho-Ha!!'"), m_name);
42 msg_format(_("%^s「受けてみい!!天将奔烈!!!」", "%^s says, 'Tensho-Honretsu!!'"), m_name);
49 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)
51 auto *floor_ptr = player_ptr->current_floor_ptr;
52 auto *m_ptr = &floor_ptr->m_list[m_idx];
53 auto see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
54 auto known = monster_near_player(floor_ptr, m_idx, t_idx);
55 auto mon_to_mon = (target_type == MONSTER_TO_MONSTER);
56 auto mon_to_player = (target_type == MONSTER_TO_PLAYER);
57 GAME_TEXT m_name[MAX_NLEN], t_name[MAX_NLEN];
58 monster_name(player_ptr, m_idx, m_name);
59 monster_name(player_ptr, t_idx, t_name);
61 if (!spell_RF4_BREATH_special_message(m_ptr->r_idx, GF_TYPE, m_name)) {
62 if (player_ptr->blind) {
63 if (mon_to_player || (mon_to_mon && known && see_either)) {
64 msg_format(_("%^sが何かのブレスを吐いた。", "%^s breathes."), m_name);
68 msg_format(_("%^sが%^sのブレスを吐いた。", "%^s breathes %^s."), m_name, type_s.data());
69 } else if (mon_to_mon && known && see_either) {
70 _(msg_format("%^sが%^sに%^sのブレスを吐いた。", m_name, t_name, type_s.data()), msg_format("%^s breathes %^s at %^s.", m_name, type_s.data(), t_name));
75 if (mon_to_mon && known && !see_either) {
76 floor_ptr->monster_noise = true;
79 if (known || see_either) {
84 static std::pair<MonsterAbilityType, MSpellData> make_breath_elemental(MonsterAbilityType ms_type, AttributeType GF_TYPE, std::string_view type_s)
86 return { ms_type, { [type_s, GF_TYPE](auto *player_ptr, auto m_idx, auto t_idx, int target_type) {
87 message_breath(player_ptr, m_idx, t_idx, target_type, type_s, GF_TYPE);
93 static std::pair<MonsterAbilityType, MSpellData> make_breath_elemental(MonsterAbilityType ms_type, AttributeType GF_TYPE, std::string_view type_s, MSpellDrsData drs)
95 return { ms_type, { [type_s, GF_TYPE](auto *player_ptr, auto m_idx, auto t_idx, int target_type) {
96 message_breath(player_ptr, m_idx, t_idx, target_type, type_s, GF_TYPE);
102 const std::unordered_map<MonsterAbilityType, MSpellData> breath_list = {
103 make_breath_elemental(MonsterAbilityType::BR_ACID, AttributeType::ACID, _("酸", "acid"), DRS_ACID),
104 make_breath_elemental(MonsterAbilityType::BR_ELEC, AttributeType::ELEC, _("稲妻", "lightning"), DRS_ELEC),
105 make_breath_elemental(MonsterAbilityType::BR_FIRE, AttributeType::FIRE, _("火炎", "fire"), DRS_FIRE),
106 make_breath_elemental(MonsterAbilityType::BR_COLD, AttributeType::COLD, _("冷気", "frost"), DRS_COLD),
107 make_breath_elemental(MonsterAbilityType::BR_POIS, AttributeType::POIS, _("ガス", "gas"), DRS_POIS),
108 make_breath_elemental(MonsterAbilityType::BR_NETH, AttributeType::NETHER, _("地獄", "nether"), DRS_NETH),
109 make_breath_elemental(MonsterAbilityType::BR_LITE, AttributeType::LITE, _("閃光", "light"), DRS_LITE),
110 make_breath_elemental(MonsterAbilityType::BR_DARK, AttributeType::DARK, _("暗黒", "darkness"), DRS_DARK),
111 make_breath_elemental(MonsterAbilityType::BR_CONF, AttributeType::CONFUSION, _("混乱", "confusion"), DRS_CONF),
112 make_breath_elemental(MonsterAbilityType::BR_SOUN, AttributeType::SOUND, _("轟音", "sound"), DRS_SOUND),
113 make_breath_elemental(MonsterAbilityType::BR_CHAO, AttributeType::CHAOS, _("カオス", "chaos"), DRS_CHAOS),
114 make_breath_elemental(MonsterAbilityType::BR_DISE, AttributeType::DISENCHANT, _("劣化", "disenchantment"), DRS_DISEN),
115 make_breath_elemental(MonsterAbilityType::BR_NEXU, AttributeType::NEXUS, _("因果混乱", "nexus"), DRS_NEXUS),
116 make_breath_elemental(MonsterAbilityType::BR_TIME, AttributeType::TIME, _("時間逆転", "time")),
117 make_breath_elemental(MonsterAbilityType::BR_INER, AttributeType::INERTIAL, _("遅鈍", "inertia")),
118 make_breath_elemental(MonsterAbilityType::BR_GRAV, AttributeType::GRAVITY, _("重力", "gravity")),
119 make_breath_elemental(MonsterAbilityType::BR_SHAR, AttributeType::SHARDS, _("破片", "shards"), DRS_SHARD),
120 make_breath_elemental(MonsterAbilityType::BR_PLAS, AttributeType::PLASMA, _("プラズマ", "plasma")),
121 make_breath_elemental(MonsterAbilityType::BR_FORC, AttributeType::FORCE, _("フォース", "force")),
122 make_breath_elemental(MonsterAbilityType::BR_MANA, AttributeType::MANA, _("魔力", "mana")),
123 make_breath_elemental(MonsterAbilityType::BR_NUKE, AttributeType::NUKE, _("放射性廃棄物", "toxic waste"), DRS_POIS),
124 make_breath_elemental(MonsterAbilityType::BR_DISI, AttributeType::DISINTEGRATE, _("分解", "disintegration")),
125 make_breath_elemental(MonsterAbilityType::BR_VOID, AttributeType::VOID_MAGIC, _("虚無", "void")),
126 make_breath_elemental(MonsterAbilityType::BR_ABYSS, AttributeType::ABYSS, _("深淵", "abyss")),
130 * @brief RF4_BR_*の処理。各種ブレス。 /
131 * @param player_ptr プレイヤーへの参照ポインタ
132 * @param GF_TYPE ブレスの属性
135 * @param m_idx 呪文を唱えるモンスターID
136 * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
137 * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
141 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)
144 auto mon_to_player = (target_type == MONSTER_TO_PLAYER);
145 std::unique_ptr<MSpellData> data;
147 if (breath_list.find(ms_type) != breath_list.end()) {
148 dam = monspell_damage(player_ptr, ms_type, m_idx, DAM_ROLL);
149 data = std::make_unique<MSpellData>(breath_list.at(ms_type));
152 data = std::make_unique<MSpellData>([](auto *player_ptr, auto m_idx, auto t_idx, int target_type) {
153 message_breath(player_ptr, m_idx, t_idx, target_type, _("不明", "Unknown"), AttributeType::NONE);
156 AttributeType::NONE);
159 data->msg.output(player_ptr, m_idx, t_idx, target_type);
161 const auto proj_res = breath(player_ptr, y, x, m_idx, data->type, dam, 0, target_type);
164 data->drs.execute(player_ptr, m_idx);
167 auto res = MonsterSpellResult::make_valid(dam);
168 res.learnable = proj_res.affected_player;