1 #include "mspell/mspell-summon.h"
2 #include "core/disturbance.h"
3 #include "effect/attribute-types.h"
4 #include "effect/effect-characteristics.h"
5 #include "effect/effect-processor.h"
6 #include "floor/cave.h"
7 #include "game-option/birth-options.h"
8 #include "monster-floor/monster-summon.h"
9 #include "monster-floor/place-monster-types.h"
10 #include "monster-race/monster-race.h"
11 #include "monster-race/race-flags1.h"
12 #include "monster-race/race-indice-types.h"
13 #include "monster/monster-describer.h"
14 #include "monster/monster-description-types.h"
15 #include "monster/monster-info.h"
16 #include "monster/monster-status.h"
17 #include "mspell/mspell-result.h"
18 #include "mspell/mspell-util.h"
19 #include "mspell/specified-summon.h"
20 #include "spell-kind/spells-launcher.h"
21 #include "spell/spells-summon.h"
22 #include "spell/summon-types.h"
23 #include "system/floor-type-definition.h"
24 #include "system/monster-race-definition.h"
25 #include "system/monster-type-definition.h"
26 #include "system/player-type-definition.h"
27 #include "util/bit-flags-calculator.h"
28 #include "view/display-messages.h"
30 /* summoning number */
31 constexpr int S_NUM_6 = 6;
32 constexpr int S_NUM_4 = 4;
35 * @brief モンスターが召喚呪文を使った際にプレイヤーの連続行動を止める処理 /
36 * @param player_ptr プレイヤーへの参照ポインタ
37 * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
38 * @param known モンスターが近くにいる場合TRUE
39 * @param see_either モンスターを視認可能な場合TRUE
41 static void summon_disturb(PlayerType *player_ptr, int target_type, bool known, bool see_either)
43 bool mon_to_mon = target_type == MONSTER_TO_MONSTER;
44 bool mon_to_player = target_type == MONSTER_TO_PLAYER;
45 if (mon_to_player || (mon_to_mon && known && see_either)) {
46 disturb(player_ptr, true, true);
51 * @brief 特定条件のモンスター召喚のみPM_ALLOW_UNIQUEを許可する /
52 * @param floor_ptr 現在フロアへの参照ポインタ
53 * @param m_idx モンスターID
54 * @return 召喚可能であればPM_ALLOW_UNIQUEを返す。
56 static BIT_FLAGS monster_u_mode(floor_type *floor_ptr, MONSTER_IDX m_idx)
58 BIT_FLAGS u_mode = 0L;
59 auto *m_ptr = &floor_ptr->m_list[m_idx];
60 bool pet = is_pet(m_ptr);
62 u_mode |= PM_ALLOW_UNIQUE;
68 * @brief 救援召喚の通常処理。同シンボルのモンスターを召喚する。 /
69 * @param player_ptr プレイヤーへの参照ポインタ
72 * @param rlev 呪文を唱えるモンスターのレベル
73 * @param m_idx 呪文を唱えるモンスターID
74 * @return 召喚したモンスターの数を返す。
76 static MONSTER_NUMBER summon_Kin(PlayerType *player_ptr, POSITION y, POSITION x, int rlev, MONSTER_IDX m_idx)
79 for (int k = 0; k < 4; k++) {
80 count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_KIN, PM_ALLOW_GROUP);
86 static void decide_summon_kin_caster(
87 PlayerType *player_ptr, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type, concptr m_name, concptr m_poss, const bool known)
89 auto *floor_ptr = player_ptr->current_floor_ptr;
90 auto *m_ptr = &floor_ptr->m_list[m_idx];
91 bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
92 bool mon_to_mon = target_type == MONSTER_TO_MONSTER;
93 bool mon_to_player = target_type == MONSTER_TO_PLAYER;
95 if (m_ptr->r_idx == MonsterRaceId::SERPENT || m_ptr->r_idx == MonsterRaceId::ZOMBI_SERPENT) {
96 mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."),
97 _("%^sがダンジョンの主を召喚した。", "%^s magically summons guardians of dungeons."),
98 _("%^sがダンジョンの主を召喚した。", "%^s magically summons guardians of dungeons."));
100 monspell_message(player_ptr, m_idx, t_idx, msg, target_type);
104 summon_disturb(player_ptr, target_type, known, see_either);
106 if (player_ptr->blind) {
108 msg_format(_("%^sが何かをつぶやいた。", "%^s mumbles."), m_name);
110 } else if (mon_to_player || (mon_to_mon && known && see_either)) {
111 auto *r_ptr = &r_info[m_ptr->r_idx];
115 _(msg_format("%sが魔法で%sを召喚した。", m_name, (r_ptr->kind_flags.has(MonsterKindType::UNIQUE) ? "手下" : "仲間")),
116 msg_format("%^s magically summons %s %s.", m_name, m_poss, (r_ptr->kind_flags.has(MonsterKindType::UNIQUE) ? "minions" : "kin")));
119 if (mon_to_mon && known && !see_either) {
120 floor_ptr->monster_noise = true;
125 * @brief RF6_S_KINの処理。救援召喚。使用するモンスターの種類により、実処理に分岐させる。 /
126 * @param player_ptr プレイヤーへの参照ポインタ
129 * @param m_idx 呪文を唱えるモンスターID
130 * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
131 * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
135 MonsterSpellResult spell_RF6_S_KIN(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type)
137 auto *floor_ptr = player_ptr->current_floor_ptr;
138 auto *m_ptr = &floor_ptr->m_list[m_idx];
139 DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
140 GAME_TEXT m_name[MAX_NLEN], t_name[MAX_NLEN], m_poss[80];
141 monster_name(player_ptr, m_idx, m_name);
142 monster_name(player_ptr, t_idx, t_name);
143 monster_desc(player_ptr, m_poss, m_ptr, MD_PRON_VISIBLE | MD_POSSESSIVE);
145 bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
146 bool known = monster_near_player(floor_ptr, m_idx, t_idx);
148 summon_disturb(player_ptr, target_type, known, see_either);
150 decide_summon_kin_caster(player_ptr, m_idx, t_idx, target_type, m_name, m_poss, known);
152 switch (m_ptr->r_idx) {
153 case MonsterRaceId::MENELDOR:
154 case MonsterRaceId::GWAIHIR:
155 case MonsterRaceId::THORONDOR:
156 count += summon_EAGLE(player_ptr, y, x, rlev, m_idx);
158 case MonsterRaceId::BULLGATES:
159 count += summon_EDGE(player_ptr, y, x, rlev, m_idx);
161 case MonsterRaceId::SERPENT:
162 case MonsterRaceId::ZOMBI_SERPENT:
163 count += summon_guardian(player_ptr, y, x, rlev, m_idx, t_idx, target_type);
165 case MonsterRaceId::TIAMAT:
166 count += summon_HIGHEST_DRAGON(player_ptr, y, x, m_idx);
168 case MonsterRaceId::CALDARM:
169 count += summon_LOCKE_CLONE(player_ptr, y, x, m_idx);
171 case MonsterRaceId::LOUSY:
172 count += summon_LOUSE(player_ptr, y, x, rlev, m_idx);
174 case MonsterRaceId::VAIF:
175 count += summon_MOAI(player_ptr, y, x, rlev, m_idx);
177 case MonsterRaceId::DEMON_SLAYER_SENIOR:
178 count += summon_DEMON_SLAYER(player_ptr, y, x, m_idx);
180 case MonsterRaceId::ALDUIN:
181 count += summon_HIGHEST_DRAGON(player_ptr, y, x, m_idx);
183 case MonsterRaceId::MIRAAK:
184 count += summon_APOCRYPHA(player_ptr, y, x, m_idx);
186 case MonsterRaceId::IMHOTEP:
187 count += summon_PYRAMID(player_ptr, y, x, rlev, m_idx);
189 case MonsterRaceId::JOBZ:
190 count += summon_EYE_PHORN(player_ptr, y, x, rlev, m_idx);
192 case MonsterRaceId::QUEEN_VESPOID:
193 count += summon_VESPOID(player_ptr, y, x, rlev, m_idx);
195 case MonsterRaceId::YENDOR_WIZARD_1:
196 count += summon_YENDER_WIZARD(player_ptr, y, x, m_idx);
198 case MonsterRaceId::LEE_QIEZI:
199 msg_print(_("しかし、誰も来てくれなかった…。", "However, no one answered the call..."));
201 case MonsterRaceId::THUNDERS:
202 count += summon_THUNDERS(player_ptr, y, x, rlev, m_idx);
204 case MonsterRaceId::OOTSUKI:
205 count += summon_PLASMA(player_ptr, y, x, rlev, m_idx);
208 count += summon_Kin(player_ptr, y, x, rlev, m_idx);
212 if (player_ptr->blind && count && (target_type == MONSTER_TO_PLAYER)) {
213 msg_print(_("多くのものが間近に現れた音がする。", "You hear many things appear nearby."));
216 if (known && !see_monster(player_ptr, t_idx) && count && (target_type == MONSTER_TO_MONSTER)) {
217 floor_ptr->monster_noise = true;
220 auto res = MonsterSpellResult::make_valid();
221 res.learnable = target_type == MONSTER_TO_PLAYER;
227 * @brief RF6_S_CYBERの処理。サイバー・デーモン召喚。 /
228 * @param player_ptr プレイヤーへの参照ポインタ
231 * @param m_idx 呪文を唱えるモンスターID
232 * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
233 * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
237 MonsterSpellResult spell_RF6_S_CYBER(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type)
239 auto *floor_ptr = player_ptr->current_floor_ptr;
240 auto *m_ptr = &floor_ptr->m_list[m_idx];
241 DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
242 bool mon_to_mon = (target_type == MONSTER_TO_MONSTER);
243 bool mon_to_player = (target_type == MONSTER_TO_PLAYER);
244 bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
245 bool known = monster_near_player(floor_ptr, m_idx, t_idx);
246 mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."),
247 _("%^sがサイバーデーモンを召喚した!", "%^s magically summons Cyberdemons!"),
248 _("%^sがサイバーデーモンを召喚した!", "%^s magically summons Cyberdemons!"));
250 monspell_message(player_ptr, m_idx, t_idx, msg, target_type);
251 summon_disturb(player_ptr, target_type, known, see_either);
254 if (is_friendly(m_ptr) && mon_to_mon) {
255 count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_CYBER, (PM_ALLOW_GROUP));
257 count += summon_cyber(player_ptr, m_idx, y, x);
260 if (player_ptr->blind && count && mon_to_player) {
261 msg_print(_("重厚な足音が近くで聞こえる。", "You hear heavy steps nearby."));
264 if (monster_near_player(floor_ptr, m_idx, t_idx) && !see_monster(player_ptr, t_idx) && count && mon_to_mon) {
265 floor_ptr->monster_noise = true;
268 auto res = MonsterSpellResult::make_valid();
269 res.learnable = target_type == MONSTER_TO_PLAYER;
275 * @brief RF6_S_MONSTERの処理。モンスター一体召喚。 /
276 * @param player_ptr プレイヤーへの参照ポインタ
279 * @param m_idx 呪文を唱えるモンスターID
280 * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
281 * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
285 MonsterSpellResult spell_RF6_S_MONSTER(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type)
287 auto *floor_ptr = player_ptr->current_floor_ptr;
288 DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
289 bool mon_to_mon = (target_type == MONSTER_TO_MONSTER);
290 bool mon_to_player = (target_type == MONSTER_TO_PLAYER);
291 bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
292 bool known = monster_near_player(floor_ptr, m_idx, t_idx);
294 mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."), _("%^sが魔法で仲間を召喚した!", "%^s magically summons help!"),
295 _("%^sが魔法で仲間を召喚した!", "%^s magically summons help!"));
297 monspell_message(player_ptr, m_idx, t_idx, msg, target_type);
298 summon_disturb(player_ptr, target_type, known, see_either);
301 for (int k = 0; k < 1; k++) {
303 count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_NONE, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE));
307 count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_NONE, (monster_u_mode(floor_ptr, m_idx)));
311 if (player_ptr->blind && count && mon_to_player) {
312 msg_print(_("何かが間近に現れた音がする。", "You hear something appear nearby."));
315 if (monster_near_player(floor_ptr, m_idx, t_idx) && !see_monster(player_ptr, t_idx) && count && mon_to_mon) {
316 floor_ptr->monster_noise = true;
319 auto res = MonsterSpellResult::make_valid();
320 res.learnable = target_type == MONSTER_TO_PLAYER;
326 * @brief RF6_S_MONSTERSの処理。モンスター複数召喚。 /
327 * @param player_ptr プレイヤーへの参照ポインタ
330 * @param m_idx 呪文を唱えるモンスターID
331 * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
332 * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
336 MonsterSpellResult spell_RF6_S_MONSTERS(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type)
338 auto *floor_ptr = player_ptr->current_floor_ptr;
339 DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
340 bool mon_to_mon = (target_type == MONSTER_TO_MONSTER);
341 bool mon_to_player = (target_type == MONSTER_TO_PLAYER);
342 bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
343 bool known = monster_near_player(floor_ptr, m_idx, t_idx);
345 mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."),
346 _("%^sが魔法でモンスターを召喚した!", "%^s magically summons monsters!"), _("%^sが魔法でモンスターを召喚した!", "%^s magically summons monsters!"));
348 monspell_message(player_ptr, m_idx, t_idx, msg, target_type);
349 summon_disturb(player_ptr, target_type, known, see_either);
352 for (auto k = 0; k < S_NUM_6; k++) {
354 count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_NONE, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE));
358 count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_NONE, (PM_ALLOW_GROUP | monster_u_mode(floor_ptr, m_idx)));
362 if (player_ptr->blind && count && mon_to_player) {
363 msg_print(_("多くのものが間近に現れた音がする。", "You hear many things appear nearby."));
366 if (monster_near_player(floor_ptr, m_idx, t_idx) && !see_monster(player_ptr, t_idx) && count && mon_to_mon) {
367 floor_ptr->monster_noise = true;
370 auto res = MonsterSpellResult::make_valid();
371 res.learnable = target_type == MONSTER_TO_PLAYER;
377 * @brief RF6_S_ANTの処理。アリ召喚。 /
378 * @param player_ptr プレイヤーへの参照ポインタ
381 * @param m_idx 呪文を唱えるモンスターID
382 * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
383 * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
387 MonsterSpellResult spell_RF6_S_ANT(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type)
389 auto *floor_ptr = player_ptr->current_floor_ptr;
390 DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
391 bool mon_to_mon = (target_type == MONSTER_TO_MONSTER);
392 bool mon_to_player = (target_type == MONSTER_TO_PLAYER);
393 bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
394 bool known = monster_near_player(floor_ptr, m_idx, t_idx);
396 mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."), _("%^sが魔法でアリを召喚した。", "%^s magically summons ants."),
397 _("%^sが魔法でアリを召喚した。", "%^s magically summons ants."));
399 monspell_message(player_ptr, m_idx, t_idx, msg, target_type);
400 summon_disturb(player_ptr, target_type, known, see_either);
403 for (auto k = 0; k < S_NUM_6; k++) {
404 count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_ANT, PM_ALLOW_GROUP);
407 if (player_ptr->blind && count && mon_to_player) {
408 msg_print(_("多くのものが間近に現れた音がする。", "You hear many things appear nearby."));
411 if (monster_near_player(floor_ptr, m_idx, t_idx) && !see_monster(player_ptr, t_idx) && count && mon_to_mon) {
412 floor_ptr->monster_noise = true;
415 auto res = MonsterSpellResult::make_valid();
416 res.learnable = target_type == MONSTER_TO_PLAYER;
422 * @brief RF6_S_SPIDERの処理。クモ召喚。 /
423 * @param player_ptr プレイヤーへの参照ポインタ
426 * @param m_idx 呪文を唱えるモンスターID
427 * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
428 * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
432 MonsterSpellResult spell_RF6_S_SPIDER(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type)
434 auto *floor_ptr = player_ptr->current_floor_ptr;
435 DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
436 bool mon_to_mon = (target_type == MONSTER_TO_MONSTER);
437 bool mon_to_player = (target_type == MONSTER_TO_PLAYER);
438 bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
439 bool known = monster_near_player(floor_ptr, m_idx, t_idx);
441 mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."), _("%^sが魔法でクモを召喚した。", "%^s magically summons spiders."),
442 _("%^sが魔法でクモを召喚した。", "%^s magically summons spiders."));
444 monspell_message(player_ptr, m_idx, t_idx, msg, target_type);
445 summon_disturb(player_ptr, target_type, known, see_either);
448 for (auto k = 0; k < S_NUM_6; k++) {
449 count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_SPIDER, PM_ALLOW_GROUP);
452 if (player_ptr->blind && count && mon_to_player) {
453 msg_print(_("多くのものが間近に現れた音がする。", "You hear many things appear nearby."));
456 if (monster_near_player(floor_ptr, m_idx, t_idx) && !see_monster(player_ptr, t_idx) && count && mon_to_mon) {
457 floor_ptr->monster_noise = true;
460 auto res = MonsterSpellResult::make_valid();
461 res.learnable = target_type == MONSTER_TO_PLAYER;
467 * @brief RF6_S_HOUNDの処理。ハウンド召喚。 /
468 * @param player_ptr プレイヤーへの参照ポインタ
471 * @param m_idx 呪文を唱えるモンスターID
472 * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
473 * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
477 MonsterSpellResult spell_RF6_S_HOUND(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type)
479 auto *floor_ptr = player_ptr->current_floor_ptr;
480 DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
481 bool mon_to_mon = (target_type == MONSTER_TO_MONSTER);
482 bool mon_to_player = (target_type == MONSTER_TO_PLAYER);
483 bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
484 bool known = monster_near_player(floor_ptr, m_idx, t_idx);
486 mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."),
487 _("%^sが魔法でハウンドを召喚した。", "%^s magically summons hounds."), _("%^sが魔法でハウンドを召喚した。", "%^s magically summons hounds."));
489 monspell_message(player_ptr, m_idx, t_idx, msg, target_type);
490 summon_disturb(player_ptr, target_type, known, see_either);
493 for (auto k = 0; k < S_NUM_4; k++) {
494 count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_HOUND, PM_ALLOW_GROUP);
497 if (player_ptr->blind && count && mon_to_player) {
498 msg_print(_("多くのものが間近に現れた音がする。", "You hear many things appear nearby."));
501 if (monster_near_player(floor_ptr, m_idx, t_idx) && !see_monster(player_ptr, t_idx) && count && mon_to_mon) {
502 floor_ptr->monster_noise = true;
505 auto res = MonsterSpellResult::make_valid();
506 res.learnable = target_type == MONSTER_TO_PLAYER;
512 * @brief RF6_S_HYDRAの処理。ヒドラ召喚。 /
513 * @param player_ptr プレイヤーへの参照ポインタ
516 * @param m_idx 呪文を唱えるモンスターID
517 * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
518 * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
522 MonsterSpellResult spell_RF6_S_HYDRA(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type)
524 auto *floor_ptr = player_ptr->current_floor_ptr;
525 DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
526 bool mon_to_mon = (target_type == MONSTER_TO_MONSTER);
527 bool mon_to_player = (target_type == MONSTER_TO_PLAYER);
528 bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
529 bool known = monster_near_player(floor_ptr, m_idx, t_idx);
531 mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."),
532 _("%^sが魔法でヒドラを召喚した。", "%^s magically summons hydras."), _("%^sが魔法でヒドラを召喚した。", "%^s magically summons hydras."));
534 monspell_message(player_ptr, m_idx, t_idx, msg, target_type);
535 summon_disturb(player_ptr, target_type, known, see_either);
538 for (auto k = 0; k < S_NUM_4; k++) {
539 count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_HYDRA, PM_ALLOW_GROUP);
542 if (player_ptr->blind && count && mon_to_player) {
543 msg_print(_("多くのものが間近に現れた音がする。", "You hear many things appear nearby."));
546 if (monster_near_player(floor_ptr, m_idx, t_idx) && !see_monster(player_ptr, t_idx) && count && mon_to_mon) {
547 floor_ptr->monster_noise = true;
550 auto res = MonsterSpellResult::make_valid();
551 res.learnable = target_type == MONSTER_TO_PLAYER;
557 * @brief RF6_S_ANGELの処理。天使一体召喚。 /
558 * @param player_ptr プレイヤーへの参照ポインタ
561 * @param m_idx 呪文を唱えるモンスターID
562 * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
563 * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
567 MonsterSpellResult spell_RF6_S_ANGEL(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type)
569 auto *floor_ptr = player_ptr->current_floor_ptr;
570 DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
571 bool mon_to_mon = (target_type == MONSTER_TO_MONSTER);
572 bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
573 bool known = monster_near_player(floor_ptr, m_idx, t_idx);
575 mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."),
576 _("%^sが魔法で天使を召喚した!", "%^s magically summons an angel!"), _("%^sが魔法で天使を召喚した!", "%^s magically summons an angel!"));
578 monspell_message(player_ptr, m_idx, t_idx, msg, target_type);
579 summon_disturb(player_ptr, target_type, known, see_either);
581 auto *m_ptr = &floor_ptr->m_list[m_idx];
582 auto *r_ptr = &r_info[m_ptr->r_idx];
584 if (r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
585 num += r_ptr->level / 40;
589 for (int k = 0; k < num; k++) {
590 count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_ANGEL, PM_ALLOW_GROUP);
594 if (player_ptr->blind && count) {
595 msg_print(_("何かが間近に現れた音がする。", "You hear something appear nearby."));
598 if (player_ptr->blind) {
599 msg_print(_("多くのものが間近に現れた音がする。", "You hear many things appear nearby."));
603 if (monster_near_player(floor_ptr, m_idx, t_idx) && !see_monster(player_ptr, t_idx) && count && mon_to_mon) {
604 floor_ptr->monster_noise = true;
607 auto res = MonsterSpellResult::make_valid();
608 res.learnable = target_type == MONSTER_TO_PLAYER;
614 * @brief RF6_S_DEMONの処理。デーモン一体召喚。 /
615 * @param player_ptr プレイヤーへの参照ポインタ
618 * @param m_idx 呪文を唱えるモンスターID
619 * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
620 * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
624 MonsterSpellResult spell_RF6_S_DEMON(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type)
626 auto *floor_ptr = player_ptr->current_floor_ptr;
627 DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
628 bool mon_to_mon = (target_type == MONSTER_TO_MONSTER);
629 bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
630 bool known = monster_near_player(floor_ptr, m_idx, t_idx);
632 mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."),
633 _("%^sは魔法で混沌の宮廷から悪魔を召喚した!", "%^s magically summons a demon from the Courts of Chaos!"),
634 _("%^sは魔法で混沌の宮廷から悪魔を召喚した!", "%^s magically summons a demon from the Courts of Chaos!"));
636 monspell_message(player_ptr, m_idx, t_idx, msg, target_type);
637 summon_disturb(player_ptr, target_type, known, see_either);
640 for (int k = 0; k < 1; k++) {
641 count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_DEMON, PM_ALLOW_GROUP);
644 if (player_ptr->blind && count) {
645 msg_print(_("何かが間近に現れた音がする。", "You hear something appear nearby."));
648 if (monster_near_player(floor_ptr, m_idx, t_idx) && !see_monster(player_ptr, t_idx) && count && mon_to_mon) {
649 floor_ptr->monster_noise = true;
652 auto res = MonsterSpellResult::make_valid();
653 res.learnable = target_type == MONSTER_TO_PLAYER;
659 * @brief RF6_S_UNDEADの処理。アンデッド一体召喚。 /
660 * @param player_ptr プレイヤーへの参照ポインタ
663 * @param m_idx 呪文を唱えるモンスターID
664 * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
665 * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
669 MonsterSpellResult spell_RF6_S_UNDEAD(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type)
671 auto *floor_ptr = player_ptr->current_floor_ptr;
672 DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
673 bool mon_to_mon = (target_type == MONSTER_TO_MONSTER);
674 bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
675 bool known = monster_near_player(floor_ptr, m_idx, t_idx);
677 mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."),
678 _("%^sが魔法でアンデッドの強敵を召喚した!", "%^s magically summons an undead adversary!"),
679 _("%sが魔法でアンデッドを召喚した。", "%^s magically summons undead."));
681 monspell_message(player_ptr, m_idx, t_idx, msg, target_type);
682 summon_disturb(player_ptr, target_type, known, see_either);
685 for (int k = 0; k < 1; k++) {
686 count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_UNDEAD, PM_ALLOW_GROUP);
689 if (player_ptr->blind && count) {
690 msg_print(_("何かが間近に現れた音がする。", "You hear something appear nearby."));
693 if (monster_near_player(floor_ptr, m_idx, t_idx) && !see_monster(player_ptr, t_idx) && count && mon_to_mon) {
694 floor_ptr->monster_noise = true;
697 auto res = MonsterSpellResult::make_valid();
698 res.learnable = target_type == MONSTER_TO_PLAYER;
704 * @brief RF6_S_DRAGONの処理。ドラゴン一体召喚。 /
705 * @param player_ptr プレイヤーへの参照ポインタ
708 * @param m_idx 呪文を唱えるモンスターID
709 * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
710 * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
714 MonsterSpellResult spell_RF6_S_DRAGON(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type)
716 auto *floor_ptr = player_ptr->current_floor_ptr;
717 DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
718 bool mon_to_mon = (target_type == MONSTER_TO_MONSTER);
719 bool mon_to_player = (target_type == MONSTER_TO_PLAYER);
720 bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
721 bool known = monster_near_player(floor_ptr, m_idx, t_idx);
723 mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."),
724 _("%^sが魔法でドラゴンを召喚した!", "%^s magically summons a dragon!"), _("%^sが魔法でドラゴンを召喚した!", "%^s magically summons a dragon!"));
726 monspell_message(player_ptr, m_idx, t_idx, msg, target_type);
727 summon_disturb(player_ptr, target_type, known, see_either);
731 count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_DRAGON, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE));
735 count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_DRAGON, (PM_ALLOW_GROUP | monster_u_mode(floor_ptr, m_idx)));
738 if (player_ptr->blind && count) {
739 msg_print(_("何かが間近に現れた音がする。", "You hear something appear nearby."));
742 if (monster_near_player(floor_ptr, m_idx, t_idx) && !see_monster(player_ptr, t_idx) && count && mon_to_mon) {
743 floor_ptr->monster_noise = true;
746 auto res = MonsterSpellResult::make_valid();
747 res.learnable = target_type == MONSTER_TO_PLAYER;
753 * @brief RF6_S_HI_UNDEADの処理。強力なアンデッド召喚。 /
754 * @param player_ptr プレイヤーへの参照ポインタ
757 * @param m_idx 呪文を唱えるモンスターID
758 * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
759 * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
763 MonsterSpellResult spell_RF6_S_HI_UNDEAD(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type)
765 auto *floor_ptr = player_ptr->current_floor_ptr;
766 auto *m_ptr = &floor_ptr->m_list[m_idx];
767 DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
768 bool mon_to_mon = (target_type == MONSTER_TO_MONSTER);
769 bool mon_to_player = (target_type == MONSTER_TO_PLAYER);
770 bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
771 bool known = monster_near_player(floor_ptr, m_idx, t_idx);
773 GAME_TEXT m_name[MAX_NLEN];
774 monster_name(player_ptr, m_idx, m_name);
775 summon_disturb(player_ptr, target_type, known, see_either);
778 if (((m_ptr->r_idx == MonsterRaceId::MORGOTH) || (m_ptr->r_idx == MonsterRaceId::SAURON) || (m_ptr->r_idx == MonsterRaceId::ANGMAR)) && ((r_info[MonsterRaceId::NAZGUL].cur_num + 2) < r_info[MonsterRaceId::NAZGUL].max_num) && mon_to_player) {
779 count += summon_NAZGUL(player_ptr, y, x, m_idx);
781 mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."),
782 _("%^sが魔法で強力なアンデッドを召喚した!", "%^s magically summons greater undead!"),
783 _("%sが魔法でアンデッドを召喚した。", "%^s magically summons undead."));
785 monspell_message(player_ptr, m_idx, t_idx, msg, target_type);
787 for (auto k = 0; k < S_NUM_6; k++) {
789 count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_HI_UNDEAD, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE));
793 count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_HI_UNDEAD, (PM_ALLOW_GROUP | monster_u_mode(floor_ptr, m_idx)));
798 if (player_ptr->blind && count && mon_to_player) {
799 msg_print(_("間近で何か多くのものが這い回る音が聞こえる。", "You hear many creepy things appear nearby."));
802 if (monster_near_player(floor_ptr, m_idx, t_idx) && !see_monster(player_ptr, t_idx) && count && mon_to_mon) {
803 floor_ptr->monster_noise = true;
806 auto res = MonsterSpellResult::make_valid();
807 res.learnable = target_type == MONSTER_TO_PLAYER;
813 * @brief RF6_S_HI_DRAGONの処理。古代ドラゴン召喚。 /
814 * @param player_ptr プレイヤーへの参照ポインタ
817 * @param m_idx 呪文を唱えるモンスターID
818 * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
819 * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
823 MonsterSpellResult spell_RF6_S_HI_DRAGON(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type)
825 auto *floor_ptr = player_ptr->current_floor_ptr;
826 DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
827 bool mon_to_mon = (target_type == MONSTER_TO_MONSTER);
828 bool mon_to_player = (target_type == MONSTER_TO_PLAYER);
829 bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
830 bool known = monster_near_player(floor_ptr, m_idx, t_idx);
832 mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."),
833 _("%^sが魔法で古代ドラゴンを召喚した!", "%^s magically summons ancient dragons!"),
834 _("%^sが魔法で古代ドラゴンを召喚した!", "%^s magically summons ancient dragons!"));
836 monspell_message(player_ptr, m_idx, t_idx, msg, target_type);
837 summon_disturb(player_ptr, target_type, known, see_either);
840 for (auto k = 0; k < S_NUM_4; k++) {
842 count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_HI_DRAGON, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE));
846 count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_HI_DRAGON, (PM_ALLOW_GROUP | monster_u_mode(floor_ptr, m_idx)));
850 if (player_ptr->blind && count && mon_to_player) {
851 msg_print(_("多くの力強いものが間近に現れた音が聞こえる。", "You hear many powerful things appear nearby."));
854 if (monster_near_player(floor_ptr, m_idx, t_idx) && !see_monster(player_ptr, t_idx) && count && mon_to_mon) {
855 floor_ptr->monster_noise = true;
858 auto res = MonsterSpellResult::make_valid();
859 res.learnable = target_type == MONSTER_TO_PLAYER;
865 * @brief RF6_S_AMBERITESの処理。アンバーの王族召喚。 /
866 * @param player_ptr プレイヤーへの参照ポインタ
869 * @param m_idx 呪文を唱えるモンスターID
870 * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
871 * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
875 MonsterSpellResult spell_RF6_S_AMBERITES(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type)
877 auto *floor_ptr = player_ptr->current_floor_ptr;
878 DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
879 bool mon_to_mon = (target_type == MONSTER_TO_MONSTER);
880 bool mon_to_player = (target_type == MONSTER_TO_PLAYER);
881 bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
882 bool known = monster_near_player(floor_ptr, m_idx, t_idx);
884 mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."),
885 _("%^sがアンバーの王族を召喚した!", "%^s magically summons Lords of Amber!"),
886 _("%^sがアンバーの王族を召喚した!", "%^s magically summons Lords of Amber!"));
888 monspell_message(player_ptr, m_idx, t_idx, msg, target_type);
889 summon_disturb(player_ptr, target_type, known, see_either);
892 for (auto k = 0; k < S_NUM_4; k++) {
893 count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_AMBERITES, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE));
896 if (player_ptr->blind && count && mon_to_player) {
897 msg_print(_("何者かが次元を超えて現れた気配がした。", "You feel shadow shifting by immortal beings."));
900 if (monster_near_player(floor_ptr, m_idx, t_idx) && !see_monster(player_ptr, t_idx) && count && mon_to_mon) {
901 floor_ptr->monster_noise = true;
904 auto res = MonsterSpellResult::make_valid();
905 res.learnable = target_type == MONSTER_TO_PLAYER;
911 * @brief RF6_S_UNIQUEの処理。ユニーク・モンスター召喚。 /
912 * @param player_ptr プレイヤーへの参照ポインタ
915 * @param m_idx 呪文を唱えるモンスターID
916 * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
917 * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
921 MonsterSpellResult spell_RF6_S_UNIQUE(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type)
923 auto *floor_ptr = player_ptr->current_floor_ptr;
924 DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
925 bool mon_to_mon = (target_type == MONSTER_TO_MONSTER);
926 bool mon_to_player = (target_type == MONSTER_TO_PLAYER);
927 bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
928 bool known = monster_near_player(floor_ptr, m_idx, t_idx);
930 mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."),
931 _("%^sが魔法で特別な強敵を召喚した!", "%^s magically summons special opponents!"),
932 _("%^sが魔法で特別な強敵を召喚した!", "%^s magically summons special opponents!"));
934 monspell_message(player_ptr, m_idx, t_idx, msg, target_type);
935 summon_disturb(player_ptr, target_type, known, see_either);
937 auto *m_ptr = &floor_ptr->m_list[m_idx];
938 bool uniques_are_summoned = false;
940 for (auto k = 0; k < S_NUM_4; k++) {
941 count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_UNIQUE, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE));
945 uniques_are_summoned = true;
948 summon_type non_unique_type = SUMMON_HI_UNDEAD;
949 if ((m_ptr->sub_align & (SUB_ALIGN_GOOD | SUB_ALIGN_EVIL)) == (SUB_ALIGN_GOOD | SUB_ALIGN_EVIL)) {
950 non_unique_type = SUMMON_NONE;
951 } else if (m_ptr->sub_align & SUB_ALIGN_GOOD) {
952 non_unique_type = SUMMON_ANGEL;
955 for (auto k = count; k < S_NUM_4; k++) {
956 count += summon_specific(player_ptr, m_idx, y, x, rlev, non_unique_type, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE));
959 if (player_ptr->blind && count && mon_to_player) {
960 msg_format(_("多くの%sが間近に現れた音が聞こえる。", "You hear many %s appear nearby."),
961 uniques_are_summoned ? _("力強いもの", "powerful things") : _("もの", "things"));
964 if (monster_near_player(floor_ptr, m_idx, t_idx) && !see_monster(player_ptr, t_idx) && count && mon_to_mon) {
965 floor_ptr->monster_noise = true;
968 auto res = MonsterSpellResult::make_valid();
969 res.learnable = target_type == MONSTER_TO_PLAYER;