1 | /* |
1 | /* |
2 | * static char *rcsid_map_c = |
2 | * static char *rcsid_map_c = |
3 | * "$Id: map.c,v 1.3 2006/02/21 11:00:07 root Exp $"; |
3 | * "$Id: map.c,v 1.5 2006/02/22 19:08:43 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 | |
… | |
… | |
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), |
… | |
… | |
2004 | */ |
2037 | */ |
2005 | |
2038 | |
2006 | return m; |
2039 | return m; |
2007 | } |
2040 | } |
2008 | |
2041 | |
|
|
2042 | /** |
2009 | // return wether map2 is adjacent to map1 and store their distance |
2043 | * Return whether map2 is adjacent to map1. If so, store the distance from |
2010 | // in dx/dy if yes. |
2044 | * map1 to map2 in dx/dy. |
|
|
2045 | */ |
2011 | static int adjacent_map (mapstruct *map1, mapstruct *map2, int *dx, int *dy) |
2046 | static int adjacent_map(const mapstruct *map1, const mapstruct *map2, int *dx, int *dy) { |
2012 | { |
|
|
2013 | if (!map1 || !map2) |
2047 | if (!map1 || !map2) |
2014 | return 0; |
2048 | return 0; |
2015 | |
2049 | |
2016 | else if (map1 == map2) |
2050 | if (map1 == map2) { |
|
|
2051 | *dx = 0; |
2017 | *dx = *dy = 0; |
2052 | *dy = 0; |
2018 | |
2053 | |
2019 | else if (map1->tile_map[0] == map2) // up |
2054 | } else if (map1->tile_map[0] == map2) { /* up */ |
|
|
2055 | *dx = 0; |
2020 | (*dx = 0), (*dy = -MAP_HEIGHT (map2)); |
2056 | *dy = -MAP_HEIGHT(map2); |
2021 | else if (map1->tile_map[1] == map2) // right |
2057 | } else if (map1->tile_map[1] == map2) { /* right */ |
2022 | (*dx = MAP_WIDTH (map2)), (*dy = 0); |
2058 | *dx = MAP_WIDTH(map1); |
|
|
2059 | *dy = 0; |
2023 | else if (map1->tile_map[2] == map2) // down |
2060 | } else if (map1->tile_map[2] == map2) { /* down */ |
2024 | (*dx = 0), (*dy = MAP_HEIGHT (map2)); |
2061 | *dx = 0; |
|
|
2062 | *dy = MAP_HEIGHT(map1); |
2025 | else if (map1->tile_map[3] == map2) // left |
2063 | } else if (map1->tile_map[3] == map2) { /* left */ |
2026 | (*dx = -MAP_WIDTH (map2)), (*dy = 0); |
2064 | *dx = -MAP_WIDTH(map2); |
|
|
2065 | *dy = 0; |
2027 | |
2066 | |
2028 | else if (map1->tile_map[0] && map1->tile_map[0]->tile_map[1] == map2) // up right |
2067 | } 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])); |
2068 | *dx = MAP_WIDTH(map1->tile_map[0]); |
|
|
2069 | *dy = -MAP_HEIGHT(map1->tile_map[0]); |
2030 | else if (map1->tile_map[0] && map1->tile_map[0]->tile_map[3] == map2) // up left |
2070 | } 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])); |
2071 | *dx = -MAP_WIDTH(map2); |
|
|
2072 | *dy = -MAP_HEIGHT(map1->tile_map[0]); |
2032 | else if (map1->tile_map[1] && map1->tile_map[1]->tile_map[0] == map2) // right up |
2073 | } 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)); |
2074 | *dx = MAP_WIDTH(map1); |
|
|
2075 | *dy = -MAP_HEIGHT(map2); |
2034 | else if (map1->tile_map[1] && map1->tile_map[1]->tile_map[2] == map2) // right down |
2076 | } 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)); |
2077 | *dx = MAP_WIDTH(map1); |
|
|
2078 | *dy = MAP_HEIGHT(map1->tile_map[1]); |
2036 | else if (map1->tile_map[2] && map1->tile_map[2]->tile_map[1] == map2) // down right |
2079 | } 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])); |
2080 | *dx = MAP_WIDTH(map1->tile_map[2]); |
|
|
2081 | *dy = MAP_HEIGHT(map1); |
2038 | else if (map1->tile_map[2] && map1->tile_map[2]->tile_map[3] == map2) // down left |
2082 | } 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])); |
2083 | *dx = -MAP_WIDTH(map2); |
|
|
2084 | *dy = MAP_HEIGHT(map1); |
2040 | else if (map1->tile_map[3] && map1->tile_map[3]->tile_map[0] == map2) // left up |
2085 | } 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)); |
2086 | *dx = -MAP_WIDTH(map1->tile_map[3]); |
|
|
2087 | *dy = -MAP_HEIGHT(map2); |
2042 | else if (map1->tile_map[3] && map1->tile_map[3]->tile_map[2] == map2) // left down |
2088 | } 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)); |
2089 | *dx = -MAP_WIDTH(map1->tile_map[3]); |
|
|
2090 | *dy = MAP_HEIGHT(map1->tile_map[3]); |
2044 | |
2091 | |
2045 | else // not "adjacent" enough |
2092 | } else { /* not "adjacent" enough */ |
|
|
2093 | return 0; |
|
|
2094 | } |
|
|
2095 | |
2046 | return 0; |
2096 | return 1; |
2047 | |
|
|
2048 | return 1; |
|
|
2049 | } |
2097 | } |
2050 | |
2098 | |
2051 | /* From map.c |
2099 | /* From map.c |
2052 | * This is used by get_player to determine where the other |
2100 | * This is used by get_player to determine where the other |
2053 | * creature is. get_rangevector takes into account map tiling, |
2101 | * creature is. get_rangevector takes into account map tiling, |
… | |
… | |
2067 | * |
2115 | * |
2068 | * currently, the only flag supported (0x1) is don't translate for |
2116 | * currently, the only flag supported (0x1) is don't translate for |
2069 | * closest body part of 'op1' |
2117 | * closest body part of 'op1' |
2070 | */ |
2118 | */ |
2071 | |
2119 | |
2072 | void get_rangevector(object *op1, object *op2, rv_vector *retval, int flags) |
2120 | void get_rangevector(object *op1, object *op2, rv_vector *retval, int flags) { |
2073 | { |
|
|
2074 | if (!adjacent_map (op1->map, op2->map, &(retval->distance_x), &(retval->distance_y))) |
2121 | if (!adjacent_map(op1->map, op2->map, &retval->distance_x, &retval->distance_y)) { |
2075 | { |
|
|
2076 | // be conservative and fill in _some_ data |
2122 | /* be conservative and fill in _some_ data */ |
2077 | retval->distance = 100000; |
2123 | retval->distance = 100000; |
2078 | retval->distance_x = 32767; |
2124 | retval->distance_x = 32767; |
2079 | retval->distance_y = 32767; |
2125 | retval->distance_y = 32767; |
2080 | retval->direction = 0; |
2126 | retval->direction = 0; |
2081 | retval->part = 0; |
2127 | retval->part = 0; |
2082 | } |
|
|
2083 | else |
2128 | } else { |
2084 | { |
|
|
2085 | object *best; |
2129 | object *best; |
2086 | |
2130 | |
2087 | retval->distance_x += op2->x - op1->x; |
2131 | retval->distance_x += op2->x-op1->x; |
2088 | retval->distance_y += op2->y - op1->y; |
2132 | retval->distance_y += op2->y-op1->y; |
2089 | |
2133 | |
2090 | best = op1; |
2134 | best = op1; |
2091 | /* If this is multipart, find the closest part now */ |
2135 | /* If this is multipart, find the closest part now */ |
2092 | if (!(flags & 0x1) && op1->more) { |
2136 | if (!(flags&0x1) && op1->more) { |
2093 | object *tmp; |
2137 | object *tmp; |
2094 | int best_distance = retval->distance_x * retval->distance_x + |
2138 | int best_distance = retval->distance_x*retval->distance_x+ |
2095 | retval->distance_y * retval->distance_y, tmpi; |
2139 | retval->distance_y*retval->distance_y, tmpi; |
2096 | |
2140 | |
2097 | /* we just tkae the offset of the piece to head to figure |
2141 | /* we just take the offset of the piece to head to figure |
2098 | * distance instead of doing all that work above again |
2142 | * distance instead of doing all that work above again |
2099 | * since the distance fields we set above are positive in the |
2143 | * since the distance fields we set above are positive in the |
2100 | * same axis as is used for multipart objects, the simply arithemetic |
2144 | * same axis as is used for multipart objects, the simply arithmetic |
2101 | * below works. |
2145 | * below works. |
2102 | */ |
2146 | */ |
2103 | for (tmp=op1->more; tmp; tmp=tmp->more) { |
2147 | for (tmp = op1->more; tmp != NULL; tmp = tmp->more) { |
2104 | tmpi = (op1->x - tmp->x + retval->distance_x) * (op1->x - tmp->x + retval->distance_x) + |
2148 | tmpi = (op1->x-tmp->x+retval->distance_x)*(op1->x-tmp->x+retval->distance_x)+ |
2105 | (op1->y - tmp->y + retval->distance_y) * (op1->y - tmp->y + retval->distance_y); |
2149 | (op1->y-tmp->y+retval->distance_y)*(op1->y-tmp->y+retval->distance_y); |
2106 | if (tmpi < best_distance) { |
2150 | if (tmpi < best_distance) { |
2107 | best_distance = tmpi; |
2151 | best_distance = tmpi; |
2108 | best = tmp; |
2152 | best = tmp; |
2109 | } |
2153 | } |
2110 | } |
2154 | } |
2111 | if (best != op1) { |
2155 | if (best != op1) { |
2112 | retval->distance_x += op1->x - best->x; |
2156 | retval->distance_x += op1->x-best->x; |
2113 | retval->distance_y += op1->y - best->y; |
2157 | retval->distance_y += op1->y-best->y; |
2114 | } |
2158 | } |
2115 | } |
2159 | } |
2116 | retval->part = best; |
2160 | retval->part = best; |
2117 | retval->distance = isqrt(retval->distance_x*retval->distance_x + retval->distance_y*retval->distance_y); |
2161 | retval->distance = isqrt(retval->distance_x*retval->distance_x+retval->distance_y*retval->distance_y); |
2118 | retval->direction = find_dir_2(-retval->distance_x, -retval->distance_y); |
2162 | retval->direction = find_dir_2(-retval->distance_x, -retval->distance_y); |
2119 | } |
2163 | } |
2120 | } |
2164 | } |
2121 | |
2165 | |
2122 | /* this is basically the same as get_rangevector above, but instead of |
2166 | /* this is basically the same as get_rangevector above, but instead of |
2123 | * the first parameter being an object, it instead is the map |
2167 | * the first parameter being an object, it instead is the map |
2124 | * and x,y coordinates - this is used for path to player - |
2168 | * and x,y coordinates - this is used for path to player - |
… | |
… | |
2128 | * be more consistant with the above function and also in case they are needed |
2172 | * be more consistant with the above function and also in case they are needed |
2129 | * for something in the future. Also, since no object is pasted, the best |
2173 | * for something in the future. Also, since no object is pasted, the best |
2130 | * field of the rv_vector is set to NULL. |
2174 | * field of the rv_vector is set to NULL. |
2131 | */ |
2175 | */ |
2132 | |
2176 | |
2133 | void get_rangevector_from_mapcoord(mapstruct *m, int x, int y, object *op2, rv_vector *retval,int flags) |
2177 | void get_rangevector_from_mapcoord(const mapstruct *m, int x, int y, const object *op2, rv_vector *retval, int flags) { |
2134 | { |
|
|
2135 | if (!adjacent_map (m, op2->map, &(retval->distance_x), &(retval->distance_y))) |
2178 | if (!adjacent_map(m, op2->map, &retval->distance_x, &retval->distance_y)) { |
2136 | { |
|
|
2137 | // be conservative and fill in _some_ data |
2179 | /* be conservative and fill in _some_ data */ |
2138 | retval->distance = 100000; |
2180 | retval->distance = 100000; |
2139 | retval->distance_x = 32767; |
2181 | retval->distance_x = 32767; |
2140 | retval->distance_y = 32767; |
2182 | retval->distance_y = 32767; |
2141 | retval->direction = 0; |
2183 | retval->direction = 0; |
2142 | retval->part = 0; |
2184 | retval->part = 0; |
2143 | } |
|
|
2144 | else |
2185 | } else { |
2145 | { |
|
|
2146 | retval->distance_x += op2->x - x; |
2186 | retval->distance_x += op2->x-x; |
2147 | retval->distance_y += op2->y - y; |
2187 | retval->distance_y += op2->y-y; |
2148 | |
2188 | |
2149 | retval->part = NULL; |
2189 | retval->part = NULL; |
2150 | retval->distance = isqrt(retval->distance_x*retval->distance_x + retval->distance_y*retval->distance_y); |
2190 | retval->distance = isqrt(retval->distance_x*retval->distance_x+retval->distance_y*retval->distance_y); |
2151 | retval->direction = find_dir_2(-retval->distance_x, -retval->distance_y); |
2191 | retval->direction = find_dir_2(-retval->distance_x, -retval->distance_y); |
2152 | } |
2192 | } |
2153 | } |
2193 | } |
2154 | |
2194 | |
2155 | /* Returns true of op1 and op2 are effectively on the same map |
2195 | /* Returns true of op1 and op2 are effectively on the same map |
2156 | * (as related to map tiling). Note that this looks for a path from |
2196 | * (as related to map tiling). Note that this looks for a path from |
2157 | * op1 to op2, so if the tiled maps are assymetric and op2 has a path |
2197 | * op1 to op2, so if the tiled maps are assymetric and op2 has a path |
2158 | * to op1, this will still return false. |
2198 | * to op1, this will still return false. |
2159 | * Note we only look one map out to keep the processing simple |
2199 | * Note we only look one map out to keep the processing simple |
2160 | * and efficient. This could probably be a macro. |
2200 | * and efficient. This could probably be a macro. |
2161 | * MSW 2001-08-05 |
2201 | * MSW 2001-08-05 |
2162 | */ |
2202 | */ |
2163 | int on_same_map(object *op1, object *op2) |
2203 | int on_same_map(const object *op1, const object *op2) { |
2164 | { |
|
|
2165 | int dx, dy; |
2204 | int dx, dy; |
2166 | |
2205 | |
2167 | return adjacent_map (op1->map, op2->map, &dx, &dy); |
2206 | return adjacent_map(op1->map, op2->map, &dx, &dy); |
2168 | } |
2207 | } |