OSDN Git Service

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