1 | /* |
1 | /* |
2 | * static char *rcsid_map_c = |
2 | * static char *rcsid_map_c = |
3 | * "$Id: map.c,v 1.1 2006/02/03 07:11:37 root Exp $"; |
3 | * "$Id: map.c,v 1.2 2006/02/08 03:46:15 root Exp $"; |
4 | */ |
4 | */ |
5 | |
5 | |
6 | /* |
6 | /* |
7 | CrossFire, A Multiplayer game for X-windows |
7 | CrossFire, A Multiplayer game for X-windows |
8 | |
8 | |
… | |
… | |
2008 | return (get_map_from_coord(m->tile_map[2], x, y)); |
2008 | return (get_map_from_coord(m->tile_map[2], x, y)); |
2009 | } |
2009 | } |
2010 | return NULL; /* Shouldn't get here */ |
2010 | return NULL; /* Shouldn't get here */ |
2011 | } |
2011 | } |
2012 | |
2012 | |
|
|
2013 | // return wether map2 is adjacent to map1 and store their distance |
|
|
2014 | // in dx/dy if yes. |
|
|
2015 | static int adjacent_map (mapstruct *map1, mapstruct *map2, int *dx, int *dy) |
|
|
2016 | { |
|
|
2017 | if (!map1 || !map2) |
|
|
2018 | return 0; |
|
|
2019 | |
|
|
2020 | else if (map1 == map2) |
|
|
2021 | *dx = *dy = 0; |
|
|
2022 | |
|
|
2023 | else if (map1->tile_map[0] == map2) // up |
|
|
2024 | (*dx = 0), (*dy = -MAP_HEIGHT (map2)); |
|
|
2025 | else if (map1->tile_map[1] == map2) // right |
|
|
2026 | (*dx = MAP_WIDTH (map2)), (*dy = 0); |
|
|
2027 | else if (map1->tile_map[2] == map2) // down |
|
|
2028 | (*dx = 0), (*dy = MAP_HEIGHT (map2)); |
|
|
2029 | else if (map1->tile_map[3] == map2) // left |
|
|
2030 | (*dx = -MAP_WIDTH (map2)), (*dy = 0); |
|
|
2031 | |
|
|
2032 | else if (map1->tile_map[0] && map1->tile_map[0]->tile_map[1] == map2) // up right |
|
|
2033 | (*dx = MAP_WIDTH (map2)), (*dy = -MAP_HEIGHT (map1->tile_map[0])); |
|
|
2034 | else if (map1->tile_map[0] && map1->tile_map[0]->tile_map[3] == map2) // up left |
|
|
2035 | (*dx = -MAP_WIDTH (map2)), (*dy = -MAP_HEIGHT (map1->tile_map[0])); |
|
|
2036 | else if (map1->tile_map[1] && map1->tile_map[1]->tile_map[0] == map2) // right up |
|
|
2037 | (*dx = MAP_HEIGHT (map1->tile_map[1])), (*dy = -MAP_WIDTH (map2)); |
|
|
2038 | else if (map1->tile_map[1] && map1->tile_map[1]->tile_map[2] == map2) // right down |
|
|
2039 | (*dx = MAP_HEIGHT (map1->tile_map[1])), (*dy = MAP_WIDTH (map2)); |
|
|
2040 | else if (map1->tile_map[2] && map1->tile_map[2]->tile_map[1] == map2) // down right |
|
|
2041 | (*dx = MAP_WIDTH (map2)), (*dy = MAP_HEIGHT (map1->tile_map[2])); |
|
|
2042 | else if (map1->tile_map[2] && map1->tile_map[2]->tile_map[3] == map2) // down left |
|
|
2043 | (*dx = -MAP_WIDTH (map2)), (*dy = MAP_HEIGHT (map1->tile_map[2])); |
|
|
2044 | else if (map1->tile_map[3] && map1->tile_map[3]->tile_map[0] == map2) // left up |
|
|
2045 | (*dx = -MAP_HEIGHT (map1->tile_map[3])), (*dy = -MAP_WIDTH (map2)); |
|
|
2046 | else if (map1->tile_map[3] && map1->tile_map[3]->tile_map[2] == map2) // left down |
|
|
2047 | (*dx = MAP_HEIGHT (map1->tile_map[3])), (*dy = MAP_WIDTH (map2)); |
|
|
2048 | |
|
|
2049 | else // not "adjacent" enough |
|
|
2050 | return 0; |
|
|
2051 | |
|
|
2052 | return 1; |
|
|
2053 | } |
|
|
2054 | |
2013 | /* From map.c |
2055 | /* From map.c |
2014 | * This is used by get_player to determine where the other |
2056 | * This is used by get_player to determine where the other |
2015 | * creature is. get_rangevector takes into account map tiling, |
2057 | * creature is. get_rangevector takes into account map tiling, |
2016 | * so you just can not look the the map coordinates and get the |
2058 | * so you just can not look the the map coordinates and get the |
2017 | * righte value. distance_x/y are distance away, which |
2059 | * righte value. distance_x/y are distance away, which |
… | |
… | |
2031 | * closest body part of 'op1' |
2073 | * closest body part of 'op1' |
2032 | */ |
2074 | */ |
2033 | |
2075 | |
2034 | void get_rangevector(object *op1, object *op2, rv_vector *retval, int flags) |
2076 | void get_rangevector(object *op1, object *op2, rv_vector *retval, int flags) |
2035 | { |
2077 | { |
|
|
2078 | if (!adjacent_map (op1->map, op2->map, &(retval->distance_x), &(retval->distance_y))) |
|
|
2079 | { |
|
|
2080 | // be conservative and fill in _some_ data |
|
|
2081 | retval->distance = 100000; |
|
|
2082 | retval->distance_x = 32767; |
|
|
2083 | retval->distance_y = 32767; |
|
|
2084 | retval->direction = 0; |
|
|
2085 | retval->part = 0; |
|
|
2086 | } |
|
|
2087 | else |
|
|
2088 | { |
2036 | object *best; |
2089 | object *best; |
2037 | |
2090 | |
2038 | if (op1->map->tile_map[0] == op2->map) { |
|
|
2039 | retval->distance_x = op2->x - op1->x; |
2091 | retval->distance_x += op2->x - op1->x; |
2040 | retval->distance_y = -(op1->y +(MAP_HEIGHT(op2->map)- op2->y)); |
|
|
2041 | |
|
|
2042 | } |
|
|
2043 | else if (op1->map->tile_map[1] == op2->map) { |
|
|
2044 | retval->distance_y = op2->y - op1->y; |
2092 | retval->distance_y += op2->y - op1->y; |
2045 | retval->distance_x = (MAP_WIDTH(op1->map) - op1->x) + op2->x; |
|
|
2046 | } |
|
|
2047 | else if (op1->map->tile_map[2] == op2->map) { |
|
|
2048 | retval->distance_x = op2->x - op1->x; |
|
|
2049 | retval->distance_y = (MAP_HEIGHT(op1->map) - op1->y) +op2->y; |
|
|
2050 | |
2093 | |
2051 | } |
|
|
2052 | else if (op1->map->tile_map[3] == op2->map) { |
|
|
2053 | retval->distance_y = op2->y - op1->y; |
|
|
2054 | retval->distance_x = -(op1->x +(MAP_WIDTH(op2->map)- op2->x)); |
|
|
2055 | } |
|
|
2056 | else if (op1->map == op2->map) { |
|
|
2057 | retval->distance_x = op2->x - op1->x; |
|
|
2058 | retval->distance_y = op2->y - op1->y; |
|
|
2059 | |
|
|
2060 | } |
|
|
2061 | best = op1; |
2094 | best = op1; |
2062 | /* If this is multipart, find the closest part now */ |
2095 | /* If this is multipart, find the closest part now */ |
2063 | if (!(flags & 0x1) && op1->more) { |
2096 | if (!(flags & 0x1) && op1->more) { |
2064 | object *tmp; |
2097 | object *tmp; |
2065 | int best_distance = retval->distance_x * retval->distance_x + |
2098 | int best_distance = retval->distance_x * retval->distance_x + |
2066 | retval->distance_y * retval->distance_y, tmpi; |
2099 | retval->distance_y * retval->distance_y, tmpi; |
2067 | |
2100 | |
2068 | /* we just tkae the offset of the piece to head to figure |
2101 | /* we just tkae the offset of the piece to head to figure |
2069 | * distance instead of doing all that work above again |
2102 | * distance instead of doing all that work above again |
2070 | * since the distance fields we set above are positive in the |
2103 | * since the distance fields we set above are positive in the |
2071 | * same axis as is used for multipart objects, the simply arithemetic |
2104 | * same axis as is used for multipart objects, the simply arithemetic |
2072 | * below works. |
2105 | * below works. |
2073 | */ |
2106 | */ |
2074 | for (tmp=op1->more; tmp; tmp=tmp->more) { |
2107 | for (tmp=op1->more; tmp; tmp=tmp->more) { |
2075 | tmpi = (op1->x - tmp->x + retval->distance_x) * (op1->x - tmp->x + retval->distance_x) + |
2108 | tmpi = (op1->x - tmp->x + retval->distance_x) * (op1->x - tmp->x + retval->distance_x) + |
2076 | (op1->y - tmp->y + retval->distance_y) * (op1->y - tmp->y + retval->distance_y); |
2109 | (op1->y - tmp->y + retval->distance_y) * (op1->y - tmp->y + retval->distance_y); |
2077 | if (tmpi < best_distance) { |
2110 | if (tmpi < best_distance) { |
2078 | best_distance = tmpi; |
2111 | best_distance = tmpi; |
2079 | best = tmp; |
2112 | best = tmp; |
2080 | } |
2113 | } |
2081 | } |
2114 | } |
2082 | if (best != op1) { |
2115 | if (best != op1) { |
2083 | retval->distance_x += op1->x - best->x; |
2116 | retval->distance_x += op1->x - best->x; |
2084 | retval->distance_y += op1->y - best->y; |
2117 | retval->distance_y += op1->y - best->y; |
2085 | } |
2118 | } |
2086 | } |
2119 | } |
2087 | retval->part = best; |
2120 | retval->part = best; |
2088 | retval->distance = isqrt(retval->distance_x*retval->distance_x + retval->distance_y*retval->distance_y); |
2121 | retval->distance = isqrt(retval->distance_x*retval->distance_x + retval->distance_y*retval->distance_y); |
2089 | retval->direction = find_dir_2(-retval->distance_x, -retval->distance_y); |
2122 | retval->direction = find_dir_2(-retval->distance_x, -retval->distance_y); |
|
|
2123 | } |
2090 | } |
2124 | } |
2091 | |
2125 | |
2092 | /* this is basically the same as get_rangevector above, but instead of |
2126 | /* this is basically the same as get_rangevector above, but instead of |
2093 | * the first parameter being an object, it instead is the map |
2127 | * the first parameter being an object, it instead is the map |
2094 | * and x,y coordinates - this is used for path to player - |
2128 | * and x,y coordinates - this is used for path to player - |
… | |
… | |
2100 | * field of the rv_vector is set to NULL. |
2134 | * field of the rv_vector is set to NULL. |
2101 | */ |
2135 | */ |
2102 | |
2136 | |
2103 | void get_rangevector_from_mapcoord(mapstruct *m, int x, int y, object *op2, rv_vector *retval,int flags) |
2137 | void get_rangevector_from_mapcoord(mapstruct *m, int x, int y, object *op2, rv_vector *retval,int flags) |
2104 | { |
2138 | { |
2105 | if (m->tile_map[0] == op2->map) { |
2139 | if (!adjacent_map (m, op2->map, &(retval->distance_x), &(retval->distance_y))) |
|
|
2140 | { |
|
|
2141 | // be conservative and fill in _some_ data |
|
|
2142 | retval->distance = 100000; |
|
|
2143 | retval->distance_x = 32767; |
|
|
2144 | retval->distance_y = 32767; |
|
|
2145 | retval->direction = 0; |
|
|
2146 | retval->part = 0; |
|
|
2147 | } |
|
|
2148 | else |
|
|
2149 | { |
2106 | retval->distance_x = op2->x - x; |
2150 | retval->distance_x += op2->x - x; |
2107 | retval->distance_y = -(y +(MAP_HEIGHT(op2->map)- op2->y)); |
|
|
2108 | |
|
|
2109 | } |
|
|
2110 | else if (m->tile_map[1] == op2->map) { |
|
|
2111 | retval->distance_y = op2->y - y; |
2151 | retval->distance_y += op2->y - y; |
2112 | retval->distance_x = (MAP_WIDTH(m) - x) + op2->x; |
|
|
2113 | } |
|
|
2114 | else if (m->tile_map[2] == op2->map) { |
|
|
2115 | retval->distance_x = op2->x - x; |
|
|
2116 | retval->distance_y = (MAP_HEIGHT(m) - y) +op2->y; |
|
|
2117 | |
2152 | |
2118 | } |
|
|
2119 | else if (m->tile_map[3] == op2->map) { |
|
|
2120 | retval->distance_y = op2->y - y; |
|
|
2121 | retval->distance_x = -(x +(MAP_WIDTH(op2->map)- op2->y)); |
|
|
2122 | } |
|
|
2123 | else if (m == op2->map) { |
|
|
2124 | retval->distance_x = op2->x - x; |
|
|
2125 | retval->distance_y = op2->y - y; |
|
|
2126 | |
|
|
2127 | } |
|
|
2128 | retval->part = NULL; |
2153 | retval->part = NULL; |
2129 | retval->distance = isqrt(retval->distance_x*retval->distance_x + retval->distance_y*retval->distance_y); |
2154 | retval->distance = isqrt(retval->distance_x*retval->distance_x + retval->distance_y*retval->distance_y); |
2130 | retval->direction = find_dir_2(-retval->distance_x, -retval->distance_y); |
2155 | retval->direction = find_dir_2(-retval->distance_x, -retval->distance_y); |
|
|
2156 | } |
2131 | } |
2157 | } |
2132 | |
2158 | |
2133 | /* Returns true of op1 and op2 are effectively on the same map |
2159 | /* Returns true of op1 and op2 are effectively on the same map |
2134 | * (as related to map tiling). Note that this looks for a path from |
2160 | * (as related to map tiling). Note that this looks for a path from |
2135 | * op1 to op2, so if the tiled maps are assymetric and op2 has a path |
2161 | * op1 to op2, so if the tiled maps are assymetric and op2 has a path |
… | |
… | |
2138 | * and efficient. This could probably be a macro. |
2164 | * and efficient. This could probably be a macro. |
2139 | * MSW 2001-08-05 |
2165 | * MSW 2001-08-05 |
2140 | */ |
2166 | */ |
2141 | int on_same_map(object *op1, object *op2) |
2167 | int on_same_map(object *op1, object *op2) |
2142 | { |
2168 | { |
2143 | mapstruct *tmp; |
2169 | int dx, dy; |
2144 | |
2170 | |
2145 | /* If the object isn't on a map, can't be on the same map, now can it? |
2171 | return adjacent_map (op1->map, op2->map, &dx, &dy); |
2146 | * this check also prevents crashes below. |
|
|
2147 | */ |
|
|
2148 | if (op1->map == NULL || op2->map == NULL) return FALSE; |
|
|
2149 | |
|
|
2150 | /* on same map? */ |
|
|
2151 | if (op1->map == op2->map) return TRUE; |
|
|
2152 | |
|
|
2153 | /* on adjacent map? */ |
|
|
2154 | if (op1->map->tile_map[0] == op2->map) return TRUE; |
|
|
2155 | if (op1->map->tile_map[1] == op2->map) return TRUE; |
|
|
2156 | if (op1->map->tile_map[2] == op2->map) return TRUE; |
|
|
2157 | if (op1->map->tile_map[3] == op2->map) return TRUE; |
|
|
2158 | |
|
|
2159 | /* on diagonally adjacent map? */ |
|
|
2160 | tmp = op1->map->tile_map[0]; |
|
|
2161 | if (tmp != NULL) { |
|
|
2162 | if (tmp->tile_map[1] == op2->map || tmp->tile_map[3] == op2->map) return TRUE; |
|
|
2163 | } |
|
|
2164 | |
|
|
2165 | tmp = op1->map->tile_map[1]; |
|
|
2166 | if (tmp != NULL) { |
|
|
2167 | if (tmp->tile_map[0] == op2->map || tmp->tile_map[2] == op2->map) return TRUE; |
|
|
2168 | } |
|
|
2169 | |
|
|
2170 | tmp = op1->map->tile_map[2]; |
|
|
2171 | if (tmp != NULL) { |
|
|
2172 | if (tmp->tile_map[1] == op2->map || tmp->tile_map[3] == op2->map) return TRUE; |
|
|
2173 | } |
|
|
2174 | |
|
|
2175 | tmp = op1->map->tile_map[3]; |
|
|
2176 | if (tmp != NULL) { |
|
|
2177 | if (tmp->tile_map[0] == op2->map || tmp->tile_map[2] == op2->map) return TRUE; |
|
|
2178 | } |
|
|
2179 | |
|
|
2180 | return FALSE; |
|
|
2181 | } |
2172 | } |