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-kind-mask.h"
8 #include "monster-race/monster-race-hook.h"
9 #include "monster-race/monster-race.h"
10 #include "monster-race/race-flags1.h"
11 #include "monster-race/race-flags3.h"
12 #include "monster-race/race-flags7.h"
13 #include "monster-race/race-indice-types.h"
14 #include "monster/monster-flag-types.h"
15 #include "monster/monster-info.h"
16 #include "monster/monster-list.h"
17 #include "monster/monster-status-setter.h"
18 #include "monster/monster-status.h"
19 #include "object-enchant/trc-types.h"
20 #include "pet/pet-fall-off.h"
21 #include "pet/pet-util.h"
22 #include "player-base/player-class.h"
23 #include "player/player-status-flags.h"
24 #include "spell/spells-diceroll.h"
25 #include "status/bad-status-setter.h"
26 #include "system/floor-type-definition.h"
27 #include "system/grid-type-definition.h"
28 #include "system/monster-race-definition.h"
29 #include "system/monster-type-definition.h"
30 #include "system/player-type-definition.h"
31 #include "util/bit-flags-calculator.h"
32 #include "view/display-messages.h"
34 static void effect_monster_charm_resist(PlayerType *player_ptr, effect_monster_type *em_ptr)
36 if (common_saving_throw_charm(player_ptr, em_ptr->dam, em_ptr->m_ptr)) {
37 em_ptr->note = _("には効果がなかった。", " is unaffected.");
38 em_ptr->obvious = false;
41 em_ptr->m_ptr->mflag2.set(MonsterConstantFlagType::NOPET);
42 } else if (has_aggravate(player_ptr)) {
43 em_ptr->note = _("はあなたに敵意を抱いている!", " hates you too much!");
45 em_ptr->m_ptr->mflag2.set(MonsterConstantFlagType::NOPET);
47 em_ptr->note = _("は突然友好的になったようだ!", " suddenly seems friendly!");
48 set_pet(player_ptr, em_ptr->m_ptr);
50 chg_virtue(player_ptr, V_INDIVIDUALISM, -1);
51 if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::ANIMAL))
52 chg_virtue(player_ptr, V_NATURE, 1);
56 process_result effect_monster_charm(PlayerType *player_ptr, effect_monster_type *em_ptr)
58 int vir = virtue_number(player_ptr, V_HARMONY);
60 em_ptr->dam += player_ptr->virtues[vir - 1] / 10;
63 vir = virtue_number(player_ptr, V_INDIVIDUALISM);
65 em_ptr->dam -= player_ptr->virtues[vir - 1] / 20;
69 em_ptr->obvious = true;
71 effect_monster_charm_resist(player_ptr, em_ptr);
73 return PROCESS_CONTINUE;
76 process_result effect_monster_control_undead(PlayerType *player_ptr, effect_monster_type *em_ptr)
79 em_ptr->obvious = true;
81 int vir = virtue_number(player_ptr, V_UNLIFE);
83 em_ptr->dam += player_ptr->virtues[vir - 1] / 10;
86 vir = virtue_number(player_ptr, V_INDIVIDUALISM);
88 em_ptr->dam -= player_ptr->virtues[vir - 1] / 20;
91 if (common_saving_throw_control(player_ptr, em_ptr->dam, em_ptr->m_ptr) || em_ptr->r_ptr->kind_flags.has_not(MonsterKindType::UNDEAD)) {
92 em_ptr->note = _("には効果がなかった。", " is unaffected.");
93 em_ptr->obvious = false;
95 em_ptr->m_ptr->mflag2.set(MonsterConstantFlagType::NOPET);
96 } else if (has_aggravate(player_ptr)) {
97 em_ptr->note = _("はあなたに敵意を抱いている!", " hates you too much!");
99 em_ptr->m_ptr->mflag2.set(MonsterConstantFlagType::NOPET);
101 em_ptr->note = _("は既にあなたの奴隷だ!", " is in your thrall!");
102 set_pet(player_ptr, em_ptr->m_ptr);
106 return PROCESS_CONTINUE;
109 process_result effect_monster_control_demon(PlayerType *player_ptr, effect_monster_type *em_ptr)
112 em_ptr->obvious = true;
114 int vir = virtue_number(player_ptr, V_UNLIFE);
116 em_ptr->dam += player_ptr->virtues[vir - 1] / 10;
119 vir = virtue_number(player_ptr, V_INDIVIDUALISM);
121 em_ptr->dam -= player_ptr->virtues[vir - 1] / 20;
124 if (common_saving_throw_control(player_ptr, em_ptr->dam, em_ptr->m_ptr) || em_ptr->r_ptr->kind_flags.has_not(MonsterKindType::DEMON)) {
125 em_ptr->note = _("には効果がなかった。", " is unaffected.");
126 em_ptr->obvious = false;
128 em_ptr->m_ptr->mflag2.set(MonsterConstantFlagType::NOPET);
129 } else if (has_aggravate(player_ptr)) {
130 em_ptr->note = _("はあなたに敵意を抱いている!", " hates you too much!");
132 em_ptr->m_ptr->mflag2.set(MonsterConstantFlagType::NOPET);
134 em_ptr->note = _("は既にあなたの奴隷だ!", " is in your thrall!");
135 set_pet(player_ptr, em_ptr->m_ptr);
139 return PROCESS_CONTINUE;
142 process_result effect_monster_control_animal(PlayerType *player_ptr, effect_monster_type *em_ptr)
145 em_ptr->obvious = true;
147 int vir = virtue_number(player_ptr, V_NATURE);
149 em_ptr->dam += player_ptr->virtues[vir - 1] / 10;
152 vir = virtue_number(player_ptr, V_INDIVIDUALISM);
154 em_ptr->dam -= player_ptr->virtues[vir - 1] / 20;
157 if (common_saving_throw_control(player_ptr, em_ptr->dam, em_ptr->m_ptr) || em_ptr->r_ptr->kind_flags.has_not(MonsterKindType::ANIMAL)) {
158 em_ptr->note = _("には効果がなかった。", " is unaffected.");
159 em_ptr->obvious = false;
161 em_ptr->m_ptr->mflag2.set(MonsterConstantFlagType::NOPET);
162 } else if (has_aggravate(player_ptr)) {
163 em_ptr->note = _("はあなたに敵意を抱いている!", " hates you too much!");
165 em_ptr->m_ptr->mflag2.set(MonsterConstantFlagType::NOPET);
167 em_ptr->note = _("はなついた。", " is tamed!");
168 set_pet(player_ptr, em_ptr->m_ptr);
169 if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::ANIMAL))
170 chg_virtue(player_ptr, V_NATURE, 1);
174 return PROCESS_CONTINUE;
177 process_result effect_monster_charm_living(PlayerType *player_ptr, effect_monster_type *em_ptr)
179 int vir = virtue_number(player_ptr, V_UNLIFE);
181 em_ptr->obvious = true;
183 vir = virtue_number(player_ptr, V_UNLIFE);
185 em_ptr->dam -= player_ptr->virtues[vir - 1] / 10;
188 vir = virtue_number(player_ptr, V_INDIVIDUALISM);
190 em_ptr->dam -= player_ptr->virtues[vir - 1] / 20;
193 msg_format(_("%sを見つめた。", "You stare at %s."), em_ptr->m_name);
195 if (common_saving_throw_charm(player_ptr, em_ptr->dam, em_ptr->m_ptr) || !monster_living(em_ptr->m_ptr->r_idx)) {
196 em_ptr->note = _("には効果がなかった。", " is unaffected.");
197 em_ptr->obvious = false;
199 em_ptr->m_ptr->mflag2.set(MonsterConstantFlagType::NOPET);
200 } else if (has_aggravate(player_ptr)) {
201 em_ptr->note = _("はあなたに敵意を抱いている!", " hates you too much!");
203 em_ptr->m_ptr->mflag2.set(MonsterConstantFlagType::NOPET);
205 em_ptr->note = _("を支配した。", " is tamed!");
206 set_pet(player_ptr, em_ptr->m_ptr);
207 if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::ANIMAL))
208 chg_virtue(player_ptr, V_NATURE, 1);
212 return PROCESS_CONTINUE;
215 static void effect_monster_domination_corrupted_addition(PlayerType *player_ptr, effect_monster_type *em_ptr)
217 BadStatusSetter bss(player_ptr);
218 switch (randint1(4)) {
220 (void)bss.mod_stun(em_ptr->dam / 2);
223 (void)bss.mod_confusion(em_ptr->dam / 2);
226 if (any_bits(em_ptr->r_ptr->flags3, RF3_NO_FEAR)) {
227 em_ptr->note = _("には効果がなかった。", " is unaffected.");
229 (void)bss.mod_afraidness(static_cast<TIME_EFFECT>(em_ptr->dam));
236 // Powerful demons & undead can turn a mindcrafter's attacks back on them.
237 static void effect_monster_domination_corrupted(PlayerType *player_ptr, effect_monster_type *em_ptr)
239 bool is_corrupted = em_ptr->r_ptr->kind_flags.has_any_of(has_corrupted_mind) && (em_ptr->r_ptr->level > player_ptr->lev / 2) && (one_in_(2));
241 em_ptr->note = _("には効果がなかった。", " is unaffected.");
242 em_ptr->obvious = false;
246 em_ptr->note = nullptr;
247 msg_format(_("%^sの堕落した精神は攻撃を跳ね返した!",
248 (em_ptr->seen ? "%^s's corrupted mind backlashes your attack!" : "%^ss corrupted mind backlashes your attack!")),
250 if (randint0(100 + em_ptr->r_ptr->level / 2) < player_ptr->skill_sav) {
251 msg_print(_("しかし効力を跳ね返した!", "You resist the effects!"));
255 effect_monster_domination_corrupted_addition(player_ptr, em_ptr);
258 static void effect_monster_domination_addition(effect_monster_type *em_ptr)
260 switch (randint1(4)) {
262 em_ptr->do_stun = em_ptr->dam / 2;
265 em_ptr->do_conf = em_ptr->dam / 2;
268 em_ptr->do_fear = em_ptr->dam;
272 process_result effect_monster_domination(PlayerType *player_ptr, effect_monster_type *em_ptr)
274 if (!is_hostile(em_ptr->m_ptr))
275 return PROCESS_CONTINUE;
278 em_ptr->obvious = true;
280 if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE) || any_bits(em_ptr->r_ptr->flags1, RF1_QUESTOR) || (em_ptr->r_ptr->flags3 & RF3_NO_CONF) || (em_ptr->r_ptr->level > randint1((em_ptr->dam - 10) < 1 ? 1 : (em_ptr->dam - 10)) + 10)) {
281 if (((em_ptr->r_ptr->flags3 & RF3_NO_CONF) != 0) && is_original_ap_and_seen(player_ptr, em_ptr->m_ptr))
282 em_ptr->r_ptr->r_flags3 |= (RF3_NO_CONF);
285 effect_monster_domination_corrupted(player_ptr, em_ptr);
287 return PROCESS_CONTINUE;
290 if (!common_saving_throw_charm(player_ptr, em_ptr->dam, em_ptr->m_ptr)) {
291 em_ptr->note = _("があなたに隷属した。", " is in your thrall!");
292 set_pet(player_ptr, em_ptr->m_ptr);
294 return PROCESS_CONTINUE;
297 effect_monster_domination_addition(em_ptr);
299 return PROCESS_CONTINUE;
302 static bool effect_monster_crusade_domination(PlayerType *player_ptr, effect_monster_type *em_ptr)
304 if ((em_ptr->r_ptr->kind_flags.has_not(MonsterKindType::GOOD)) || player_ptr->current_floor_ptr->inside_arena)
307 if (em_ptr->r_ptr->flags3 & RF3_NO_CONF)
312 if (is_pet(em_ptr->m_ptr)) {
313 em_ptr->note = _("の動きが速くなった。", " starts moving faster.");
314 (void)set_monster_fast(player_ptr, em_ptr->g_ptr->m_idx, monster_fast_remaining(em_ptr->m_ptr) + 100);
318 bool failed = any_bits(em_ptr->r_ptr->flags1, RF1_QUESTOR);
319 failed |= em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE);
320 failed |= em_ptr->m_ptr->mflag2.has(MonsterConstantFlagType::NOPET);
321 failed |= has_aggravate(player_ptr);
322 failed |= (em_ptr->r_ptr->level + 10) > randint1(em_ptr->dam);
326 em_ptr->m_ptr->mflag2.set(MonsterConstantFlagType::NOPET);
331 em_ptr->note = _("を支配した。", " is tamed!");
332 set_pet(player_ptr, em_ptr->m_ptr);
333 (void)set_monster_fast(player_ptr, em_ptr->g_ptr->m_idx, monster_fast_remaining(em_ptr->m_ptr) + 100);
334 if (is_original_ap_and_seen(player_ptr, em_ptr->m_ptr))
335 em_ptr->r_ptr->r_kind_flags.set(MonsterKindType::GOOD);
340 process_result effect_monster_crusade(PlayerType *player_ptr, effect_monster_type *em_ptr)
343 em_ptr->obvious = true;
344 bool success = effect_monster_crusade_domination(player_ptr, em_ptr);
347 return PROCESS_CONTINUE;
350 if ((em_ptr->r_ptr->flags3 & RF3_NO_FEAR) == 0)
351 em_ptr->do_fear = randint1(90) + 10;
352 else if (is_original_ap_and_seen(player_ptr, em_ptr->m_ptr))
353 em_ptr->r_ptr->r_flags3 |= RF3_NO_FEAR;
356 return PROCESS_CONTINUE;
360 * @brief モンスターボールで捕まえられる最大HPを計算する
361 * @param player_ptr プレイヤー情報への参照ポインタ
362 * @param m_ptr モンスター情報への参照ポインタ
366 static HIT_POINT calcutate_capturable_hp(PlayerType *player_ptr, monster_type *m_ptr, HIT_POINT hp)
371 if (PlayerClass(player_ptr).equals(PlayerClassType::BEASTMASTER) && monster_living(m_ptr->r_idx))
378 * @brief モンスターボールで捕らえた処理
379 * @param player_ptr プレイヤー情報への参照ポインタ
380 * @param em_ptr 効果情報への参照ポインタ
382 static void effect_monster_captured(PlayerType *player_ptr, effect_monster_type *em_ptr)
384 if (em_ptr->m_ptr->mflag2.has(MonsterConstantFlagType::CHAMELEON))
385 choose_new_monster(player_ptr, em_ptr->g_ptr->m_idx, false, MON_CHAMELEON);
387 msg_format(_("%sを捕えた!", "You capture %^s!"), em_ptr->m_name);
388 cap_mon = em_ptr->m_ptr->r_idx;
389 cap_mspeed = static_cast<byte>(em_ptr->m_ptr->mspeed);
390 cap_hp = static_cast<short>(em_ptr->m_ptr->hp);
391 cap_maxhp = static_cast<short>(em_ptr->m_ptr->max_maxhp);
392 cap_nickname = em_ptr->m_ptr->nickname;
393 if ((em_ptr->g_ptr->m_idx == player_ptr->riding) && process_fall_off_horse(player_ptr, -1, false))
394 msg_format(_("地面に落とされた。", "You have fallen from %s."), em_ptr->m_name);
396 delete_monster_idx(player_ptr, em_ptr->g_ptr->m_idx);
397 calculate_upkeep(player_ptr);
401 * @brief モンスターボールで捕らえる効果(CAPTURE)
402 * @param player_ptr プレイヤー情報への参照ポインタ
403 * @param em_ptr 効果情報への参照ポインタ
406 process_result effect_monster_capture(PlayerType *player_ptr, effect_monster_type *em_ptr)
408 auto *floor_ptr = player_ptr->current_floor_ptr;
410 bool cannot_capture = (inside_quest(floor_ptr->quest_number) && (quest[enum2i(floor_ptr->quest_number)].type == QuestKindType::KILL_ALL) && !is_pet(em_ptr->m_ptr));
411 cannot_capture |= em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE);
412 cannot_capture |= any_bits(em_ptr->r_ptr->flags1, RF1_QUESTOR);
413 cannot_capture |= any_bits(em_ptr->r_ptr->flags7, RF7_NAZGUL | RF7_UNIQUE2);
414 cannot_capture |= (em_ptr->m_ptr->parent_m_idx != 0);
415 if (cannot_capture) {
416 msg_format(_("%sには効果がなかった。", "%s is unaffected."), em_ptr->m_name);
417 em_ptr->skipped = true;
418 return PROCESS_CONTINUE;
421 auto r_max_hp = em_ptr->r_ptr->hdice * em_ptr->r_ptr->hside;
422 auto threshold_hp = calcutate_capturable_hp(player_ptr, em_ptr->m_ptr, r_max_hp);
423 auto capturable_hp = std::max(2, calcutate_capturable_hp(player_ptr, em_ptr->m_ptr, em_ptr->m_ptr->max_maxhp));
425 if (threshold_hp < 2 || em_ptr->m_ptr->hp >= capturable_hp) {
426 msg_format(_("もっと弱らせないと。", "You need to weaken %s more."), em_ptr->m_name);
427 em_ptr->skipped = true;
428 return PROCESS_CONTINUE;
431 if (em_ptr->m_ptr->hp <= randint1(capturable_hp)) {
432 effect_monster_captured(player_ptr, em_ptr);
436 msg_format(_("うまく捕まえられなかった。", "You failed to capture %s."), em_ptr->m_name);
437 em_ptr->skipped = true;
438 return PROCESS_CONTINUE;