1 /**
2 * \file project.c
3 * \brief The project() function and helpers
4 *
5 * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
6 *
7 * This work is free software; you can redistribute it and/or modify it
8 * under the terms of either:
9 *
10 * a) the GNU General Public License as published by the Free Software
11 * Foundation, version 2, or
12 *
13 * b) the "Angband licence":
14 * This software may be copied and distributed for educational, research,
15 * and not for profit purposes provided that this copyright and statement
16 * are included in all such copies. Other copyrights may also apply.
17 */
18
19 #include "angband.h"
20 #include "cave.h"
21 #include "game-event.h"
22 #include "game-input.h"
23 #include "generate.h"
24 #include "init.h"
25 #include "mon-predicate.h"
26 #include "mon-util.h"
27 #include "player-calcs.h"
28 #include "player-timed.h"
29 #include "project.h"
30 #include "source.h"
31 #include "trap.h"
32
33 struct projection *projections;
34
35 /*
36 * Specify attr/char pairs for visual special effects for project()
37 * Ideally move these and PROJ-type colors to the UI - NRM
38 */
39 byte proj_to_attr[PROJ_MAX][BOLT_MAX];
40 wchar_t proj_to_char[PROJ_MAX][BOLT_MAX];
41
42 /**
43 * ------------------------------------------------------------------------
44 * PROJ type info needed for projections
45 *
46 * Note that elements come first, so PROJ_ACID == ELEM_ACID, etc
47 * ------------------------------------------------------------------------ */
48 static const char *proj_name_list[] =
49 {
50 #define ELEM(a) #a,
51 #include "list-elements.h"
52 #undef ELEM
53 #define PROJ(a) #a,
54 #include "list-projections.h"
55 #undef PROJ
56 "MAX",
57 NULL
58 };
59
proj_name_to_idx(const char * name)60 int proj_name_to_idx(const char *name)
61 {
62 int i;
63 for (i = 0; proj_name_list[i]; i++) {
64 if (!my_stricmp(name, proj_name_list[i]))
65 return i;
66 }
67
68 return -1;
69 }
70
proj_idx_to_name(int type)71 const char *proj_idx_to_name(int type)
72 {
73 assert(type >= 0);
74 assert(type < PROJ_MAX);
75
76 return proj_name_list[type];
77 }
78
79 /**
80 * ------------------------------------------------------------------------
81 * Projection paths
82 * ------------------------------------------------------------------------ */
83 /**
84 * Determine the path taken by a projection.
85 *
86 * The projection will always start from the grid1, and will travel
87 * towards grid2, touching one grid per unit of distance along
88 * the major axis, and stopping when it enters the finish grid or a
89 * wall grid, or has travelled the maximum legal distance of "range".
90 *
91 * Note that "distance" in this function (as in the "update_view()" code)
92 * is defined as "MAX(dy,dx) + MIN(dy,dx)/2", which means that the player
93 * actually has an "octagon of projection" not a "circle of projection".
94 *
95 * The path grids are saved into the grid array pointed to by "gp", and
96 * there should be room for at least "range" grids in "gp". Note that
97 * due to the way in which distance is calculated, this function normally
98 * uses fewer than "range" grids for the projection path, so the result
99 * of this function should never be compared directly to "range". Note
100 * that the initial grid grid1 is never saved into the grid array, not
101 * even if the initial grid is also the final grid. XXX XXX XXX
102 *
103 * The "flg" flags can be used to modify the behavior of this function.
104 *
105 * In particular, the "PROJECT_STOP" and "PROJECT_THRU" flags have the same
106 * semantics as they do for the "project" function, namely, that the path
107 * will stop as soon as it hits a monster, or that the path will continue
108 * through the finish grid, respectively.
109 *
110 * The "PROJECT_JUMP" flag, which for the "project()" function means to
111 * start at a special grid (which makes no sense in this function), means
112 * that the path should be "angled" slightly if needed to avoid any wall
113 * grids, allowing the player to "target" any grid which is in "view".
114 * This flag is non-trivial and has not yet been implemented, but could
115 * perhaps make use of the "vinfo" array (above). XXX XXX XXX
116 *
117 * This function returns the number of grids (if any) in the path. This
118 * function will return zero if and only if grid1 and grid2 are equal.
119 *
120 * This algorithm is similar to, but slightly different from, the one used
121 * by "update_view_los()", and very different from the one used by "los()".
122 */
project_path(struct loc * gp,int range,struct loc grid1,struct loc grid2,int flg)123 int project_path(struct loc *gp, int range, struct loc grid1, struct loc grid2,
124 int flg)
125 {
126 int y, x;
127
128 int n = 0;
129 int k = 0;
130
131 /* Absolute */
132 int ay, ax;
133
134 /* Offsets */
135 int sy, sx;
136
137 /* Fractions */
138 int frac;
139
140 /* Scale factors */
141 int full, half;
142
143 /* Slope */
144 int m;
145
146 /* Possible decoy */
147 struct loc decoy = cave_find_decoy(cave);
148
149 /* No path necessary (or allowed) */
150 if (loc_eq(grid1, grid2)) return (0);
151
152
153 /* Analyze "dy" */
154 if (grid2.y < grid1.y) {
155 ay = (grid1.y - grid2.y);
156 sy = -1;
157 } else {
158 ay = (grid2.y - grid1.y);
159 sy = 1;
160 }
161
162 /* Analyze "dx" */
163 if (grid2.x < grid1.x) {
164 ax = (grid1.x - grid2.x);
165 sx = -1;
166 } else {
167 ax = (grid2.x - grid1.x);
168 sx = 1;
169 }
170
171
172 /* Number of "units" in one "half" grid */
173 half = (ay * ax);
174
175 /* Number of "units" in one "full" grid */
176 full = half << 1;
177
178
179 /* Vertical */
180 if (ay > ax) {
181 /* Start at tile edge */
182 frac = ax * ax;
183
184 /* Let m = ((dx/dy) * full) = (dx * dx * 2) = (frac * 2) */
185 m = frac << 1;
186
187 /* Start */
188 y = grid1.y + sy;
189 x = grid1.x;
190
191 /* Create the projection path */
192 while (1) {
193 /* Save grid */
194 gp[n++] = loc(x, y);
195
196 /* Hack -- Check maximum range */
197 if ((n + (k >> 1)) >= range) break;
198
199 /* Sometimes stop at finish grid */
200 if (!(flg & (PROJECT_THRU)))
201 if (loc_eq(loc(x, y), grid2)) break;
202
203 /* Don't stop if making paths through rock for generation */
204 if (!(flg & (PROJECT_ROCK))) {
205 /* Stop at non-initial wall grids, except where that would
206 * leak info during targetting */
207 if (!(flg & (PROJECT_INFO))) {
208 if ((n > 0) && !square_isprojectable(cave, loc(x, y)))
209 break;
210 } else if ((n > 0) && square_isbelievedwall(cave, loc(x, y))) {
211 break;
212 }
213 }
214
215 /* Sometimes stop at non-initial monsters/players, decoys */
216 if (flg & (PROJECT_STOP)) {
217 if ((n > 0) && (square(cave, loc(x, y))->mon != 0)) break;
218 if (loc_eq(loc(x, y), decoy)) break;
219 }
220
221 /* Slant */
222 if (m) {
223 /* Advance (X) part 1 */
224 frac += m;
225
226 /* Horizontal change */
227 if (frac >= half) {
228 /* Advance (X) part 2 */
229 x += sx;
230
231 /* Advance (X) part 3 */
232 frac -= full;
233
234 /* Track distance */
235 k++;
236 }
237 }
238
239 /* Advance (Y) */
240 y += sy;
241 }
242 }
243
244 /* Horizontal */
245 else if (ax > ay) {
246 /* Start at tile edge */
247 frac = ay * ay;
248
249 /* Let m = ((dy/dx) * full) = (dy * dy * 2) = (frac * 2) */
250 m = frac << 1;
251
252 /* Start */
253 y = grid1.y;
254 x = grid1.x + sx;
255
256 /* Create the projection path */
257 while (1) {
258 /* Save grid */
259 gp[n++] = loc(x, y);
260
261 /* Hack -- Check maximum range */
262 if ((n + (k >> 1)) >= range) break;
263
264 /* Sometimes stop at finish grid */
265 if (!(flg & (PROJECT_THRU)))
266 if (loc_eq(loc(x, y), grid2)) break;
267
268 /* Don't stop if making paths through rock for generation */
269 if (!(flg & (PROJECT_ROCK))) {
270 /* Stop at non-initial wall grids, except where that would
271 * leak info during targetting */
272 if (!(flg & (PROJECT_INFO))) {
273 if ((n > 0) && !square_isprojectable(cave, loc(x, y)))
274 break;
275 } else if ((n > 0) && square_isbelievedwall(cave, loc(x, y))) {
276 break;
277 }
278 }
279
280 /* Sometimes stop at non-initial monsters/players, decoys */
281 if (flg & (PROJECT_STOP)) {
282 if ((n > 0) && (square(cave, loc(x, y))->mon != 0)) break;
283 if (loc_eq(loc(x, y), decoy)) break;
284 }
285
286 /* Slant */
287 if (m) {
288 /* Advance (Y) part 1 */
289 frac += m;
290
291 /* Vertical change */
292 if (frac >= half) {
293 /* Advance (Y) part 2 */
294 y += sy;
295
296 /* Advance (Y) part 3 */
297 frac -= full;
298
299 /* Track distance */
300 k++;
301 }
302 }
303
304 /* Advance (X) */
305 x += sx;
306 }
307 }
308
309 /* Diagonal */
310 else {
311 /* Start */
312 y = grid1.y + sy;
313 x = grid1.x + sx;
314
315 /* Create the projection path */
316 while (1) {
317 /* Save grid */
318 gp[n++] = loc(x, y);
319
320 /* Hack -- Check maximum range */
321 if ((n + (n >> 1)) >= range) break;
322
323 /* Sometimes stop at finish grid */
324 if (!(flg & (PROJECT_THRU)))
325 if (loc_eq(loc(x, y), grid2)) break;
326
327 /* Don't stop if making paths through rock for generation */
328 if (!(flg & (PROJECT_ROCK))) {
329 /* Stop at non-initial wall grids, except where that would
330 * leak info during targetting */
331 if (!(flg & (PROJECT_INFO))) {
332 if ((n > 0) && !square_isprojectable(cave, loc(x, y)))
333 break;
334 } else if ((n > 0) && square_isbelievedwall(cave, loc(x, y))) {
335 break;
336 }
337 }
338
339 /* Sometimes stop at non-initial monsters/players, decoys */
340 if (flg & (PROJECT_STOP)) {
341 if ((n > 0) && (square(cave, loc(x, y))->mon != 0)) break;
342 if (loc_eq(loc(x, y), decoy)) break;
343 }
344
345 /* Advance */
346 y += sy;
347 x += sx;
348 }
349 }
350
351 /* Length */
352 return (n);
353 }
354
355
356 /**
357 * Determine if a bolt spell cast from grid1 to grid2 will arrive
358 * at the final destination, assuming that no monster gets in the way,
359 * using the project_path() function to check the projection path.
360 *
361 * Note that no grid is ever projectable() from itself.
362 *
363 * This function is used to determine if the player can (easily) target
364 * a given grid, and if a monster can target the player.
365 */
projectable(struct chunk * c,struct loc grid1,struct loc grid2,int flg)366 bool projectable(struct chunk *c, struct loc grid1, struct loc grid2, int flg)
367 {
368 struct loc grid_g[512];
369 int grid_n = 0;
370 int max_range = z_info->max_range;
371
372 /* Check for shortened projection range */
373 if ((flg & PROJECT_SHORT) && player->timed[TMD_COVERTRACKS]) {
374 max_range /= 4;
375 }
376
377 /* Check the projection path */
378 grid_n = project_path(grid_g, max_range, grid1, grid2, flg);
379
380 /* No grid is ever projectable from itself */
381 if (!grid_n) return false;
382
383 /* May not end in a wall grid */
384 if (!square_ispassable(c, grid_g[grid_n - 1])) return false;
385
386 /* May not end in an unrequested grid */
387 if (!loc_eq(grid_g[grid_n - 1], grid2)) return false;
388
389 /* Assume okay */
390 return (true);
391 }
392
393
394
395
396 /**
397 * ------------------------------------------------------------------------
398 * The main project() function and its helpers
399 * ------------------------------------------------------------------------ */
400
401 /**
402 * Given an origin, find its coordinates and return them
403 *
404 * If there is no origin, return (-1, -1)
405 */
origin_get_loc(struct source origin)406 struct loc origin_get_loc(struct source origin)
407 {
408 switch (origin.what) {
409 case SRC_MONSTER: {
410 struct monster *who = cave_monster(cave, origin.which.monster);
411 return who ? who->grid : loc(-1, -1);
412 }
413
414 case SRC_TRAP: {
415 struct trap *trap = origin.which.trap;
416 return trap->grid;
417 }
418
419 case SRC_PLAYER:
420 case SRC_OBJECT: /* Currently only worn cursed objects use this */
421 case SRC_CHEST_TRAP:
422 return player->grid;
423
424 case SRC_NONE:
425 return loc(-1, -1);
426 }
427
428 return loc(-1, -1);
429 }
430
431 /**
432 * Generic "beam"/"bolt"/"ball" projection routine.
433 * -BEN-, some changes by -LM-
434 *
435 * \param origin Origin of the projection
436 * \param rad Radius of explosion (0 = beam/bolt, 1 to 20 = ball), or maximum
437 * length of arc from the source.
438 * \param y Target location (or location to travel towards)
439 * \param x Target location (or location to travel towards)
440 * \param dam Base damage to apply to monsters, terrain, objects, or player
441 * \param typ Type of projection (fire, frost, dispel demons etc.)
442 * \param flg Extra bit flags that control projection behavior
443 * \param degrees_of_arc How wide an arc spell is (in degrees).
444 * \param diameter_of_source how wide the source diameter is.
445 * \param obj An object that the projection ignores
446 *
447 * \return true if any effects of the projection were observed, else false
448 *
449 *
450 * At present, there are five major types of projections:
451 *
452 * Point-effect projection: (no PROJECT_BEAM flag, radius of zero, and either
453 * jumps directly to target or has a single source and target grid)
454 * A point-effect projection has no line of projection, and only affects one
455 * grid. It is used for most area-effect spells (like dispel evil) and
456 * pinpoint strikes like the monster Holding prayer.
457 *
458 * Bolt: (no PROJECT_BEAM flag, radius of zero, has to travel from source to
459 * target)
460 * A bolt travels from source to target and affects only the final grid in its
461 * projection path. If given the PROJECT_STOP flag, it is stopped by any
462 * monster or character in its path (at present, all bolts use this flag).
463 *
464 * Beam: (PROJECT_BEAM)
465 * A beam travels from source to target, affecting all grids passed through
466 * with full damage. It is never stopped by monsters in its path. Beams
467 * may never be combined with any other projection type.
468 *
469 * Ball: (positive radius, unless the PROJECT_ARC flag is set)
470 * A ball travels from source towards the target, and always explodes. Unless
471 * specified, it does not affect wall grids, but otherwise affects any grids
472 * in LOS from the center of the explosion.
473 * If used with a direction, a ball will explode on the first occupied grid in
474 * its path. If given a target, it will explode on that target. If a
475 * wall is in the way, it will explode against the wall. If a ball reaches
476 * z_info->max_range without hitting anything or reaching its target, it will
477 * explode at that point.
478 *
479 * Arc: (positive radius, with the PROJECT_ARC flag set)
480 * An arc is a portion of a source-centered ball that explodes outwards
481 * towards the target grid. Like a ball, it affects all non-wall grids in
482 * LOS of the source in the explosion area. The width of arc spells is con-
483 * trolled by degrees_of_arc.
484 * An arc is created by rejecting all grids that form the endpoints of lines
485 * whose angular difference (in degrees) from the centerline of the arc is
486 * greater than one-half the input "degrees_of_arc". See the table "get_
487 * angle_to_grid" in "util.c" for more information.
488 * Note: An arc with a value for degrees_of_arc of zero is actually a beam of
489 * defined length.
490 *
491 * Projections that effect all monsters in LOS are handled through the use
492 * of the PROJECT_LOS effect, which applies a single-grid projection to
493 * individual monsters. Projections that light up rooms or affect all
494 * monsters on the level are more efficiently handled through special
495 * functions.
496 *
497 *
498 * Variations:
499 *
500 * PROJECT_STOP forces a path of projection to stop at the first occupied grid
501 * it hits. This is used with bolts, and also by ball spells travelling in
502 * a specific direction rather than towards a target.
503 *
504 * PROJECT_THRU allows a path of projection towards a target to continue
505 * past that target. It also allows a spell to affect wall grids adjacent
506 * to a grid in LOS of the center of the explosion.
507 *
508 * PROJECT_JUMP allows a projection to immediately set the source of the pro-
509 * jection to the target. This is used for all area effect spells (like
510 * dispel evil), and can also be used for bombardments.
511 *
512 * PROJECT_HIDE erases all graphical effects, making the projection invisible.
513 *
514 * PROJECT_GRID allows projections to affect terrain features.
515 *
516 * PROJECT_ITEM allows projections to affect objects on the ground.
517 *
518 * PROJECT_KILL allows projections to affect monsters.
519 *
520 * PROJECT_PLAY allows projections to affect the player.
521 *
522 * degrees_of_arc controls the width of arc spells. With a value for
523 * degrees_of_arc of zero, arcs act like beams of defined length.
524 *
525 * diameter_of_source controls how quickly explosions lose strength with dis-
526 * tance from the target. Most ball spells have a source diameter of 10,
527 * which means that they do 1/2 damage at range 1, 1/3 damage at range 2,
528 * and so on. Caster-centered balls usually have a source diameter of 20,
529 * which allows them to do full damage to all adjacent grids. Arcs have
530 * source diameters ranging up from 20, which allows the spell designer to
531 * fine-tune how quickly a breath loses strength outwards from the breather.
532 *
533 *
534 * Implementation notes:
535 *
536 * If the source grid is not the same as the target, we project along the path
537 * between them. Bolts stop if they hit anything, beams stop if they hit a
538 * wall, and balls and arcs may exhibit either bahavior. When they reach
539 * the final grid in the path, balls and arcs explode. We do not allow
540 * beams to be combined with explosions.
541 * Balls affect all floor grids in LOS (optionally, also wall grids adjacent
542 * to a grid in LOS) within their radius. Arcs do the same, but only within
543 * their cone of projection.
544 * Because affected grids are only scanned once, and it is really helpful to
545 * have explosions that travel outwards from the source, they are sorted by
546 * distance. For each distance, an adjusted damage is calculated.
547 * In successive passes, the code then displays explosion graphics, erases
548 * these graphics, marks terrain for possible later changes, affects
549 * objects, monsters, the character, and finally changes features and
550 * teleports monsters and characters in marked grids.
551 *
552 *
553 * Usage and graphics notes:
554 *
555 * Only 256 grids can be affected per projection, limiting the effective
556 * radius of standard ball attacks to nine units (diameter nineteen). Arcs
557 * can have larger radii; an arc capable of going out to range 20 should not
558 * be wider than 70 degrees.
559 *
560 * Balls must explode BEFORE hitting walls, or they would affect monsters on
561 * both sides of a wall.
562 *
563 * Note that for consistency, we pretend that the bolt actually takes time
564 * to move from point A to point B, even if the player cannot see part of the
565 * projection path. Note that in general, the player will *always* see part
566 * of the path, since it either starts at the player or ends on the player.
567 *
568 * Hack -- we assume that every "projection" is "self-illuminating".
569 *
570 * Hack -- when only a single monster is affected, we automatically track
571 * (and recall) that monster, unless "PROJECT_JUMP" is used.
572 *
573 * Note that we must call "handle_stuff()" after affecting terrain features
574 * in the blast radius, in case the illumination of the grid was changed,
575 * and "update_view()" and "update_monsters()" need to be called.
576 */
project(struct source origin,int rad,struct loc finish,int dam,int typ,int flg,int degrees_of_arc,byte diameter_of_source,const struct object * obj)577 bool project(struct source origin, int rad, struct loc finish,
578 int dam, int typ, int flg,
579 int degrees_of_arc, byte diameter_of_source,
580 const struct object *obj)
581 {
582 int i, j, k, dist_from_centre;
583
584 u32b dam_temp;
585
586 struct loc centre;
587 struct loc start;
588
589 int n1y = 0;
590 int n1x = 0;
591
592 /* Assume the player sees nothing */
593 bool notice = false;
594
595 /* Notify the UI if it can draw this projection */
596 bool drawing = false;
597
598 /* Is the player blind? */
599 bool blind = (player->timed[TMD_BLIND] ? true : false);
600
601 /* Number of grids in the "path" */
602 int num_path_grids = 0;
603
604 /* Actual grids in the "path" */
605 struct loc path_grid[512];
606
607 /* Number of grids in the "blast area" (including the "beam" path) */
608 int num_grids = 0;
609
610 /* Coordinates of the affected grids */
611 struct loc blast_grid[256];
612
613 /* Distance to each of the affected grids. */
614 int distance_to_grid[256];
615
616 /* Player visibility of each of the affected grids. */
617 bool player_sees_grid[256];
618
619 /* Precalculated damage values for each distance. */
620 int *dam_at_dist = malloc((z_info->max_range + 1) * sizeof(*dam_at_dist));
621
622 /* Flush any pending output */
623 handle_stuff(player);
624
625 /* No projection path - jump to target */
626 if (flg & PROJECT_JUMP) {
627 start = finish;
628
629 /* Clear the flag */
630 flg &= ~(PROJECT_JUMP);
631 } else {
632 start = origin_get_loc(origin);
633
634 /* Default to finish grid */
635 if (start.y == -1 && start.x == -1) {
636 start = finish;
637 }
638 }
639
640 /* Default center of explosion (if any) */
641 centre = start;
642
643 /*
644 * An arc spell with no width and a non-zero radius is actually a
645 * beam of defined length. Mark it as such.
646 */
647 if ((flg & (PROJECT_ARC)) && (degrees_of_arc == 0) && (rad != 0)) {
648 /* No longer an arc */
649 flg &= ~(PROJECT_ARC);
650
651 /* Now considered a beam */
652 flg |= (PROJECT_BEAM);
653 flg |= (PROJECT_THRU);
654 }
655
656 /*
657 * If a single grid is both start and finish (for example
658 * if PROJECT_JUMP is set), store it; otherwise, travel along the
659 * projection path.
660 */
661 if (loc_eq(start, finish)) {
662 blast_grid[num_grids] = finish;
663 centre = finish;
664 distance_to_grid[num_grids] = 0;
665 sqinfo_on(square(cave, finish)->info, SQUARE_PROJECT);
666 num_grids++;
667 } else {
668 /* Start from caster */
669 int y = start.y;
670 int x = start.x;
671
672 /* Calculate the projection path */
673 num_path_grids = project_path(path_grid, z_info->max_range, start,
674 finish, flg);
675
676 /* Some beams have limited length. */
677 if (flg & (PROJECT_BEAM)) {
678 /* Use length limit, if any is given. */
679 if ((rad > 0) && (rad < num_path_grids)) {
680 num_path_grids = rad;
681 }
682 }
683
684
685 /* Project along the path (except for arcs) */
686 if (!(flg & (PROJECT_ARC))) {
687 for (i = 0; i < num_path_grids; ++i) {
688 int oy = y;
689 int ox = x;
690
691 int ny = path_grid[i].y;
692 int nx = path_grid[i].x;
693
694 /* Hack -- Balls explode before reaching walls. */
695 if (!square_ispassable(cave, path_grid[i]) && (rad > 0) &&
696 !(flg & (PROJECT_BEAM)))
697 break;
698
699 /* Advance */
700 y = ny;
701 x = nx;
702
703 /* Beams collect all grids in the path, all other methods
704 * collect only the final grid in the path. */
705 if (flg & (PROJECT_BEAM)) {
706 blast_grid[num_grids].y = y;
707 blast_grid[num_grids].x = x;
708 distance_to_grid[num_grids] = 0;
709 sqinfo_on(square(cave, loc(x, y))->info, SQUARE_PROJECT);
710 num_grids++;
711 } else if (i == num_path_grids - 1) {
712 blast_grid[num_grids].y = y;
713 blast_grid[num_grids].x = x;
714 distance_to_grid[num_grids] = 0;
715 sqinfo_on(square(cave, loc(x, y))->info, SQUARE_PROJECT);
716 num_grids++;
717 }
718
719 /* Only do visuals if requested and within range limit. */
720 if (!blind && !(flg & (PROJECT_HIDE))) {
721 bool seen = square_isview(cave, loc(x, y));
722 bool beam = flg & (PROJECT_BEAM);
723
724 /* Tell the UI to display the bolt */
725 event_signal_bolt(EVENT_BOLT, typ, drawing, seen, beam, oy,
726 ox, y, x);
727 }
728 }
729 }
730
731 /* Save the "blast epicenter" */
732 centre.y = y;
733 centre.x = x;
734 }
735
736 /* Now check for explosions. Beams have already stored all the grids they
737 * will affect; all non-beam projections with positive radius explode in
738 * some way */
739 if ((rad > 0) && (!(flg & (PROJECT_BEAM)))) {
740 int y, x;
741
742 /* Pre-calculate some things for arcs. */
743 if ((flg & (PROJECT_ARC)) && (num_path_grids != 0)) {
744 /* Explosion centers on the caster. */
745 centre = start;
746
747 /* The radius of arcs cannot be more than 20 */
748 if (rad > 20)
749 rad = 20;
750
751 /* Ensure legal access into get_angle_to_grid table */
752 if (num_path_grids < 21)
753 i = num_path_grids - 1;
754 else
755 i = 20;
756
757 /* Reorient the grid forming the end of the arc's centerline. */
758 n1y = path_grid[i].y - centre.y + 20;
759 n1x = path_grid[i].x - centre.x + 20;
760 }
761
762 /* If the explosion centre hasn't been saved already, save it now. */
763 if (num_grids == 0) {
764 blast_grid[num_grids] = centre;
765 distance_to_grid[num_grids] = 0;
766 sqinfo_on(square(cave, centre)->info, SQUARE_PROJECT);
767 num_grids++;
768 }
769
770 /* Scan every grid that might possibly be in the blast radius. */
771 for (y = centre.y - rad; y <= centre.y + rad; y++) {
772 for (x = centre.x - rad; x <= centre.x + rad; x++) {
773 struct loc grid = loc(x, y);
774 bool on_path = false;
775
776 /* Center grid has already been stored. */
777 if (loc_eq(grid, centre))
778 continue;
779
780 /* Precaution: Stay within area limit. */
781 if (num_grids >= 255)
782 break;
783
784 /* Ignore "illegal" locations */
785 if (!square_in_bounds(cave, grid))
786 continue;
787
788 /* Most explosions are immediately stopped by walls. If
789 * PROJECT_THRU is set, walls can be affected if adjacent to
790 * a grid visible from the explosion centre - note that as of
791 * Angband 3.5.0 there are no such explosions - NRM.
792 * All explosions can affect one layer of terrain which is
793 * passable but not projectable */
794 if ((flg & (PROJECT_THRU)) || square_ispassable(cave, grid)) {
795 /* If this is a wall grid, ... */
796 if (!square_isprojectable(cave, grid)) {
797 bool can_see_one = false;
798 /* Check neighbors */
799 for (i = 0; i < 8; i++) {
800 struct loc adj_grid = loc_sum(grid, ddgrid_ddd[i]);
801 if (los(cave, centre, adj_grid)) {
802 can_see_one = true;
803 break;
804 }
805 }
806
807 /* Require at least one adjacent grid in LOS. */
808 if (!can_see_one)
809 continue;
810 }
811 } else if (!square_isprojectable(cave, grid))
812 continue;
813
814 /* Must be within maximum distance. */
815 dist_from_centre = (distance(centre, grid));
816 if (dist_from_centre > rad)
817 continue;
818
819 /* Mark grids which are on the projection path */
820 for (i = 0; i < num_path_grids; i++) {
821 if (loc_eq(grid, path_grid[i])) {
822 on_path = true;
823 }
824 }
825
826 /* Do we need to consider a restricted angle? */
827 if (flg & (PROJECT_ARC)) {
828 /* Use angle comparison to delineate an arc. */
829 int n2y, n2x, tmp, rotate, diff;
830
831 /* Reorient current grid for table access. */
832 n2y = y - start.y + 20;
833 n2x = x - start.x + 20;
834
835 /* Find the angular difference (/2) between the lines to
836 * the end of the arc's center-line and to the current grid.
837 */
838 rotate = 90 - get_angle_to_grid[n1y][n1x];
839 tmp = ABS(get_angle_to_grid[n2y][n2x] + rotate) % 180;
840 diff = ABS(90 - tmp);
841
842 /* If difference is greater then that allowed, skip it,
843 * unless it's on the target path */
844 if ((diff >= (degrees_of_arc + 6) / 4) && !on_path)
845 continue;
846 }
847
848 /* Accept remaining grids if in LOS or on the projection path */
849 if (los(cave, centre, grid) || on_path) {
850 blast_grid[num_grids].y = y;
851 blast_grid[num_grids].x = x;
852 distance_to_grid[num_grids] = dist_from_centre;
853 sqinfo_on(square(cave, grid)->info, SQUARE_PROJECT);
854 num_grids++;
855 }
856 }
857 }
858 }
859
860 /* Calculate and store the actual damage at each distance. */
861 for (i = 0; i <= z_info->max_range; i++) {
862 if (i > rad) {
863 /* No damage outside the radius. */
864 dam_temp = 0;
865 } else if ((!diameter_of_source) || (i == 0)) {
866 /* Standard damage calc. for 10' source diameters, or at origin. */
867 dam_temp = (dam + i) / (i + 1);
868 } else {
869 /* If a particular diameter for the source of the explosion's
870 * energy is given, it is full strength to that diameter and
871 * then reduces */
872 dam_temp = (diameter_of_source * dam) / (i + 1);
873 if (dam_temp > (u32b) dam) {
874 dam_temp = dam;
875 }
876 }
877
878 /* Store it. */
879 dam_at_dist[i] = dam_temp;
880 }
881
882
883 /* Sort the blast grids by distance from the centre. */
884 for (i = 0, k = 0; i <= rad; i++) {
885 /* Collect all the grids of a given distance together. */
886 for (j = k; j < num_grids; j++) {
887 if (distance_to_grid[j] == i) {
888 struct loc tmp;
889 int tmp_d = distance_to_grid[k];
890 tmp = blast_grid[k];
891
892 blast_grid[k] = blast_grid[j];
893 distance_to_grid[k] = distance_to_grid[j];
894
895 blast_grid[j] = tmp;
896 distance_to_grid[j] = tmp_d;
897
898 /* Write to next slot */
899 k++;
900 }
901 }
902 }
903
904 /* Establish which grids are visible - no blast visuals with PROJECT_HIDE */
905 for (i = 0; i < num_grids; i++) {
906 if (panel_contains(blast_grid[i].y, blast_grid[i].x) &&
907 square_isview(cave, blast_grid[i]) &&
908 !blind && !(flg & (PROJECT_HIDE))) {
909 player_sees_grid[i] = true;
910 } else {
911 player_sees_grid[i] = false;
912 }
913 }
914
915 /* Tell the UI to display the blast */
916 event_signal_blast(EVENT_EXPLOSION, typ, num_grids, distance_to_grid,
917 drawing, player_sees_grid, blast_grid, centre);
918
919 /* Affect objects on every relevant grid */
920 if (flg & (PROJECT_ITEM)) {
921 for (i = 0; i < num_grids; i++) {
922 if (project_o(origin, distance_to_grid[i], blast_grid[i],
923 dam_at_dist[distance_to_grid[i]], typ, obj)) {
924 notice = true;
925 }
926 }
927 }
928
929 /* Check monsters */
930 if (flg & (PROJECT_KILL)) {
931 bool was_obvious = false;
932 bool did_hit = false;
933 int num_hit = 0;
934 struct loc last_hit_grid = loc(0, 0);
935
936 /* Scan for monsters */
937 for (i = 0; i < num_grids; i++) {
938 struct monster *mon = NULL;
939
940 /* Check this monster hasn't been processed already */
941 if (!square_isproject(cave, blast_grid[i]))
942 continue;
943
944 /* Check there is actually a monster here */
945 mon = square_monster(cave, blast_grid[i]);
946 if (mon == NULL)
947 continue;
948
949 /* Affect the monster in the grid */
950 project_m(origin, distance_to_grid[i], blast_grid[i],
951 dam_at_dist[distance_to_grid[i]], typ, flg,
952 &did_hit, &was_obvious);
953 if (was_obvious) {
954 notice = true;
955 }
956 if (did_hit) {
957 num_hit++;
958
959 /* Monster location may have been updated by project_m() */
960 last_hit_grid = mon->grid;
961 }
962 }
963
964 /* Player affected one monster (without "jumping") */
965 if (origin.what == SRC_PLAYER &&
966 num_hit == 1 &&
967 !(flg & PROJECT_JUMP)) {
968 /* Location */
969 int x = last_hit_grid.x;
970 int y = last_hit_grid.y;
971
972 /* Track if possible */
973 if (square(cave, loc(x, y))->mon > 0) {
974 struct monster *mon = square_monster(cave, loc(x, y));
975
976 /* Recall and track */
977 if (monster_is_visible(mon)) {
978 monster_race_track(player->upkeep, mon->race);
979 health_track(player->upkeep, mon);
980 }
981 }
982 }
983 }
984
985 /* Look for the player, affect them when found */
986 if (flg & (PROJECT_PLAY)) {
987 /* Set power */
988 int power = 0;
989 if (origin.what == SRC_MONSTER) {
990 struct monster *mon = cave_monster(cave, origin.which.monster);
991 power = mon->race->spell_power;
992
993 /* Breaths from powerful monsters get power effects as well */
994 if (monster_is_powerful(mon))
995 power = MAX(power, 80);
996 }
997 for (i = 0; i < num_grids; i++) {
998 if (project_p(origin, distance_to_grid[i], blast_grid[i],
999 dam_at_dist[distance_to_grid[i]], typ, power,
1000 flg & PROJECT_SELF)) {
1001 notice = true;
1002 if (player->is_dead) {
1003 free(dam_at_dist);
1004 return notice;
1005 }
1006 break;
1007 }
1008 }
1009 }
1010
1011 /* Affect features in every relevant grid */
1012 if (flg & (PROJECT_GRID)) {
1013 for (i = 0; i < num_grids; i++) {
1014 if (project_f(origin, distance_to_grid[i], blast_grid[i],
1015 dam_at_dist[distance_to_grid[i]], typ)) {
1016 notice = true;
1017 }
1018 }
1019 }
1020
1021 /* Clear all the processing marks. */
1022 for (i = 0; i < num_grids; i++) {
1023 /* Clear the mark */
1024 sqinfo_off(square(cave, blast_grid[i])->info, SQUARE_PROJECT);
1025 }
1026
1027 /* Update stuff if needed */
1028 if (player->upkeep->update) update_stuff(player);
1029
1030 free(dam_at_dist);
1031
1032 /* Return "something was noticed" */
1033 return (notice);
1034 }
1035