1 | /* |
1 | /* |
2 | * static char *rcsid_map_c = |
2 | * static char *rcsid_map_c = |
3 | * "$Id: map.c,v 1.1.1.1 2006/02/03 07:11:37 root Exp $"; |
3 | * "$Id: map.c,v 1.1.1.2 2006/02/22 18:01:21 elmex 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 | |
… | |
… | |
207 | * Prints out debug-information about a map. |
207 | * Prints out debug-information about a map. |
208 | * Dumping these at llevError doesn't seem right, but is |
208 | * Dumping these at llevError doesn't seem right, but is |
209 | * necessary to make sure the information is in fact logged. |
209 | * necessary to make sure the information is in fact logged. |
210 | */ |
210 | */ |
211 | |
211 | |
212 | void dump_map(mapstruct *m) { |
212 | void dump_map(const mapstruct *m) { |
213 | LOG(llevError,"Map %s status: %d.\n",m->path,m->in_memory); |
213 | LOG(llevError,"Map %s status: %d.\n",m->path,m->in_memory); |
214 | LOG(llevError,"Size: %dx%d Start: %d,%d\n", |
214 | LOG(llevError,"Size: %dx%d Start: %d,%d\n", |
215 | MAP_WIDTH(m), MAP_HEIGHT(m), |
215 | MAP_WIDTH(m), MAP_HEIGHT(m), |
216 | MAP_ENTER_X(m), MAP_ENTER_Y(m)); |
216 | MAP_ENTER_X(m), MAP_ENTER_Y(m)); |
217 | |
217 | |
218 | if(m->msg!=NULL) |
218 | if(m->msg!=NULL) |
219 | LOG(llevError,"Message:\n%s",m->msg); |
219 | LOG(llevError,"Message:\n%s",m->msg); |
|
|
220 | |
|
|
221 | if(m->maplore!=NULL) |
|
|
222 | LOG(llevError,"Lore:\n%s",m->maplore); |
220 | |
223 | |
221 | if(m->tmpname!=NULL) |
224 | if(m->tmpname!=NULL) |
222 | LOG(llevError,"Tmpname: %s\n",m->tmpname); |
225 | LOG(llevError,"Tmpname: %s\n",m->tmpname); |
223 | |
226 | |
224 | LOG(llevError,"Difficulty: %d\n",m->difficulty); |
227 | LOG(llevError,"Difficulty: %d\n",m->difficulty); |
… | |
… | |
304 | * go further. Not true for players - all sorts of special |
307 | * go further. Not true for players - all sorts of special |
305 | * things we need to do for players. |
308 | * things we need to do for players. |
306 | */ |
309 | */ |
307 | if (ob->type != PLAYER && ! (mflags & P_IS_ALIVE) && (blocked==0)) return 0; |
310 | if (ob->type != PLAYER && ! (mflags & P_IS_ALIVE) && (blocked==0)) return 0; |
308 | |
311 | |
|
|
312 | /* if there isn't anytyhing alive on this space, and this space isn't |
|
|
313 | * otherwise blocked, we can return now. Only if there is a living |
|
|
314 | * creature do we need to investigate if it is part of this creature |
|
|
315 | * or another. Likewise, only if something is blocking us do we |
|
|
316 | * need to investigate if there is a special circumstance that would |
|
|
317 | * let the player through (inventory checkers for example) |
|
|
318 | */ |
|
|
319 | if (!(mflags & P_IS_ALIVE) && !OB_TYPE_MOVE_BLOCK(ob, blocked)) return 0; |
309 | |
320 | |
310 | if(ob->head != NULL) |
321 | if(ob->head != NULL) |
311 | ob=ob->head; |
322 | ob=ob->head; |
312 | |
323 | |
313 | /* We basically go through the stack of objects, and if there is |
324 | /* We basically go through the stack of objects, and if there is |
… | |
… | |
381 | * Note this used to be arch_blocked, but with new movement |
392 | * Note this used to be arch_blocked, but with new movement |
382 | * code, we need to have actual object to check its move_type |
393 | * code, we need to have actual object to check its move_type |
383 | * against the move_block values. |
394 | * against the move_block values. |
384 | */ |
395 | */ |
385 | |
396 | |
386 | int ob_blocked(object *ob,mapstruct *m,sint16 x,sint16 y) { |
397 | int ob_blocked(const object *ob,mapstruct *m,sint16 x,sint16 y) { |
387 | archetype *tmp; |
398 | archetype *tmp; |
388 | int flag; |
399 | int flag; |
389 | mapstruct *m1; |
400 | mapstruct *m1; |
390 | sint16 sx, sy; |
401 | sint16 sx, sy; |
391 | |
402 | |
… | |
… | |
401 | flag = get_map_flags(m, &m1, x+tmp->clone.x,y+tmp->clone.y, &sx, &sy); |
412 | flag = get_map_flags(m, &m1, x+tmp->clone.x,y+tmp->clone.y, &sx, &sy); |
402 | |
413 | |
403 | if (flag & P_OUT_OF_MAP) return P_OUT_OF_MAP; |
414 | if (flag & P_OUT_OF_MAP) return P_OUT_OF_MAP; |
404 | if (flag & P_IS_ALIVE) return P_IS_ALIVE; |
415 | if (flag & P_IS_ALIVE) return P_IS_ALIVE; |
405 | |
416 | |
|
|
417 | /* find_first_free_spot() calls this function. However, often |
|
|
418 | * ob doesn't have any move type (when used to place exits) |
|
|
419 | * so the AND operation in OB_TYPE_MOVE_BLOCK doesn't work. |
|
|
420 | */ |
|
|
421 | |
|
|
422 | if (ob->move_type == 0 && GET_MAP_MOVE_BLOCK(m1, sx, sy) != MOVE_ALL) continue; |
|
|
423 | |
406 | /* Note it is intentional that we check ob - the movement type of the |
424 | /* Note it is intentional that we check ob - the movement type of the |
407 | * head of the object should correspond for the entire object. |
425 | * head of the object should correspond for the entire object. |
408 | */ |
426 | */ |
409 | |
|
|
410 | if (OB_TYPE_MOVE_BLOCK(ob, GET_MAP_MOVE_BLOCK(m1, sx, sy))) |
427 | if (OB_TYPE_MOVE_BLOCK(ob, GET_MAP_MOVE_BLOCK(m1, sx, sy))) |
411 | return AB_NO_PASS; |
428 | return AB_NO_PASS; |
412 | |
429 | |
413 | } |
430 | } |
414 | return 0; |
431 | return 0; |
… | |
… | |
778 | * return 0 on success, 1 on failure. |
795 | * return 0 on success, 1 on failure. |
779 | */ |
796 | */ |
780 | |
797 | |
781 | static int load_map_header(FILE *fp, mapstruct *m) |
798 | static int load_map_header(FILE *fp, mapstruct *m) |
782 | { |
799 | { |
783 | char buf[HUGE_BUF], msgbuf[HUGE_BUF], *key=NULL, *value, *end; |
800 | char buf[HUGE_BUF], msgbuf[HUGE_BUF], maplorebuf[HUGE_BUF], *key=NULL, *value, *end; |
784 | int msgpos=0; |
801 | int msgpos=0; |
|
|
802 | int maplorepos=0; |
785 | |
803 | |
786 | while (fgets(buf, HUGE_BUF-1, fp)!=NULL) { |
804 | while (fgets(buf, HUGE_BUF-1, fp)!=NULL) { |
787 | buf[HUGE_BUF-1] = 0; |
805 | buf[HUGE_BUF-1] = 0; |
788 | key = buf; |
806 | key = buf; |
789 | while (isspace(*key)) key++; |
807 | while (isspace(*key)) key++; |
… | |
… | |
843 | * keep the empty message. Also, msgbuf contains garbage data |
861 | * keep the empty message. Also, msgbuf contains garbage data |
844 | * when msgpos is zero, so copying it results in crashes |
862 | * when msgpos is zero, so copying it results in crashes |
845 | */ |
863 | */ |
846 | if (msgpos != 0) |
864 | if (msgpos != 0) |
847 | m->msg = strdup_local(msgbuf); |
865 | m->msg = strdup_local(msgbuf); |
|
|
866 | } |
|
|
867 | else if (!strcmp(key,"maplore")) { |
|
|
868 | while (fgets(buf, HUGE_BUF-1, fp)!=NULL) { |
|
|
869 | if (!strcmp(buf,"endmaplore\n")) break; |
|
|
870 | else { |
|
|
871 | /* slightly more efficient than strcat */ |
|
|
872 | strcpy(maplorebuf+maplorepos, buf); |
|
|
873 | maplorepos += strlen(buf); |
|
|
874 | } |
|
|
875 | } |
|
|
876 | if (maplorepos != 0) |
|
|
877 | m->maplore = strdup_local(maplorebuf); |
848 | } |
878 | } |
849 | else if (!strcmp(key,"end")) { |
879 | else if (!strcmp(key,"end")) { |
850 | break; |
880 | break; |
851 | } |
881 | } |
852 | else if (value == NULL) { |
882 | else if (value == NULL) { |
… | |
… | |
1259 | if (m->width) fprintf(fp,"width %d\n", m->width); |
1289 | if (m->width) fprintf(fp,"width %d\n", m->width); |
1260 | if (m->height) fprintf(fp,"height %d\n", m->height); |
1290 | if (m->height) fprintf(fp,"height %d\n", m->height); |
1261 | if (m->enter_x) fprintf(fp,"enter_x %d\n", m->enter_x); |
1291 | if (m->enter_x) fprintf(fp,"enter_x %d\n", m->enter_x); |
1262 | if (m->enter_y) fprintf(fp,"enter_y %d\n", m->enter_y); |
1292 | if (m->enter_y) fprintf(fp,"enter_y %d\n", m->enter_y); |
1263 | if (m->msg) fprintf(fp,"msg\n%sendmsg\n", m->msg); |
1293 | if (m->msg) fprintf(fp,"msg\n%sendmsg\n", m->msg); |
|
|
1294 | if (m->maplore) fprintf(fp,"maplore\n%sendmaplore\n", m->maplore); |
1264 | if (m->unique) fprintf(fp,"unique %d\n", m->unique); |
1295 | if (m->unique) fprintf(fp,"unique %d\n", m->unique); |
1265 | if (m->template) fprintf(fp,"template %d\n", m->template); |
1296 | if (m->template) fprintf(fp,"template %d\n", m->template); |
1266 | if (m->outdoor) fprintf(fp,"outdoor %d\n", m->outdoor); |
1297 | if (m->outdoor) fprintf(fp,"outdoor %d\n", m->outdoor); |
1267 | if (m->temp) fprintf(fp, "temp %d\n", m->temp); |
1298 | if (m->temp) fprintf(fp, "temp %d\n", m->temp); |
1268 | if (m->pressure) fprintf(fp, "pressure %d\n", m->pressure); |
1299 | if (m->pressure) fprintf(fp, "pressure %d\n", m->pressure); |
… | |
… | |
1395 | } |
1426 | } |
1396 | if (flag && m->spaces) free_all_objects(m); |
1427 | if (flag && m->spaces) free_all_objects(m); |
1397 | if (m->name) FREE_AND_CLEAR(m->name); |
1428 | if (m->name) FREE_AND_CLEAR(m->name); |
1398 | if (m->spaces) FREE_AND_CLEAR(m->spaces); |
1429 | if (m->spaces) FREE_AND_CLEAR(m->spaces); |
1399 | if (m->msg) FREE_AND_CLEAR(m->msg); |
1430 | if (m->msg) FREE_AND_CLEAR(m->msg); |
|
|
1431 | if (m->maplore) FREE_AND_CLEAR(m->maplore); |
1400 | if (m->shopitems) FREE_AND_CLEAR(m->shopitems); |
1432 | if (m->shopitems) FREE_AND_CLEAR(m->shopitems); |
1401 | if (m->shoprace) FREE_AND_CLEAR(m->shoprace); |
1433 | if (m->shoprace) FREE_AND_CLEAR(m->shoprace); |
1402 | if (m->buttons) |
1434 | if (m->buttons) |
1403 | free_objectlinkpt(m->buttons); |
1435 | free_objectlinkpt(m->buttons); |
1404 | m->buttons = NULL; |
1436 | m->buttons = NULL; |
… | |
… | |
1692 | void update_position (mapstruct *m, int x, int y) { |
1724 | void update_position (mapstruct *m, int x, int y) { |
1693 | object *tmp, *last = NULL; |
1725 | object *tmp, *last = NULL; |
1694 | uint8 flags = 0, oldflags, light=0, anywhere=0; |
1726 | uint8 flags = 0, oldflags, light=0, anywhere=0; |
1695 | New_Face *top,*floor, *middle; |
1727 | New_Face *top,*floor, *middle; |
1696 | object *top_obj, *floor_obj, *middle_obj; |
1728 | object *top_obj, *floor_obj, *middle_obj; |
1697 | MoveType move_block=0, move_slow=0, move_on=0, move_off=0; |
1729 | MoveType move_block=0, move_slow=0, move_on=0, move_off=0, move_allow=0; |
1698 | |
1730 | |
1699 | oldflags = GET_MAP_FLAGS(m,x,y); |
1731 | oldflags = GET_MAP_FLAGS(m,x,y); |
1700 | if (!(oldflags & P_NEED_UPDATE)) { |
1732 | if (!(oldflags & P_NEED_UPDATE)) { |
1701 | LOG(llevDebug,"update_position called with P_NEED_UPDATE not set: %s (%d, %d)\n", |
1733 | LOG(llevDebug,"update_position called with P_NEED_UPDATE not set: %s (%d, %d)\n", |
1702 | m->path, x, y); |
1734 | m->path, x, y); |
… | |
… | |
1765 | |
1797 | |
1766 | move_slow |= tmp->move_slow; |
1798 | move_slow |= tmp->move_slow; |
1767 | move_block |= tmp->move_block; |
1799 | move_block |= tmp->move_block; |
1768 | move_on |= tmp->move_on; |
1800 | move_on |= tmp->move_on; |
1769 | move_off |= tmp->move_off; |
1801 | move_off |= tmp->move_off; |
|
|
1802 | move_allow |= tmp->move_allow; |
1770 | |
1803 | |
1771 | if (QUERY_FLAG(tmp,FLAG_ALIVE)) |
1804 | if (QUERY_FLAG(tmp,FLAG_ALIVE)) |
1772 | flags |= P_IS_ALIVE; |
1805 | flags |= P_IS_ALIVE; |
1773 | if (QUERY_FLAG(tmp,FLAG_NO_MAGIC)) |
1806 | if (QUERY_FLAG(tmp,FLAG_NO_MAGIC)) |
1774 | flags |= P_NO_MAGIC; |
1807 | flags |= P_NO_MAGIC; |
… | |
… | |
1788 | LOG(llevDebug,"update_position: updated flags do not match old flags: %s (old=%d,new=%d) %x != %x\n", |
1821 | LOG(llevDebug,"update_position: updated flags do not match old flags: %s (old=%d,new=%d) %x != %x\n", |
1789 | m->path, x, y, |
1822 | m->path, x, y, |
1790 | (oldflags & ~P_NEED_UPDATE), flags); |
1823 | (oldflags & ~P_NEED_UPDATE), flags); |
1791 | } |
1824 | } |
1792 | SET_MAP_FLAGS(m, x, y, flags); |
1825 | SET_MAP_FLAGS(m, x, y, flags); |
1793 | SET_MAP_MOVE_BLOCK(m, x, y, move_block); |
1826 | SET_MAP_MOVE_BLOCK(m, x, y, move_block & ~move_allow); |
1794 | SET_MAP_MOVE_ON(m, x, y, move_on); |
1827 | SET_MAP_MOVE_ON(m, x, y, move_on); |
1795 | SET_MAP_MOVE_OFF(m, x, y, move_off); |
1828 | SET_MAP_MOVE_OFF(m, x, y, move_off); |
1796 | SET_MAP_MOVE_SLOW(m, x, y, move_slow); |
1829 | SET_MAP_MOVE_SLOW(m, x, y, move_slow); |
1797 | |
1830 | |
1798 | /* At this point, we have a floor face (if there is a floor), |
1831 | /* At this point, we have a floor face (if there is a floor), |
… | |
… | |
2008 | return (get_map_from_coord(m->tile_map[2], x, y)); |
2041 | return (get_map_from_coord(m->tile_map[2], x, y)); |
2009 | } |
2042 | } |
2010 | return NULL; /* Shouldn't get here */ |
2043 | return NULL; /* Shouldn't get here */ |
2011 | } |
2044 | } |
2012 | |
2045 | |
|
|
2046 | /** |
|
|
2047 | * Return whether map2 is adjacent to map1. If so, store the distance from |
|
|
2048 | * map1 to map2 in dx/dy. |
|
|
2049 | */ |
|
|
2050 | static int adjacent_map(const mapstruct *map1, const mapstruct *map2, int *dx, int *dy) { |
|
|
2051 | if (!map1 || !map2) |
|
|
2052 | return 0; |
|
|
2053 | |
|
|
2054 | if (map1 == map2) { |
|
|
2055 | *dx = 0; |
|
|
2056 | *dy = 0; |
|
|
2057 | |
|
|
2058 | } else if (map1->tile_map[0] == map2) { /* up */ |
|
|
2059 | *dx = 0; |
|
|
2060 | *dy = -MAP_HEIGHT(map2); |
|
|
2061 | } else if (map1->tile_map[1] == map2) { /* right */ |
|
|
2062 | *dx = MAP_WIDTH(map1); |
|
|
2063 | *dy = 0; |
|
|
2064 | } else if (map1->tile_map[2] == map2) { /* down */ |
|
|
2065 | *dx = 0; |
|
|
2066 | *dy = MAP_HEIGHT(map1); |
|
|
2067 | } else if (map1->tile_map[3] == map2) { /* left */ |
|
|
2068 | *dx = -MAP_WIDTH(map2); |
|
|
2069 | *dy = 0; |
|
|
2070 | |
|
|
2071 | } else if (map1->tile_map[0] && map1->tile_map[0]->tile_map[1] == map2) { /* up right */ |
|
|
2072 | *dx = MAP_WIDTH(map1->tile_map[0]); |
|
|
2073 | *dy = -MAP_HEIGHT(map1->tile_map[0]); |
|
|
2074 | } else if (map1->tile_map[0] && map1->tile_map[0]->tile_map[3] == map2) { /* up left */ |
|
|
2075 | *dx = -MAP_WIDTH(map2); |
|
|
2076 | *dy = -MAP_HEIGHT(map1->tile_map[0]); |
|
|
2077 | } else if (map1->tile_map[1] && map1->tile_map[1]->tile_map[0] == map2) { /* right up */ |
|
|
2078 | *dx = MAP_WIDTH(map1); |
|
|
2079 | *dy = -MAP_HEIGHT(map2); |
|
|
2080 | } else if (map1->tile_map[1] && map1->tile_map[1]->tile_map[2] == map2) { /* right down */ |
|
|
2081 | *dx = MAP_WIDTH(map1); |
|
|
2082 | *dy = MAP_HEIGHT(map1->tile_map[1]); |
|
|
2083 | } else if (map1->tile_map[2] && map1->tile_map[2]->tile_map[1] == map2) { /* down right */ |
|
|
2084 | *dx = MAP_WIDTH(map1->tile_map[2]); |
|
|
2085 | *dy = MAP_HEIGHT(map1); |
|
|
2086 | } else if (map1->tile_map[2] && map1->tile_map[2]->tile_map[3] == map2) { /* down left */ |
|
|
2087 | *dx = -MAP_WIDTH(map2); |
|
|
2088 | *dy = MAP_HEIGHT(map1); |
|
|
2089 | } else if (map1->tile_map[3] && map1->tile_map[3]->tile_map[0] == map2) { /* left up */ |
|
|
2090 | *dx = -MAP_WIDTH(map1->tile_map[3]); |
|
|
2091 | *dy = -MAP_HEIGHT(map2); |
|
|
2092 | } else if (map1->tile_map[3] && map1->tile_map[3]->tile_map[2] == map2) { /* left down */ |
|
|
2093 | *dx = -MAP_WIDTH(map1->tile_map[3]); |
|
|
2094 | *dy = MAP_HEIGHT(map1->tile_map[3]); |
|
|
2095 | |
|
|
2096 | } else { /* not "adjacent" enough */ |
|
|
2097 | return 0; |
|
|
2098 | } |
|
|
2099 | |
|
|
2100 | return 1; |
|
|
2101 | } |
|
|
2102 | |
2013 | /* From map.c |
2103 | /* From map.c |
2014 | * This is used by get_player to determine where the other |
2104 | * This is used by get_player to determine where the other |
2015 | * creature is. get_rangevector takes into account map tiling, |
2105 | * creature is. get_rangevector takes into account map tiling, |
2016 | * so you just can not look the the map coordinates and get the |
2106 | * so you just can not look the the map coordinates and get the |
2017 | * righte value. distance_x/y are distance away, which |
2107 | * righte value. distance_x/y are distance away, which |
… | |
… | |
2029 | * |
2119 | * |
2030 | * currently, the only flag supported (0x1) is don't translate for |
2120 | * currently, the only flag supported (0x1) is don't translate for |
2031 | * closest body part of 'op1' |
2121 | * closest body part of 'op1' |
2032 | */ |
2122 | */ |
2033 | |
2123 | |
2034 | void get_rangevector(object *op1, object *op2, rv_vector *retval, int flags) |
2124 | void get_rangevector(object *op1, object *op2, rv_vector *retval, int flags) { |
2035 | { |
2125 | if (!adjacent_map(op1->map, op2->map, &retval->distance_x, &retval->distance_y)) { |
|
|
2126 | /* be conservative and fill in _some_ data */ |
|
|
2127 | retval->distance = 100000; |
|
|
2128 | retval->distance_x = 32767; |
|
|
2129 | retval->distance_y = 32767; |
|
|
2130 | retval->direction = 0; |
|
|
2131 | retval->part = 0; |
|
|
2132 | } else { |
2036 | object *best; |
2133 | object *best; |
2037 | |
2134 | |
2038 | if (op1->map->tile_map[0] == op2->map) { |
|
|
2039 | retval->distance_x = op2->x - op1->x; |
2135 | 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; |
2136 | 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 | |
2137 | |
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; |
2138 | best = op1; |
2062 | /* If this is multipart, find the closest part now */ |
2139 | /* If this is multipart, find the closest part now */ |
2063 | if (!(flags & 0x1) && op1->more) { |
2140 | if (!(flags&0x1) && op1->more) { |
2064 | object *tmp; |
2141 | object *tmp; |
2065 | int best_distance = retval->distance_x * retval->distance_x + |
2142 | int best_distance = retval->distance_x*retval->distance_x+ |
2066 | retval->distance_y * retval->distance_y, tmpi; |
2143 | retval->distance_y*retval->distance_y, tmpi; |
2067 | |
2144 | |
2068 | /* we just tkae the offset of the piece to head to figure |
2145 | /* we just take the offset of the piece to head to figure |
2069 | * distance instead of doing all that work above again |
2146 | * distance instead of doing all that work above again |
2070 | * since the distance fields we set above are positive in the |
2147 | * since the distance fields we set above are positive in the |
2071 | * same axis as is used for multipart objects, the simply arithemetic |
2148 | * same axis as is used for multipart objects, the simply arithmetic |
2072 | * below works. |
2149 | * below works. |
2073 | */ |
2150 | */ |
2074 | for (tmp=op1->more; tmp; tmp=tmp->more) { |
2151 | for (tmp = op1->more; tmp != NULL; tmp = tmp->more) { |
2075 | tmpi = (op1->x - tmp->x + retval->distance_x) * (op1->x - tmp->x + retval->distance_x) + |
2152 | 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); |
2153 | (op1->y-tmp->y+retval->distance_y)*(op1->y-tmp->y+retval->distance_y); |
2077 | if (tmpi < best_distance) { |
2154 | if (tmpi < best_distance) { |
2078 | best_distance = tmpi; |
2155 | best_distance = tmpi; |
2079 | best = tmp; |
2156 | best = tmp; |
2080 | } |
2157 | } |
2081 | } |
2158 | } |
2082 | if (best != op1) { |
2159 | if (best != op1) { |
2083 | retval->distance_x += op1->x - best->x; |
2160 | retval->distance_x += op1->x-best->x; |
2084 | retval->distance_y += op1->y - best->y; |
2161 | retval->distance_y += op1->y-best->y; |
2085 | } |
2162 | } |
2086 | } |
2163 | } |
2087 | retval->part = best; |
2164 | retval->part = best; |
2088 | retval->distance = isqrt(retval->distance_x*retval->distance_x + retval->distance_y*retval->distance_y); |
2165 | 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); |
2166 | retval->direction = find_dir_2(-retval->distance_x, -retval->distance_y); |
|
|
2167 | } |
2090 | } |
2168 | } |
2091 | |
2169 | |
2092 | /* this is basically the same as get_rangevector above, but instead of |
2170 | /* this is basically the same as get_rangevector above, but instead of |
2093 | * the first parameter being an object, it instead is the map |
2171 | * the first parameter being an object, it instead is the map |
2094 | * and x,y coordinates - this is used for path to player - |
2172 | * and x,y coordinates - this is used for path to player - |
… | |
… | |
2098 | * be more consistant with the above function and also in case they are needed |
2176 | * be more consistant with the above function and also in case they are needed |
2099 | * for something in the future. Also, since no object is pasted, the best |
2177 | * for something in the future. Also, since no object is pasted, the best |
2100 | * field of the rv_vector is set to NULL. |
2178 | * field of the rv_vector is set to NULL. |
2101 | */ |
2179 | */ |
2102 | |
2180 | |
2103 | void get_rangevector_from_mapcoord(mapstruct *m, int x, int y, object *op2, rv_vector *retval,int flags) |
2181 | void get_rangevector_from_mapcoord(const mapstruct *m, int x, int y, const object *op2, rv_vector *retval, int flags) { |
2104 | { |
2182 | if (!adjacent_map(m, op2->map, &retval->distance_x, &retval->distance_y)) { |
2105 | if (m->tile_map[0] == op2->map) { |
2183 | /* be conservative and fill in _some_ data */ |
|
|
2184 | retval->distance = 100000; |
|
|
2185 | retval->distance_x = 32767; |
|
|
2186 | retval->distance_y = 32767; |
|
|
2187 | retval->direction = 0; |
|
|
2188 | retval->part = 0; |
|
|
2189 | } else { |
2106 | retval->distance_x = op2->x - x; |
2190 | 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; |
2191 | 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 | |
2192 | |
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; |
2193 | retval->part = NULL; |
2129 | retval->distance = isqrt(retval->distance_x*retval->distance_x + retval->distance_y*retval->distance_y); |
2194 | 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); |
2195 | retval->direction = find_dir_2(-retval->distance_x, -retval->distance_y); |
|
|
2196 | } |
2131 | } |
2197 | } |
2132 | |
2198 | |
2133 | /* Returns true of op1 and op2 are effectively on the same map |
2199 | /* 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 |
2200 | * (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 |
2201 | * op1 to op2, so if the tiled maps are assymetric and op2 has a path |
2136 | * to op1, this will still return false. |
2202 | * to op1, this will still return false. |
2137 | * Note we only look one map out to keep the processing simple |
2203 | * Note we only look one map out to keep the processing simple |
2138 | * and efficient. This could probably be a macro. |
2204 | * and efficient. This could probably be a macro. |
2139 | * MSW 2001-08-05 |
2205 | * MSW 2001-08-05 |
2140 | */ |
2206 | */ |
2141 | int on_same_map(object *op1, object *op2) |
2207 | int on_same_map(const object *op1, const object *op2) { |
2142 | { |
2208 | int dx, dy; |
2143 | mapstruct *tmp; |
|
|
2144 | |
2209 | |
2145 | /* If the object isn't on a map, can't be on the same map, now can it? |
2210 | 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 | } |
2211 | } |