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"
32 static void effect_monster_charm_resist(player_type *caster_ptr, effect_monster_type *em_ptr)
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;
39 em_ptr->m_ptr->mflag2.set(MFLAG2::NOPET);
40 } else if (has_aggravate(caster_ptr)) {
41 em_ptr->note = _("はあなたに敵意を抱いている!", " hates you too much!");
43 em_ptr->m_ptr->mflag2.set(MFLAG2::NOPET);
45 em_ptr->note = _("は突然友好的になったようだ!", " suddenly seems friendly!");
46 set_pet(caster_ptr, em_ptr->m_ptr);
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);
54 process_result effect_monster_charm(player_type *caster_ptr, effect_monster_type *em_ptr)
56 int vir = virtue_number(caster_ptr, V_HARMONY);
58 em_ptr->dam += caster_ptr->virtues[vir - 1] / 10;
61 vir = virtue_number(caster_ptr, V_INDIVIDUALISM);
63 em_ptr->dam -= caster_ptr->virtues[vir - 1] / 20;
67 em_ptr->obvious = true;
69 effect_monster_charm_resist(caster_ptr, em_ptr);
71 return PROCESS_CONTINUE;
74 process_result effect_monster_control_undead(player_type *caster_ptr, effect_monster_type *em_ptr)
77 em_ptr->obvious = true;
79 int vir = virtue_number(caster_ptr, V_UNLIFE);
81 em_ptr->dam += caster_ptr->virtues[vir - 1] / 10;
84 vir = virtue_number(caster_ptr, V_INDIVIDUALISM);
86 em_ptr->dam -= caster_ptr->virtues[vir - 1] / 20;
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;
93 em_ptr->m_ptr->mflag2.set(MFLAG2::NOPET);
94 } else if (has_aggravate(caster_ptr)) {
95 em_ptr->note = _("はあなたに敵意を抱いている!", " hates you too much!");
97 em_ptr->m_ptr->mflag2.set(MFLAG2::NOPET);
99 em_ptr->note = _("は既にあなたの奴隷だ!", " is in your thrall!");
100 set_pet(caster_ptr, em_ptr->m_ptr);
104 return PROCESS_CONTINUE;
107 process_result effect_monster_control_demon(player_type *caster_ptr, effect_monster_type *em_ptr)
110 em_ptr->obvious = true;
112 int vir = virtue_number(caster_ptr, V_UNLIFE);
114 em_ptr->dam += caster_ptr->virtues[vir - 1] / 10;
117 vir = virtue_number(caster_ptr, V_INDIVIDUALISM);
119 em_ptr->dam -= caster_ptr->virtues[vir - 1] / 20;
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;
126 em_ptr->m_ptr->mflag2.set(MFLAG2::NOPET);
127 } else if (has_aggravate(caster_ptr)) {
128 em_ptr->note = _("はあなたに敵意を抱いている!", " hates you too much!");
130 em_ptr->m_ptr->mflag2.set(MFLAG2::NOPET);
132 em_ptr->note = _("は既にあなたの奴隷だ!", " is in your thrall!");
133 set_pet(caster_ptr, em_ptr->m_ptr);
137 return PROCESS_CONTINUE;
140 process_result effect_monster_control_animal(player_type *caster_ptr, effect_monster_type *em_ptr)
143 em_ptr->obvious = true;
145 int vir = virtue_number(caster_ptr, V_NATURE);
147 em_ptr->dam += caster_ptr->virtues[vir - 1] / 10;
150 vir = virtue_number(caster_ptr, V_INDIVIDUALISM);
152 em_ptr->dam -= caster_ptr->virtues[vir - 1] / 20;
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;
159 em_ptr->m_ptr->mflag2.set(MFLAG2::NOPET);
160 } else if (has_aggravate(caster_ptr)) {
161 em_ptr->note = _("はあなたに敵意を抱いている!", " hates you too much!");
163 em_ptr->m_ptr->mflag2.set(MFLAG2::NOPET);
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);
172 return PROCESS_CONTINUE;
175 process_result effect_monster_charm_living(player_type *caster_ptr, effect_monster_type *em_ptr)
177 int vir = virtue_number(caster_ptr, V_UNLIFE);
179 em_ptr->obvious = true;
181 vir = virtue_number(caster_ptr, V_UNLIFE);
183 em_ptr->dam -= caster_ptr->virtues[vir - 1] / 10;
186 vir = virtue_number(caster_ptr, V_INDIVIDUALISM);
188 em_ptr->dam -= caster_ptr->virtues[vir - 1] / 20;
191 msg_format(_("%sを見つめた。", "You stare at %s."), em_ptr->m_name);
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;
197 em_ptr->m_ptr->mflag2.set(MFLAG2::NOPET);
198 } else if (has_aggravate(caster_ptr)) {
199 em_ptr->note = _("はあなたに敵意を抱いている!", " hates you too much!");
201 em_ptr->m_ptr->mflag2.set(MFLAG2::NOPET);
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);
210 return PROCESS_CONTINUE;
213 static void effect_monster_domination_corrupted_addition(player_type *caster_ptr, effect_monster_type *em_ptr)
215 switch (randint1(4)) {
217 set_stun(caster_ptr, caster_ptr->stun + em_ptr->dam / 2);
220 set_confused(caster_ptr, caster_ptr->confused + em_ptr->dam / 2);
223 if (em_ptr->r_ptr->flags3 & RF3_NO_FEAR)
224 em_ptr->note = _("には効果がなかった。", " is unaffected.");
226 set_afraid(caster_ptr, caster_ptr->afraid + em_ptr->dam);
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)
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));
236 em_ptr->note = _("には効果がなかった。", " is unaffected.");
237 em_ptr->obvious = false;
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!")),
245 if (randint0(100 + em_ptr->r_ptr->level / 2) < caster_ptr->skill_sav) {
246 msg_print(_("しかし効力を跳ね返した!", "You resist the effects!"));
250 effect_monster_domination_corrupted_addition(caster_ptr, em_ptr);
253 static void effect_monster_domination_addition(effect_monster_type *em_ptr)
255 switch (randint1(4)) {
257 em_ptr->do_stun = em_ptr->dam / 2;
260 em_ptr->do_conf = em_ptr->dam / 2;
263 em_ptr->do_fear = em_ptr->dam;
267 process_result effect_monster_domination(player_type *caster_ptr, effect_monster_type *em_ptr)
269 if (!is_hostile(em_ptr->m_ptr))
270 return PROCESS_CONTINUE;
273 em_ptr->obvious = true;
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);
281 effect_monster_domination_corrupted(caster_ptr, em_ptr);
283 return PROCESS_CONTINUE;
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);
290 return PROCESS_CONTINUE;
293 effect_monster_domination_addition(em_ptr);
295 return PROCESS_CONTINUE;
298 static bool effect_monster_crusade_domination(player_type *caster_ptr, effect_monster_type *em_ptr)
300 if (((em_ptr->r_ptr->flags3 & RF3_GOOD) == 0) || caster_ptr->current_floor_ptr->inside_arena)
303 if (em_ptr->r_ptr->flags3 & RF3_NO_CONF)
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);
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))) {
317 em_ptr->m_ptr->mflag2.set(MFLAG2::NOPET);
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;
331 process_result effect_monster_crusade(player_type *caster_ptr, effect_monster_type *em_ptr)
334 em_ptr->obvious = true;
335 bool success = effect_monster_crusade_domination(caster_ptr, em_ptr);
338 return PROCESS_CONTINUE;
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;
347 return PROCESS_CONTINUE;
351 * @brief モンスターボールで捕まえられる最大HPを計算する
352 * @param caster_ptr プレイヤー情報への参照ポインタ
353 * @param m_ptr モンスター情報への参照ポインタ
357 static HIT_POINT calcutate_capturable_hp(player_type *caster_ptr, monster_type *m_ptr, HIT_POINT hp)
362 if ((caster_ptr->pclass == CLASS_BEASTMASTER) && monster_living(m_ptr->r_idx))
369 * @brief モンスターボールで捕らえた処理
370 * @param caster_ptr プレイヤー情報への参照ポインタ
371 * @param em_ptr 効果情報への参照ポインタ
373 static void effect_monster_captured(player_type *caster_ptr, effect_monster_type *em_ptr)
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);
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);
387 delete_monster_idx(caster_ptr, em_ptr->g_ptr->m_idx);
388 calculate_upkeep(caster_ptr);
392 * @brief モンスターボールで捕らえる効果(GF_CAPTURE)
393 * @param caster_ptr プレイヤー情報への参照ポインタ
394 * @param em_ptr 効果情報への参照ポインタ
397 process_result effect_monster_capture(player_type *caster_ptr, effect_monster_type *em_ptr)
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;
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));
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;
418 if (em_ptr->m_ptr->hp <= randint1(capturable_hp)) {
419 effect_monster_captured(caster_ptr, em_ptr);
423 msg_format(_("うまく捕まえられなかった。", "You failed to capture %s."), em_ptr->m_name);
424 em_ptr->skipped = true;
425 return PROCESS_CONTINUE;