OSDN Git Service

[Refactor] #1448 Replaced 'NULL' to 'nullptr' except for Win32API
[hengbandforosx/hengbandosx.git] / src / effect / effect-monster-charm.cpp
1 #include "effect/effect-monster-charm.h"
2 #include "avatar/avatar.h"
3 #include "dungeon/quest.h"
4 #include "effect/effect-monster-util.h"
5 #include "effect/spells-effect-util.h"
6 #include "monster-floor/monster-remover.h"
7 #include "monster-race/monster-race-hook.h"
8 #include "monster-race/monster-race.h"
9 #include "monster-race/race-flags1.h"
10 #include "monster-race/race-flags3.h"
11 #include "monster-race/race-flags7.h"
12 #include "monster-race/race-indice-types.h"
13 #include "monster/monster-flag-types.h"
14 #include "monster/monster-info.h"
15 #include "monster/monster-list.h"
16 #include "monster/monster-status-setter.h"
17 #include "monster/monster-status.h"
18 #include "object-enchant/trc-types.h"
19 #include "pet/pet-fall-off.h"
20 #include "pet/pet-util.h"
21 #include "player/player-status-flags.h"
22 #include "spell/spells-diceroll.h"
23 #include "status/bad-status-setter.h"
24 #include "system/floor-type-definition.h"
25 #include "system/grid-type-definition.h"
26 #include "system/monster-race-definition.h"
27 #include "system/monster-type-definition.h"
28 #include "system/player-type-definition.h"
29 #include "util/bit-flags-calculator.h"
30 #include "view/display-messages.h"
31
32 static void effect_monster_charm_resist(player_type *caster_ptr, effect_monster_type *em_ptr)
33 {
34     if (common_saving_throw_charm(caster_ptr, em_ptr->dam, em_ptr->m_ptr)) {
35         em_ptr->note = _("には効果がなかった。", " is unaffected.");
36         em_ptr->obvious = false;
37
38         if (one_in_(4))
39             em_ptr->m_ptr->mflag2.set(MFLAG2::NOPET);
40     } else if (has_aggravate(caster_ptr)) {
41         em_ptr->note = _("はあなたに敵意を抱いている!", " hates you too much!");
42         if (one_in_(4))
43             em_ptr->m_ptr->mflag2.set(MFLAG2::NOPET);
44     } else {
45         em_ptr->note = _("は突然友好的になったようだ!", " suddenly seems friendly!");
46         set_pet(caster_ptr, em_ptr->m_ptr);
47
48         chg_virtue(caster_ptr, V_INDIVIDUALISM, -1);
49         if (em_ptr->r_ptr->flags3 & RF3_ANIMAL)
50             chg_virtue(caster_ptr, V_NATURE, 1);
51     }
52 }
53
54 process_result effect_monster_charm(player_type *caster_ptr, effect_monster_type *em_ptr)
55 {
56     int vir = virtue_number(caster_ptr, V_HARMONY);
57     if (vir) {
58         em_ptr->dam += caster_ptr->virtues[vir - 1] / 10;
59     }
60
61     vir = virtue_number(caster_ptr, V_INDIVIDUALISM);
62     if (vir) {
63         em_ptr->dam -= caster_ptr->virtues[vir - 1] / 20;
64     }
65
66     if (em_ptr->seen)
67         em_ptr->obvious = true;
68
69     effect_monster_charm_resist(caster_ptr, em_ptr);
70     em_ptr->dam = 0;
71     return PROCESS_CONTINUE;
72 }
73
74 process_result effect_monster_control_undead(player_type *caster_ptr, effect_monster_type *em_ptr)
75 {
76     if (em_ptr->seen)
77         em_ptr->obvious = true;
78
79     int vir = virtue_number(caster_ptr, V_UNLIFE);
80     if (vir) {
81         em_ptr->dam += caster_ptr->virtues[vir - 1] / 10;
82     }
83
84     vir = virtue_number(caster_ptr, V_INDIVIDUALISM);
85     if (vir) {
86         em_ptr->dam -= caster_ptr->virtues[vir - 1] / 20;
87     }
88
89     if (common_saving_throw_control(caster_ptr, em_ptr->dam, em_ptr->m_ptr) || !(em_ptr->r_ptr->flags3 & RF3_UNDEAD)) {
90         em_ptr->note = _("には効果がなかった。", " is unaffected.");
91         em_ptr->obvious = false;
92         if (one_in_(4))
93             em_ptr->m_ptr->mflag2.set(MFLAG2::NOPET);
94     } else if (has_aggravate(caster_ptr)) {
95         em_ptr->note = _("はあなたに敵意を抱いている!", " hates you too much!");
96         if (one_in_(4))
97             em_ptr->m_ptr->mflag2.set(MFLAG2::NOPET);
98     } else {
99         em_ptr->note = _("は既にあなたの奴隷だ!", " is in your thrall!");
100         set_pet(caster_ptr, em_ptr->m_ptr);
101     }
102
103     em_ptr->dam = 0;
104     return PROCESS_CONTINUE;
105 }
106
107 process_result effect_monster_control_demon(player_type *caster_ptr, effect_monster_type *em_ptr)
108 {
109     if (em_ptr->seen)
110         em_ptr->obvious = true;
111
112     int vir = virtue_number(caster_ptr, V_UNLIFE);
113     if (vir) {
114         em_ptr->dam += caster_ptr->virtues[vir - 1] / 10;
115     }
116
117     vir = virtue_number(caster_ptr, V_INDIVIDUALISM);
118     if (vir) {
119         em_ptr->dam -= caster_ptr->virtues[vir - 1] / 20;
120     }
121
122     if (common_saving_throw_control(caster_ptr, em_ptr->dam, em_ptr->m_ptr) || !(em_ptr->r_ptr->flags3 & RF3_DEMON)) {
123         em_ptr->note = _("には効果がなかった。", " is unaffected.");
124         em_ptr->obvious = false;
125         if (one_in_(4))
126             em_ptr->m_ptr->mflag2.set(MFLAG2::NOPET);
127     } else if (has_aggravate(caster_ptr)) {
128         em_ptr->note = _("はあなたに敵意を抱いている!", " hates you too much!");
129         if (one_in_(4))
130             em_ptr->m_ptr->mflag2.set(MFLAG2::NOPET);
131     } else {
132         em_ptr->note = _("は既にあなたの奴隷だ!", " is in your thrall!");
133         set_pet(caster_ptr, em_ptr->m_ptr);
134     }
135
136     em_ptr->dam = 0;
137     return PROCESS_CONTINUE;
138 }
139
140 process_result effect_monster_control_animal(player_type *caster_ptr, effect_monster_type *em_ptr)
141 {
142     if (em_ptr->seen)
143         em_ptr->obvious = true;
144
145     int vir = virtue_number(caster_ptr, V_NATURE);
146     if (vir) {
147         em_ptr->dam += caster_ptr->virtues[vir - 1] / 10;
148     }
149
150     vir = virtue_number(caster_ptr, V_INDIVIDUALISM);
151     if (vir) {
152         em_ptr->dam -= caster_ptr->virtues[vir - 1] / 20;
153     }
154
155     if (common_saving_throw_control(caster_ptr, em_ptr->dam, em_ptr->m_ptr) || !(em_ptr->r_ptr->flags3 & RF3_ANIMAL)) {
156         em_ptr->note = _("には効果がなかった。", " is unaffected.");
157         em_ptr->obvious = false;
158         if (one_in_(4))
159             em_ptr->m_ptr->mflag2.set(MFLAG2::NOPET);
160     } else if (has_aggravate(caster_ptr)) {
161         em_ptr->note = _("はあなたに敵意を抱いている!", " hates you too much!");
162         if (one_in_(4))
163             em_ptr->m_ptr->mflag2.set(MFLAG2::NOPET);
164     } else {
165         em_ptr->note = _("はなついた。", " is tamed!");
166         set_pet(caster_ptr, em_ptr->m_ptr);
167         if (em_ptr->r_ptr->flags3 & RF3_ANIMAL)
168             chg_virtue(caster_ptr, V_NATURE, 1);
169     }
170
171     em_ptr->dam = 0;
172     return PROCESS_CONTINUE;
173 }
174
175 process_result effect_monster_charm_living(player_type *caster_ptr, effect_monster_type *em_ptr)
176 {
177     int vir = virtue_number(caster_ptr, V_UNLIFE);
178     if (em_ptr->seen)
179         em_ptr->obvious = true;
180
181     vir = virtue_number(caster_ptr, V_UNLIFE);
182     if (vir) {
183         em_ptr->dam -= caster_ptr->virtues[vir - 1] / 10;
184     }
185
186     vir = virtue_number(caster_ptr, V_INDIVIDUALISM);
187     if (vir) {
188         em_ptr->dam -= caster_ptr->virtues[vir - 1] / 20;
189     }
190
191     msg_format(_("%sを見つめた。", "You stare at %s."), em_ptr->m_name);
192
193     if (common_saving_throw_charm(caster_ptr, em_ptr->dam, em_ptr->m_ptr) || !monster_living(em_ptr->m_ptr->r_idx)) {
194         em_ptr->note = _("には効果がなかった。", " is unaffected.");
195         em_ptr->obvious = false;
196         if (one_in_(4))
197             em_ptr->m_ptr->mflag2.set(MFLAG2::NOPET);
198     } else if (has_aggravate(caster_ptr)) {
199         em_ptr->note = _("はあなたに敵意を抱いている!", " hates you too much!");
200         if (one_in_(4))
201             em_ptr->m_ptr->mflag2.set(MFLAG2::NOPET);
202     } else {
203         em_ptr->note = _("を支配した。", " is tamed!");
204         set_pet(caster_ptr, em_ptr->m_ptr);
205         if (em_ptr->r_ptr->flags3 & RF3_ANIMAL)
206             chg_virtue(caster_ptr, V_NATURE, 1);
207     }
208
209     em_ptr->dam = 0;
210     return PROCESS_CONTINUE;
211 }
212
213 static void effect_monster_domination_corrupted_addition(player_type *caster_ptr, effect_monster_type *em_ptr)
214 {
215     switch (randint1(4)) {
216     case 1:
217         set_stun(caster_ptr, caster_ptr->stun + em_ptr->dam / 2);
218         break;
219     case 2:
220         set_confused(caster_ptr, caster_ptr->confused + em_ptr->dam / 2);
221         break;
222     default: {
223         if (em_ptr->r_ptr->flags3 & RF3_NO_FEAR)
224             em_ptr->note = _("には効果がなかった。", " is unaffected.");
225         else
226             set_afraid(caster_ptr, caster_ptr->afraid + em_ptr->dam);
227     }
228     }
229 }
230
231 // Powerful demons & undead can turn a mindcrafter's attacks back on them.
232 static void effect_monster_domination_corrupted(player_type *caster_ptr, effect_monster_type *em_ptr)
233 {
234     bool is_corrupted = ((em_ptr->r_ptr->flags3 & (RF3_UNDEAD | RF3_DEMON)) != 0) && (em_ptr->r_ptr->level > caster_ptr->lev / 2) && (one_in_(2));
235     if (!is_corrupted) {
236         em_ptr->note = _("には効果がなかった。", " is unaffected.");
237         em_ptr->obvious = false;
238         return;
239     }
240
241     em_ptr->note = nullptr;
242     msg_format(_("%^sの堕落した精神は攻撃を跳ね返した!",
243                    (em_ptr->seen ? "%^s's corrupted mind backlashes your attack!" : "%^ss corrupted mind backlashes your attack!")),
244         em_ptr->m_name);
245     if (randint0(100 + em_ptr->r_ptr->level / 2) < caster_ptr->skill_sav) {
246         msg_print(_("しかし効力を跳ね返した!", "You resist the effects!"));
247         return;
248     }
249
250     effect_monster_domination_corrupted_addition(caster_ptr, em_ptr);
251 }
252
253 static void effect_monster_domination_addition(effect_monster_type *em_ptr)
254 {
255     switch (randint1(4)) {
256     case 1:
257         em_ptr->do_stun = em_ptr->dam / 2;
258         break;
259     case 2:
260         em_ptr->do_conf = em_ptr->dam / 2;
261         break;
262     default:
263         em_ptr->do_fear = em_ptr->dam;
264     }
265 }
266
267 process_result effect_monster_domination(player_type *caster_ptr, effect_monster_type *em_ptr)
268 {
269     if (!is_hostile(em_ptr->m_ptr))
270         return PROCESS_CONTINUE;
271
272     if (em_ptr->seen)
273         em_ptr->obvious = true;
274
275     if ((em_ptr->r_ptr->flags1 & (RF1_UNIQUE | RF1_QUESTOR)) || (em_ptr->r_ptr->flags3 & RF3_NO_CONF)
276         || (em_ptr->r_ptr->level > randint1((em_ptr->dam - 10) < 1 ? 1 : (em_ptr->dam - 10)) + 10)) {
277         if (((em_ptr->r_ptr->flags3 & RF3_NO_CONF) != 0) && is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr))
278             em_ptr->r_ptr->r_flags3 |= (RF3_NO_CONF);
279
280         em_ptr->do_conf = 0;
281         effect_monster_domination_corrupted(caster_ptr, em_ptr);
282         em_ptr->dam = 0;
283         return PROCESS_CONTINUE;
284     }
285
286     if (!common_saving_throw_charm(caster_ptr, em_ptr->dam, em_ptr->m_ptr)) {
287         em_ptr->note = _("があなたに隷属した。", " is in your thrall!");
288         set_pet(caster_ptr, em_ptr->m_ptr);
289         em_ptr->dam = 0;
290         return PROCESS_CONTINUE;
291     }
292
293     effect_monster_domination_addition(em_ptr);
294     em_ptr->dam = 0;
295     return PROCESS_CONTINUE;
296 }
297
298 static bool effect_monster_crusade_domination(player_type *caster_ptr, effect_monster_type *em_ptr)
299 {
300     if (((em_ptr->r_ptr->flags3 & RF3_GOOD) == 0) || caster_ptr->current_floor_ptr->inside_arena)
301         return false;
302
303     if (em_ptr->r_ptr->flags3 & RF3_NO_CONF)
304         em_ptr->dam -= 50;
305     if (em_ptr->dam < 1)
306         em_ptr->dam = 1;
307
308     if (is_pet(em_ptr->m_ptr)) {
309         em_ptr->note = _("の動きが速くなった。", " starts moving faster.");
310         (void)set_monster_fast(caster_ptr, em_ptr->g_ptr->m_idx, monster_fast_remaining(em_ptr->m_ptr) + 100);
311         return true;
312     }
313
314     if ((em_ptr->r_ptr->flags1 & RF1_QUESTOR) || (em_ptr->r_ptr->flags1 & RF1_UNIQUE) || em_ptr->m_ptr->mflag2.has(MFLAG2::NOPET) || has_aggravate(caster_ptr)
315         || ((em_ptr->r_ptr->level + 10) > randint1(em_ptr->dam))) {
316         if (one_in_(4))
317             em_ptr->m_ptr->mflag2.set(MFLAG2::NOPET);
318
319         return false;
320     }
321
322     em_ptr->note = _("を支配した。", " is tamed!");
323     set_pet(caster_ptr, em_ptr->m_ptr);
324     (void)set_monster_fast(caster_ptr, em_ptr->g_ptr->m_idx, monster_fast_remaining(em_ptr->m_ptr) + 100);
325     if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr))
326         em_ptr->r_ptr->r_flags3 |= RF3_GOOD;
327
328     return true;
329 }
330
331 process_result effect_monster_crusade(player_type *caster_ptr, effect_monster_type *em_ptr)
332 {
333     if (em_ptr->seen)
334         em_ptr->obvious = true;
335     bool success = effect_monster_crusade_domination(caster_ptr, em_ptr);
336     if (success) {
337         em_ptr->dam = 0;
338         return PROCESS_CONTINUE;
339     }
340
341     if ((em_ptr->r_ptr->flags3 & RF3_NO_FEAR) == 0)
342         em_ptr->do_fear = randint1(90) + 10;
343     else if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr))
344         em_ptr->r_ptr->r_flags3 |= RF3_NO_FEAR;
345
346     em_ptr->dam = 0;
347     return PROCESS_CONTINUE;
348 }
349
350 /*!
351  * @brief モンスターボールで捕まえられる最大HPを計算する
352  * @param caster_ptr プレイヤー情報への参照ポインタ
353  * @param m_ptr モンスター情報への参照ポインタ
354  * @param hp 計算対象のHP
355  * @return 捕まえられる最大HP
356  */
357 static HIT_POINT calcutate_capturable_hp(player_type *caster_ptr, monster_type *m_ptr, HIT_POINT hp)
358 {
359     if (is_pet(m_ptr))
360         return hp * 4L;
361
362     if ((caster_ptr->pclass == CLASS_BEASTMASTER) && monster_living(m_ptr->r_idx))
363         return hp * 3 / 10;
364
365     return hp * 3 / 20;
366 }
367
368 /*!
369  * @brief モンスターボールで捕らえた処理
370  * @param caster_ptr プレイヤー情報への参照ポインタ
371  * @param em_ptr 効果情報への参照ポインタ
372  */
373 static void effect_monster_captured(player_type *caster_ptr, effect_monster_type *em_ptr)
374 {
375     if (em_ptr->m_ptr->mflag2.has(MFLAG2::CHAMELEON))
376         choose_new_monster(caster_ptr, em_ptr->g_ptr->m_idx, false, MON_CHAMELEON);
377
378     msg_format(_("%sを捕えた!", "You capture %^s!"), em_ptr->m_name);
379     cap_mon = em_ptr->m_ptr->r_idx;
380     cap_mspeed = em_ptr->m_ptr->mspeed;
381     cap_hp = em_ptr->m_ptr->hp;
382     cap_maxhp = em_ptr->m_ptr->max_maxhp;
383     cap_nickname = em_ptr->m_ptr->nickname;
384     if ((em_ptr->g_ptr->m_idx == caster_ptr->riding) && process_fall_off_horse(caster_ptr, -1, false))
385         msg_format(_("地面に落とされた。", "You have fallen from %s."), em_ptr->m_name);
386
387     delete_monster_idx(caster_ptr, em_ptr->g_ptr->m_idx);
388     calculate_upkeep(caster_ptr);
389 }
390
391 /*!
392  * @brief モンスターボールで捕らえる効果(GF_CAPTURE)
393  * @param caster_ptr プレイヤー情報への参照ポインタ
394  * @param em_ptr 効果情報への参照ポインタ
395  * @return 効果発動結果
396  */
397 process_result effect_monster_capture(player_type *caster_ptr, effect_monster_type *em_ptr)
398 {
399     floor_type *floor_ptr = caster_ptr->current_floor_ptr;
400     if ((floor_ptr->inside_quest && (quest[floor_ptr->inside_quest].type == QUEST_TYPE_KILL_ALL) && !is_pet(em_ptr->m_ptr))
401         || any_bits(em_ptr->r_ptr->flags1, RF1_UNIQUE | RF1_QUESTOR) || any_bits(em_ptr->r_ptr->flags7, RF7_NAZGUL | RF7_UNIQUE2)
402         || em_ptr->m_ptr->parent_m_idx) {
403         msg_format(_("%sには効果がなかった。", "%s is unaffected."), em_ptr->m_name);
404         em_ptr->skipped = true;
405         return PROCESS_CONTINUE;
406     }
407
408     auto r_max_hp = em_ptr->r_ptr->hdice * em_ptr->r_ptr->hside;
409     auto threshold_hp = calcutate_capturable_hp(caster_ptr, em_ptr->m_ptr, r_max_hp);
410     auto capturable_hp = MAX(2, calcutate_capturable_hp(caster_ptr, em_ptr->m_ptr, em_ptr->m_ptr->max_maxhp));
411
412     if (threshold_hp < 2 || em_ptr->m_ptr->hp >= capturable_hp) {
413         msg_format(_("もっと弱らせないと。", "You need to weaken %s more."), em_ptr->m_name);
414         em_ptr->skipped = true;
415         return PROCESS_CONTINUE;
416     }
417
418     if (em_ptr->m_ptr->hp <= randint1(capturable_hp)) {
419         effect_monster_captured(caster_ptr, em_ptr);
420         return PROCESS_TRUE;
421     }
422
423     msg_format(_("うまく捕まえられなかった。", "You failed to capture %s."), em_ptr->m_name);
424     em_ptr->skipped = true;
425     return PROCESS_CONTINUE;
426 }