OSDN Git Service

[Implement] ウサウサストライカー召喚処理を追加
[hengbandforosx/hengbandosx.git] / src / monster-floor / monster-runaway.cpp
1 /*!
2  * @brief モンスターの逃走に関する処理
3  * @date 2020/03/08
4  * @author Hourier
5  */
6
7 #include "monster-floor/monster-runaway.h"
8 #include "core/disturbance.h"
9 #include "dungeon/quest-completion-checker.h"
10 #include "grid/grid.h"
11 #include "monster-floor/monster-remover.h"
12 #include "monster-race/monster-race.h"
13 #include "monster-race/race-flags1.h"
14 #include "monster-race/race-flags2.h"
15 #include "monster-race/race-flags7.h"
16 #include "monster-race/race-indice-types.h"
17 #include "monster/monster-describer.h"
18 #include "monster/monster-info.h"
19 #include "monster/monster-processor-util.h"
20 #include "pet/pet-fall-off.h"
21 #include "system/angband-system.h"
22 #include "system/floor-type-definition.h"
23 #include "system/monster-entity.h"
24 #include "system/monster-race-info.h"
25 #include "system/player-type-definition.h"
26 #include "target/projection-path-calculator.h"
27 #include "view/display-messages.h"
28
29 /*!
30  * @brief monspeak.txt において、発話ではなく行動のみが描写されているモンスターであるかを調べる
31  * @param r_idx モンスター種族ID
32  * @return 会話内容が行動のみのモンスターか否か
33  */
34 static bool is_acting_monster(const MonsterRaceId r_idx)
35 {
36     auto is_acting_monster = r_idx == MonsterRaceId::GRIP;
37     is_acting_monster |= r_idx == MonsterRaceId::WOLF;
38     is_acting_monster |= r_idx == MonsterRaceId::FANG;
39     return is_acting_monster;
40 }
41
42 /*!
43  * @brief HPが1/3未満になった友好的なユニークモンスターの逃走処理を行う
44  * @param player_ptr プレイヤーへの参照ポインタ
45  * @param is_riding_mon 騎乗状態ならばTRUE
46  * @param m_ptr モンスターへの参照ポインタ
47  * @param m_name モンスター名称
48  */
49 static void escape_monster(PlayerType *player_ptr, turn_flags *turn_flags_ptr, MonsterEntity *m_ptr, concptr m_name)
50 {
51     if (turn_flags_ptr->is_riding_mon) {
52         msg_format(_("%sはあなたの束縛から脱出した。", "%s^ succeeded to escape from your restriction!"), m_name);
53         if (process_fall_off_horse(player_ptr, -1, false)) {
54             msg_print(_("地面に落とされた。", "You have fallen from the pet you were riding."));
55         }
56     }
57
58     if (turn_flags_ptr->see_m) {
59         static constexpr auto flags = {
60             MonsterSpeakType::SPEAK_ALL,
61             MonsterSpeakType::SPEAK_BATTLE,
62             MonsterSpeakType::SPEAK_FEAR,
63         };
64
65         auto speak = m_ptr->get_monrace().speak_flags.has_any_of(flags);
66         speak &= !is_acting_monster(m_ptr->r_idx);
67         speak &= player_ptr->current_floor_ptr->has_los({ m_ptr->fy, m_ptr->fx });
68         speak &= projectable(player_ptr, m_ptr->fy, m_ptr->fx, player_ptr->y, player_ptr->x);
69         if (speak) {
70             msg_format(_("%s^「ピンチだ!退却させてもらう!」", "%s^ says 'It is the pinch! I will retreat'."), m_name);
71         }
72
73         msg_format(_("%s^がテレポート・レベルの巻物を読んだ。", "%s^ reads a scroll of teleport level."), m_name);
74         msg_format(_("%s^が消え去った。", "%s^ disappears."), m_name);
75     }
76
77     if (turn_flags_ptr->is_riding_mon && process_fall_off_horse(player_ptr, -1, false)) {
78         msg_print(_("地面に落とされた。", "You have fallen from the pet you were riding."));
79     }
80 }
81
82 /*!
83  * @brief ペットや友好的なモンスターがフロアから逃げる処理を行う
84  * @param player_ptr プレイヤーへの参照ポインタ
85  * @param m_idx モンスターID
86  * @param is_riding_mon 騎乗状態ならばTRUE
87  * @param see_m モンスターが視界内にいたらTRUE
88  * @return モンスターがフロアから消えたらTRUE
89  */
90 bool runaway_monster(PlayerType *player_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx)
91 {
92     auto *m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx];
93     auto *r_ptr = &m_ptr->get_monrace();
94     bool can_runaway = m_ptr->is_pet() || m_ptr->is_friendly();
95     can_runaway &= (r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) || (r_ptr->population_flags.has(MonsterPopulationType::NAZGUL));
96     can_runaway &= !AngbandSystem::get_instance().is_phase_out();
97     if (!can_runaway) {
98         return false;
99     }
100
101     static int riding_pinch = 0;
102
103     if (m_ptr->hp >= m_ptr->maxhp / 3) {
104         /* Reset the counter */
105         if (turn_flags_ptr->is_riding_mon) {
106             riding_pinch = 0;
107         }
108
109         return false;
110     }
111
112     const auto m_name = monster_desc(player_ptr, m_ptr, 0);
113     if (turn_flags_ptr->is_riding_mon && riding_pinch < 2) {
114         msg_format(
115             _("%sは傷の痛さの余りあなたの束縛から逃れようとしている。", "%s^ seems to be in so much pain and tries to escape from your restriction."), m_name.data());
116         riding_pinch++;
117         disturb(player_ptr, true, true);
118         return false;
119     }
120
121     escape_monster(player_ptr, turn_flags_ptr, m_ptr, m_name.data());
122     QuestCompletionChecker(player_ptr, m_ptr).complete();
123     delete_monster_idx(player_ptr, m_idx);
124     return true;
125 }