ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/los.C
(Generate patch)

Comparing deliantra/server/common/los.C (file contents):
Revision 1.2 by root, Tue Aug 29 08:01:35 2006 UTC vs.
Revision 1.16 by pippijn, Sat Jan 6 14:42:29 2007 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines