OSDN Git Service

[Refactor] #3286 Removed player-redraw-types.h
[hengbandforosx/hengbandosx.git] / src / effect / effect-monster-oldies.cpp
1 #include "effect/effect-monster-oldies.h"
2 #include "avatar/avatar.h"
3 #include "effect/effect-monster-util.h"
4 #include "monster-floor/monster-generator.h"
5 #include "monster-race/monster-race.h"
6 #include "monster-race/race-flags1.h"
7 #include "monster-race/race-flags3.h"
8 #include "monster-race/race-flags7.h"
9 #include "monster-race/race-indice-types.h"
10 #include "monster/monster-info.h"
11 #include "monster/monster-status-setter.h"
12 #include "monster/monster-status.h"
13 #include "system/floor-type-definition.h"
14 #include "system/grid-type-definition.h"
15 #include "system/monster-entity.h"
16 #include "system/monster-race-info.h"
17 #include "system/player-type-definition.h"
18 #include "system/redrawing-flags-updater.h"
19 #include "util/bit-flags-calculator.h"
20 #include "view/display-messages.h"
21
22 // Powerful monsters can resist.
23 ProcessResult effect_monster_old_poly(effect_monster_type *em_ptr)
24 {
25     if (em_ptr->seen) {
26         em_ptr->obvious = true;
27     }
28     em_ptr->do_polymorph = true;
29
30     bool has_resistance = em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE);
31     has_resistance |= any_bits(em_ptr->r_ptr->flags1, RF1_QUESTOR);
32     has_resistance |= (em_ptr->r_ptr->level > randint1(std::max(1, em_ptr->dam - 10)) + 10);
33
34     if (has_resistance) {
35         em_ptr->note = _("には効果がなかった。", " is unaffected.");
36         em_ptr->do_polymorph = false;
37         em_ptr->obvious = false;
38     }
39
40     em_ptr->dam = 0;
41     return ProcessResult::PROCESS_CONTINUE;
42 }
43
44 ProcessResult effect_monster_old_clone(PlayerType *player_ptr, effect_monster_type *em_ptr)
45 {
46     if (em_ptr->seen) {
47         em_ptr->obvious = true;
48     }
49
50     bool has_resistance = (player_ptr->current_floor_ptr->inside_arena);
51     has_resistance |= em_ptr->m_ptr->is_pet();
52     has_resistance |= em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE);
53     has_resistance |= any_bits(em_ptr->r_ptr->flags1, RF1_QUESTOR);
54     has_resistance |= em_ptr->r_ptr->population_flags.has(MonsterPopulationType::NAZGUL);
55     has_resistance |= any_bits(em_ptr->r_ptr->flags7, RF7_UNIQUE2);
56
57     if (has_resistance) {
58         em_ptr->note = _("には効果がなかった。", " is unaffected.");
59         em_ptr->dam = 0;
60         return ProcessResult::PROCESS_CONTINUE;
61     }
62
63     em_ptr->m_ptr->hp = em_ptr->m_ptr->maxhp;
64     if (multiply_monster(player_ptr, em_ptr->g_ptr->m_idx, true, 0L)) {
65         em_ptr->note = _("が分裂した!", " spawns!");
66     }
67
68     em_ptr->dam = 0;
69     return ProcessResult::PROCESS_CONTINUE;
70 }
71
72 ProcessResult effect_monster_star_heal(PlayerType *player_ptr, effect_monster_type *em_ptr)
73 {
74     if (em_ptr->seen) {
75         em_ptr->obvious = true;
76     }
77
78     (void)set_monster_csleep(player_ptr, em_ptr->g_ptr->m_idx, 0);
79
80     if (em_ptr->m_ptr->maxhp < em_ptr->m_ptr->max_maxhp) {
81         if (em_ptr->seen_msg) {
82             msg_print(_(format("%s^の強さが戻った。", em_ptr->m_name), format("%s^ recovers %s vitality.", em_ptr->m_name, em_ptr->m_poss)));
83         }
84         em_ptr->m_ptr->maxhp = em_ptr->m_ptr->max_maxhp;
85     }
86
87     auto &rfu = RedrawingFlagsUpdater::get_instance();
88     if (!em_ptr->dam) {
89         if (player_ptr->health_who == em_ptr->g_ptr->m_idx) {
90             rfu.set_flag(MainWindowRedrawingFlag::HEALTH);
91         }
92
93         if (player_ptr->riding == em_ptr->g_ptr->m_idx) {
94             rfu.set_flag(MainWindowRedrawingFlag::UHEALTH);
95         }
96
97         return ProcessResult::PROCESS_FALSE;
98     }
99
100     effect_monster_old_heal(player_ptr, em_ptr);
101     return ProcessResult::PROCESS_TRUE;
102 }
103
104 // who == 0ならばプレイヤーなので、それの判定.
105 static void effect_monster_old_heal_check_player(PlayerType *player_ptr, effect_monster_type *em_ptr)
106 {
107     if (em_ptr->who != 0) {
108         return;
109     }
110
111     chg_virtue(player_ptr, Virtue::VITALITY, 1);
112     if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
113         chg_virtue(player_ptr, Virtue::INDIVIDUALISM, 1);
114     }
115
116     if (em_ptr->m_ptr->is_friendly()) {
117         chg_virtue(player_ptr, Virtue::HONOUR, 1);
118     } else if (em_ptr->r_ptr->kind_flags.has_not(MonsterKindType::EVIL)) {
119         if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::GOOD)) {
120             chg_virtue(player_ptr, Virtue::COMPASSION, 2);
121         } else {
122             chg_virtue(player_ptr, Virtue::COMPASSION, 1);
123         }
124     }
125
126     if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::ANIMAL)) {
127         chg_virtue(player_ptr, Virtue::NATURE, 1);
128     }
129 }
130
131 static void effect_monster_old_heal_recovery(PlayerType *player_ptr, effect_monster_type *em_ptr)
132 {
133     if (em_ptr->m_ptr->get_remaining_stun()) {
134         if (em_ptr->seen_msg) {
135             msg_format(_("%s^は朦朧状態から立ち直った。", "%s^ is no longer stunned."), em_ptr->m_name);
136         }
137
138         (void)set_monster_stunned(player_ptr, em_ptr->g_ptr->m_idx, 0);
139     }
140
141     if (em_ptr->m_ptr->is_confused()) {
142         if (em_ptr->seen_msg) {
143             msg_format(_("%s^は混乱から立ち直った。", "%s^ is no longer confused."), em_ptr->m_name);
144         }
145
146         (void)set_monster_confused(player_ptr, em_ptr->g_ptr->m_idx, 0);
147     }
148
149     if (em_ptr->m_ptr->is_fearful()) {
150         if (em_ptr->seen_msg) {
151             msg_print(_(format("%s^は勇気を取り戻した。", em_ptr->m_name), format("%s^ recovers %s courage.", em_ptr->m_name, em_ptr->m_poss)));
152         }
153
154         (void)set_monster_monfear(player_ptr, em_ptr->g_ptr->m_idx, 0);
155     }
156 }
157
158 ProcessResult effect_monster_old_heal(PlayerType *player_ptr, effect_monster_type *em_ptr)
159 {
160     if (em_ptr->seen) {
161         em_ptr->obvious = true;
162     }
163
164     /* Wake up */
165     (void)set_monster_csleep(player_ptr, em_ptr->g_ptr->m_idx, 0);
166     effect_monster_old_heal_recovery(player_ptr, em_ptr);
167     if (em_ptr->m_ptr->hp < MONSTER_MAXHP) {
168         em_ptr->m_ptr->hp += em_ptr->dam;
169     }
170     if (em_ptr->m_ptr->hp > em_ptr->m_ptr->maxhp) {
171         em_ptr->m_ptr->hp = em_ptr->m_ptr->maxhp;
172     }
173
174     effect_monster_old_heal_check_player(player_ptr, em_ptr);
175     if (em_ptr->m_ptr->r_idx == MonsterRaceId::LEPER) {
176         em_ptr->heal_leper = true;
177         if (!em_ptr->who) {
178             chg_virtue(player_ptr, Virtue::COMPASSION, 5);
179         }
180     }
181
182     auto &rfu = RedrawingFlagsUpdater::get_instance();
183     if (player_ptr->health_who == em_ptr->g_ptr->m_idx) {
184         rfu.set_flag(MainWindowRedrawingFlag::HEALTH);
185     }
186
187     if (player_ptr->riding == em_ptr->g_ptr->m_idx) {
188         rfu.set_flag(MainWindowRedrawingFlag::UHEALTH);
189     }
190
191     em_ptr->note = _("は体力を回復したようだ。", " looks healthier.");
192     em_ptr->dam = 0;
193     return ProcessResult::PROCESS_CONTINUE;
194 }
195
196 ProcessResult effect_monster_old_speed(PlayerType *player_ptr, effect_monster_type *em_ptr)
197 {
198     if (em_ptr->seen) {
199         em_ptr->obvious = true;
200     }
201
202     if (set_monster_fast(player_ptr, em_ptr->g_ptr->m_idx, em_ptr->m_ptr->get_remaining_acceleration() + 100)) {
203         em_ptr->note = _("の動きが速くなった。", " starts moving faster.");
204     }
205
206     if (!em_ptr->who) {
207         if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
208             chg_virtue(player_ptr, Virtue::INDIVIDUALISM, 1);
209         }
210         if (em_ptr->m_ptr->is_friendly()) {
211             chg_virtue(player_ptr, Virtue::HONOUR, 1);
212         }
213     }
214
215     em_ptr->dam = 0;
216     return ProcessResult::PROCESS_CONTINUE;
217 }
218
219 ProcessResult effect_monster_old_slow(PlayerType *player_ptr, effect_monster_type *em_ptr)
220 {
221     if (em_ptr->seen) {
222         em_ptr->obvious = true;
223     }
224
225     bool has_resistance = em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE);
226     has_resistance |= (em_ptr->r_ptr->level > randint1(std::max(1, em_ptr->dam - 10)) + 10);
227
228     /* Powerful monsters can resist */
229     if (has_resistance) {
230         em_ptr->note = _("には効果がなかった。", " is unaffected.");
231         em_ptr->obvious = false;
232         em_ptr->dam = 0;
233         return ProcessResult::PROCESS_CONTINUE;
234     }
235
236     if (set_monster_slow(player_ptr, em_ptr->g_ptr->m_idx, em_ptr->m_ptr->get_remaining_deceleration() + 50)) {
237         em_ptr->note = _("の動きが遅くなった。", " starts moving slower.");
238     }
239
240     em_ptr->dam = 0;
241     return ProcessResult::PROCESS_CONTINUE;
242 }
243
244 /*!
245  * @todo 「ユニークは (魔法では)常に眠らない」はMonsterRaceDefinitionの趣旨に反すると思われる
246  * 眠る確率を半分にするとかしておいた方が良さそう
247  */
248 ProcessResult effect_monster_old_sleep(PlayerType *player_ptr, effect_monster_type *em_ptr)
249 {
250     if (em_ptr->seen) {
251         em_ptr->obvious = true;
252     }
253
254     bool has_resistance = em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE);
255     has_resistance |= any_bits(em_ptr->r_ptr->flags3, RF3_NO_SLEEP);
256     has_resistance |= (em_ptr->r_ptr->level > randint1(std::max(1, em_ptr->dam - 10)) + 10);
257
258     if (has_resistance) {
259         if (em_ptr->r_ptr->flags3 & RF3_NO_SLEEP) {
260             if (is_original_ap_and_seen(player_ptr, em_ptr->m_ptr)) {
261                 em_ptr->r_ptr->r_flags3 |= (RF3_NO_SLEEP);
262             }
263         }
264
265         em_ptr->note = _("には効果がなかった。", " is unaffected.");
266         em_ptr->obvious = false;
267     } else {
268         em_ptr->note = _("は眠り込んでしまった!", " falls asleep!");
269         em_ptr->do_sleep = 500;
270     }
271
272     em_ptr->dam = 0;
273     return ProcessResult::PROCESS_CONTINUE;
274 }
275
276 /*!
277  * @todo 「ユニークは (魔法では)常に混乱しない」はMonsterRaceDefinitionの趣旨に反すると思われる
278  * 眠る確率を半分にするとかしておいた方が良さそう
279  */
280 ProcessResult effect_monster_old_conf(PlayerType *player_ptr, effect_monster_type *em_ptr)
281 {
282     if (em_ptr->seen) {
283         em_ptr->obvious = true;
284     }
285
286     em_ptr->do_conf = damroll(3, (em_ptr->dam / 2)) + 1;
287
288     bool has_resistance = em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE);
289     has_resistance |= any_bits(em_ptr->r_ptr->flags3, RF3_NO_CONF);
290     has_resistance |= (em_ptr->r_ptr->level > randint1(std::max(1, em_ptr->dam - 10)) + 10);
291     if (has_resistance) {
292         if (em_ptr->r_ptr->flags3 & (RF3_NO_CONF)) {
293             if (is_original_ap_and_seen(player_ptr, em_ptr->m_ptr)) {
294                 em_ptr->r_ptr->r_flags3 |= (RF3_NO_CONF);
295             }
296         }
297
298         em_ptr->do_conf = 0;
299         em_ptr->note = _("には効果がなかった。", " is unaffected.");
300         em_ptr->obvious = false;
301     }
302
303     em_ptr->dam = 0;
304     return ProcessResult::PROCESS_CONTINUE;
305 }
306
307 ProcessResult effect_monster_stasis(effect_monster_type *em_ptr, bool to_evil)
308 {
309     if (em_ptr->seen) {
310         em_ptr->obvious = true;
311     }
312
313     int stasis_damage = (em_ptr->dam - 10) < 1 ? 1 : (em_ptr->dam - 10);
314     bool has_resistance = em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE);
315     has_resistance |= em_ptr->r_ptr->level > randint1(stasis_damage) + 10;
316     if (to_evil) {
317         has_resistance |= em_ptr->r_ptr->kind_flags.has_not(MonsterKindType::EVIL);
318     }
319
320     if (has_resistance) {
321         em_ptr->note = _("には効果がなかった。", " is unaffected.");
322         em_ptr->obvious = false;
323     } else {
324         em_ptr->note = _("は動けなくなった!", " is suspended!");
325         em_ptr->do_sleep = 500;
326     }
327
328     em_ptr->dam = 0;
329     return ProcessResult::PROCESS_CONTINUE;
330 }
331
332 ProcessResult effect_monster_stun(effect_monster_type *em_ptr)
333 {
334     if (em_ptr->seen) {
335         em_ptr->obvious = true;
336     }
337
338     em_ptr->do_stun = damroll((em_ptr->caster_lev / 20) + 3, (em_ptr->dam)) + 1;
339
340     bool has_resistance = em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE);
341     has_resistance |= (em_ptr->r_ptr->level > randint1(std::max(1, em_ptr->dam - 10)) + 10);
342     if (has_resistance) {
343         em_ptr->do_stun = 0;
344         em_ptr->note = _("には効果がなかった。", " is unaffected.");
345         em_ptr->obvious = false;
346     }
347
348     em_ptr->dam = 0;
349     return ProcessResult::PROCESS_CONTINUE;
350 }