… | |
… | |
409 | flag = get_map_flags (m, &m1, x, y, &sx, &sy); |
409 | flag = get_map_flags (m, &m1, x, y, &sx, &sy); |
410 | if (flag & P_OUT_OF_MAP) |
410 | if (flag & P_OUT_OF_MAP) |
411 | return P_OUT_OF_MAP; |
411 | return P_OUT_OF_MAP; |
412 | |
412 | |
413 | /* don't have object, so don't know what types would block */ |
413 | /* don't have object, so don't know what types would block */ |
414 | return (GET_MAP_MOVE_BLOCK (m1, sx, sy)); |
414 | return m1->at (sx, sy).move_block; |
415 | } |
415 | } |
416 | |
416 | |
417 | for (tmp = ob->arch; tmp != NULL; tmp = tmp->more) |
417 | for (tmp = ob->arch; tmp; tmp = tmp->more) |
418 | { |
418 | { |
419 | flag = get_map_flags (m, &m1, x + tmp->clone.x, y + tmp->clone.y, &sx, &sy); |
419 | flag = get_map_flags (m, &m1, x + tmp->clone.x, y + tmp->clone.y, &sx, &sy); |
420 | |
420 | |
421 | if (flag & P_OUT_OF_MAP) |
421 | if (flag & P_OUT_OF_MAP) |
422 | return P_OUT_OF_MAP; |
422 | return P_OUT_OF_MAP; |
423 | if (flag & P_IS_ALIVE) |
423 | if (flag & P_IS_ALIVE) |
424 | return P_IS_ALIVE; |
424 | return P_IS_ALIVE; |
425 | |
425 | |
|
|
426 | mapspace &ms = m1->at (sx, sy); |
|
|
427 | |
|
|
428 | |
426 | /* find_first_free_spot() calls this function. However, often |
429 | /* find_first_free_spot() calls this function. However, often |
427 | * ob doesn't have any move type (when used to place exits) |
430 | * ob doesn't have any move type (when used to place exits) |
428 | * so the AND operation in OB_TYPE_MOVE_BLOCK doesn't work. |
431 | * so the AND operation in OB_TYPE_MOVE_BLOCK doesn't work. |
429 | */ |
432 | */ |
430 | |
433 | |
431 | if (ob->move_type == 0 && GET_MAP_MOVE_BLOCK (m1, sx, sy) != MOVE_ALL) |
434 | if (ob->move_type == 0 && ms.move_block != MOVE_ALL) |
432 | continue; |
435 | continue; |
433 | |
436 | |
434 | /* Note it is intentional that we check ob - the movement type of the |
437 | /* Note it is intentional that we check ob - the movement type of the |
435 | * head of the object should correspond for the entire object. |
438 | * head of the object should correspond for the entire object. |
436 | */ |
439 | */ |
437 | if (OB_TYPE_MOVE_BLOCK (ob, GET_MAP_MOVE_BLOCK (m1, sx, sy))) |
440 | if (OB_TYPE_MOVE_BLOCK (ob, ms.move_block)) |
438 | return P_NO_PASS; |
441 | return P_NO_PASS; |
439 | } |
442 | } |
440 | |
443 | |
441 | return 0; |
444 | return 0; |
442 | } |
445 | } |
… | |
… | |
541 | if (op->arch == NULL) |
544 | if (op->arch == NULL) |
542 | { |
545 | { |
543 | LOG (llevDebug, "Discarding object without arch: %s\n", op->name ? (const char *) op->name : "(null)"); |
546 | LOG (llevDebug, "Discarding object without arch: %s\n", op->name ? (const char *) op->name : "(null)"); |
544 | continue; |
547 | continue; |
545 | } |
548 | } |
546 | |
|
|
547 | |
549 | |
548 | switch (i) |
550 | switch (i) |
549 | { |
551 | { |
550 | case LL_NORMAL: |
552 | case LL_NORMAL: |
551 | /* if we are loading an overlay, put the floors on the bottom */ |
553 | /* if we are loading an overlay, put the floors on the bottom */ |
… | |
… | |
1121 | strcpy (m->path, filename); |
1123 | strcpy (m->path, filename); |
1122 | if (load_map_header (thawer, m)) |
1124 | if (load_map_header (thawer, m)) |
1123 | { |
1125 | { |
1124 | LOG (llevError, "Error loading map header for %s, flags=%d\n", filename, flags); |
1126 | LOG (llevError, "Error loading map header for %s, flags=%d\n", filename, flags); |
1125 | delete_map (m); |
1127 | delete_map (m); |
1126 | return NULL; |
1128 | return 0; |
1127 | } |
1129 | } |
1128 | |
1130 | |
1129 | m->allocate (); |
1131 | m->allocate (); |
1130 | |
1132 | |
1131 | m->in_memory = MAP_LOADING; |
1133 | m->in_memory = MAP_LOADING; |
… | |
… | |
1214 | if (load_map_header (thawer, m)) |
1216 | if (load_map_header (thawer, m)) |
1215 | { |
1217 | { |
1216 | LOG (llevError, "Error loading map header for overlay %s (%s)\n", m->path, pathname); |
1218 | LOG (llevError, "Error loading map header for overlay %s (%s)\n", m->path, pathname); |
1217 | delete_map (m); |
1219 | delete_map (m); |
1218 | m = load_original_map (m->path, 0); |
1220 | m = load_original_map (m->path, 0); |
1219 | return NULL; |
1221 | return 0; |
1220 | } |
1222 | } |
1221 | /*m->allocate ();*/ |
1223 | /*m->allocate ();*/ |
1222 | |
1224 | |
1223 | m->in_memory = MAP_LOADING; |
1225 | m->in_memory = MAP_LOADING; |
1224 | load_objects (m, thawer, MAP_OVERLAY); |
1226 | load_objects (m, thawer, MAP_OVERLAY); |
… | |
… | |
1250 | if (QUERY_FLAG (op, FLAG_IS_FLOOR) && QUERY_FLAG (op, FLAG_UNIQUE)) |
1252 | if (QUERY_FLAG (op, FLAG_IS_FLOOR) && QUERY_FLAG (op, FLAG_UNIQUE)) |
1251 | unique = 1; |
1253 | unique = 1; |
1252 | |
1254 | |
1253 | if (op->head == NULL && (QUERY_FLAG (op, FLAG_UNIQUE) || unique)) |
1255 | if (op->head == NULL && (QUERY_FLAG (op, FLAG_UNIQUE) || unique)) |
1254 | { |
1256 | { |
1255 | clean_object (op); |
1257 | op->destroy_inv (false); |
1256 | |
|
|
1257 | if (QUERY_FLAG (op, FLAG_IS_LINKED)) |
|
|
1258 | remove_button_link (op); |
|
|
1259 | |
|
|
1260 | op->destroy (); |
1258 | op->destroy (); |
1261 | } |
1259 | } |
1262 | } |
1260 | } |
1263 | } |
1261 | } |
1264 | } |
1262 | } |
… | |
… | |
1446 | freezer.save (filename); |
1444 | freezer.save (filename); |
1447 | |
1445 | |
1448 | return 0; |
1446 | return 0; |
1449 | } |
1447 | } |
1450 | |
1448 | |
1451 | |
|
|
1452 | /* |
|
|
1453 | * Remove and free all objects in the inventory of the given object. |
|
|
1454 | * object.c ? |
|
|
1455 | */ |
|
|
1456 | |
|
|
1457 | void |
|
|
1458 | clean_object (object *op) |
|
|
1459 | { |
|
|
1460 | object *tmp, *next; |
|
|
1461 | |
|
|
1462 | for (tmp = op->inv; tmp; tmp = next) |
|
|
1463 | { |
|
|
1464 | next = tmp->below; |
|
|
1465 | |
|
|
1466 | clean_object (tmp); |
|
|
1467 | if (QUERY_FLAG (tmp, FLAG_IS_LINKED)) |
|
|
1468 | remove_button_link (tmp); |
|
|
1469 | |
|
|
1470 | tmp->destroy (); |
|
|
1471 | } |
|
|
1472 | } |
|
|
1473 | |
|
|
1474 | /* |
1449 | /* |
1475 | * Remove and free all objects in the given map. |
1450 | * Remove and free all objects in the given map. |
1476 | */ |
1451 | */ |
1477 | |
|
|
1478 | void |
1452 | void |
1479 | free_all_objects (maptile *m) |
1453 | free_all_objects (maptile *m) |
1480 | { |
1454 | { |
1481 | int i, j; |
1455 | if (!m->spaces) |
1482 | object *op; |
1456 | return; |
1483 | |
1457 | |
1484 | for (i = 0; i < MAP_WIDTH (m); i++) |
1458 | for (int i = 0; i < MAP_WIDTH (m); i++) |
1485 | for (j = 0; j < MAP_HEIGHT (m); j++) |
1459 | for (int j = 0; j < MAP_HEIGHT (m); j++) |
1486 | { |
1460 | { |
1487 | object *previous_obj = NULL; |
1461 | mapspace &ms = m->at (i, j); |
1488 | |
1462 | |
1489 | while ((op = GET_MAP_OB (m, i, j)) != NULL) |
1463 | while (object *op = ms.bottom) |
1490 | { |
1464 | { |
1491 | if (op == previous_obj) |
|
|
1492 | { |
|
|
1493 | LOG (llevDebug, "free_all_objects: Link error, bailing out.\n"); |
|
|
1494 | break; |
|
|
1495 | } |
|
|
1496 | |
|
|
1497 | previous_obj = op; |
|
|
1498 | |
|
|
1499 | if (op->head != NULL) |
1465 | if (op->head) |
1500 | op = op->head; |
1466 | op = op->head; |
1501 | |
1467 | |
1502 | /* If the map isn't in memory, free_object will remove and |
1468 | op->destroy_inv (false); |
1503 | * free objects in op's inventory. So let it do the job. |
|
|
1504 | */ |
|
|
1505 | if (m->in_memory == MAP_IN_MEMORY) |
|
|
1506 | clean_object (op); |
|
|
1507 | |
|
|
1508 | op->destroy (); |
1469 | op->destroy (); |
1509 | } |
1470 | } |
1510 | } |
1471 | } |
1511 | } |
1472 | } |
1512 | |
1473 | |
1513 | /* |
1474 | /* |
1514 | * Frees everything allocated by the given maptileure. |
1475 | * Frees everything allocated by the given maptileure. |
1515 | * don't free tmpname - our caller is left to do that |
1476 | * don't free tmpname - our caller is left to do that |
1516 | */ |
1477 | */ |
1517 | |
|
|
1518 | void |
1478 | void |
1519 | free_map (maptile *m, int flag) |
1479 | free_map (maptile *m, int flag) |
1520 | { |
1480 | { |
1521 | int i; |
1481 | if (m->in_memory != MAP_IN_MEMORY) |
1522 | |
|
|
1523 | if (!m->in_memory) |
|
|
1524 | { |
|
|
1525 | LOG (llevError, "Trying to free freed map.\n"); |
|
|
1526 | return; |
1482 | return; |
1527 | } |
1483 | |
|
|
1484 | m->in_memory = MAP_SAVING; |
1528 | |
1485 | |
1529 | // TODO: use new/delete |
1486 | // TODO: use new/delete |
1530 | #define FREE_AND_CLEAR(p) { free (p); p = NULL; } |
1487 | #define FREE_AND_CLEAR(p) { free (p); p = NULL; } |
1531 | |
1488 | |
1532 | if (flag && m->spaces) |
1489 | if (flag && m->spaces) |
… | |
… | |
1549 | if (m->buttons) |
1506 | if (m->buttons) |
1550 | free_objectlinkpt (m->buttons); |
1507 | free_objectlinkpt (m->buttons); |
1551 | |
1508 | |
1552 | m->buttons = NULL; |
1509 | m->buttons = NULL; |
1553 | |
1510 | |
1554 | for (i = 0; i < 4; i++) |
1511 | for (int i = 0; i < 4; i++) |
1555 | { |
1512 | { |
1556 | if (m->tile_path[i]) |
1513 | if (m->tile_path[i]) |
1557 | FREE_AND_CLEAR (m->tile_path[i]); |
1514 | FREE_AND_CLEAR (m->tile_path[i]); |
|
|
1515 | |
1558 | m->tile_map[i] = NULL; |
1516 | m->tile_map[i] = 0; |
1559 | } |
1517 | } |
1560 | |
1518 | |
1561 | m->in_memory = MAP_SWAPPED; |
1519 | m->in_memory = MAP_SWAPPED; |
1562 | |
1520 | |
1563 | #undef FREE_AND_CLEAR |
1521 | #undef FREE_AND_CLEAR |
1564 | |
|
|
1565 | } |
1522 | } |
1566 | |
1523 | |
1567 | /* |
1524 | maptile::~maptile () |
1568 | * function: vanish maptile |
1525 | { |
1569 | * m : pointer to maptile, if NULL no action |
1526 | free_map (this, 1); |
1570 | * this deletes all the data on the map (freeing pointers) |
1527 | free (tmpname); |
1571 | * and then removes this map from the global linked list of maps. |
1528 | } |
|
|
1529 | |
|
|
1530 | void |
|
|
1531 | maptile::do_destroy () |
|
|
1532 | { |
|
|
1533 | attachable::do_destroy (); |
|
|
1534 | |
|
|
1535 | free_all_objects (this); |
|
|
1536 | |
|
|
1537 | /* We need to look through all the maps and see if any maps |
|
|
1538 | * are pointing at this one for tiling information. Since |
|
|
1539 | * tiling can be asymetric, we just can not look to see which |
|
|
1540 | * maps this map tiles with and clears those. |
1572 | */ |
1541 | */ |
|
|
1542 | //TODO: non-euclidean-tiling MUST GO |
|
|
1543 | for (maptile *m = first_map; m; m = m->next) |
|
|
1544 | for (int i = 0; i < 4; i++) |
|
|
1545 | if (m->tile_map[i] == this) |
|
|
1546 | m->tile_map[i] = 0; |
1573 | |
1547 | |
|
|
1548 | if (first_map == this) |
|
|
1549 | first_map = next; |
|
|
1550 | else |
|
|
1551 | for (maptile *m = first_map; m; m = m->next) |
|
|
1552 | if (m->next = this) |
|
|
1553 | { |
|
|
1554 | m->next = next; |
|
|
1555 | break; |
|
|
1556 | } |
|
|
1557 | } |
|
|
1558 | |
|
|
1559 | //TODO: must go |
1574 | void |
1560 | void |
1575 | delete_map (maptile *m) |
1561 | delete_map (maptile *m) |
1576 | { |
1562 | { |
1577 | maptile *tmp, *last; |
|
|
1578 | int i; |
|
|
1579 | |
|
|
1580 | if (!m) |
1563 | if (m) |
1581 | return; |
1564 | m->destroy (); |
1582 | |
|
|
1583 | m->clear (); |
|
|
1584 | |
|
|
1585 | if (m->in_memory == MAP_IN_MEMORY) |
|
|
1586 | { |
|
|
1587 | /* change to MAP_SAVING, even though we are not, |
|
|
1588 | * so that remove_ob doesn't do as much work. |
|
|
1589 | */ |
|
|
1590 | m->in_memory = MAP_SAVING; |
|
|
1591 | free_map (m, 1); |
|
|
1592 | } |
|
|
1593 | /* move this out of free_map, since tmpname can still be needed if |
|
|
1594 | * the map is swapped out. |
|
|
1595 | */ |
|
|
1596 | if (m->tmpname) |
|
|
1597 | { |
|
|
1598 | free (m->tmpname); |
|
|
1599 | m->tmpname = NULL; |
|
|
1600 | } |
|
|
1601 | last = NULL; |
|
|
1602 | /* We need to look through all the maps and see if any maps |
|
|
1603 | * are pointing at this one for tiling information. Since |
|
|
1604 | * tiling can be assymetric, we just can not look to see which |
|
|
1605 | * maps this map tiles with and clears those. |
|
|
1606 | */ |
|
|
1607 | for (tmp = first_map; tmp != NULL; tmp = tmp->next) |
|
|
1608 | { |
|
|
1609 | if (tmp->next == m) |
|
|
1610 | last = tmp; |
|
|
1611 | |
|
|
1612 | /* This should hopefully get unrolled on a decent compiler */ |
|
|
1613 | for (i = 0; i < 4; i++) |
|
|
1614 | if (tmp->tile_map[i] == m) |
|
|
1615 | tmp->tile_map[i] = NULL; |
|
|
1616 | } |
|
|
1617 | |
|
|
1618 | /* If last is null, then this should be the first map in the list */ |
|
|
1619 | if (!last) |
|
|
1620 | { |
|
|
1621 | if (m == first_map) |
|
|
1622 | first_map = m->next; |
|
|
1623 | else |
|
|
1624 | /* m->path is a static char, so should hopefully still have |
|
|
1625 | * some useful data in it. |
|
|
1626 | */ |
|
|
1627 | LOG (llevError, "delete_map: Unable to find map %s in list\n", m->path); |
|
|
1628 | } |
|
|
1629 | else |
|
|
1630 | last->next = m->next; |
|
|
1631 | |
|
|
1632 | delete m; |
|
|
1633 | } |
1565 | } |
1634 | |
1566 | |
1635 | /* |
1567 | /* |
1636 | * Makes sure the given map is loaded and swapped in. |
1568 | * Makes sure the given map is loaded and swapped in. |
1637 | * name is path name of the map. |
1569 | * name is path name of the map. |
… | |
… | |
1644 | * Returns a pointer to the given map. |
1576 | * Returns a pointer to the given map. |
1645 | */ |
1577 | */ |
1646 | maptile * |
1578 | maptile * |
1647 | ready_map_name (const char *name, int flags) |
1579 | ready_map_name (const char *name, int flags) |
1648 | { |
1580 | { |
1649 | maptile *m; |
|
|
1650 | |
|
|
1651 | if (!name) |
1581 | if (!name) |
1652 | return (NULL); |
1582 | return 0; |
1653 | |
1583 | |
1654 | /* Have we been at this level before? */ |
1584 | /* Have we been at this level before? */ |
1655 | m = has_been_loaded (name); |
1585 | maptile *m = has_been_loaded (name); |
1656 | |
1586 | |
1657 | /* Map is good to go, so just return it */ |
1587 | /* Map is good to go, so just return it */ |
1658 | if (m && (m->in_memory == MAP_LOADING || m->in_memory == MAP_IN_MEMORY)) |
1588 | if (m && (m->in_memory == MAP_LOADING || m->in_memory == MAP_IN_MEMORY)) |
1659 | { |
|
|
1660 | return m; |
1589 | return m; |
1661 | } |
|
|
1662 | |
1590 | |
1663 | /* unique maps always get loaded from their original location, and never |
1591 | /* unique maps always get loaded from their original location, and never |
1664 | * a temp location. Likewise, if map_flush is set, or we have never loaded |
1592 | * a temp location. Likewise, if map_flush is set, or we have never loaded |
1665 | * this map, load it now. I removed the reset checking from here - |
1593 | * this map, load it now. I removed the reset checking from here - |
1666 | * it seems the probability of a player trying to enter a map that should |
1594 | * it seems the probability of a player trying to enter a map that should |
… | |
… | |
1668 | * a bit cleaner (and players probably shouldn't rely on exact timing for |
1596 | * a bit cleaner (and players probably shouldn't rely on exact timing for |
1669 | * resets in any case - if they really care, they should use the 'maps command. |
1597 | * resets in any case - if they really care, they should use the 'maps command. |
1670 | */ |
1598 | */ |
1671 | if ((flags & (MAP_FLUSH | MAP_PLAYER_UNIQUE)) || !m) |
1599 | if ((flags & (MAP_FLUSH | MAP_PLAYER_UNIQUE)) || !m) |
1672 | { |
1600 | { |
1673 | |
|
|
1674 | /* first visit or time to reset */ |
1601 | /* first visit or time to reset */ |
1675 | if (m) |
1602 | if (m) |
1676 | { |
1603 | { |
1677 | clean_tmp_map (m); /* Doesn't make much difference */ |
1604 | clean_tmp_map (m); /* Doesn't make much difference */ |
1678 | delete_map (m); |
1605 | delete_map (m); |