1 #include "target/projection-path-calculator.h"
2 #include "effect/effect-characteristics.h"
3 #include "floor/cave.h"
4 #include "grid/feature-flag-types.h"
6 #include "system/floor-type-definition.h"
8 typedef struct projection_path_type {
28 } projection_path_type;
31 * @brief Convert a "location" (Y, X) into a "grid" (G)
34 * return
\8co
\98H
\8dÀ
\95W
36 static u16b location_to_grid(POSITION y, POSITION x) { return 256 * y + x; }
38 static projection_path_type *initialize_projection_path_type(
39 projection_path_type *pp_ptr, u16b *gp, POSITION range, BIT_FLAGS flag, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
42 pp_ptr->range = range;
51 static void set_asxy(projection_path_type *pp_ptr)
53 if (pp_ptr->y2 < pp_ptr->y1) {
54 pp_ptr->ay = pp_ptr->y1 - pp_ptr->y2;
57 pp_ptr->ay = pp_ptr->y2 - pp_ptr->y1;
61 if (pp_ptr->x2 < pp_ptr->x1) {
62 pp_ptr->ax = pp_ptr->x1 - pp_ptr->x2;
65 pp_ptr->ax = pp_ptr->x2 - pp_ptr->x1;
70 static bool calc_vertical_projection(player_type *player_ptr, projection_path_type *pp_ptr)
72 if (pp_ptr->ay > pp_ptr->ax)
75 pp_ptr->m = pp_ptr->ax * pp_ptr->ax * 2;
76 pp_ptr->y = pp_ptr->y1 + pp_ptr->sy;
77 pp_ptr->x = pp_ptr->x1;
78 pp_ptr->frac = pp_ptr->m;
79 if (pp_ptr->frac > pp_ptr->half) {
80 pp_ptr->x += pp_ptr->sx;
81 pp_ptr->frac -= pp_ptr->full;
85 floor_type *floor_ptr = player_ptr->current_floor_ptr;
87 pp_ptr->gp[pp_ptr->n++] = location_to_grid(pp_ptr->y, pp_ptr->x);
88 if ((pp_ptr->n + (pp_ptr->k >> 1)) >= pp_ptr->range)
91 if (!(pp_ptr->flag & PROJECT_THRU)) {
92 if ((pp_ptr->x == pp_ptr->x2) && (pp_ptr->y == pp_ptr->y2))
96 if (pp_ptr->flag & PROJECT_DISI) {
97 if ((pp_ptr->n > 0) && cave_stop_disintegration(floor_ptr, pp_ptr->y, pp_ptr->x))
99 } else if (pp_ptr->flag & PROJECT_LOS) {
100 if ((pp_ptr->n > 0) && !cave_los_bold(floor_ptr, pp_ptr->y, pp_ptr->x))
102 } else if (!(pp_ptr->flag & PROJECT_PATH)) {
103 if ((pp_ptr->n > 0) && !cave_have_flag_bold(floor_ptr, pp_ptr->y, pp_ptr->x, FF_PROJECT))
107 if (pp_ptr->flag & PROJECT_STOP) {
108 if ((pp_ptr->n > 0) && (player_bold(player_ptr, pp_ptr->y, pp_ptr->x) || floor_ptr->grid_array[pp_ptr->y][pp_ptr->x].m_idx != 0))
112 if (!in_bounds(floor_ptr, pp_ptr->y, pp_ptr->x))
116 pp_ptr->frac += pp_ptr->m;
117 if (pp_ptr->frac > pp_ptr->half) {
118 pp_ptr->x += pp_ptr->sx;
119 pp_ptr->frac -= pp_ptr->full;
124 pp_ptr->y += pp_ptr->sy;
131 * @brief
\8en
\93_
\82©
\82ç
\8fI
\93_
\82Ö
\82Ì
\92¼
\90ü
\8co
\98H
\82ð
\95Ô
\82· /
132 * Determine the path taken by a projection.
133 * @param player_ptr
\83v
\83\8c\81[
\83\84\81[
\82Ö
\82Ì
\8eQ
\8fÆ
\83|
\83C
\83\93\83^
134 * @param gp
\8co
\98H
\8dÀ
\95W
\83\8a\83X
\83g
\82ð
\95Ô
\82·
\8eQ
\8fÆ
\83|
\83C
\83\93\83^
135 * @param range
\8b\97\97£
136 * @param y1
\8en
\93_Y
\8dÀ
\95W
137 * @param x1
\8en
\93_X
\8dÀ
\95W
138 * @param y2
\8fI
\93_Y
\8dÀ
\95W
139 * @param x2
\8fI
\93_X
\8dÀ
\95W
140 * @param flag
\83t
\83\89\83OID
141 * @return
\83\8a\83X
\83g
\82Ì
\92·
\82³
143 int projection_path(player_type *player_ptr, u16b *gp, POSITION range, POSITION y1, POSITION x1, POSITION y2, POSITION x2, BIT_FLAGS flag)
145 if ((x1 == x2) && (y1 == y2))
148 projection_path_type tmp_projection_path;
149 projection_path_type *pp_ptr = initialize_projection_path_type(&tmp_projection_path, gp, range, flag, y1, x1, y2, x2);
151 pp_ptr->half = pp_ptr->ay * pp_ptr->ax;
152 pp_ptr->full = pp_ptr->half << 1;
156 if (calc_vertical_projection(player_ptr, pp_ptr))
160 if (pp_ptr->ax > pp_ptr->ay) {
161 pp_ptr->m = pp_ptr->ay * pp_ptr->ay * 2;
163 pp_ptr->x = x1 + pp_ptr->sx;
164 pp_ptr->frac = pp_ptr->m;
165 if (pp_ptr->frac > pp_ptr->half) {
166 pp_ptr->y += pp_ptr->sy;
167 pp_ptr->frac -= pp_ptr->full;
171 floor_type *floor_ptr = player_ptr->current_floor_ptr;
173 gp[pp_ptr->n++] = location_to_grid(pp_ptr->y, pp_ptr->x);
174 if ((pp_ptr->n + (pp_ptr->k >> 1)) >= range)
177 if (!(flag & (PROJECT_THRU))) {
178 if ((pp_ptr->x == x2) && (pp_ptr->y == y2))
182 if (flag & (PROJECT_DISI)) {
183 if ((pp_ptr->n > 0) && cave_stop_disintegration(floor_ptr, pp_ptr->y, pp_ptr->x))
185 } else if (flag & (PROJECT_LOS)) {
186 if ((pp_ptr->n > 0) && !cave_los_bold(floor_ptr, pp_ptr->y, pp_ptr->x))
188 } else if (!(flag & (PROJECT_PATH))) {
189 if ((pp_ptr->n > 0) && !cave_have_flag_bold(floor_ptr, pp_ptr->y, pp_ptr->x, FF_PROJECT))
193 if (flag & (PROJECT_STOP)) {
194 if ((pp_ptr->n > 0) && (player_bold(player_ptr, pp_ptr->y, pp_ptr->x) || floor_ptr->grid_array[pp_ptr->y][pp_ptr->x].m_idx != 0))
198 if (!in_bounds(floor_ptr, pp_ptr->y, pp_ptr->x))
202 pp_ptr->frac += pp_ptr->m;
203 if (pp_ptr->frac > pp_ptr->half) {
204 pp_ptr->y += pp_ptr->sy;
205 pp_ptr->frac -= pp_ptr->full;
210 pp_ptr->x += pp_ptr->sx;
216 pp_ptr->y = y1 + pp_ptr->sy;
217 pp_ptr->x = x1 + pp_ptr->sx;
219 floor_type *floor_ptr = player_ptr->current_floor_ptr;
221 gp[pp_ptr->n++] = location_to_grid(pp_ptr->y, pp_ptr->x);
222 if ((pp_ptr->n + (pp_ptr->n >> 1)) >= range)
225 if (!(flag & PROJECT_THRU)) {
226 if ((pp_ptr->x == x2) && (pp_ptr->y == y2))
230 if (flag & PROJECT_DISI) {
231 if ((pp_ptr->n > 0) && cave_stop_disintegration(floor_ptr, pp_ptr->y, pp_ptr->x))
233 } else if (flag & PROJECT_LOS) {
234 if ((pp_ptr->n > 0) && !cave_los_bold(floor_ptr, pp_ptr->y, pp_ptr->x))
236 } else if (!(flag & PROJECT_PATH)) {
237 if ((pp_ptr->n > 0) && !cave_have_flag_bold(floor_ptr, pp_ptr->y, pp_ptr->x, FF_PROJECT))
241 if (flag & PROJECT_STOP) {
242 if ((pp_ptr->n > 0) && (player_bold(player_ptr, pp_ptr->y, pp_ptr->x) || floor_ptr->grid_array[pp_ptr->y][pp_ptr->x].m_idx != 0))
246 if (!in_bounds(floor_ptr, pp_ptr->y, pp_ptr->x))
249 pp_ptr->y += pp_ptr->sy;
250 pp_ptr->x += pp_ptr->sx;