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

Comparing deliantra/server/common/map.c (file contents):
Revision 1.1 by root, Fri Feb 3 07:11:37 2006 UTC vs.
Revision 1.3 by root, Tue Feb 21 11:00:07 2006 UTC

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.3 2006/02/21 11:00:07 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
1918 * case. This generally shouldn't happen, but if the 1918 * case. This generally shouldn't happen, but if the
1919 * map loads fail below, it could happen. 1919 * map loads fail below, it could happen.
1920 */ 1920 */
1921 if (!m) return 0; 1921 if (!m) return 0;
1922 1922
1923 /* Simple case - coordinates are within this local
1924 * map.
1925 */
1926 if ( x>=0 && x<MAP_WIDTH(m) && y>=0 && y < MAP_HEIGHT(m))
1927 return 0;
1928
1929 if (x<0) { 1923 if (x<0) {
1930 if (!m->tile_path[3]) return 1; 1924 if (!m->tile_path[3]) return 1;
1931 if (!m->tile_map[3] || m->tile_map[3]->in_memory != MAP_IN_MEMORY) { 1925 if (!m->tile_map[3] || m->tile_map[3]->in_memory != MAP_IN_MEMORY) {
1932 load_and_link_tiled_map(m, 3); 1926 load_and_link_tiled_map(m, 3);
1933 } 1927 }
1952 if (!m->tile_map[2] || m->tile_map[2]->in_memory != MAP_IN_MEMORY) { 1946 if (!m->tile_map[2] || m->tile_map[2]->in_memory != MAP_IN_MEMORY) {
1953 load_and_link_tiled_map(m, 2); 1947 load_and_link_tiled_map(m, 2);
1954 } 1948 }
1955 return (out_of_map(m->tile_map[2], x, y - MAP_HEIGHT(m))); 1949 return (out_of_map(m->tile_map[2], x, y - MAP_HEIGHT(m)));
1956 } 1950 }
1951
1952 /* Simple case - coordinates are within this local
1953 * map.
1954 */
1957 return 1; 1955 return 0;
1958} 1956}
1959 1957
1960/* This is basically the same as out_of_map above, but 1958/* This is basically the same as out_of_map above, but
1961 * instead we return NULL if no map is valid (coordinates 1959 * instead we return NULL if no map is valid (coordinates
1962 * out of bounds and no tiled map), otherwise it returns 1960 * out of bounds and no tiled map), otherwise it returns
1966 * and then figuring out what the real map is 1964 * and then figuring out what the real map is
1967 */ 1965 */
1968mapstruct *get_map_from_coord(mapstruct *m, sint16 *x, sint16 *y) 1966mapstruct *get_map_from_coord(mapstruct *m, sint16 *x, sint16 *y)
1969{ 1967{
1970 1968
1971 /* Simple case - coordinates are within this local
1972 * map.
1973 */
1974
1975 if (*x>=0 && *x<MAP_WIDTH(m) && *y>=0 && *y < MAP_HEIGHT(m))
1976 return m;
1977
1978 if (*x<0) { 1969 if (*x<0) {
1979 if (!m->tile_path[3]) return NULL; 1970 if (!m->tile_path[3]) return NULL;
1980 if (!m->tile_map[3] || m->tile_map[3]->in_memory != MAP_IN_MEMORY) 1971 if (!m->tile_map[3] || m->tile_map[3]->in_memory != MAP_IN_MEMORY)
1981 load_and_link_tiled_map(m, 3); 1972 load_and_link_tiled_map(m, 3);
1982 1973
2005 load_and_link_tiled_map(m, 2); 1996 load_and_link_tiled_map(m, 2);
2006 1997
2007 *y -= MAP_HEIGHT(m); 1998 *y -= MAP_HEIGHT(m);
2008 return (get_map_from_coord(m->tile_map[2], x, y)); 1999 return (get_map_from_coord(m->tile_map[2], x, y));
2009 } 2000 }
2010 return NULL; /* Shouldn't get here */ 2001
2002 /* Simple case - coordinates are within this local
2003 * map.
2004 */
2005
2006 return m;
2007}
2008
2009// return wether map2 is adjacent to map1 and store their distance
2010// in dx/dy if yes.
2011static int adjacent_map (mapstruct *map1, mapstruct *map2, int *dx, int *dy)
2012{
2013 if (!map1 || !map2)
2014 return 0;
2015
2016 else if (map1 == map2)
2017 *dx = *dy = 0;
2018
2019 else if (map1->tile_map[0] == map2) // up
2020 (*dx = 0), (*dy = -MAP_HEIGHT (map2));
2021 else if (map1->tile_map[1] == map2) // right
2022 (*dx = MAP_WIDTH (map2)), (*dy = 0);
2023 else if (map1->tile_map[2] == map2) // down
2024 (*dx = 0), (*dy = MAP_HEIGHT (map2));
2025 else if (map1->tile_map[3] == map2) // left
2026 (*dx = -MAP_WIDTH (map2)), (*dy = 0);
2027
2028 else if (map1->tile_map[0] && map1->tile_map[0]->tile_map[1] == map2) // up right
2029 (*dx = MAP_WIDTH (map2)), (*dy = -MAP_HEIGHT (map1->tile_map[0]));
2030 else if (map1->tile_map[0] && map1->tile_map[0]->tile_map[3] == map2) // up left
2031 (*dx = -MAP_WIDTH (map2)), (*dy = -MAP_HEIGHT (map1->tile_map[0]));
2032 else if (map1->tile_map[1] && map1->tile_map[1]->tile_map[0] == map2) // right up
2033 (*dx = MAP_HEIGHT (map1->tile_map[1])), (*dy = -MAP_WIDTH (map2));
2034 else if (map1->tile_map[1] && map1->tile_map[1]->tile_map[2] == map2) // right down
2035 (*dx = MAP_HEIGHT (map1->tile_map[1])), (*dy = MAP_WIDTH (map2));
2036 else if (map1->tile_map[2] && map1->tile_map[2]->tile_map[1] == map2) // down right
2037 (*dx = MAP_WIDTH (map2)), (*dy = MAP_HEIGHT (map1->tile_map[2]));
2038 else if (map1->tile_map[2] && map1->tile_map[2]->tile_map[3] == map2) // down left
2039 (*dx = -MAP_WIDTH (map2)), (*dy = MAP_HEIGHT (map1->tile_map[2]));
2040 else if (map1->tile_map[3] && map1->tile_map[3]->tile_map[0] == map2) // left up
2041 (*dx = -MAP_HEIGHT (map1->tile_map[3])), (*dy = -MAP_WIDTH (map2));
2042 else if (map1->tile_map[3] && map1->tile_map[3]->tile_map[2] == map2) // left down
2043 (*dx = MAP_HEIGHT (map1->tile_map[3])), (*dy = MAP_WIDTH (map2));
2044
2045 else // not "adjacent" enough
2046 return 0;
2047
2048 return 1;
2011} 2049}
2012 2050
2013/* From map.c 2051/* From map.c
2014 * This is used by get_player to determine where the other 2052 * This is used by get_player to determine where the other
2015 * creature is. get_rangevector takes into account map tiling, 2053 * creature is. get_rangevector takes into account map tiling,
2031 * closest body part of 'op1' 2069 * closest body part of 'op1'
2032 */ 2070 */
2033 2071
2034void get_rangevector(object *op1, object *op2, rv_vector *retval, int flags) 2072void get_rangevector(object *op1, object *op2, rv_vector *retval, int flags)
2035{ 2073{
2074 if (!adjacent_map (op1->map, op2->map, &(retval->distance_x), &(retval->distance_y)))
2075 {
2076 // be conservative and fill in _some_ data
2077 retval->distance = 100000;
2078 retval->distance_x = 32767;
2079 retval->distance_y = 32767;
2080 retval->direction = 0;
2081 retval->part = 0;
2082 }
2083 else
2084 {
2036 object *best; 2085 object *best;
2037 2086
2038 if (op1->map->tile_map[0] == op2->map) {
2039 retval->distance_x = op2->x - op1->x; 2087 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; 2088 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 2089
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; 2090 best = op1;
2062 /* If this is multipart, find the closest part now */ 2091 /* If this is multipart, find the closest part now */
2063 if (!(flags & 0x1) && op1->more) { 2092 if (!(flags & 0x1) && op1->more) {
2064 object *tmp; 2093 object *tmp;
2065 int best_distance = retval->distance_x * retval->distance_x + 2094 int best_distance = retval->distance_x * retval->distance_x +
2066 retval->distance_y * retval->distance_y, tmpi; 2095 retval->distance_y * retval->distance_y, tmpi;
2067 2096
2068 /* we just tkae the offset of the piece to head to figure 2097 /* we just tkae the offset of the piece to head to figure
2069 * distance instead of doing all that work above again 2098 * distance instead of doing all that work above again
2070 * since the distance fields we set above are positive in the 2099 * since the distance fields we set above are positive in the
2071 * same axis as is used for multipart objects, the simply arithemetic 2100 * same axis as is used for multipart objects, the simply arithemetic
2072 * below works. 2101 * below works.
2073 */ 2102 */
2074 for (tmp=op1->more; tmp; tmp=tmp->more) { 2103 for (tmp=op1->more; tmp; tmp=tmp->more) {
2075 tmpi = (op1->x - tmp->x + retval->distance_x) * (op1->x - tmp->x + retval->distance_x) + 2104 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); 2105 (op1->y - tmp->y + retval->distance_y) * (op1->y - tmp->y + retval->distance_y);
2077 if (tmpi < best_distance) { 2106 if (tmpi < best_distance) {
2078 best_distance = tmpi; 2107 best_distance = tmpi;
2079 best = tmp; 2108 best = tmp;
2080 } 2109 }
2081 } 2110 }
2082 if (best != op1) { 2111 if (best != op1) {
2083 retval->distance_x += op1->x - best->x; 2112 retval->distance_x += op1->x - best->x;
2084 retval->distance_y += op1->y - best->y; 2113 retval->distance_y += op1->y - best->y;
2085 } 2114 }
2086 } 2115 }
2087 retval->part = best; 2116 retval->part = best;
2088 retval->distance = isqrt(retval->distance_x*retval->distance_x + retval->distance_y*retval->distance_y); 2117 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); 2118 retval->direction = find_dir_2(-retval->distance_x, -retval->distance_y);
2119 }
2090} 2120}
2091 2121
2092/* this is basically the same as get_rangevector above, but instead of 2122/* this is basically the same as get_rangevector above, but instead of
2093 * the first parameter being an object, it instead is the map 2123 * the first parameter being an object, it instead is the map
2094 * and x,y coordinates - this is used for path to player - 2124 * and x,y coordinates - this is used for path to player -
2100 * field of the rv_vector is set to NULL. 2130 * field of the rv_vector is set to NULL.
2101 */ 2131 */
2102 2132
2103void get_rangevector_from_mapcoord(mapstruct *m, int x, int y, object *op2, rv_vector *retval,int flags) 2133void get_rangevector_from_mapcoord(mapstruct *m, int x, int y, object *op2, rv_vector *retval,int flags)
2104{ 2134{
2105 if (m->tile_map[0] == op2->map) { 2135 if (!adjacent_map (m, op2->map, &(retval->distance_x), &(retval->distance_y)))
2136 {
2137 // be conservative and fill in _some_ data
2138 retval->distance = 100000;
2139 retval->distance_x = 32767;
2140 retval->distance_y = 32767;
2141 retval->direction = 0;
2142 retval->part = 0;
2143 }
2144 else
2145 {
2106 retval->distance_x = op2->x - x; 2146 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; 2147 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 2148
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; 2149 retval->part = NULL;
2129 retval->distance = isqrt(retval->distance_x*retval->distance_x + retval->distance_y*retval->distance_y); 2150 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); 2151 retval->direction = find_dir_2(-retval->distance_x, -retval->distance_y);
2152 }
2131} 2153}
2132 2154
2133/* Returns true of op1 and op2 are effectively on the same map 2155/* 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 2156 * (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 2157 * op1 to op2, so if the tiled maps are assymetric and op2 has a path
2138 * and efficient. This could probably be a macro. 2160 * and efficient. This could probably be a macro.
2139 * MSW 2001-08-05 2161 * MSW 2001-08-05
2140 */ 2162 */
2141int on_same_map(object *op1, object *op2) 2163int on_same_map(object *op1, object *op2)
2142{ 2164{
2143 mapstruct *tmp; 2165 int dx, dy;
2144 2166
2145 /* If the object isn't on a map, can't be on the same map, now can it? 2167 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} 2168}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines