… | |
… | |
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
20 | |
20 | |
21 | The authors can be reached via e-mail at <crossfire@schmorp.de> |
21 | The authors can be reached via e-mail at <crossfire@schmorp.de> |
22 | */ |
22 | */ |
23 | |
23 | |
24 | |
|
|
25 | #include <global.h> |
24 | #include <global.h> |
26 | #include <funcpoint.h> |
25 | #include <funcpoint.h> |
27 | |
26 | |
28 | #include <loader.h> |
27 | #include <loader.h> |
29 | #include <unistd.h> |
28 | #include <unistd.h> |
… | |
… | |
35 | * return NULL if no match is found. |
34 | * return NULL if no match is found. |
36 | */ |
35 | */ |
37 | maptile * |
36 | maptile * |
38 | has_been_loaded (const char *name) |
37 | has_been_loaded (const char *name) |
39 | { |
38 | { |
40 | maptile *map; |
|
|
41 | |
|
|
42 | if (!name || !*name) |
39 | if (!name || !*name) |
43 | return 0; |
40 | return 0; |
44 | |
41 | |
45 | for (map = first_map; map; map = map->next) |
42 | for_all_maps (map) |
46 | if (!strcmp (name, map->path)) |
43 | if (!strcmp (name, map->path)) |
47 | break; |
|
|
48 | |
|
|
49 | return (map); |
44 | return map; |
|
|
45 | |
|
|
46 | return 0; |
50 | } |
47 | } |
51 | |
48 | |
52 | /* |
49 | /* |
53 | * This makes a path absolute outside the world of Crossfire. |
50 | * This makes a path absolute outside the world of Crossfire. |
54 | * In other words, it prepends LIBDIR/MAPDIR/ to the given path |
51 | * In other words, it prepends LIBDIR/MAPDIR/ to the given path |
… | |
… | |
221 | */ |
218 | */ |
222 | |
219 | |
223 | void |
220 | void |
224 | dump_all_maps (void) |
221 | dump_all_maps (void) |
225 | { |
222 | { |
226 | maptile *m; |
223 | for_all_maps (m) |
227 | |
|
|
228 | for (m = first_map; m; m = m->next) |
|
|
229 | dump_map (m); |
224 | dump_map (m); |
230 | } |
225 | } |
231 | |
226 | |
232 | /* This rolls up wall, blocks_magic, blocks_view, etc, all into |
227 | /* This rolls up wall, blocks_magic, blocks_view, etc, all into |
233 | * one function that just returns a P_.. value (see map.h) |
228 | * one function that just returns a P_.. value (see map.h) |
… | |
… | |
476 | * for objects whose arch says they are multipart yet according to the |
471 | * for objects whose arch says they are multipart yet according to the |
477 | * info we have, they only have the head (as would be expected when |
472 | * info we have, they only have the head (as would be expected when |
478 | * they are saved). We do have to look for the old maps that did save |
473 | * they are saved). We do have to look for the old maps that did save |
479 | * the more sections and not re-add sections for them. |
474 | * the more sections and not re-add sections for them. |
480 | */ |
475 | */ |
481 | |
|
|
482 | static void |
476 | static void |
483 | link_multipart_objects (maptile *m) |
477 | link_multipart_objects (maptile *m) |
484 | { |
478 | { |
485 | int x, y; |
479 | int x, y; |
486 | object *tmp, *op, *last, *above; |
480 | object *tmp, *op, *last, *above; |
… | |
… | |
617 | for (op = m->at (i, j).bot; op; op = op->above) |
611 | for (op = m->at (i, j).bot; op; op = op->above) |
618 | { |
612 | { |
619 | if (op->flag [FLAG_UNIQUE] && op->flag [FLAG_IS_FLOOR]) |
613 | if (op->flag [FLAG_UNIQUE] && op->flag [FLAG_IS_FLOOR]) |
620 | unique = 1; |
614 | unique = 1; |
621 | |
615 | |
622 | if (op->type == PLAYER) |
616 | if (!op->can_map_save ()) |
623 | continue; |
|
|
624 | |
|
|
625 | if (op->head || op->owner) |
|
|
626 | continue; |
617 | continue; |
627 | |
618 | |
628 | if (unique || op->flag [FLAG_UNIQUE]) |
619 | if (unique || op->flag [FLAG_UNIQUE]) |
629 | save_object (fp2, op, 1); |
620 | save_object (fp2, op, 1); |
630 | else if (flag == 0 || (flag == 2 && (!op->flag [FLAG_OBJ_ORIGINAL] && !op->flag [FLAG_UNPAID]))) |
621 | else if (flag == 0 || (flag == 2 && (!op->flag [FLAG_OBJ_ORIGINAL] && !op->flag [FLAG_UNPAID]))) |
… | |
… | |
634 | } |
625 | } |
635 | |
626 | |
636 | maptile::maptile () |
627 | maptile::maptile () |
637 | { |
628 | { |
638 | in_memory = MAP_SWAPPED; |
629 | in_memory = MAP_SWAPPED; |
|
|
630 | |
639 | /* The maps used to pick up default x and y values from the |
631 | /* The maps used to pick up default x and y values from the |
640 | * map archetype. Mimic that behaviour. |
632 | * map archetype. Mimic that behaviour. |
641 | */ |
633 | */ |
642 | this->width = 16; |
634 | width = 16; |
643 | this->height = 16; |
635 | height = 16; |
644 | this->reset_timeout = 0; |
636 | reset_timeout = 0; |
645 | this->timeout = 300; |
637 | timeout = 300; |
646 | this->enter_x = 0; |
638 | enter_x = 0; |
647 | this->enter_y = 0; |
639 | enter_y = 0; |
648 | /*set part to -1 indicating conversion to weather map not yet done */ |
640 | /*set part to -1 indicating conversion to weather map not yet done */ |
649 | this->worldpartx = -1; |
641 | worldpartx = -1; |
650 | this->worldparty = -1; |
642 | worldparty = -1; |
|
|
643 | } |
|
|
644 | |
|
|
645 | void |
|
|
646 | maptile::link () |
|
|
647 | { |
|
|
648 | next = first_map; |
|
|
649 | first_map = this; |
|
|
650 | } |
|
|
651 | |
|
|
652 | void |
|
|
653 | maptile::unlink () |
|
|
654 | { |
|
|
655 | if (first_map == this) |
|
|
656 | first_map = next; |
|
|
657 | else |
|
|
658 | for_all_maps (m) |
|
|
659 | if (m->next = this) |
|
|
660 | { |
|
|
661 | m->next = next; |
|
|
662 | break; |
|
|
663 | } |
651 | } |
664 | } |
652 | |
665 | |
653 | /* |
666 | /* |
654 | * Allocates, initialises, and returns a pointer to a maptile. |
667 | * Allocates, initialises, and returns a pointer to a maptile. |
655 | * Modified to no longer take a path option which was not being |
668 | * Modified to no longer take a path option which was not being |
656 | * used anyways. MSW 2001-07-01 |
669 | * used anyways. MSW 2001-07-01 |
657 | */ |
670 | */ |
658 | maptile * |
671 | maptile * |
659 | get_linked_map (void) |
672 | get_linked_map (void) |
660 | { |
673 | { |
661 | maptile *mp, *map = new maptile; |
674 | maptile *map = new maptile; |
662 | |
675 | map->link (); |
663 | for (mp = first_map; mp && mp->next; mp = mp->next); |
|
|
664 | |
|
|
665 | if (mp == NULL) |
|
|
666 | first_map = map; |
|
|
667 | else |
|
|
668 | mp->next = map; |
|
|
669 | |
|
|
670 | return map; |
676 | return map; |
671 | } |
677 | } |
672 | |
678 | |
673 | /* |
679 | /* |
674 | * Allocates the arrays contained in a maptile. |
680 | * Allocates the arrays contained in a maptile. |
… | |
… | |
685 | * that is their poor assumption. |
691 | * that is their poor assumption. |
686 | */ |
692 | */ |
687 | if (spaces) |
693 | if (spaces) |
688 | { |
694 | { |
689 | LOG (llevError, "allocate_map called with already allocated map (%s)\n", path); |
695 | LOG (llevError, "allocate_map called with already allocated map (%s)\n", path); |
690 | free (spaces); |
696 | sfree (spaces, size ()); |
691 | } |
697 | } |
692 | |
698 | |
693 | spaces = (mapspace *) |
699 | spaces = salloc0<mapspace> (size ()); |
694 | calloc (1, width * height * sizeof (mapspace)); |
|
|
695 | |
|
|
696 | if (!spaces) |
|
|
697 | fatal (OUT_OF_MEMORY); |
|
|
698 | } |
700 | } |
699 | |
701 | |
700 | /* Create and returns a map of the specific size. Used |
702 | /* Create and returns a map of the specific size. Used |
701 | * in random map code and the editor. |
703 | * in random map code and the editor. |
702 | */ |
704 | */ |
… | |
… | |
735 | p = strchr (p, ';'); |
737 | p = strchr (p, ';'); |
736 | number_of_entries++; |
738 | number_of_entries++; |
737 | if (p) |
739 | if (p) |
738 | p++; |
740 | p++; |
739 | } |
741 | } |
|
|
742 | |
740 | p = shop_string; |
743 | p = shop_string; |
741 | strip_endline (p); |
744 | strip_endline (p); |
742 | items = new shopitems[number_of_entries + 1]; |
745 | items = new shopitems[number_of_entries + 1]; |
743 | for (i = 0; i < number_of_entries; i++) |
746 | for (i = 0; i < number_of_entries; i++) |
744 | { |
747 | { |
745 | if (!p) |
748 | if (!p) |
746 | { |
749 | { |
747 | LOG (llevError, "parse_shop_string: I seem to have run out of string, that shouldn't happen.\n"); |
750 | LOG (llevError, "parse_shop_string: I seem to have run out of string, that shouldn't happen.\n"); |
748 | break; |
751 | break; |
749 | } |
752 | } |
|
|
753 | |
750 | next_semicolon = strchr (p, ';'); |
754 | next_semicolon = strchr (p, ';'); |
751 | next_colon = strchr (p, ':'); |
755 | next_colon = strchr (p, ':'); |
752 | /* if there is a stregth specified, figure out what it is, we'll need it soon. */ |
756 | /* if there is a stregth specified, figure out what it is, we'll need it soon. */ |
753 | if (next_colon && (!next_semicolon || next_colon < next_semicolon)) |
757 | if (next_colon && (!next_semicolon || next_colon < next_semicolon)) |
754 | items[i].strength = atoi (strchr (p, ':') + 1); |
758 | items[i].strength = atoi (strchr (p, ':') + 1); |
… | |
… | |
781 | * the next entry while we're at it, better print a warning |
785 | * the next entry while we're at it, better print a warning |
782 | */ |
786 | */ |
783 | LOG (llevError, "invalid type %s defined in shopitems in string %s\n", p, input_string); |
787 | LOG (llevError, "invalid type %s defined in shopitems in string %s\n", p, input_string); |
784 | } |
788 | } |
785 | } |
789 | } |
|
|
790 | |
786 | items[i].index = number_of_entries; |
791 | items[i].index = number_of_entries; |
787 | if (next_semicolon) |
792 | if (next_semicolon) |
788 | p = ++next_semicolon; |
793 | p = ++next_semicolon; |
789 | else |
794 | else |
790 | p = NULL; |
795 | p = NULL; |
791 | } |
796 | } |
|
|
797 | |
792 | free (shop_string); |
798 | free (shop_string); |
793 | return items; |
799 | return items; |
794 | } |
800 | } |
795 | |
801 | |
796 | /* opposite of parse string, this puts the string that was originally fed in to |
802 | /* opposite of parse string, this puts the string that was originally fed in to |
… | |
… | |
805 | for (i = 0; i < m->shopitems[0].index; i++) |
811 | for (i = 0; i < m->shopitems[0].index; i++) |
806 | { |
812 | { |
807 | if (m->shopitems[i].typenum) |
813 | if (m->shopitems[i].typenum) |
808 | { |
814 | { |
809 | if (m->shopitems[i].strength) |
815 | if (m->shopitems[i].strength) |
810 | { |
|
|
811 | sprintf (tmp, "%s:%d;", m->shopitems[i].name, m->shopitems[i].strength); |
816 | sprintf (tmp, "%s:%d;", m->shopitems[i].name, m->shopitems[i].strength); |
812 | } |
|
|
813 | else |
817 | else |
814 | sprintf (tmp, "%s;", m->shopitems[i].name); |
818 | sprintf (tmp, "%s;", m->shopitems[i].name); |
815 | } |
819 | } |
816 | else |
820 | else |
817 | { |
821 | { |
818 | if (m->shopitems[i].strength) |
822 | if (m->shopitems[i].strength) |
819 | { |
|
|
820 | sprintf (tmp, "*:%d;", m->shopitems[i].strength); |
823 | sprintf (tmp, "*:%d;", m->shopitems[i].strength); |
821 | } |
|
|
822 | else |
824 | else |
823 | sprintf (tmp, "*"); |
825 | sprintf (tmp, "*"); |
824 | } |
826 | } |
|
|
827 | |
825 | strcat (output_string, tmp); |
828 | strcat (output_string, tmp); |
826 | } |
829 | } |
827 | } |
830 | } |
828 | |
831 | |
829 | /* This loads the header information of the map. The header |
832 | /* This loads the header information of the map. The header |
… | |
… | |
1097 | * MAP_BLOCK, in which case we block on this load. This happens in all |
1100 | * MAP_BLOCK, in which case we block on this load. This happens in all |
1098 | * cases, no matter if this flag is set or not. |
1101 | * cases, no matter if this flag is set or not. |
1099 | * MAP_STYLE: style map - don't add active objects, don't add to server |
1102 | * MAP_STYLE: style map - don't add active objects, don't add to server |
1100 | * managed map list. |
1103 | * managed map list. |
1101 | */ |
1104 | */ |
1102 | |
|
|
1103 | maptile * |
1105 | maptile * |
1104 | load_original_map (const char *filename, int flags) |
1106 | load_original_map (const char *filename, int flags) |
1105 | { |
1107 | { |
1106 | maptile *m; |
1108 | maptile *m; |
1107 | char pathname[MAX_BUF]; |
1109 | char pathname[MAX_BUF]; |
… | |
… | |
1146 | /* |
1148 | /* |
1147 | * Loads a map, which has been loaded earlier, from file. |
1149 | * Loads a map, which has been loaded earlier, from file. |
1148 | * Return the map object we load into (this can change from the passed |
1150 | * Return the map object we load into (this can change from the passed |
1149 | * option if we can't find the original map) |
1151 | * option if we can't find the original map) |
1150 | */ |
1152 | */ |
1151 | |
|
|
1152 | static maptile * |
1153 | static maptile * |
1153 | load_temporary_map (maptile *m) |
1154 | load_temporary_map (maptile *m) |
1154 | { |
1155 | { |
1155 | char buf[MAX_BUF]; |
1156 | char buf[MAX_BUF]; |
1156 | |
1157 | |
… | |
… | |
1200 | /* |
1201 | /* |
1201 | * Loads a map, which has been loaded earlier, from file. |
1202 | * Loads a map, which has been loaded earlier, from file. |
1202 | * Return the map object we load into (this can change from the passed |
1203 | * Return the map object we load into (this can change from the passed |
1203 | * option if we can't find the original map) |
1204 | * option if we can't find the original map) |
1204 | */ |
1205 | */ |
1205 | |
|
|
1206 | maptile * |
1206 | maptile * |
1207 | load_overlay_map (const char *filename, maptile *m) |
1207 | load_overlay_map (const char *filename, maptile *m) |
1208 | { |
1208 | { |
1209 | char pathname[MAX_BUF]; |
1209 | char pathname[MAX_BUF]; |
1210 | |
1210 | |
… | |
… | |
1260 | op->destroy (); |
1260 | op->destroy (); |
1261 | } |
1261 | } |
1262 | } |
1262 | } |
1263 | } |
1263 | } |
1264 | } |
1264 | } |
1265 | |
|
|
1266 | |
1265 | |
1267 | /* |
1266 | /* |
1268 | * Loads unique objects from file(s) into the map which is in memory |
1267 | * Loads unique objects from file(s) into the map which is in memory |
1269 | * m is the map to load unique items into. |
1268 | * m is the map to load unique items into. |
1270 | */ |
1269 | */ |
… | |
… | |
1487 | // TODO: use new/delete |
1486 | // TODO: use new/delete |
1488 | |
1487 | |
1489 | if (flag && m->spaces) |
1488 | if (flag && m->spaces) |
1490 | free_all_objects (m); |
1489 | free_all_objects (m); |
1491 | |
1490 | |
|
|
1491 | sfree (m->spaces, m->size ()), m->spaces = 0; |
|
|
1492 | |
1492 | free (m->name), m->name = 0; |
1493 | free (m->name), m->name = 0; |
1493 | free (m->spaces), m->spaces = 0; |
|
|
1494 | free (m->msg), m->msg = 0; |
1494 | free (m->msg), m->msg = 0; |
1495 | free (m->maplore), m->maplore = 0; |
1495 | free (m->maplore), m->maplore = 0; |
1496 | free (m->shoprace), m->shoprace = 0; |
1496 | free (m->shoprace), m->shoprace = 0; |
1497 | delete [] m->shopitems, m->shopitems = 0; |
1497 | delete [] m->shopitems, m->shopitems = 0; |
1498 | |
1498 | |
1499 | if (m->buttons) |
1499 | if (m->buttons) |
1500 | free_objectlinkpt (m->buttons), m->buttons = 0; |
1500 | free_objectlinkpt (m->buttons), m->buttons = 0; |
1501 | |
1501 | |
1502 | for (int i = 0; i < 4; i++) |
1502 | for (int i = 0; i < 4; i++) |
1503 | { |
|
|
1504 | if (m->tile_path[i]) |
|
|
1505 | free (m->tile_path[i]), m->tile_path[i] = 0; |
1503 | free (m->tile_path[i]), m->tile_path[i] = 0; |
1506 | |
|
|
1507 | m->tile_map[i] = 0; |
|
|
1508 | } |
|
|
1509 | |
1504 | |
1510 | m->in_memory = MAP_SWAPPED; |
1505 | m->in_memory = MAP_SWAPPED; |
1511 | } |
1506 | } |
1512 | |
1507 | |
1513 | maptile::~maptile () |
1508 | maptile::~maptile () |
1514 | { |
1509 | { |
1515 | free_map (this, 1); |
1510 | assert (destroyed ()); |
1516 | free (tmpname); |
|
|
1517 | } |
1511 | } |
1518 | |
1512 | |
1519 | void |
1513 | void |
1520 | maptile::do_destroy () |
1514 | maptile::do_destroy () |
1521 | { |
1515 | { |
1522 | attachable::do_destroy (); |
1516 | attachable::do_destroy (); |
1523 | |
1517 | |
1524 | free_all_objects (this); |
1518 | unlink (); |
|
|
1519 | |
|
|
1520 | free_map (this, 1); |
|
|
1521 | free (tmpname), tmpname = 0; |
1525 | |
1522 | |
1526 | /* We need to look through all the maps and see if any maps |
1523 | /* We need to look through all the maps and see if any maps |
1527 | * are pointing at this one for tiling information. Since |
1524 | * are pointing at this one for tiling information. Since |
1528 | * tiling can be asymetric, we just can not look to see which |
1525 | * tiling can be asymetric, we just can not look to see which |
1529 | * maps this map tiles with and clears those. |
1526 | * maps this map tiles with and clears those. |
1530 | */ |
1527 | */ |
1531 | //TODO: non-euclidean-tiling MUST GO |
1528 | //TODO: non-euclidean-tiling MUST GO |
1532 | for (maptile *m = first_map; m; m = m->next) |
1529 | for_all_maps (m) |
1533 | for (int i = 0; i < 4; i++) |
1530 | for (int i = 0; i < 4; i++) |
1534 | if (m->tile_map[i] == this) |
1531 | if (m->tile_map[i] == this) |
1535 | m->tile_map[i] = 0; |
1532 | m->tile_map[i] = 0; |
1536 | |
|
|
1537 | if (first_map == this) |
|
|
1538 | first_map = next; |
|
|
1539 | else |
|
|
1540 | for (maptile *m = first_map; m; m = m->next) |
|
|
1541 | if (m->next = this) |
|
|
1542 | { |
|
|
1543 | m->next = next; |
|
|
1544 | break; |
|
|
1545 | } |
|
|
1546 | } |
1533 | } |
1547 | |
1534 | |
1548 | //TODO: must go |
1535 | //TODO: must go |
1549 | void |
1536 | void |
1550 | delete_map (maptile *m) |
1537 | delete_map (maptile *m) |
… | |
… | |
1598 | if (flags & MAP_PLAYER_UNIQUE) |
1585 | if (flags & MAP_PLAYER_UNIQUE) |
1599 | LOG (llevDebug, "Trying to load map %s.\n", name); |
1586 | LOG (llevDebug, "Trying to load map %s.\n", name); |
1600 | else |
1587 | else |
1601 | LOG (llevDebug, "Trying to load map %s.\n", create_pathname (name)); |
1588 | LOG (llevDebug, "Trying to load map %s.\n", create_pathname (name)); |
1602 | |
1589 | |
1603 | //eval_pv ("$x = Event::time", 1);//D |
|
|
1604 | if (!(m = load_original_map (name, (flags & MAP_PLAYER_UNIQUE)))) |
1590 | if (!(m = load_original_map (name, (flags & MAP_PLAYER_UNIQUE)))) |
1605 | return (NULL); |
1591 | return (NULL); |
1606 | //eval_pv ("warn \"LOAD \", Event::time - $x", 1);//D |
|
|
1607 | |
1592 | |
1608 | fix_auto_apply (m); /* Chests which open as default */ |
1593 | fix_auto_apply (m); /* Chests which open as default */ |
1609 | |
1594 | |
1610 | /* If a player unique map, no extra unique object file to load. |
1595 | /* If a player unique map, no extra unique object file to load. |
1611 | * if from the editor, likewise. |
1596 | * if from the editor, likewise. |
… | |
… | |
1747 | if (first_map->in_memory == MAP_SAVING) |
1732 | if (first_map->in_memory == MAP_SAVING) |
1748 | first_map->in_memory = MAP_IN_MEMORY; |
1733 | first_map->in_memory = MAP_IN_MEMORY; |
1749 | delete_map (first_map); |
1734 | delete_map (first_map); |
1750 | real_maps++; |
1735 | real_maps++; |
1751 | } |
1736 | } |
|
|
1737 | |
1752 | LOG (llevDebug, "free_all_maps: Freed %d maps\n", real_maps); |
1738 | LOG (llevDebug, "free_all_maps: Freed %d maps\n", real_maps); |
1753 | } |
1739 | } |
1754 | |
1740 | |
1755 | /* change_map_light() - used to change map light level (darkness) |
1741 | /* change_map_light() - used to change map light level (darkness) |
1756 | * up or down. Returns true if successful. It should now be |
1742 | * up or down. Returns true if successful. It should now be |