version 1.2 | | version 1.3 |
---|
| | |
/* | | /* |
* static char *rcsid_los_c = | | * static char *rcsid_los_c = |
* "$Id: los.c,v 1.2 1999/07/13 06:02:41 cvs Exp $"; | | * "$Id: los.c,v 1.3 2001/06/04 06:41:02 mwedel Exp $"; |
*/ | | */ |
| | |
/* | | /* |
CrossFire, A Multiplayer game for X-windows | | CrossFire, A Multiplayer game for X-windows |
| | |
| | Copyright (C) 2001 Mark Wedel |
Copyright (C) 1992 Frank Tore Johansen | | Copyright (C) 1992 Frank Tore Johansen |
| | |
This program is free software; you can redistribute it and/or modify | | This program is free software; you can redistribute it and/or modify |
| | |
along with this program; if not, write to the Free Software | | along with this program; if not, write to the Free Software |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| | |
The author can be reached via e-mail to frankj@ifi.uio.no. | | The author can be reached via e-mail to mwedel@scruz.net |
| | |
This file was made based on an idea by vidarl@ifi.uio.no | | This file was made based on an idea by vidarl@ifi.uio.no |
*/ | | */ |
| | |
| | |
#include <global.h> | | #include <global.h> |
#include <funcpoint.h> | | #include <funcpoint.h> |
| | #include <math.h> |
| | |
| | |
| | /* Distance must be less than this for the object to be blocked. |
| | * An object is 1.0 wide, so if set to 0.5, it means the object |
| | * that blocks half the view (0.0 is complete block) will |
| | * block view in our tables. |
| | * .4 or less lets you see through walls. .5 is about right. |
| | */ |
| | |
| | #define SPACE_BLOCK 0.5 |
| | |
typedef struct blstr { | | typedef struct blstr { |
int x[4],y[4],b[4]; | | int x[4],y[4]; |
int index; | | int index; |
} blocks; | | } blocks; |
| | |
blocks block[11][11]; | | blocks block[MAP_CLIENT_X][MAP_CLIENT_Y]; |
| | |
/* | | /* |
* Used to initialise the array used by the LOS routines. | | * Used to initialise the array used by the LOS routines. |
| | * What this sets if that x,y blocks the view of bx,by |
| | * This then sets up a relation - for example, something |
| | * at 5,4 blocks view at 5,3 which blocks view at 5,2 |
| | * etc. So when we check 5,4 and find it block, we have |
| | * the data to know that 5,3 and 5,2 and 5,1 should also |
| | * be blocked. |
*/ | | */ |
| | |
void set_block(int x,int y,int bx, int by) { | | void set_block(int x,int y,int bx, int by) { |
int index=block[x][y].index; | | int index=block[x][y].index,i; |
| | |
| | /* Due to flipping, we may get duplicates - better safe than sorry. |
| | */ |
| | for (i=0; i<index; i++) { |
| | if (block[x][y].x[i] == bx && block[x][y].y[i] == by) return; |
| | } |
| | |
block[x][y].x[index]=bx; | | block[x][y].x[index]=bx; |
block[x][y].y[index]=by; | | block[x][y].y[index]=by; |
block[x][y].index++; | | block[x][y].index++; |
| | #ifdef LOS_DEBUG |
| | fprintf(stderr,"setblock: added %d %d -> %d %d (%d)\n", x, y, bx, by, |
| | block[x][y].index); |
| | #endif |
} | | } |
| | |
/* | | /* |
* initialises the array used by the LOS routines. | | * initialises the array used by the LOS routines. |
*/ | | */ |
| | |
| | /* since we are only doing the upper left quadrant, only |
| | * these spaces could possibly get blocked, since these |
| | * are the only ones further out that are still possibly in the |
| | * sightline. |
| | */ |
| | |
void init_block() { | | void init_block() { |
int x,y; | | int x,y, dx, dy, i; |
for(x=0;x<11;x++) | | static int block_x[3] = {-1, -1, 0}, block_y[3] = {-1, 0, -1}; |
for(y=0;y<11;y++) { | | |
| | for(x=0;x<MAP_CLIENT_X;x++) |
| | for(y=0;y<MAP_CLIENT_Y;y++) { |
block[x][y].index=0; | | block[x][y].index=0; |
} | | } |
| | |
/* region 1 */ | | |
| | |
set_block(5,4,4,3); | | /* The table should be symmetric, so only do the upper left |
set_block(5,4,5,3); | | * quadrant - makes the processing easier. |
set_block(5,4,6,3); | | */ |
set_block(4,3,4,2); | | for (x=1; x<=MAP_CLIENT_X/2; x++) { |
set_block(5,3,5,2); | | for (y=1; y<=MAP_CLIENT_Y/2; y++) { |
set_block(6,3,6,2); | | for (i=0; i< 3; i++) { |
set_block(4,2,4,1); | | dx = x + block_x[i]; |
set_block(4,2,3,1); | | dy = y + block_y[i]; |
set_block(5,2,5,1); | | |
set_block(6,2,6,1); | | /* center space never blocks */ |
set_block(6,2,7,1); | | if (x == MAP_CLIENT_X/2 && y == MAP_CLIENT_Y/2) continue; |
set_block(3,1,3,0); | | |
set_block(4,1,4,0); | | /* If its a straight line, its blocked */ |
set_block(5,1,5,0); | | if ((dx == x && x == MAP_CLIENT_X/2) || |
set_block(6,1,6,0); | | (dy==y && y == MAP_CLIENT_Y/2)) { |
set_block(7,1,7,0); | | /* For simplicity, we mirror the coordinates to block the other |
| | * quadrants. |
/* region 2 */ | | */ |
| | set_block(x, y, dx, dy); |
set_block(6,4,7,3); | | if (x == MAP_CLIENT_X/2) { |
set_block(7,3,7,2); | | set_block(x, MAP_CLIENT_Y - y -1, dx, MAP_CLIENT_Y - dy-1); |
set_block(7,3,8,2); | | } else if (y == MAP_CLIENT_Y/2) { |
set_block(7,3,8,3); | | set_block(MAP_CLIENT_X - x -1, y, MAP_CLIENT_X - dx - 1, dy); |
set_block(7,2,8,1); | | } |
set_block(8,2,9,1); | | } else { |
set_block(8,3,9,2); | | float d1, r, s,l; |
set_block(8,1,8,0); | | |
set_block(8,1,9,0); | | /* We use the algorihm that found out how close the point |
set_block(9,1,10,0); | | * (x,y) is to the line from dx,dy to the center of the viewable |
set_block(9,2,10,1); | | * area. l is the distance from x,y to the line. |
set_block(9,2,10,2); | | * r is more a curiosity - it lets us know what direction (left/right) |
| | * the line is off |
/* region 3 */ | | */ |
| | |
set_block(6,5,7,4); | | d1 = (float) (pow(MAP_CLIENT_X/2 - dx, 2) + pow(MAP_CLIENT_Y/2 - dy,2)); |
set_block(6,5,7,5); | | r = (float)((dy-y)*(dy - MAP_CLIENT_Y/2) - (dx-x)*(MAP_CLIENT_X/2-dx))/d1; |
set_block(6,5,7,6); | | s = (float)((dy-y)*(MAP_CLIENT_X/2 - dx ) - (dx-x)*(MAP_CLIENT_Y/2-dy))/d1; |
set_block(7,4,8,4); | | l = FABS(sqrt(d1) * s); |
set_block(7,5,8,5); | | |
set_block(7,6,8,6); | | if (l <= SPACE_BLOCK) { |
set_block(8,4,9,3); | | /* For simplicity, we mirror the coordinates to block the other |
set_block(8,4,9,4); | | * quadrants. |
set_block(8,5,9,5); | | */ |
set_block(8,6,9,6); | | set_block(x,y,dx,dy); |
set_block(8,6,9,7); | | set_block(MAP_CLIENT_X - x -1, y, MAP_CLIENT_X - dx - 1, dy); |
set_block(9,3,10,3); | | set_block(x, MAP_CLIENT_Y - y -1, dx, MAP_CLIENT_Y - dy - 1); |
set_block(9,4,10,4); | | set_block(MAP_CLIENT_X -x-1, MAP_CLIENT_Y -y-1, MAP_CLIENT_X - dx-1, MAP_CLIENT_Y - dy-1); |
set_block(9,5,10,5); | | } |
set_block(9,6,10,6); | | } |
set_block(9,7,10,7); | | } |
| | } |
/* region 4 */ | | } |
| | |
set_block(6,6,7,7); | | |
set_block(7,7,8,7); | | |
set_block(7,7,8,8); | | |
set_block(7,7,7,8); | | |
set_block(8,7,9,8); | | |
set_block(8,8,9,9); | | |
set_block(7,8,8,9); | | |
set_block(9,8,10,8); | | |
set_block(9,8,10,9); | | |
set_block(9,9,10,10); | | |
set_block(8,9,9,10); | | |
set_block(8,9,8,10); | | |
| | |
/* region 5 */ | | |
| | |
set_block(5,6,4,7); | | |
set_block(5,6,5,7); | | |
set_block(5,6,6,7); | | |
set_block(4,7,4,8); | | |
set_block(5,7,5,8); | | |
set_block(6,7,6,8); | | |
set_block(4,8,3,9); | | |
set_block(4,8,4,9); | | |
set_block(5,8,5,9); | | |
set_block(6,8,6,9); | | |
set_block(6,8,7,9); | | |
set_block(3,9,3,10); | | |
set_block(4,9,4,10); | | |
set_block(5,9,5,10); | | |
set_block(6,9,6,10); | | |
set_block(7,9,7,10); | | |
| | |
/* region 6 */ | | |
| | |
set_block(4,6,3,7); | | |
set_block(3,7,2,7); | | |
set_block(3,7,2,8); | | |
set_block(3,7,3,8); | | |
set_block(2,7,1,8); | | |
set_block(2,8,1,9); | | |
set_block(3,8,2,9); | | |
set_block(1,8,0,8); | | |
set_block(1,8,0,9); | | |
set_block(1,9,0,10); | | |
set_block(2,9,1,10); | | |
set_block(2,9,2,10); | | |
| | |
/* region 7 */ | | |
| | |
set_block(4,5,3,4); | | |
set_block(4,5,3,5); | | |
set_block(4,5,3,6); | | |
set_block(3,4,2,4); | | |
set_block(3,5,2,5); | | |
set_block(3,6,2,6); | | |
set_block(2,4,1,3); | | |
set_block(2,4,1,4); | | |
set_block(2,5,1,5); | | |
set_block(2,6,1,6); | | |
set_block(2,6,1,7); | | |
set_block(1,3,0,3); | | |
set_block(1,4,0,4); | | |
set_block(1,5,0,5); | | |
set_block(1,6,0,6); | | |
set_block(1,7,0,7); | | |
| | |
/* region 8 */ | | |
| | |
set_block(4,4,3,3); | | |
set_block(3,3,3,2); | | |
set_block(3,3,2,2); | | |
set_block(3,3,2,3); | | |
set_block(3,2,2,1); | | |
set_block(2,2,1,1); | | |
set_block(2,3,1,2); | | |
set_block(2,1,1,0); | | |
set_block(2,1,2,0); | | |
set_block(1,1,0,0); | | |
set_block(1,2,0,1); | | |
set_block(1,2,0,2); | | |
} | | } |
| | |
/* | | /* |
* Used to initialise the array used by the LOS routines. | | * Used to initialise the array used by the LOS routines. |
| | * x,y are indexes into the blocked[][] array. |
*/ | | */ |
| | |
void set_wall(object *op,int x,int y) { | | static void set_wall(object *op,int x,int y) { |
int i; | | int i; |
| | |
for(i=0;i<block[x][y].index;i++) { | | for(i=0;i<block[x][y].index;i++) { |
int dx=block[x][y].x[i],dy=block[x][y].y[i]; | | int dx=block[x][y].x[i],dy=block[x][y].y[i],ax,ay; |
op->contr->blocked_los[dx][dy]=100; | | |
| | /* ax, ay are the values as adjusted to be in the |
| | * socket look structure. |
| | */ |
| | ax = dx - (MAP_CLIENT_X - op->contr->socket.mapx)/2; |
| | ay = dy - (MAP_CLIENT_Y - op->contr->socket.mapy)/2; |
| | |
| | if (ax < 0 || ax>=op->contr->socket.mapx || |
| | ay < 0 || ay>=op->contr->socket.mapy) continue; |
| | #ifdef LOS_DEBUG |
| | fprintf(stderr,"blocked %d %d -> %d %d\n", |
| | #endif dx, dy, ax, ay); |
| | |
| | /* we need to adjust to the fact that the socket |
| | * code wants the los to start from the 0,0 |
| | * and not be relative to middle of los array. |
| | */ |
| | op->contr->blocked_los[ax][ay]=100; |
set_wall(op,dx,dy); | | set_wall(op,dx,dy); |
} | | } |
} | | } |
| | |
/* | | /* |
* Used to initialise the array used by the LOS routines. | | * Used to initialise the array used by the LOS routines. |
| | * op is the object, x and y values based on MAP_CLIENT_X and Y. |
| | * this is because they index the blocked[][] arrays. |
*/ | | */ |
| | |
void check_wall(object *op,int x,int y) { | | static void check_wall(object *op,int x,int y) { |
| | int ax, ay; |
if(!block[x][y].index) | | if(!block[x][y].index) |
return; | | return; |
if(blocks_view(op->map,op->x-5+x,op->y-5+y)) | | |
| | /* ax, ay are coordinates as indexed into the look window */ |
| | ax = x - (MAP_CLIENT_X - op->contr->socket.mapx)/2; |
| | ay = y - (MAP_CLIENT_Y - op->contr->socket.mapy)/2; |
| | |
| | /* If the converted coordinates are outside the viewable |
| | * area for the client, return now. |
| | */ |
| | if (ax < 0 || ay < 0 || ax >= op->contr->socket.mapx || ay >= op->contr->socket.mapy) |
| | return; |
| | |
| | if(blocks_view(op->map,op->x-op->contr->socket.mapx/2 + ax, |
| | op->y-op->contr->socket.mapy/2 + ay)) |
set_wall(op,x,y); | | set_wall(op,x,y); |
else { | | else { |
int i; | | int i; |
| | |
*/ | | */ |
| | |
void clear_los(object *op) { | | void clear_los(object *op) { |
| | /* This is safer than using the socket->mapx, mapy because |
| | * we index the blocked_los as a 2 way array, so clearing |
| | * the first z spaces may not not cover the spaces we are |
| | * actually going to use |
| | */ |
(void)memset((void *) op->contr->blocked_los,0, | | (void)memset((void *) op->contr->blocked_los,0, |
(WINRIGHT-WINLEFT+1)*(WINLOWER-WINUPPER+1)); | | MAP_CLIENT_X * MAP_CLIENT_Y); |
} | | } |
| | |
/* change_map_light() - used to change map light level (darkness) | | /* change_map_light() - used to change map light level (darkness) |
* up or down by *1*. This fctn is not designed to change by | | * up or down by *1*. This fctn is not designed to change by |
* more than that! Returns true if successful. -b.t. */ | | * more than that! Returns true if successful. -b.t. |
| | */ |
| | |
int change_map_light(mapstruct *m, int change) { | | int change_map_light(mapstruct *m, int change) { |
int new_level = m->darkness + change; | | int new_level = m->darkness + change; |
| | |
if(new_level>MAX_DARKNESS) return 0; | | if(new_level>MAX_DARKNESS) return 0; |
| | |
if(change) { | | if(change) { |
char buf[MAX_BUF]; | | |
| | |
if(change>0) sprintf(buf,"It becomes darker."); | | |
else sprintf(buf,"It becomes brighter."); | | |
| | |
/* inform all players on the map */ | | /* inform all players on the map */ |
(info_map_func)(NDI_BLACK, m,buf); | | if (change>0) |
| | (info_map_func)(NDI_BLACK, m,"It becomes darker."); |
| | else |
| | (info_map_func)(NDI_BLACK, m,"It becomes brighter."); |
| | |
m->darkness=m->map_object->invisible=new_level; | | m->darkness=m->map_object->invisible=new_level; |
m->do_los=0; /* to insure that los is updated */ | | m->do_los=0; /* to insure that los is updated */ |
update_all_los(m); | | update_all_los(m); |
return 1; | | return 1; |
} | | } |
| | |
return 0; | | return 0; |
} | | } |
| | |
| | |
* able to see, and expands the visible area a bit, so the player will, | | * able to see, and expands the visible area a bit, so the player will, |
* to a certain degree, be able to see into corners. | | * to a certain degree, be able to see into corners. |
* This is somewhat suboptimal, would be better to improve the formula. | | * This is somewhat suboptimal, would be better to improve the formula. |
* There are two versions of this function, based on whether or not | | |
* CD_LINE_OF_SIGHT is defined. If it is defined, the function | | |
* becomes a bit more time-consuming, but covers a few more "corners"... | | |
*/ | | */ |
| | |
| | |
void expand_sight(object *op) | | void expand_sight(object *op) |
{ | | { |
int i,x,y, dx, dy; | | int i,x,y, dx, dy; |
| | |
for(x=1;x<10;x++) /* loop over inner squares */ | | for(x=1;x<op->contr->socket.mapx-1;x++) /* loop over inner squares */ |
for(y=1;y<10;y++) | | for(y=1;y<op->contr->socket.mapy-1;y++) { |
if(!op->contr->blocked_los[x][y]&& | | if(!op->contr->blocked_los[x][y]&& |
!blocks_view(op->map,op->x-5+x,op->y-5+y)) | | !blocks_view(op->map,op->x-op->contr->socket.mapx/2+x, |
| | op->y-op->contr->socket.mapy/2+y)) |
| | |
for(i=1;i<=8;i+=1) { /* mark all directions */ | | for(i=1;i<=8;i+=1) { /* mark all directions */ |
dx = x + freearr_x[i]; | | dx = x + freearr_x[i]; |
dy = y + freearr_y[i]; | | dy = y + freearr_y[i]; |
if(op->contr->blocked_los[dx][dy] > 0) /* for any square blocked */ | | if(op->contr->blocked_los[dx][dy] > 0) /* for any square blocked */ |
op->contr->blocked_los[dx][dy]= -1; | | op->contr->blocked_los[dx][dy]= -1; |
} | | } |
| | } |
| | |
#ifdef USE_LIGHTING | | #ifdef USE_LIGHTING |
if(op->map->do_los) update_map_lights(op->map); | | if(op->map->do_los) update_map_lights(op->map); |
| | |
#endif | | #endif |
| | |
/* clear mark squares */ | | /* clear mark squares */ |
for (x = 0; x < 11; x++) | | for (x = 0; x < op->contr->socket.mapx; x++) |
for (y = 0; y < 11; y++) | | for (y = 0; y < op->contr->socket.mapy; y++) |
if (op->contr->blocked_los[x][y] < 0) | | if (op->contr->blocked_los[x][y] < 0) |
op->contr->blocked_los[x][y] = 0; | | op->contr->blocked_los[x][y] = 0; |
} | | } |
| | |
void add_light_to_list (object *light, object *op) { | | void add_light_to_list (object *light, object *op) { |
objectlink *obl=get_objectlink(); | | objectlink *obl; |
| | |
if(!light||light->glow_radius<1||QUERY_FLAG(light, FLAG_FREED)) return; | | if(!light||light->glow_radius<1||QUERY_FLAG(light, FLAG_FREED)) return; |
| | |
obl = (objectlink *) malloc(sizeof(objectlink)); | | obl = get_objectlink(); |
obl->ob = light; | | obl->ob = light; |
obl->id = light->count; | | obl->id = light->count; |
obl->next = op->lights; | | obl->next = op->lights; |
| | |
LOG(llevDebug,"Adding light %s (%d) to op %s light list\n" | | LOG(llevDebug,"Adding light %s (%d) to op %s light list\n" |
,light->name,light->count,op->name); | | ,light->name,light->count,op->name); |
#endif | | #endif |
| | |
} | | } |
| | |
| | |
| | |
| | |
prev=first=obl; | | prev=first=obl; |
while(obl) { | | while(obl) { |
nxt = obl->next ? obl->next: NULL; | | nxt = obl->next; |
if(obl->id==light->count) { | | if(obl->id==light->count) { |
if(obl==first) { | | if(obl==first) { |
op->lights = nxt; | | op->lights = nxt; |
| | |
nxt = obl->next ? obl->next: NULL; | | nxt = obl->next ? obl->next: NULL; |
if(!(tmp=obl->ob)||(obl->id!=tmp->count)||QUERY_FLAG(tmp,FLAG_FREED) | | if(!(tmp=obl->ob)||(obl->id!=tmp->count)||QUERY_FLAG(tmp,FLAG_FREED) |
||tmp->glow_radius<1) { | | ||tmp->glow_radius<1) { |
| | |
if(obl==first) { | | if(obl==first) { |
first = prev = nxt; | | first = prev = nxt; |
nxt = (nxt&&nxt->next) ? nxt->next: NULL; | | nxt = (nxt&&nxt->next) ? nxt->next: NULL; |
| | |
| | |
darklevel = MAP_DARKNESS(m); | | darklevel = MAP_DARKNESS(m); |
| | |
| | |
/* If the player can see in the dark, lower the darklevel for him */ | | /* If the player can see in the dark, lower the darklevel for him */ |
if(QUERY_FLAG(op,FLAG_SEE_IN_DARK)) darklevel -= 2; | | if(QUERY_FLAG(op,FLAG_SEE_IN_DARK)) darklevel -= 2; |
| | |
/* add light, by finding all (non-null) nearby light sources, then | | /* add light, by finding all (non-null) nearby light sources, then |
* mark those squares specially. If the darklevel<1, there is no | | * mark those squares specially. If the darklevel<1, there is no |
* reason to do this, so we skip this function */ | | * reason to do this, so we skip this function |
| | */ |
| | |
if(darklevel<1) return; | | if(darklevel<1) return; |
/* First, limit player furthest (unlighted) vision */ | | /* First, limit player furthest (unlighted) vision */ |
for (x = 0; x < 11; x++) | | for (x = 0; x < op->contr->socket.mapx; x++) |
for (y = 0; y < 11; y++) | | for (y = 0; y < op->contr->socket.mapy; y++) |
if(!(op->contr->blocked_los[x][y]==100)) | | if(!(op->contr->blocked_los[x][y]==100)) |
op->contr->blocked_los[x][y]= 4; | | op->contr->blocked_los[x][y]= 4; |
| | |
| | |
| | |
/* if the light is not carried by a live creature *or* if its | | /* if the light is not carried by a live creature *or* if its |
* on the map but its not the top object we ignore it (unless | | * on the map but its not the top object we ignore it (unless |
* its invisible). This helps to speed up the game. */ | | * its invisible). This helps to speed up the game. |
| | * |
| | * Remove that check (MSW 2001-05-29). Best I can see, this |
| | * means we will process lights in piles of loot - I don't see |
| | * a problem with that - I personally find it odd if something |
| | * gets dropped onto a space with a torch that it suddenly gets |
| | * darker - the ordering of objects in crossfire is somewhat suspect. |
| | */ |
| | |
| | #if 0 |
if(!tmp->env&&tmp->above&&!tmp->invisible) continue; | | if(!tmp->env&&tmp->above&&!tmp->invisible) continue; |
| | #endif |
| | |
/* which coordinates to use for the light */ | | /* which coordinates to use for the light */ |
if(!tmp->env) /* use map coord */ | | if(!tmp->env) /* use map coord */ |
| | |
| | |
radius = BRIGHTNESS(tmp); | | radius = BRIGHTNESS(tmp); |
| | |
/* ok, lets do it if in viewable range */ | | /* dx and dy are number of spaces it is away from player */ |
if(dx<=(4+radius)&&dy<=(4+radius)) { | | if(dx<=(op->contr->socket.mapx/2+radius)&&dy<=(op->contr->socket.mapy/2+radius)) { |
| | /* Its within range to do some good */ |
int basex,basey; | | int basex,basey; |
| | |
if(!tmp->env) { /* get right coord for the light */ | | if(!tmp->env) { /* get right coord for the light */ |
basex=tmp->x-op->x+5,basey=tmp->y-op->y+5; | | basex=tmp->x-op->x+op->contr->socket.mapx/2; |
| | basey=tmp->y-op->y+op->contr->socket.mapy/2; |
} else { | | } else { |
basex=tmp->env->x-op->x+5,basey=tmp->env->y-op->y+5; | | basex=tmp->env->x-op->x+op->contr->socket.mapx/2; |
| | basey=tmp->env->y-op->y+op->contr->socket.mapy/2; |
} | | } |
radius-=1; /* so we get right size illumination */ | | radius-=1; /* so we get right size illumination */ |
| | |
| | |
for(y=-radius;y<=radius;y++) { | | for(y=-radius;y<=radius;y++) { |
/* round corners */ | | /* round corners */ |
if(radius>1&&(abs(x)==radius)&&(abs(y)==radius)) continue; | | if(radius>1&&(abs(x)==radius)&&(abs(y)==radius)) continue; |
| | |
dx=basex+x,dy=basey+y; | | dx=basex+x,dy=basey+y; |
if(dx>=0&&dx<11&&dy>=0&&dy<11 | | if(dx>=0 && dx<op->contr->socket.mapx && |
&&!(op->contr->blocked_los[dx][dy]==100)) | | dy>=0 && dy<op->contr->socket.mapy && |
| | !(op->contr->blocked_los[dx][dy]==100)) |
op->contr->blocked_los[dx][dy]-= radius - MAX(abs(x),abs(y))+1; | | op->contr->blocked_los[dx][dy]-= radius - MAX(abs(x),abs(y))+1; |
} | | } |
} | | } |
| | |
/* grant some vision to the player, based on the darklevel */ | | /* grant some vision to the player, based on the darklevel */ |
for(x=darklevel-5; x<6-darklevel; x++) | | for(x=darklevel-5; x<6-darklevel; x++) |
for(y=darklevel-5; y<6-darklevel; y++) | | for(y=darklevel-5; y<6-darklevel; y++) |
if(!(op->contr->blocked_los[x+5][y+5]==100)) | | if(!(op->contr->blocked_los[x+op->contr->socket.mapx/2][y+op->contr->socket.mapy/2]==100)) |
op->contr->blocked_los[x+5][y+5]-= MAX(0,6 -darklevel - MAX(abs(x),abs(y))); | | op->contr->blocked_los[x+op->contr->socket.mapx/2][y+op->contr->socket.mapx/2]-= MAX(0,6 -darklevel - MAX(abs(x),abs(y))); |
} | | } |
| | |
/* blinded_sight() - sets all veiwable squares to blocked except | | /* blinded_sight() - sets all veiwable squares to blocked except |
| | |
void blinded_sight (object *op) { | | void blinded_sight (object *op) { |
int x,y; | | int x,y; |
| | |
for (x = 0; x < 11; x++) | | for (x = 0; x < op->contr->socket.mapx; x++) |
for (y = 0; y < 11; y++) | | for (y = 0; y < op->contr->socket.mapy; y++) |
op->contr->blocked_los[x][y] = 100; | | op->contr->blocked_los[x][y] = 100; |
| | |
op->contr->blocked_los[5][5] = 0; | | op->contr->blocked_los[ op->contr->socket.mapx/2][ op->contr->socket.mapy/2] = 0; |
} | | } |
| | |
/* | | /* |
| | |
*/ | | */ |
| | |
void update_los(object *op) { | | void update_los(object *op) { |
int i; | | int i, dx = op->contr->socket.mapx/2, dy = op->contr->socket.mapy/2; |
| | |
if(QUERY_FLAG(op,FLAG_REMOVED)) | | if(QUERY_FLAG(op,FLAG_REMOVED)) |
return; | | return; |
| | |
clear_los(op); | | clear_los(op); |
if(QUERY_FLAG(op,FLAG_WIZ) /* ||XRAYS(op) */) | | if(QUERY_FLAG(op,FLAG_WIZ) /* ||XRAYS(op) */) |
return; | | return; |
| | |
| | |
for(i=1;i<9;i++) | | for(i=1;i<9;i++) |
check_wall(op,5+freearr_x[i],5+freearr_y[i]); | | /* The block[][] array presumes player always in center relative to |
| | * full size, and not client size, as that is a global structure. |
| | */ |
| | check_wall(op,MAP_CLIENT_X/2+freearr_x[i],MAP_CLIENT_Y/2+freearr_y[i]); |
| | |
/* do the los of the player. 3 (potential) cases */ | | /* do the los of the player. 3 (potential) cases */ |
if(QUERY_FLAG(op,FLAG_BLIND)) /* player is blind */ | | if(QUERY_FLAG(op,FLAG_BLIND)) /* player is blind */ |
| | |
int x, y; | | int x, y; |
for (x = -2; x <= 2; x++) | | for (x = -2; x <= 2; x++) |
for (y = -2; y <= 2; y++) | | for (y = -2; y <= 2; y++) |
op->contr->blocked_los[5 + x][5 + y] = 0; | | op->contr->blocked_los[dx + x][dy + y] = 0; |
} | | } |
} | | } |
| | |
| | |
char buf[50], buf2[10]; | | char buf[50], buf2[10]; |
| | |
strcpy(buf," "); | | strcpy(buf," "); |
for(x=0;x<11;x++) | | for(x=0;x<op->contr->socket.mapx;x++) { |
{ | | |
sprintf(buf2,"%2d",x); | | sprintf(buf2,"%2d",x); |
strcat(buf,buf2); | | strcat(buf,buf2); |
} | | } |
(*draw_info_func)(NDI_UNIQUE, 0, op, buf); | | (*draw_info_func)(NDI_UNIQUE, 0, op, buf); |
for(y=0;y<11;y++) { | | for(y=0;y<op->contr->socket.mapy;y++) { |
sprintf(buf,"%2d:",y); | | sprintf(buf,"%2d:",y); |
for(x=0;x<11;x++) | | for(x=0;x<op->contr->socket.mapx;x++) { |
{ | | |
sprintf(buf2," %1d",op->contr->blocked_los[x][y]); | | sprintf(buf2," %1d",op->contr->blocked_los[x][y]); |
strcat(buf,buf2); | | strcat(buf,buf2); |
} | | } |
| | |
| | |
for (pl = first_player; pl; pl = pl->next) | | for (pl = first_player; pl; pl = pl->next) |
if (pl->ob->map == op->map && | | if (pl->ob->map == op->map && |
pl->ob->y + WINUPPER <= op->y && pl->ob->y + WINLOWER >= op->y && | | pl->ob->y - pl->socket.mapy/2 <= op->y && |
pl->ob->x + WINLEFT <= op->x && pl->ob->x + WINRIGHT >= op->x) | | pl->ob->y + pl->socket.mapy/2 >= op->y && |
pl->blocked_los[5 + op->x - pl->ob->x][5 + op->y - pl->ob->y] = 0; | | pl->ob->x - pl->socket.mapx/2 <= op->x && |
| | pl->ob->x + pl->socket.mapx/2 >= op->x) |
| | pl->blocked_los[pl->socket.mapx/2 + op->x - pl->ob->x] |
| | [pl->socket.mapy/2 + op->y - pl->ob->y] = 0; |
} | | } |
| | |
/* | | /* |
| | |
player *pl; | | player *pl; |
for (pl = first_player; pl; pl = pl->next) | | for (pl = first_player; pl; pl = pl->next) |
if (pl->ob->map == op->map && | | if (pl->ob->map == op->map && |
pl->ob->y + WINUPPER <= op->y && pl->ob->y + WINLOWER >= op->y && | | pl->ob->y - pl->socket.mapy/2 <= op->y && |
pl->ob->x + WINLEFT <= op->x && pl->ob->x + WINRIGHT >= op->x) | | pl->ob->y + pl->socket.mapy/2 >= op->y && |
| | pl->ob->x - pl->socket.mapx/2 <= op->x && |
| | pl->ob->x + pl->socket.mapx/2 >= op->x) |
pl->do_los = 1; | | pl->do_los = 1; |
} | | } |