1 | /* |
1 | /* |
2 | * static char *rcsid_map_c = |
2 | * static char *rcsid_map_c = |
3 | * "$Id: map.C,v 1.21 2006/09/03 22:45:55 root Exp $"; |
3 | * "$Id: map.C,v 1.28 2006/09/08 18:26:22 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 | |
… | |
… | |
155 | { |
155 | { |
156 | char buf[MAX_BUF]; |
156 | char buf[MAX_BUF]; |
157 | #ifndef WIN32 |
157 | #ifndef WIN32 |
158 | char *endbuf; |
158 | char *endbuf; |
159 | struct stat statbuf; |
159 | struct stat statbuf; |
160 | int mode = 0, i; |
160 | int mode = 0; |
161 | #endif |
161 | #endif |
162 | |
162 | |
163 | if (prepend_dir) |
163 | if (prepend_dir) |
164 | strcpy (buf, create_pathname(name)); |
164 | strcpy (buf, create_pathname(name)); |
165 | else |
165 | else |
… | |
… | |
255 | if (mp != oldmap) |
255 | if (mp != oldmap) |
256 | retval |= P_NEW_MAP; |
256 | retval |= P_NEW_MAP; |
257 | if (newmap) *newmap = mp; |
257 | if (newmap) *newmap = mp; |
258 | if (nx) *nx = newx; |
258 | if (nx) *nx = newx; |
259 | if (ny) *ny = newy; |
259 | if (ny) *ny = newy; |
|
|
260 | |
260 | retval |= mp->spaces[newx + mp->width * newy].flags; |
261 | retval |= mp->spaces[newx + mp->width * newy].flags; |
261 | |
|
|
262 | if (retval & P_SAFE) |
|
|
263 | retval |= P_NO_MAGIC | P_NO_CLERIC; // P_SAFE does imply these |
|
|
264 | |
262 | |
265 | return retval; |
263 | return retval; |
266 | } |
264 | } |
267 | |
265 | |
268 | |
266 | |
… | |
… | |
494 | insert_ob_in_map(op, op->map, tmp,INS_NO_MERGE|INS_ABOVE_FLOOR_ONLY|INS_NO_WALK_ON); |
492 | insert_ob_in_map(op, op->map, tmp,INS_NO_MERGE|INS_ABOVE_FLOOR_ONLY|INS_NO_WALK_ON); |
495 | } /* for at = tmp->arch->more */ |
493 | } /* for at = tmp->arch->more */ |
496 | } /* for objects on this space */ |
494 | } /* for objects on this space */ |
497 | } |
495 | } |
498 | |
496 | |
499 | |
|
|
500 | |
|
|
501 | /* |
497 | /* |
502 | * Loads (ands parses) the objects into a given map from the specified |
498 | * Loads (ands parses) the objects into a given map from the specified |
503 | * file pointer. |
499 | * file pointer. |
504 | * mapflags is the same as we get with load_original_map |
500 | * mapflags is the same as we get with load_original_map |
505 | */ |
501 | */ |
506 | |
502 | void |
507 | void load_objects (mapstruct *m, object_thawer &fp, int mapflags) { |
503 | load_objects (mapstruct *m, object_thawer &fp, int mapflags) |
|
|
504 | { |
508 | int i,j; |
505 | int i, j; |
509 | int unique; |
506 | int unique; |
510 | object *op, *prev=NULL,*last_more=NULL, *otmp; |
507 | object *op, *prev = NULL, *last_more = NULL, *otmp; |
511 | |
508 | |
512 | op=get_object(); |
509 | op = get_object (); |
513 | op->map = m; /* To handle buttons correctly */ |
510 | op->map = m; /* To handle buttons correctly */ |
514 | |
511 | |
515 | while((i = load_object (fp, op, mapflags))) { |
512 | while ((i = load_object (fp, op, mapflags))) |
|
|
513 | { |
516 | /* if the archetype for the object is null, means that we |
514 | /* if the archetype for the object is null, means that we |
517 | * got an invalid object. Don't do anything with it - the game |
515 | * got an invalid object. Don't do anything with it - the game |
518 | * or editor will not be able to do anything with it either. |
516 | * or editor will not be able to do anything with it either. |
519 | */ |
517 | */ |
520 | if (op->arch==NULL) { |
518 | if (op->arch == NULL) |
521 | LOG(llevDebug,"Discarding object without arch: %s\n", op->name?(const char *)op->name:"(null)"); |
519 | { |
|
|
520 | LOG (llevDebug, "Discarding object without arch: %s\n", |
|
|
521 | op->name ? (const char *) op->name : "(null)"); |
522 | continue; |
522 | continue; |
|
|
523 | } |
|
|
524 | |
|
|
525 | |
|
|
526 | switch (i) |
523 | } |
527 | { |
524 | |
|
|
525 | |
|
|
526 | switch(i) { |
|
|
527 | case LL_NORMAL: |
528 | case LL_NORMAL: |
528 | /* if we are loading an overlay, put the floors on the bottom */ |
529 | /* if we are loading an overlay, put the floors on the bottom */ |
529 | if ((QUERY_FLAG(op, FLAG_IS_FLOOR) || |
530 | if ((QUERY_FLAG (op, FLAG_IS_FLOOR) || |
530 | QUERY_FLAG(op, FLAG_OVERLAY_FLOOR)) && mapflags & MAP_OVERLAY) |
531 | QUERY_FLAG (op, FLAG_OVERLAY_FLOOR)) && mapflags & MAP_OVERLAY) |
531 | insert_ob_in_map(op,m,op,INS_NO_MERGE | INS_NO_WALK_ON | INS_ABOVE_FLOOR_ONLY | INS_MAP_LOAD); |
532 | insert_ob_in_map (op, m, op, |
|
|
533 | INS_NO_MERGE | INS_NO_WALK_ON | |
|
|
534 | INS_ABOVE_FLOOR_ONLY | INS_MAP_LOAD); |
532 | else |
535 | else |
533 | insert_ob_in_map(op,m,op,INS_NO_MERGE | INS_NO_WALK_ON | INS_ON_TOP | INS_MAP_LOAD); |
536 | insert_ob_in_map (op, m, op, |
|
|
537 | INS_NO_MERGE | INS_NO_WALK_ON | INS_ON_TOP | |
|
|
538 | INS_MAP_LOAD); |
534 | |
539 | |
535 | if (op->inv) |
540 | if (op->inv) |
536 | sum_weight(op); |
541 | sum_weight (op); |
537 | |
542 | |
538 | prev=op,last_more=op; |
543 | prev = op, last_more = op; |
539 | break; |
544 | break; |
540 | |
545 | |
541 | case LL_MORE: |
546 | case LL_MORE: |
542 | insert_ob_in_map(op,m, op, INS_NO_MERGE | INS_NO_WALK_ON | INS_ABOVE_FLOOR_ONLY); |
547 | insert_ob_in_map (op, m, op, |
|
|
548 | INS_NO_MERGE | INS_NO_WALK_ON | |
|
|
549 | INS_ABOVE_FLOOR_ONLY); |
543 | op->head=prev,last_more->more=op,last_more=op; |
550 | op->head = prev, last_more->more = op, last_more = op; |
544 | break; |
551 | break; |
545 | } |
552 | } |
|
|
553 | |
546 | if (mapflags & MAP_STYLE) { |
554 | if (mapflags & MAP_STYLE) |
547 | remove_from_active_list(op); |
555 | remove_from_active_list (op); |
548 | } |
556 | |
549 | op=get_object(); |
557 | op = get_object (); |
550 | op->map = m; |
558 | op->map = m; |
551 | } |
559 | } |
|
|
560 | |
552 | for (i=0;i<m->width;i++){ |
561 | for (i = 0; i < m->width; i++) |
|
|
562 | { |
553 | for (j=0;j<m->height;j++){ |
563 | for (j = 0; j < m->height; j++) |
|
|
564 | { |
554 | unique =0; |
565 | unique = 0; |
555 | /* check for unique items, or unique squares */ |
566 | /* check for unique items, or unique squares */ |
556 | for (otmp = get_map_ob(m, i, j); otmp; otmp = otmp->above) { |
567 | for (otmp = get_map_ob (m, i, j); otmp; otmp = otmp->above) |
557 | if (QUERY_FLAG(otmp, FLAG_UNIQUE) || QUERY_FLAG(otmp, FLAG_OBJ_SAVE_ON_OVL)) |
568 | { |
|
|
569 | if (QUERY_FLAG (otmp, FLAG_UNIQUE) |
|
|
570 | || QUERY_FLAG (otmp, FLAG_OBJ_SAVE_ON_OVL)) |
558 | unique = 1; |
571 | unique = 1; |
559 | if (!(mapflags & (MAP_OVERLAY|MAP_PLAYER_UNIQUE) || unique)) |
572 | if (!(mapflags & (MAP_OVERLAY | MAP_PLAYER_UNIQUE) || unique)) |
560 | SET_FLAG(otmp, FLAG_OBJ_ORIGINAL); |
573 | SET_FLAG (otmp, FLAG_OBJ_ORIGINAL); |
561 | } |
574 | } |
562 | } |
575 | } |
563 | } |
576 | } |
|
|
577 | |
564 | free_object(op); |
578 | free_object (op); |
565 | link_multipart_objects(m); |
579 | link_multipart_objects (m); |
566 | } |
580 | } |
567 | |
581 | |
568 | /* This saves all the objects on the map in a non destructive fashion. |
582 | /* This saves all the objects on the map in a non destructive fashion. |
569 | * Modified by MSW 2001-07-01 to do in a single pass - reduces code, |
583 | * Modified by MSW 2001-07-01 to do in a single pass - reduces code, |
570 | * and we only save the head of multi part objects - this is needed |
584 | * and we only save the head of multi part objects - this is needed |
… | |
… | |
688 | number_of_entries++; |
702 | number_of_entries++; |
689 | if (p) p++; |
703 | if (p) p++; |
690 | } |
704 | } |
691 | p=shop_string; |
705 | p=shop_string; |
692 | strip_endline(p); |
706 | strip_endline(p); |
693 | items=(shopitems *) CALLOC(number_of_entries+1, sizeof(shopitems)); |
707 | items = new shopitems [number_of_entries + 1]; |
694 | memset(items, 0, (sizeof(shopitems) * number_of_entries+1)); |
|
|
695 | for (i=0; i<number_of_entries; i++) { |
708 | for (i=0; i<number_of_entries; i++) { |
696 | if (!p) { |
709 | if (!p) { |
697 | LOG(llevError, "parse_shop_string: I seem to have run out of string, that shouldn't happen.\n"); |
710 | LOG(llevError, "parse_shop_string: I seem to have run out of string, that shouldn't happen.\n"); |
698 | break; |
711 | break; |
699 | } |
712 | } |
… | |
… | |
800 | value = NULL; |
813 | value = NULL; |
801 | break; |
814 | break; |
802 | } |
815 | } |
803 | } |
816 | } |
804 | } |
817 | } |
|
|
818 | |
805 | if (!end) { |
819 | if (!end) { |
806 | LOG(llevError, "Error loading map header - did not find a newline - perhaps file is truncated? Buf=%s\n", |
820 | LOG(llevError, "Error loading map header - did not find a newline - perhaps file is truncated? Buf=%s\n", |
807 | buf); |
821 | buf); |
808 | return 1; |
822 | return 1; |
809 | } |
823 | } |
810 | |
|
|
811 | |
824 | |
812 | /* key is the field name, value is what it should be set |
825 | /* key is the field name, value is what it should be set |
813 | * to. We've already done the work to null terminate key, |
826 | * to. We've already done the work to null terminate key, |
814 | * and strip off any leading spaces for both of these. |
827 | * and strip off any leading spaces for both of these. |
815 | * We have not touched the newline at the end of the line - |
828 | * We have not touched the newline at the end of the line - |
… | |
… | |
995 | |
1008 | |
996 | mapstruct *load_original_map(const char *filename, int flags) { |
1009 | mapstruct *load_original_map(const char *filename, int flags) { |
997 | mapstruct *m; |
1010 | mapstruct *m; |
998 | char pathname[MAX_BUF]; |
1011 | char pathname[MAX_BUF]; |
999 | |
1012 | |
1000 | LOG(llevDebug, "load_original_map: %s (%x)\n", filename,flags); |
|
|
1001 | if (flags & MAP_PLAYER_UNIQUE) |
1013 | if (flags & MAP_PLAYER_UNIQUE) |
1002 | strcpy(pathname, filename); |
1014 | strcpy(pathname, filename); |
1003 | else if (flags & MAP_OVERLAY) |
1015 | else if (flags & MAP_OVERLAY) |
1004 | strcpy(pathname, create_overlay_pathname(filename)); |
1016 | strcpy(pathname, create_overlay_pathname(filename)); |
1005 | else |
1017 | else |
1006 | strcpy(pathname, create_pathname(filename)); |
1018 | strcpy(pathname, create_pathname(filename)); |
1007 | |
1019 | |
|
|
1020 | LOG(llevDebug, "load_original_map(%x): %s (%s)\n", flags, filename, pathname); |
|
|
1021 | |
1008 | object_thawer thawer (pathname); |
1022 | object_thawer thawer (pathname); |
1009 | |
1023 | |
1010 | if (!thawer) |
1024 | if (!thawer) |
1011 | return 0; |
1025 | return 0; |
1012 | |
1026 | |
… | |
… | |
1038 | * Return the map object we load into (this can change from the passed |
1052 | * Return the map object we load into (this can change from the passed |
1039 | * option if we can't find the original map) |
1053 | * option if we can't find the original map) |
1040 | */ |
1054 | */ |
1041 | |
1055 | |
1042 | static mapstruct *load_temporary_map(mapstruct *m) { |
1056 | static mapstruct *load_temporary_map(mapstruct *m) { |
1043 | int comp; |
|
|
1044 | char buf[MAX_BUF]; |
1057 | char buf[MAX_BUF]; |
1045 | |
1058 | |
1046 | if (!m->tmpname) { |
1059 | if (!m->tmpname) { |
1047 | LOG(llevError, "No temporary filename for map %s\n", m->path); |
1060 | LOG(llevError, "No temporary filename for map %s\n", m->path); |
1048 | strcpy(buf, m->path); |
1061 | strcpy(buf, m->path); |
… | |
… | |
1182 | */ |
1195 | */ |
1183 | |
1196 | |
1184 | int |
1197 | int |
1185 | new_save_map (mapstruct * m, int flag) |
1198 | new_save_map (mapstruct * m, int flag) |
1186 | { |
1199 | { |
1187 | char filename[MAX_BUF], buf[MAX_BUF], buf_s[MAX_BUF], shop[MAX_BUF]; |
1200 | char filename[MAX_BUF], buf[MAX_BUF], shop[MAX_BUF]; |
1188 | int i; |
1201 | int i; |
1189 | |
1202 | |
1190 | if (flag && !*m->path) |
1203 | if (flag && !*m->path) |
1191 | { |
1204 | { |
1192 | LOG (llevError, "Tried to save map without path.\n"); |
1205 | LOG (llevError, "Tried to save map without path.\n"); |
… | |
… | |
1396 | if (flag && m->spaces) free_all_objects(m); |
1409 | if (flag && m->spaces) free_all_objects(m); |
1397 | if (m->name) FREE_AND_CLEAR(m->name); |
1410 | if (m->name) FREE_AND_CLEAR(m->name); |
1398 | if (m->spaces) FREE_AND_CLEAR(m->spaces); |
1411 | if (m->spaces) FREE_AND_CLEAR(m->spaces); |
1399 | if (m->msg) FREE_AND_CLEAR(m->msg); |
1412 | if (m->msg) FREE_AND_CLEAR(m->msg); |
1400 | if (m->maplore) FREE_AND_CLEAR(m->maplore); |
1413 | if (m->maplore) FREE_AND_CLEAR(m->maplore); |
1401 | if (m->shopitems) FREE_AND_CLEAR(m->shopitems); |
1414 | if (m->shopitems) delete [] m->shopitems; m->shopitems = 0; |
1402 | if (m->shoprace) FREE_AND_CLEAR(m->shoprace); |
1415 | if (m->shoprace) FREE_AND_CLEAR(m->shoprace); |
1403 | if (m->buttons) |
1416 | if (m->buttons) |
1404 | free_objectlinkpt(m->buttons); |
1417 | free_objectlinkpt(m->buttons); |
1405 | m->buttons = NULL; |
1418 | m->buttons = NULL; |
1406 | for (i=0; i<4; i++) { |
1419 | for (i=0; i<4; i++) { |
… | |
… | |
1519 | if (flags & MAP_PLAYER_UNIQUE) |
1532 | if (flags & MAP_PLAYER_UNIQUE) |
1520 | LOG(llevDebug, "Trying to load map %s.\n", name); |
1533 | LOG(llevDebug, "Trying to load map %s.\n", name); |
1521 | else |
1534 | else |
1522 | LOG(llevDebug, "Trying to load map %s.\n", create_pathname(name)); |
1535 | LOG(llevDebug, "Trying to load map %s.\n", create_pathname(name)); |
1523 | |
1536 | |
1524 | //0.427459955215454 /var/crossfire/players/Saladon/_scorn_apartment_apartments |
|
|
1525 | //0.414906024932861 |
|
|
1526 | //0.427063941955566 |
|
|
1527 | eval_pv ("$x = Event::time", 1);//D |
1537 | //eval_pv ("$x = Event::time", 1);//D |
1528 | if (!(m = load_original_map(name, (flags & MAP_PLAYER_UNIQUE)))) |
1538 | if (!(m = load_original_map(name, (flags & MAP_PLAYER_UNIQUE)))) |
1529 | return (NULL); |
1539 | return (NULL); |
1530 | eval_pv ("warn \"LOAD \", Event::time - $x", 1);//D |
1540 | //eval_pv ("warn \"LOAD \", Event::time - $x", 1);//D |
1531 | |
1541 | |
1532 | fix_auto_apply(m); /* Chests which open as default */ |
1542 | fix_auto_apply(m); /* Chests which open as default */ |
1533 | |
1543 | |
1534 | /* If a player unique map, no extra unique object file to load. |
1544 | /* If a player unique map, no extra unique object file to load. |
1535 | * if from the editor, likewise. |
1545 | * if from the editor, likewise. |
1536 | */ |
1546 | */ |
1537 | if (! (flags & (MAP_FLUSH|MAP_PLAYER_UNIQUE))) |
1547 | if (!(flags & (MAP_FLUSH|MAP_PLAYER_UNIQUE))) |
1538 | load_unique_objects(m); |
1548 | load_unique_objects(m); |
1539 | |
1549 | |
1540 | if (! (flags & (MAP_FLUSH|MAP_PLAYER_UNIQUE|MAP_OVERLAY))) { |
1550 | if (! (flags & (MAP_FLUSH|MAP_PLAYER_UNIQUE|MAP_OVERLAY))) { |
1541 | m=load_overlay_map(name, m); |
1551 | m=load_overlay_map(name, m); |
1542 | if (m==NULL) |
1552 | if (m==NULL) |
… | |
… | |
1593 | */ |
1603 | */ |
1594 | |
1604 | |
1595 | int calculate_difficulty(mapstruct *m) { |
1605 | int calculate_difficulty(mapstruct *m) { |
1596 | object *op; |
1606 | object *op; |
1597 | archetype *at; |
1607 | archetype *at; |
1598 | int x, y, i, diff; |
1608 | int x, y, i; |
1599 | long monster_cnt = 0; |
1609 | long monster_cnt = 0; |
1600 | double avgexp = 0; |
1610 | double avgexp = 0; |
1601 | sint64 total_exp = 0; |
1611 | sint64 total_exp = 0; |
1602 | |
1612 | |
1603 | if (MAP_DIFFICULTY (m)) |
1613 | if (MAP_DIFFICULTY (m)) |
… | |
… | |
1793 | if (QUERY_FLAG(tmp,FLAG_NO_MAGIC)) |
1803 | if (QUERY_FLAG(tmp,FLAG_NO_MAGIC)) |
1794 | flags |= P_NO_MAGIC; |
1804 | flags |= P_NO_MAGIC; |
1795 | if (QUERY_FLAG(tmp,FLAG_DAMNED)) |
1805 | if (QUERY_FLAG(tmp,FLAG_DAMNED)) |
1796 | flags |= P_NO_CLERIC; |
1806 | flags |= P_NO_CLERIC; |
1797 | if (tmp->type == SAFE_GROUND) |
1807 | if (tmp->type == SAFE_GROUND) |
1798 | flags |= P_SAFE | P_NO_CLERIC | P_NO_MAGIC; |
1808 | flags |= P_SAFE; |
1799 | |
1809 | |
1800 | if (QUERY_FLAG(tmp,FLAG_BLOCKSVIEW)) |
1810 | if (QUERY_FLAG(tmp,FLAG_BLOCKSVIEW)) |
1801 | flags |= P_BLOCKSVIEW; |
1811 | flags |= P_BLOCKSVIEW; |
1802 | } /* for stack of objects */ |
1812 | } /* for stack of objects */ |
1803 | |
1813 | |