ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/los.C
Revision: 1.28
Committed: Sun Jul 1 05:00:17 2007 UTC (16 years, 11 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_2, rel-2_3
Changes since 1.27: +11 -12 lines
Log Message:
- upgrade crossfire trt to the GPL version 3 (hopefully correctly).
- add a single file covered by the GNU Affero General Public License
  (which is not yet released, so I used the current draft, which is
  legally a bit wavy, but its likely better than nothing as it expresses
  direct intent by the authors, and we can upgrade as soon as it has been
  released).
  * this should ensure availability of source code for the server at least
    and hopefully also archetypes and maps even when modified versions
    are not being distributed, in accordance of section 13 of the agplv3.

File Contents

# Content
1 /*
2 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
3 *
4 * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team
5 * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992,2007 Frank Tore Johansen
7 *
8 * Crossfire TRT is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 * The authors can be reached via e-mail to <crossfire@schmorp.de>
22 */
23
24 /* Nov 95 - inserted USE_LIGHTING code stuff in here - b.t. */
25
26 #include <global.h>
27 #include <funcpoint.h>
28 #include <math.h>
29
30 /* Distance must be less than this for the object to be blocked.
31 * An object is 1.0 wide, so if set to 0.5, it means the object
32 * that blocks half the view (0.0 is complete block) will
33 * block view in our tables.
34 * .4 or less lets you see through walls. .5 is about right.
35 */
36
37 #define SPACE_BLOCK 0.5
38
39 typedef struct blstr
40 {
41 int x[4], y[4];
42 int index;
43 } blocks;
44
45 // 31/32 == a speed hack
46 // we would like to use 32 for speed, but the code loops endlessly
47 // then, reason not yet identified, so only make the array use 32,
48 // not the define's.
49 blocks block[MAP_CLIENT_X][MAP_CLIENT_Y == 31 ? 32 : MAP_CLIENT_Y];
50
51 static void expand_lighted_sight (object *op);
52
53 /*
54 * Used to initialise the array used by the LOS routines.
55 * What this sets if that x,y blocks the view of bx,by
56 * This then sets up a relation - for example, something
57 * at 5,4 blocks view at 5,3 which blocks view at 5,2
58 * etc. So when we check 5,4 and find it block, we have
59 * the data to know that 5,3 and 5,2 and 5,1 should also
60 * be blocked.
61 */
62
63 static void
64 set_block (int x, int y, int bx, int by)
65 {
66 int index = block[x][y].index, i;
67
68 /* Due to flipping, we may get duplicates - better safe than sorry.
69 */
70 for (i = 0; i < index; i++)
71 {
72 if (block[x][y].x[i] == bx && block[x][y].y[i] == by)
73 return;
74 }
75
76 block[x][y].x[index] = bx;
77 block[x][y].y[index] = by;
78 block[x][y].index++;
79 #ifdef LOS_DEBUG
80 LOG (llevDebug, "setblock: added %d %d -> %d %d (%d)\n", x, y, bx, by, block[x][y].index);
81 #endif
82 }
83
84 /*
85 * initialises the array used by the LOS routines.
86 */
87
88 /* since we are only doing the upper left quadrant, only
89 * these spaces could possibly get blocked, since these
90 * are the only ones further out that are still possibly in the
91 * sightline.
92 */
93
94 void
95 init_block (void)
96 {
97 int x, y, dx, dy, i;
98 static int block_x[3] = { -1, -1, 0 },
99 block_y[3] = { -1, 0, -1 };
100
101 for (x = 0; x < MAP_CLIENT_X; x++)
102 for (y = 0; y < MAP_CLIENT_Y; y++)
103 block[x][y].index = 0;
104
105
106 /* The table should be symmetric, so only do the upper left
107 * quadrant - makes the processing easier.
108 */
109 for (x = 1; x <= MAP_CLIENT_X / 2; x++)
110 {
111 for (y = 1; y <= MAP_CLIENT_Y / 2; y++)
112 {
113 for (i = 0; i < 3; i++)
114 {
115 dx = x + block_x[i];
116 dy = y + block_y[i];
117
118 /* center space never blocks */
119 if (x == MAP_CLIENT_X / 2 && y == MAP_CLIENT_Y / 2)
120 continue;
121
122 /* If its a straight line, its blocked */
123 if ((dx == x && x == MAP_CLIENT_X / 2) || (dy == y && y == MAP_CLIENT_Y / 2))
124 {
125 /* For simplicity, we mirror the coordinates to block the other
126 * quadrants.
127 */
128 set_block (x, y, dx, dy);
129 if (x == MAP_CLIENT_X / 2)
130 set_block (x, MAP_CLIENT_Y - y - 1, dx, MAP_CLIENT_Y - dy - 1);
131 else if (y == MAP_CLIENT_Y / 2)
132 set_block (MAP_CLIENT_X - x - 1, y, MAP_CLIENT_X - dx - 1, dy);
133 }
134 else
135 {
136 float d1, r, s, l;
137
138 /* We use the algorihm that found out how close the point
139 * (x,y) is to the line from dx,dy to the center of the viewable
140 * area. l is the distance from x,y to the line.
141 * r is more a curiosity - it lets us know what direction (left/right)
142 * the line is off
143 */
144
145 d1 = (float) (pow (MAP_CLIENT_X / 2 - dx, 2.f) + pow (MAP_CLIENT_Y / 2 - dy, 2.f));
146 r = (float) ((dy - y) * (dy - MAP_CLIENT_Y / 2) - (dx - x) * (MAP_CLIENT_X / 2 - dx)) / d1;
147 s = (float) ((dy - y) * (MAP_CLIENT_X / 2 - dx) - (dx - x) * (MAP_CLIENT_Y / 2 - dy)) / d1;
148 l = FABS (sqrt (d1) * s);
149
150 if (l <= SPACE_BLOCK)
151 {
152 /* For simplicity, we mirror the coordinates to block the other
153 * quadrants.
154 */
155 set_block (x, y, dx, dy);
156 set_block (MAP_CLIENT_X - x - 1, y, MAP_CLIENT_X - dx - 1, dy);
157 set_block (x, MAP_CLIENT_Y - y - 1, dx, MAP_CLIENT_Y - dy - 1);
158 set_block (MAP_CLIENT_X - x - 1, MAP_CLIENT_Y - y - 1, MAP_CLIENT_X - dx - 1, MAP_CLIENT_Y - dy - 1);
159 }
160 }
161 }
162 }
163 }
164 }
165
166 /*
167 * Used to initialise the array used by the LOS routines.
168 * x,y are indexes into the blocked[][] array.
169 * This recursively sets the blocked line of sight view.
170 * From the blocked[][] array, we know for example
171 * that if some particular space is blocked, it blocks
172 * the view of the spaces 'behind' it, and those blocked
173 * spaces behind it may block other spaces, etc.
174 * In this way, the chain of visibility is set.
175 */
176 static void
177 set_wall (object *op, int x, int y)
178 {
179 int i;
180
181 for (i = 0; i < block[x][y].index; i++)
182 {
183 int dx = block[x][y].x[i], dy = block[x][y].y[i], ax, ay;
184
185 /* ax, ay are the values as adjusted to be in the
186 * socket look structure.
187 */
188 ax = dx - (MAP_CLIENT_X - op->contr->ns->mapx) / 2;
189 ay = dy - (MAP_CLIENT_Y - op->contr->ns->mapy) / 2;
190
191 if (ax < 0 || ax >= op->contr->ns->mapx || ay < 0 || ay >= op->contr->ns->mapy)
192 continue;
193 #if 0
194 LOG (llevDebug, "blocked %d %d -> %d %d\n", dx, dy, ax, ay);
195 #endif
196 /* we need to adjust to the fact that the socket
197 * code wants the los to start from the 0,0
198 * and not be relative to middle of los array.
199 */
200 op->contr->blocked_los[ax][ay] = 100;
201 set_wall (op, dx, dy);
202 }
203 }
204
205 /*
206 * Used to initialise the array used by the LOS routines.
207 * op is the object, x and y values based on MAP_CLIENT_X and Y.
208 * this is because they index the blocked[][] arrays.
209 */
210
211 static void
212 check_wall (object *op, int x, int y)
213 {
214 int ax, ay;
215
216 if (!block[x][y].index)
217 return;
218
219 /* ax, ay are coordinates as indexed into the look window */
220 ax = x - (MAP_CLIENT_X - op->contr->ns->mapx) / 2;
221 ay = y - (MAP_CLIENT_Y - op->contr->ns->mapy) / 2;
222
223 /* If the converted coordinates are outside the viewable
224 * area for the client, return now.
225 */
226 if (ax < 0 || ay < 0 || ax >= op->contr->ns->mapx || ay >= op->contr->ns->mapy)
227 return;
228
229 #if 0
230 LOG (llevDebug, "check_wall, ax,ay=%d, %d x,y = %d, %d blocksview = %d, %d\n",
231 ax, ay, x, y, op->x + x - MAP_CLIENT_X / 2, op->y + y - MAP_CLIENT_Y / 2);
232 #endif
233
234 /* If this space is already blocked, prune the processing - presumably
235 * whatever has set this space to be blocked has done the work and already
236 * done the dependency chain.
237 */
238 if (op->contr->blocked_los[ax][ay] == 100)
239 return;
240
241
242 if (get_map_flags (op->map, NULL, op->x + x - MAP_CLIENT_X / 2, op->y + y - MAP_CLIENT_Y / 2, NULL, NULL) & (P_BLOCKSVIEW | P_OUT_OF_MAP))
243 set_wall (op, x, y);
244 }
245
246 /*
247 * Clears/initialises the los-array associated to the player
248 * controlling the object.
249 */
250
251 void
252 clear_los (player *pl)
253 {
254 /* This is safer than using the ns->mapx, mapy because
255 * we index the blocked_los as a 2 way array, so clearing
256 * the first z spaces may not not cover the spaces we are
257 * actually going to use
258 */
259 memset (pl->blocked_los, 0, MAP_CLIENT_X * MAP_CLIENT_Y);
260 }
261
262 /*
263 * expand_sight goes through the array of what the given player is
264 * able to see, and expands the visible area a bit, so the player will,
265 * to a certain degree, be able to see into corners.
266 * This is somewhat suboptimal, would be better to improve the formula.
267 */
268
269 static void
270 expand_sight (object *op)
271 {
272 int i, x, y, dx, dy;
273
274 for (x = 1; x < op->contr->ns->mapx - 1; x++) /* loop over inner squares */
275 for (y = 1; y < op->contr->ns->mapy - 1; y++)
276 {
277 if (!op->contr->blocked_los[x][y] &&
278 !(get_map_flags (op->map, NULL,
279 op->x - op->contr->ns->mapx / 2 + x,
280 op->y - op->contr->ns->mapy / 2 + y, NULL, NULL) & (P_BLOCKSVIEW | P_OUT_OF_MAP)))
281 {
282
283 for (i = 1; i <= 8; i += 1)
284 { /* mark all directions */
285 dx = x + freearr_x[i];
286 dy = y + freearr_y[i];
287 if (op->contr->blocked_los[dx][dy] > 0) /* for any square blocked */
288 op->contr->blocked_los[dx][dy] = -1;
289 }
290 }
291 }
292
293 if (op->map->darkness > 0) /* player is on a dark map */
294 expand_lighted_sight (op);
295
296 /* clear mark squares */
297 for (x = 0; x < op->contr->ns->mapx; x++)
298 for (y = 0; y < op->contr->ns->mapy; y++)
299 if (op->contr->blocked_los[x][y] < 0)
300 op->contr->blocked_los[x][y] = 0;
301 }
302
303 /* returns true if op carries one or more lights
304 * This is a trivial function now days, but it used to
305 * be a bit longer. Probably better for callers to just
306 * check the op->glow_radius instead of calling this.
307 */
308
309 int
310 has_carried_lights (const object *op)
311 {
312 /* op may glow! */
313 if (op->glow_radius > 0)
314 return 1;
315
316 return 0;
317 }
318
319 static void
320 expand_lighted_sight (object *op)
321 {
322 int x, y, darklevel, ax, ay, basex, basey, mflags, light, x1, y1;
323 maptile *m = op->map;
324 sint16 nx, ny;
325
326 darklevel = m->darkness;
327
328 /* If the player can see in the dark, lower the darklevel for him */
329 if (QUERY_FLAG (op, FLAG_SEE_IN_DARK))
330 darklevel -= 2;
331
332 /* add light, by finding all (non-null) nearby light sources, then
333 * mark those squares specially. If the darklevel<1, there is no
334 * reason to do this, so we skip this function
335 */
336
337 if (darklevel < 1)
338 return;
339
340 /* Do a sanity check. If not valid, some code below may do odd
341 * things.
342 */
343 if (darklevel > MAX_DARKNESS)
344 {
345 LOG (llevError, "Map darkness for %s on %s is too high (%d)\n", &op->name, &op->map->path, darklevel);
346 darklevel = MAX_DARKNESS;
347 }
348
349 /* First, limit player furthest (unlighted) vision */
350 for (x = 0; x < op->contr->ns->mapx; x++)
351 for (y = 0; y < op->contr->ns->mapy; y++)
352 if (op->contr->blocked_los[x][y] != 100)
353 op->contr->blocked_los[x][y] = MAX_LIGHT_RADII;
354
355 /* the spaces[] darkness value contains the information we need.
356 * Only process the area of interest.
357 * the basex, basey values represent the position in the op->contr->blocked_los
358 * array. Its easier to just increment them here (and start with the right
359 * value) than to recalculate them down below.
360 */
361 for (x = (op->x - op->contr->ns->mapx / 2 - MAX_LIGHT_RADII), basex = -MAX_LIGHT_RADII;
362 x <= (op->x + op->contr->ns->mapx / 2 + MAX_LIGHT_RADII); x++, basex++)
363 {
364
365 for (y = (op->y - op->contr->ns->mapy / 2 - MAX_LIGHT_RADII), basey = -MAX_LIGHT_RADII;
366 y <= (op->y + op->contr->ns->mapy / 2 + MAX_LIGHT_RADII); y++, basey++)
367 {
368 m = op->map;
369 nx = x;
370 ny = y;
371
372 mflags = get_map_flags (m, &m, nx, ny, &nx, &ny);
373
374 if (mflags & P_OUT_OF_MAP)
375 continue;
376
377 /* This space is providing light, so we need to brighten up the
378 * spaces around here.
379 */
380 light = GET_MAP_LIGHT (m, nx, ny);
381 if (light != 0)
382 {
383 #if 0
384 LOG (llevDebug, "expand_lighted_sight: Found light at x=%d, y=%d, basex=%d, basey=%d\n", x, y, basex, basey);
385 #endif
386 for (ax = basex - light; ax <= basex + light; ax++)
387 {
388 if (ax < 0 || ax >= op->contr->ns->mapx)
389 continue;
390
391 for (ay = basey - light; ay <= basey + light; ay++)
392 {
393 if (ay < 0 || ay >= op->contr->ns->mapy)
394 continue;
395
396 /* If the space is fully blocked, do nothing. Otherwise, we
397 * brighten the space. The further the light is away from the
398 * source (basex-x), the less effect it has. Though light used
399 * to dim in a square manner, it now dims in a circular manner
400 * using the the pythagorean theorem. glow_radius still
401 * represents the radius
402 */
403 if (op->contr->blocked_los[ax][ay] != 100)
404 {
405 x1 = abs (basex - ax) * abs (basex - ax);
406 y1 = abs (basey - ay) * abs (basey - ay);
407
408 if (light > 0) op->contr->blocked_los[ax][ay] -= max (light - isqrt (x1 + y1), 0);
409 if (light < 0) op->contr->blocked_los[ax][ay] -= min (light + isqrt (x1 + y1), 0);
410 }
411 }
412 }
413 }
414 }
415 }
416
417 /* Outdoor should never really be completely pitch black dark like
418 * a dungeon, so let the player at least see a little around themselves
419 */
420 if (op->map->outdoor && darklevel > (MAX_DARKNESS - 3))
421 {
422 if (op->contr->blocked_los[op->contr->ns->mapx / 2][op->contr->ns->mapy / 2] > (MAX_DARKNESS - 3))
423 op->contr->blocked_los[op->contr->ns->mapx / 2][op->contr->ns->mapy / 2] = MAX_DARKNESS - 3;
424
425 for (x = -1; x <= 1; x++)
426 for (y = -1; y <= 1; y++)
427 {
428 if (op->contr->blocked_los[x + op->contr->ns->mapx / 2][y + op->contr->ns->mapy / 2] > (MAX_DARKNESS - 2))
429 op->contr->blocked_los[x + op->contr->ns->mapx / 2][y + op->contr->ns->mapy / 2] = MAX_DARKNESS - 2;
430 }
431 }
432
433 /* grant some vision to the player, based on the darklevel */
434 for (x = darklevel - MAX_DARKNESS; x < MAX_DARKNESS + 1 - darklevel; x++)
435 for (y = darklevel - MAX_DARKNESS; y < MAX_DARKNESS + 1 - darklevel; y++)
436 if (!(op->contr->blocked_los[x + op->contr->ns->mapx / 2][y + op->contr->ns->mapy / 2] == 100))
437 op->contr->blocked_los[x + op->contr->ns->mapx / 2][y + op->contr->ns->mapy / 2] -=
438 MAX (0, 6 - darklevel - MAX (abs (x), abs (y)));
439 }
440
441 /* blinded_sight() - sets all veiwable squares to blocked except
442 * for the one the central one that the player occupies. A little
443 * odd that you can see yourself (and what your standing on), but
444 * really need for any reasonable game play.
445 */
446 static void
447 blinded_sight (object *op)
448 {
449 int x, y;
450
451 for (x = 0; x < op->contr->ns->mapx; x++)
452 for (y = 0; y < op->contr->ns->mapy; y++)
453 op->contr->blocked_los[x][y] = 100;
454
455 op->contr->blocked_los[op->contr->ns->mapx / 2][op->contr->ns->mapy / 2] = 0;
456 }
457
458 /*
459 * update_los() recalculates the array which specifies what is
460 * visible for the given player-object.
461 */
462 void
463 update_los (object *op)
464 {
465 int dx = op->contr->ns->mapx / 2, dy = op->contr->ns->mapy / 2, x, y;
466
467 if (QUERY_FLAG (op, FLAG_REMOVED))
468 return;
469
470 clear_los (op->contr);
471
472 if (QUERY_FLAG (op, FLAG_WIZ) /* ||XRAYS(op) */ )
473 return;
474
475 /* For larger maps, this is more efficient than the old way which
476 * used the chaining of the block array. Since many space views could
477 * be blocked by different spaces in front, this mean that a lot of spaces
478 * could be examined multile times, as each path would be looked at.
479 */
480 for (x = (MAP_CLIENT_X - op->contr->ns->mapx) / 2 - 1; x < (MAP_CLIENT_X + op->contr->ns->mapx) / 2 + 1; x++)
481 for (y = (MAP_CLIENT_Y - op->contr->ns->mapy) / 2 - 1; y < (MAP_CLIENT_Y + op->contr->ns->mapy) / 2 + 1; y++)
482 check_wall (op, x, y);
483
484 /* do the los of the player. 3 (potential) cases */
485 if (QUERY_FLAG (op, FLAG_BLIND)) /* player is blind */
486 blinded_sight (op);
487 else
488 expand_sight (op);
489
490 //TODO: no range-checking whatsoever :(
491 if (QUERY_FLAG (op, FLAG_XRAYS))
492 for (int x = -2; x <= 2; x++)
493 for (int y = -2; y <= 2; y++)
494 op->contr->blocked_los[dx + x][dy + y] = 0;
495 }
496
497 /* update all_map_los is like update_all_los below,
498 * but updates everyone on the map, no matter where they
499 * are. This generally should not be used, as a per
500 * specific map change doesn't make much sense when tiling
501 * is considered (lowering darkness would certainly be a
502 * strange effect if done on a tile map, as it makes
503 * the distinction between maps much more obvious to the
504 * players, which is should not be.
505 * Currently, this function is called from the
506 * change_map_light function
507 */
508 void
509 update_all_map_los (maptile *map)
510 {
511 for_all_players (pl)
512 if (pl->ob && pl->ob->map == map)
513 pl->do_los = 1;
514 }
515
516 /*
517 * This function makes sure that update_los() will be called for all
518 * players on the given map within the next frame.
519 * It is triggered by removal or inserting of objects which blocks
520 * the sight in the map.
521 * Modified by MSW 2001-07-12 to take a coordinate of the changed
522 * position, and to also take map tiling into account. This change
523 * means that just being on the same map is not sufficient - the
524 * space that changes must be withing your viewable area.
525 *
526 * map is the map that changed, x and y are the coordinates.
527 */
528 void
529 update_all_los (const maptile *map, int x, int y)
530 {
531 for_all_players (pl)
532 {
533 /* Player should not have a null map, but do this
534 * check as a safety
535 */
536 if (!pl->ob || !pl->ob->map || !pl->ns)
537 continue;
538
539 /* Same map is simple case - see if pl is close enough.
540 * Note in all cases, we did the check for same map first,
541 * and then see if the player is close enough and update
542 * los if that is the case. If the player is on the
543 * corresponding map, but not close enough, then the
544 * player can't be on another map that may be closer,
545 * so by setting it up this way, we trim processing
546 * some.
547 */
548 if (pl->ob->map == map)
549 {
550 if ((abs (pl->ob->x - x) <= pl->ns->mapx / 2) && (abs (pl->ob->y - y) <= pl->ns->mapy / 2))
551 pl->do_los = 1;
552 }
553
554 /* Now we check to see if player is on adjacent
555 * maps to the one that changed and also within
556 * view. The tile_maps[] could be null, but in that
557 * case it should never match the pl->ob->map, so
558 * we want ever try to dereference any of the data in it.
559 *
560 * The logic for 0 and 3 is to see how far the player is
561 * from the edge of the map (height/width) - pl->ob->(x,y)
562 * and to add current position on this map - that gives a
563 * distance.
564 * For 1 and 2, we check to see how far the given
565 * coordinate (x,y) is from the corresponding edge,
566 * and then add the players location, which gives
567 * a distance.
568 */
569 else if (pl->ob->map == map->tile_map[0])
570 {
571 if ((abs (pl->ob->x - x) <= pl->ns->mapx / 2) && (abs (y + map->tile_map[0]->height - pl->ob->y) <= pl->ns->mapy / 2))
572 pl->do_los = 1;
573 }
574 else if (pl->ob->map == map->tile_map[2])
575 {
576 if ((abs (pl->ob->x - x) <= pl->ns->mapx / 2) && (abs (pl->ob->y + map->height - y) <= pl->ns->mapy / 2))
577 pl->do_los = 1;
578 }
579 else if (pl->ob->map == map->tile_map[1])
580 {
581 if ((abs (pl->ob->x + map->width - x) <= pl->ns->mapx / 2) && (abs (pl->ob->y - y) <= pl->ns->mapy / 2))
582 pl->do_los = 1;
583 }
584 else if (pl->ob->map == map->tile_map[3])
585 {
586 if ((abs (x + map->tile_map[3]->width - pl->ob->x) <= pl->ns->mapx / 2) && (abs (pl->ob->y - y) <= pl->ns->mapy / 2))
587 pl->do_los = 1;
588 }
589 }
590 }
591
592 /*
593 * Debug-routine which dumps the array which specifies the visible
594 * area of a player. Triggered by the z key in DM mode.
595 */
596 void
597 print_los (object *op)
598 {
599 int x, y;
600 char buf[50], buf2[10];
601
602 strcpy (buf, " ");
603
604 for (x = 0; x < op->contr->ns->mapx; x++)
605 {
606 sprintf (buf2, "%2d", x);
607 strcat (buf, buf2);
608 }
609
610 new_draw_info (NDI_UNIQUE, 0, op, buf);
611
612 for (y = 0; y < op->contr->ns->mapy; y++)
613 {
614 sprintf (buf, "%2d:", y);
615
616 for (x = 0; x < op->contr->ns->mapx; x++)
617 {
618 sprintf (buf2, " %1d", op->contr->blocked_los[x][y]);
619 strcat (buf, buf2);
620 }
621
622 new_draw_info (NDI_UNIQUE, 0, op, buf);
623 }
624 }
625
626 /*
627 * make_sure_seen: The object is supposed to be visible through walls, thus
628 * check if any players are nearby, and edit their LOS array.
629 */
630
631 void
632 make_sure_seen (const object *op)
633 {
634 for_all_players (pl)
635 if (pl->ob->map == op->map &&
636 pl->ob->y - pl->ns->mapy / 2 <= op->y &&
637 pl->ob->y + pl->ns->mapy / 2 >= op->y && pl->ob->x - pl->ns->mapx / 2 <= op->x && pl->ob->x + pl->ns->mapx / 2 >= op->x)
638 pl->blocked_los[pl->ns->mapx / 2 + op->x - pl->ob->x][pl->ns->mapy / 2 + op->y - pl->ob->y] = 0;
639 }
640
641 /*
642 * make_sure_not_seen: The object which is supposed to be visible through
643 * walls has just been removed from the map, so update the los of any
644 * players within its range
645 */
646
647 void
648 make_sure_not_seen (const object *op)
649 {
650 for_all_players (pl)
651 if (pl->ob->map == op->map &&
652 pl->ob->y - pl->ns->mapy / 2 <= op->y &&
653 pl->ob->y + pl->ns->mapy / 2 >= op->y && pl->ob->x - pl->ns->mapx / 2 <= op->x && pl->ob->x + pl->ns->mapx / 2 >= op->x)
654 pl->do_los = 1;
655 }