2 * @brief モンスター魔法の実装(対モンスター処理) / Monster spells (attack monster)
5 * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
6 * This software may be copied and distributed for educational, research,
7 * and not for profit purposes provided that this copyright and statement
8 * are included in all such copies. Other copyrights may also apply.
9 * 2014 Deskull rearranged comment for Doxygen.
12 #include "mspell/mspell-judgement.h"
13 #include "dungeon/dungeon.h"
14 #include "effect/effect-characteristics.h"
15 #include "floor/cave.h"
16 #include "floor/line-of-sight.h"
17 #include "grid/grid.h"
18 #include "main/sound-definitions-table.h"
19 #include "monster-race/monster-race.h"
20 #include "monster-race/race-flags-resistance.h"
21 #include "monster-race/race-flags4.h"
22 #include "monster/monster-info.h"
23 #include "monster/monster-status.h"
24 #include "player/attack-defense-types.h"
25 #include "player/player-race.h"
26 #include "player/special-defense-types.h"
27 #include "realm/realm-song-numbers.h"
28 #include "spell/range-calc.h"
29 #include "spell/spell-types.h"
30 #include "system/floor-type-definition.h"
31 #include "target/projection-path-calculator.h"
34 * @brief モンスターが敵対モンスターにビームを当てること可能かを判定する /
35 * Determine if a beam spell will hit the target.
36 * @param target_ptr プレーヤーへの参照ポインタ
41 * @param m_ptr 使用するモンスターの構造体参照ポインタ
42 * @return ビームが到達可能ならばTRUEを返す
44 bool direct_beam(player_type *target_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION x2, monster_type *m_ptr)
46 floor_type *floor_ptr = target_ptr->current_floor_ptr;
48 int grid_n = projection_path(target_ptr, grid_g, get_max_range(target_ptr), y1, x1, y2, x2, PROJECT_THRU);
54 bool is_friend = is_pet(m_ptr);
55 for (int i = 0; i < grid_n; i++) {
56 y = get_grid_y(grid_g[i]);
57 x = get_grid_x(grid_g[i]);
59 if (y == y2 && x == x2)
61 else if (is_friend && floor_ptr->grid_array[y][x].m_idx > 0 && !are_enemies(target_ptr, m_ptr, &floor_ptr->m_list[floor_ptr->grid_array[y][x].m_idx])) {
65 if (is_friend && player_bold(target_ptr, y, x))
75 * @brief モンスターが敵対モンスターに直接ブレスを当てることが可能かを判定する /
76 * Determine if a breath will hit the target.
83 * @param is_friend TRUEならば、プレイヤーを巻き込む時にブレスの判定をFALSEにする。
84 * @return ブレスを直接当てられるならばTRUEを返す
86 bool breath_direct(player_type *master_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION x2, POSITION rad, EFFECT_ID typ, bool is_friend)
103 int grid_n = projection_path(master_ptr, grid_g, get_max_range(master_ptr), y1, x1, y2, x2, flg);
107 for (i = 0; i < grid_n; ++i) {
108 int ny = get_grid_y(grid_g[i]);
109 int nx = get_grid_x(grid_g[i]);
111 if (flg & PROJECT_DISI) {
112 if (cave_stop_disintegration(master_ptr->current_floor_ptr, ny, nx))
114 } else if (flg & PROJECT_LOS) {
115 if (!cave_los_bold(master_ptr->current_floor_ptr, ny, nx))
118 if (!cave_have_flag_bold(master_ptr->current_floor_ptr, ny, nx, FF_PROJECT))
130 if (flg & PROJECT_DISI) {
131 if (in_disintegration_range(master_ptr->current_floor_ptr, y1, x1, y2, x2) && (distance(y1, x1, y2, x2) <= rad))
133 if (in_disintegration_range(master_ptr->current_floor_ptr, y1, x1, master_ptr->y, master_ptr->x)
134 && (distance(y1, x1, master_ptr->y, master_ptr->x) <= rad))
136 } else if (flg & PROJECT_LOS) {
137 if (los(master_ptr, y1, x1, y2, x2) && (distance(y1, x1, y2, x2) <= rad))
139 if (los(master_ptr, y1, x1, master_ptr->y, master_ptr->x) && (distance(y1, x1, master_ptr->y, master_ptr->x) <= rad))
142 if (projectable(master_ptr, y1, x1, y2, x2) && (distance(y1, x1, y2, x2) <= rad))
144 if (projectable(master_ptr, y1, x1, master_ptr->y, master_ptr->x) && (distance(y1, x1, master_ptr->y, master_ptr->x) <= rad))
149 POSITION gx[1024], gy[1024];
151 POSITION gm_rad = rad;
152 breath_shape(master_ptr, grid_g, grid_n, &grids, gx, gy, gm, &gm_rad, rad, y1, x1, y, x, typ);
153 for (i = 0; i < grids; i++) {
156 if ((y == y2) && (x == x2))
158 if (player_bold(master_ptr, y, x))
165 if (is_friend && hityou)
172 * @brief モンスターが特殊能力の目標地点を決める処理 /
173 * Get the actual center point of ball spells (rad > 1) (originally from TOband)
174 * @param target_ptr プレーヤーへの参照ポインタ
177 * @param ty 目標Y座標を返す参照ポインタ
178 * @param tx 目標X座標を返す参照ポインタ
179 * @param flg 判定のフラグ配列
182 void get_project_point(player_type *target_ptr, POSITION sy, POSITION sx, POSITION *ty, POSITION *tx, BIT_FLAGS flg)
185 int path_n = projection_path(target_ptr, path_g, get_max_range(target_ptr), sy, sx, *ty, *tx, flg);
188 for (int i = 0; i < path_n; i++) {
189 sy = get_grid_y(path_g[i]);
190 sx = get_grid_x(path_g[i]);
191 if (!cave_have_flag_bold(target_ptr->current_floor_ptr, sy, sx, FF_PROJECT))
200 * @brief モンスターが敵モンスターに魔力消去を使うかどうかを返す /
201 * Check should monster cast dispel spell at other monster.
202 * @param target_ptr プレーヤーへの参照ポインタ
203 * @param m_idx 術者のモンスターID
204 * @param t_idx 目標のモンスターID
205 * @return 魔力消去を使うべきならばTRUEを変えす。
207 bool dispel_check_monster(player_type *target_ptr, MONSTER_IDX m_idx, MONSTER_IDX t_idx)
209 monster_type *t_ptr = &target_ptr->current_floor_ptr->m_list[t_idx];
210 if (monster_invulner_remaining(t_ptr))
213 if ((t_ptr->mspeed < 135) && monster_fast_remaining(t_ptr))
216 if ((t_idx == target_ptr->riding) && dispel_check(target_ptr, m_idx))
223 * @brief モンスターがプレイヤーに魔力消去を与えるべきかを判定するルーチン
224 * Check should monster cast dispel spell.
225 * @param m_idx モンスターの構造体配列ID
226 * @return 魔力消去をかけるべきならTRUEを返す。
228 bool dispel_check(player_type *creature_ptr, MONSTER_IDX m_idx)
230 if (is_invuln(creature_ptr))
233 if (creature_ptr->wraith_form)
236 if (creature_ptr->shield)
239 if (creature_ptr->magicdef)
242 if (creature_ptr->multishadow)
245 if (creature_ptr->dustrobe)
248 if (creature_ptr->shero && (creature_ptr->pclass != CLASS_BERSERKER))
251 if (creature_ptr->mimic_form == MIMIC_DEMON_LORD)
254 monster_type *m_ptr = &creature_ptr->current_floor_ptr->m_list[m_idx];
255 monster_race *r_ptr = &r_info[m_ptr->r_idx];
256 if (r_ptr->flags4 & RF4_BR_ACID) {
257 if (!creature_ptr->immune_acid && (creature_ptr->oppose_acid || music_singing(creature_ptr, MUSIC_RESIST)))
260 if (creature_ptr->special_defense & DEFENSE_ACID)
264 if (r_ptr->flags4 & RF4_BR_FIRE) {
265 if (!((creature_ptr->prace == RACE_BALROG) && creature_ptr->lev > 44)) {
266 if (!creature_ptr->immune_fire && (creature_ptr->oppose_fire || music_singing(creature_ptr, MUSIC_RESIST)))
269 if (creature_ptr->special_defense & DEFENSE_FIRE)
274 if (r_ptr->flags4 & RF4_BR_ELEC) {
275 if (!creature_ptr->immune_elec && (creature_ptr->oppose_elec || music_singing(creature_ptr, MUSIC_RESIST)))
278 if (creature_ptr->special_defense & DEFENSE_ELEC)
282 if (r_ptr->flags4 & RF4_BR_COLD) {
283 if (!creature_ptr->immune_cold && (creature_ptr->oppose_cold || music_singing(creature_ptr, MUSIC_RESIST)))
286 if (creature_ptr->special_defense & DEFENSE_COLD)
290 if (((r_ptr->flags4 & (RF4_BR_POIS | RF4_BR_NUKE)) != 0) && !((creature_ptr->pclass == CLASS_NINJA) && (creature_ptr->lev > 44))) {
291 if (creature_ptr->oppose_pois || music_singing(creature_ptr, MUSIC_RESIST))
294 if (creature_ptr->special_defense & DEFENSE_POIS)
298 if (creature_ptr->ult_res)
301 if (creature_ptr->tsuyoshi)
304 if ((creature_ptr->special_attack & ATTACK_ACID) && !(r_ptr->flagsr & RFR_EFF_IM_ACID_MASK))
307 if ((creature_ptr->special_attack & ATTACK_FIRE) && !(r_ptr->flagsr & RFR_EFF_IM_FIRE_MASK))
310 if ((creature_ptr->special_attack & ATTACK_ELEC) && !(r_ptr->flagsr & RFR_EFF_IM_ELEC_MASK))
313 if ((creature_ptr->special_attack & ATTACK_COLD) && !(r_ptr->flagsr & RFR_EFF_IM_COLD_MASK))
316 if ((creature_ptr->special_attack & ATTACK_POIS) && !(r_ptr->flagsr & RFR_EFF_IM_POIS_MASK))
319 if ((creature_ptr->pspeed < 145) && is_fast(creature_ptr))
322 if (creature_ptr->lightspeed && (m_ptr->mspeed < 136))
325 if (creature_ptr->riding && (creature_ptr->current_floor_ptr->m_list[creature_ptr->riding].mspeed < 135)
326 && monster_fast_remaining(&creature_ptr->current_floor_ptr->m_list[creature_ptr->riding]))