| version 1.20 | | version 1.21 |
|---|
| | |
| char *rcsid_x11_xutil_c = | | char *rcsid_x11_xutil_c = |
| "$Id: xutil.c,v 1.20 2005/08/14 13:03:07 akirschbaum Exp $"; | | "$Id: xutil.c,v 1.21 2005/08/31 21:57:23 akirschbaum Exp $"; |
| /* | | /* |
| Crossfire client, a client program for the crossfire program. | | Crossfire client, a client program for the crossfire program. |
| | | |
| | |
| | | |
| | | |
| /* | | /* |
| * Takes three args, first is a return value that is a pointer | | * Request a map update from the server. This is to circumvent a bug in some |
| * we should put map info into. Next two are map dimensions. | | * server versions. |
| * This function supports non rectangular maps but the client | | |
| * pretty much doesn't. The caller is responsible for freeing | | |
| * the data. I have the caller pass in a map struct instead of | | |
| * returning a pointer because I didn't want to change all the | | |
| * the_map.cells to the_map->cells... | | |
| * The returned map memory is zero'ed. | | |
| */ | | |
| void allocate_map( struct Map* new_map, int ax, int ay) | | |
| { | | |
| int i= 0; | | |
| | | |
| if( new_map == NULL) | | |
| return; | | |
| | | |
| if( ax < 1 || ay < 1) { | | |
| new_map->cells= NULL; | | |
| return; | | |
| } | | |
| | | |
| new_map->cells= (struct MapCell**)calloc( sizeof( struct MapCell*) * ay | | |
| + sizeof( struct MapCell) * ax * ay, 1); | | |
| | | |
| if( new_map->cells == NULL) | | |
| return; | | |
| | | |
| /* Skip past the first row of pointers to rows and assign the start of | | |
| * the actual map data | | |
| */ | | |
| new_map->cells[0]= (struct MapCell*)((char*)new_map->cells + | | |
| (sizeof( struct MapCell*) * ay)); | | |
| | | |
| /* Finish assigning the beginning of each row relative to the first row | | |
| * assigned above | | |
| */ | | |
| for( i= 0; i < ay; i++) { | | |
| new_map->cells[i]= new_map->cells[0] + ( i * ax); | | |
| } | | |
| new_map->x= ax; | | |
| new_map->y= ay; | | |
| | | |
| return; | | |
| } | | |
| | | |
| /* | | |
| * Clears out all the cells in the current view (which is | | |
| * the whole map if not using fog_of_war, and request | | |
| * a map update from the server | | |
| */ | | */ |
| void reset_map() | | void reset_map() |
| { | | { |
| int x= 0; | | |
| int y= 0; | | |
| | | |
| pl_pos.x= the_map.x/2; | | |
| pl_pos.y= the_map.y/2; | | |
| memset( the_map.cells[0], 0, | | |
| sizeof( struct MapCell) * the_map.x * the_map.y); | | |
| for( x= pl_pos.x; x < (pl_pos.x + use_config[CONFIG_MAPWIDTH]); x++) | | |
| { | | |
| for( y= pl_pos.y; y < (pl_pos.y + use_config[CONFIG_MAPHEIGHT]); y++) | | |
| { | | |
| the_map.cells[x][y].need_update= 1; | | |
| } | | |
| } | | |
| cs_print_string(csocket.fd, "mapredraw"); | | cs_print_string(csocket.fd, "mapredraw"); |
| return; | | |
| } | | |
| | | |
| void print_darkness() | | |
| { | | |
| | | |
| int x= 0; | | |
| int y= 0; | | |
| | | |
| for( y= 0; y < use_config[CONFIG_MAPHEIGHT]; y++) | | |
| { | | |
| for( x= 0; x < use_config[CONFIG_MAPWIDTH]; x++) | | |
| { | | |
| fprintf( stderr, "[%3d]", the_map.cells[x][y].darkness); | | |
| } | | |
| fprintf( stderr, "\n"); | | |
| } | | |
| } | | |
| | | |
| void print_map() | | |
| { | | |
| int x= 0; | | |
| int y= 0; | | |
| int z= 0; | | |
| | | |
| int local_mapx = pl_pos.x + use_config[CONFIG_MAPWIDTH]; | | |
| int local_mapy = pl_pos.y + use_config[CONFIG_MAPHEIGHT]; | | |
| | | |
| if( use_config[CONFIG_FOGWAR] == TRUE) | | |
| { | | |
| printf( " Current X pos: %d -- Current Y pos: %d\n", | | |
| pl_pos.x, pl_pos.y); | | |
| } | | |
| | | |
| fprintf( stderr, "-----------------------\n"); | | |
| for( y= pl_pos.y ; y < local_mapy; y++) | | |
| { | | |
| for( z= 0; z < MAXFACES; z++) | | |
| { | | |
| for( x= pl_pos.x ; x < local_mapx; x++) | | |
| { | | |
| if(the_map.cells[x][y].heads[z].face <= 0) | | |
| fprintf( stderr, "[ -- ]"); | | |
| else | | |
| fprintf( stderr, "[%4d]", the_map.cells[x][y].heads[z].face); | | |
| } | | |
| fprintf( stderr, "\n"); | | |
| } | | |
| fprintf( stderr, "\n"); | | |
| } | | |
| fprintf( stderr, "-----------------------\n"); | | |
| return; | | |
| } | | |
| | | |
| void set_map_darkness(int x, int y, uint8 darkness) | | |
| { | | |
| x+= pl_pos.x; | | |
| y+= pl_pos.y; | | |
| | | |
| the_map.cells[x][y].have_darkness = 1; | | |
| if (darkness != (255 - the_map.cells[x][y].darkness )) { | | |
| the_map.cells[x][y].darkness = 255 - darkness; | | |
| the_map.cells[x][y].need_update = 1; | | |
| /* pretty ugly - since the light code with pngximage uses | | |
| * neighboring spaces to adjust the darkness, we now need to | | |
| * let the neighbors know they should update their darkness | | |
| * now. | | |
| */ | | |
| if (use_config[CONFIG_DISPLAYMODE]==CFG_DM_SDL) { | | |
| if (x-1>0) the_map.cells[x-1][y].need_update = 1; | | |
| if (y-1>0) the_map.cells[x][y-1].need_update = 1; | | |
| if (x+1<use_config[CONFIG_MAPWIDTH]) the_map.cells[x+1][y].need_update = 1; | | |
| if (y+1<use_config[CONFIG_MAPHEIGHT]) the_map.cells[x][y+1].need_update = 1; | | |
| } | | |
| } | | |
| } | | |
| | | |
| | | |
| /* | | |
| * Returns true if virtual view is about to butt up against | | |
| * the side of the virtual map on the next scroll | | |
| * Only used for fog of war code | | |
| */ | | |
| static int need_recenter_map( int dx, int dy) | | |
| { | | |
| if( pl_pos.x + dx + use_config[CONFIG_MAPWIDTH] + MAX_MAP_OFFSET >= the_map.x || | | |
| pl_pos.y + dy + use_config[CONFIG_MAPHEIGHT] + MAX_MAP_OFFSET >= the_map.y || | | |
| pl_pos.x + dx <= 0 || | | |
| pl_pos.y + dy <= 0 ) | | |
| { | | |
| return TRUE; | | |
| } | | |
| | | |
| return FALSE; | | |
| } | | |
| | | |
| /* | | |
| * Only used in fog of war code. | | |
| * Will recenter the virtual coordinates of the player view | | |
| * to the center of the map and try to keep as much current | | |
| * state in memory as possible | | |
| * If view is already close to center it won't move it | | |
| */ | | |
| static void recenter_virtual_map_view( struct Map *map) | | |
| { | | |
| static struct Map tmpmap; | | |
| struct MapCell **tmpcells; | | |
| int y_shift= 0; | | |
| int x_shift= 0; | | |
| int x= 0, y= 0; | | |
| | | |
| if( map == NULL) | | |
| return; | | |
| | | |
| | | |
| if( tmpmap.cells == NULL) | | |
| { | | |
| allocate_map( &tmpmap, map->x, map->y); | | |
| } | | |
| | | |
| /* | | |
| * If mapsize changed, allocate a new map | | |
| */ | | |
| if( tmpmap.x != map->x || tmpmap.y != map->y) | | |
| { | | |
| if( tmpmap.cells) | | |
| free( tmpmap.cells); | | |
| | | |
| allocate_map( &tmpmap, map->x, map->y); | | |
| } | | |
| | | |
| | | |
| /* | | |
| * If we are less then 1/4 away from either edge of the virtual map | | |
| * or the next move would push us up against the edge (for small | | |
| * virtual maps with large views this could happen before our 0,0 view | | |
| * coordinate is within 1/4 of the edge) we shift to the center. | | |
| */ | | |
| if( pl_pos.x <= (map->x/4) || (pl_pos.x +MAX_MAP_OFFSET) >= (map->x*3/4) || | | |
| pl_pos.x + use_config[CONFIG_MAPWIDTH] + 1 >= map->x ) | | |
| { | | |
| x_shift= map->x/2 - pl_pos.x; | | |
| } | | |
| if( pl_pos.y <= (map->y/4) || (pl_pos.y + MAX_MAP_OFFSET) >= (map->y*3/4) || | | |
| pl_pos.y + use_config[CONFIG_MAPHEIGHT] + 1 >= map->y ) | | |
| { | | |
| y_shift= map->y/2 - pl_pos.y; | | |
| } | | |
| | | |
| | | |
| if( x_shift == 0 && y_shift == 0) | | |
| return; | | |
| | | |
| for( x= 0; x < map->x; x++) | | |
| { | | |
| if( x + x_shift >= map->x || x + x_shift < 0) | | |
| continue; | | |
| | | |
| for( y= 0; y < map->y; y++) | | |
| { | | |
| if( y + y_shift >= map->y || y + y_shift < 0) | | |
| continue; | | |
| | | |
| memcpy( (char*)&tmpmap.cells[x + x_shift][y + y_shift], | | |
| (char*)&map->cells[x][y], | | |
| sizeof( struct MapCell) ); | | |
| } | | |
| } | | |
| | | |
| | | |
| pl_pos.x+= x_shift; | | |
| pl_pos.y+= y_shift; | | |
| | | |
| | | |
| /* | | |
| * Swap cell arrays then zero out the old cells to avoid another big memcopy | | |
| */ | | |
| tmpcells= map->cells; | | |
| map->cells= tmpmap.cells; | | |
| tmpmap.cells= tmpcells; | | |
| | | |
| memset( (char*)&tmpmap.cells[0][0], 0, | | |
| sizeof( struct MapCell) * tmpmap.x * tmpmap.y); | | |
| | | |
| return; | | |
| } | | } |
| | | |
| | | |
| void display_mapscroll(int dx,int dy) | | |
| { | | |
| int x,y; | | |
| int local_mapx= 0, local_mapy= 0; | | |
| | | |
| /* We don't need to memcopy any of this stuff around cause | | |
| * we are keeping it in memory. We do need to update our | | |
| * virtual position though | | |
| */ | | |
| | | |
| if( need_recenter_map( dx, dy) == TRUE) | | |
| recenter_virtual_map_view( &the_map); | | |
| | | |
| pl_pos.x+= dx; | | |
| pl_pos.y+= dy; | | |
| local_mapx= pl_pos.x + use_config[CONFIG_MAPWIDTH]; | | |
| local_mapy= pl_pos.y + use_config[CONFIG_MAPHEIGHT]; | | |
| | | |
| /* | | |
| * For cells about to enter the view, mark them as | | |
| * needing an update. Cells that are already in | | |
| * view don't need to be updated since we just memcpy | | |
| * the image data around. This is needed for proper | | |
| * drawing of blank or black tiles coming into view | | |
| */ | | |
| for( x= pl_pos.x; x < pl_pos.x + use_config[CONFIG_MAPWIDTH]; x++) { | | |
| for( y= pl_pos.y; y < pl_pos.y + use_config[CONFIG_MAPHEIGHT]; y++) { | | |
| the_map.cells[x][y].need_update= 1; | | |
| if( (x + dx) < pl_pos.x || (x + dx) >= (use_config[CONFIG_MAPWIDTH] + pl_pos.x) || | | |
| (y + dy) < pl_pos.y || (y + dy) >= (use_config[CONFIG_MAPHEIGHT] + pl_pos.y) ) | | |
| { | | |
| if( x < 0 || y < 0 || x >= the_map.x || y >= the_map.y) | | |
| continue; | | |
| | | |
| the_map.cells[x][y].cleared= 1; | | |
| the_map.cells[x][y].need_update= 1; | | |
| the_map.cells[x][y].keephead = 1;/*otherwise we will also mark the multipart as cleared*/ | | |
| } | | |
| } /* for y */ | | |
| } /* for x */ | | |
| | | |
| } | | |
| | | |
| | | |
| | | |
| /* | | |
| * Clears all map data - this is only called when we have lost our connection | | |
| * to a server - this way bogus data won't be around when we connect | | |
| * to the new server | | |
| */ | | |
| void reset_map_data() | | |
| { | | |
| int x= 0; | | |
| int y= 0; | | |
| | | |
| pl_pos.x= the_map.x/2; | | |
| pl_pos.y= the_map.y/2; | | |
| memset( the_map.cells[0], 0, | | |
| sizeof( struct MapCell) * the_map.x * the_map.y); | | |
| for( x= pl_pos.x; x < (pl_pos.x + use_config[CONFIG_MAPWIDTH]); x++) | | |
| { | | |
| for( y= pl_pos.y; y < (pl_pos.y + use_config[CONFIG_MAPHEIGHT]); y++) | | |
| { | | |
| the_map.cells[x][y].need_update= 1; | | |
| } | | |
| } | | |
| } | | |
| | | |
| | | |
| /* x11 client doesn't do smoothing, so don't need to do anything with this */ | | /* x11 client doesn't do smoothing, so don't need to do anything with this */ |
| void addsmooth(uint16 face, uint16 smooth_face) | | void addsmooth(uint16 face, uint16 smooth_face) |
| { | | { |