ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.C
(Generate patch)

Comparing deliantra/server/common/object.C (file contents):
Revision 1.24 by root, Sun Sep 10 16:00:23 2006 UTC vs.
Revision 1.27 by root, Mon Sep 11 12:08:45 2006 UTC

1 1
2/* 2/*
3 * static char *rcsid_object_c = 3 * static char *rcsid_object_c =
4 * "$Id: object.C,v 1.24 2006/09/10 16:00:23 root Exp $"; 4 * "$Id: object.C,v 1.27 2006/09/11 12:08:45 root Exp $";
5 */ 5 */
6 6
7/* 7/*
8 CrossFire, A Multiplayer game for X-windows 8 CrossFire, A Multiplayer game for X-windows
9 9
507 507
508 op->owner = owner; 508 op->owner = owner;
509 509
510 op->ownercount = owner->count; 510 op->ownercount = owner->count;
511 owner->refcount++; 511 owner->refcount++;
512
513} 512}
514 513
515/* Set the owner to clone's current owner and set the skill and experience 514/* Set the owner to clone's current owner and set the skill and experience
516 * objects to clone's objects (typically those objects that where the owner's 515 * objects to clone's objects (typically those objects that where the owner's
517 * current skill and experience objects at the time when clone's owner was 516 * current skill and experience objects at the time when clone's owner was
535 if (clone->type == PLAYER) 534 if (clone->type == PLAYER)
536 owner = clone; 535 owner = clone;
537 else 536 else
538 return; 537 return;
539 } 538 }
539
540 set_owner (op, owner); 540 set_owner (op, owner);
541
542} 541}
543 542
544/* Zero the key_values on op, decrementing the shared-string 543/* Zero the key_values on op, decrementing the shared-string
545 * refcounts and freeing the links. 544 * refcounts and freeing the links.
546 */ 545 */
561void object::clear () 560void object::clear ()
562{ 561{
563 attachable_base::clear (); 562 attachable_base::clear ();
564 563
565 free_key_values (this); 564 free_key_values (this);
565
566 clear_owner (this);
566 567
567 name = 0; 568 name = 0;
568 name_pl = 0; 569 name_pl = 0;
569 title = 0; 570 title = 0;
570 race = 0; 571 race = 0;
890 /* if the object is being removed, we can't make intelligent 891 /* if the object is being removed, we can't make intelligent
891 * decisions, because remove_ob can't really pass the object 892 * decisions, because remove_ob can't really pass the object
892 * that is being removed. 893 * that is being removed.
893 */ 894 */
894 else if (action == UP_OBJ_CHANGE || action == UP_OBJ_REMOVE) 895 else if (action == UP_OBJ_CHANGE || action == UP_OBJ_REMOVE)
895 {
896 update_now = 1; 896 update_now = 1;
897 }
898 else if (action == UP_OBJ_FACE) 897 else if (action == UP_OBJ_FACE)
899 {
900 /* Nothing to do for that case */ 898 /* Nothing to do for that case */;
901 }
902 else 899 else
903 {
904 LOG (llevError, "update_object called with invalid action: %d\n", action); 900 LOG (llevError, "update_object called with invalid action: %d\n", action);
905 }
906 901
907 if (update_now) 902 if (update_now)
908 { 903 {
909 SET_MAP_FLAGS (op->map, op->x, op->y, flags | P_NO_ERROR | P_NEED_UPDATE); 904 SET_MAP_FLAGS (op->map, op->x, op->y, flags | P_NO_ERROR | P_NEED_UPDATE);
910 update_position (op->map, op->x, op->y); 905 update_position (op->map, op->x, op->y);
912 907
913 if (op->more != NULL) 908 if (op->more != NULL)
914 update_object (op->more, action); 909 update_object (op->more, action);
915} 910}
916 911
917static 912static unordered_vector<object *> mortals;
918std::vector < object *> 913static std::vector<object *> freed;
919 mortals;
920 914
921void object::free_mortals () 915void object::free_mortals ()
922{ 916{
923 for (std::vector < object *>::iterator i = mortals.begin (); i != mortals.end (); ++i) 917 for (unordered_vector<object *>::iterator i = mortals.begin (); i != mortals.end (); )
924 delete * 918 if (!(*i)->refcount)
919 {
920 freed.push_back (*i);
921 mortals.erase (i);
922 }
923 else
925 i; 924 ++i;
926
927 mortals.clear ();
928} 925}
929 926
930object::object () 927object::object ()
931{ 928{
932 SET_FLAG (this, FLAG_REMOVED); 929 SET_FLAG (this, FLAG_REMOVED);
958{ 955{
959 count = 0; 956 count = 0;
960 957
961 /* Remove this object from the list of used objects */ 958 /* Remove this object from the list of used objects */
962 if (prev) 959 if (prev)
960 {
963 prev->next = next; 961 prev->next = next;
962 prev = 0;
963 }
964
964 if (next) 965 if (next)
966 {
965 next->prev = prev; 967 next->prev = prev;
968 next = 0;
969 }
970
966 if (this == objects) 971 if (this == objects)
967 objects = next; 972 objects = next;
968} 973}
969 974
970object *object::create () 975object *object::create ()
971{ 976{
972 object * 977 object *op;
978
979 if (freed.empty ())
973 op = new object; 980 op = new object;
981 else
982 {
983 // highly annoying, but the only way to get it stable right now
984 op = freed.back (); freed.pop_back ();
985 op->~object ();
986 new ((void *)op) object;
987 }
974 988
975 op->link (); 989 op->link ();
976 return op; 990 return op;
977} 991}
978 992
1062 op = tmp; 1076 op = tmp;
1063 } 1077 }
1064 } 1078 }
1065 } 1079 }
1066 1080
1081 clear_owner (this);
1082
1067 /* Remove object from the active list */ 1083 /* Remove object from the active list */
1068 speed = 0; 1084 speed = 0;
1069 update_ob_speed (this); 1085 update_ob_speed (this);
1070 1086
1071 unlink (); 1087 unlink ();
1104 */ 1120 */
1105 1121
1106void 1122void
1107remove_ob (object *op) 1123remove_ob (object *op)
1108{ 1124{
1125 object *tmp, *last = NULL;
1109 object * 1126 object *otmp;
1110 tmp, * 1127
1111 last = NULL; 1128 tag_t tag;
1112 object *
1113 otmp;
1114 tag_t
1115 tag;
1116 int
1117 check_walk_off; 1129 int check_walk_off;
1118 mapstruct * 1130 mapstruct *m;
1119 m;
1120 sint16
1121 x,
1122 y;
1123 1131
1132 sint16 x, y;
1124 1133
1125 if (QUERY_FLAG (op, FLAG_REMOVED)) 1134 if (QUERY_FLAG (op, FLAG_REMOVED))
1126 { 1135 {
1127 dump_object (op); 1136 dump_object (op);
1128 LOG (llevError, "Trying to remove removed object.\n%s\n", errmsg); 1137 LOG (llevError, "Trying to remove removed object.\n%s\n", errmsg);
1137 * so is easily enough restarted without any real problems. 1146 * so is easily enough restarted without any real problems.
1138 * MSW 2001-07-01 1147 * MSW 2001-07-01
1139 */ 1148 */
1140 abort (); 1149 abort ();
1141 } 1150 }
1151
1142 if (op->more != NULL) 1152 if (op->more != NULL)
1143 remove_ob (op->more); 1153 remove_ob (op->more);
1144 1154
1145 SET_FLAG (op, FLAG_REMOVED); 1155 SET_FLAG (op, FLAG_REMOVED);
1146 1156
1215 else 1225 else
1216 SET_MAP_TOP (m, x, y, op->below); /* we were top, set new top */ 1226 SET_MAP_TOP (m, x, y, op->below); /* we were top, set new top */
1217 1227
1218 /* Relink the object below us, if there is one */ 1228 /* Relink the object below us, if there is one */
1219 if (op->below) 1229 if (op->below)
1220 {
1221 op->below->above = op->above; 1230 op->below->above = op->above;
1222 }
1223 else 1231 else
1224 { 1232 {
1225 /* Nothing below, which means we need to relink map object for this space 1233 /* Nothing below, which means we need to relink map object for this space
1226 * use translated coordinates in case some oddness with map tiling is 1234 * use translated coordinates in case some oddness with map tiling is
1227 * evident 1235 * evident
1232 LOG (llevError, "remove_ob: GET_MAP_OB does not return object to be removed even though it appears to be on the bottom?\n%s\n", 1240 LOG (llevError, "remove_ob: GET_MAP_OB does not return object to be removed even though it appears to be on the bottom?\n%s\n",
1233 errmsg); 1241 errmsg);
1234 dump_object (GET_MAP_OB (m, x, y)); 1242 dump_object (GET_MAP_OB (m, x, y));
1235 LOG (llevError, "%s\n", errmsg); 1243 LOG (llevError, "%s\n", errmsg);
1236 } 1244 }
1245
1237 SET_MAP_OB (m, x, y, op->above); /* goes on above it. */ 1246 SET_MAP_OB (m, x, y, op->above); /* goes on above it. */
1238 } 1247 }
1248
1239 op->above = NULL; 1249 op->above = NULL;
1240 op->below = NULL; 1250 op->below = NULL;
1241 1251
1242 if (op->map->in_memory == MAP_SAVING) 1252 if (op->map->in_memory == MAP_SAVING)
1243 return; 1253 return;
1244 1254
1245 tag = op->count; 1255 tag = op->count;
1246 check_walk_off = !QUERY_FLAG (op, FLAG_NO_APPLY); 1256 check_walk_off = !QUERY_FLAG (op, FLAG_NO_APPLY);
1257
1247 for (tmp = GET_MAP_OB (m, x, y); tmp != NULL; tmp = tmp->above) 1258 for (tmp = GET_MAP_OB (m, x, y); tmp != NULL; tmp = tmp->above)
1248 { 1259 {
1249 /* No point updating the players look faces if he is the object 1260 /* No point updating the players look faces if he is the object
1250 * being removed. 1261 * being removed.
1251 */ 1262 */
1259 if (tmp->container == op) 1270 if (tmp->container == op)
1260 { 1271 {
1261 CLEAR_FLAG (op, FLAG_APPLIED); 1272 CLEAR_FLAG (op, FLAG_APPLIED);
1262 tmp->container = NULL; 1273 tmp->container = NULL;
1263 } 1274 }
1275
1264 tmp->contr->socket.update_look = 1; 1276 tmp->contr->socket.update_look = 1;
1265 } 1277 }
1266 /* See if player moving off should effect something */ 1278 /* See if player moving off should effect something */
1267 if (check_walk_off && ((op->move_type & tmp->move_off) && (op->move_type & ~tmp->move_off & ~tmp->move_block) == 0)) 1279 if (check_walk_off && ((op->move_type & tmp->move_off) && (op->move_type & ~tmp->move_off & ~tmp->move_block) == 0))
1268 { 1280 {
1269
1270 move_apply (tmp, op, NULL); 1281 move_apply (tmp, op, NULL);
1282
1271 if (was_destroyed (op, tag)) 1283 if (was_destroyed (op, tag))
1272 { 1284 {
1273 LOG (llevError, "BUG: remove_ob(): name %s, archname %s destroyed " "leaving object\n", &tmp->name, &tmp->arch->name); 1285 LOG (llevError, "BUG: remove_ob(): name %s, archname %s destroyed " "leaving object\n", &tmp->name, &tmp->arch->name);
1274 } 1286 }
1275 } 1287 }
1276 1288
1277 /* Eneq(@csd.uu.se): Fixed this to skip tmp->above=tmp */ 1289 /* Eneq(@csd.uu.se): Fixed this to skip tmp->above=tmp */
1278 1290
1279 if (tmp->above == tmp) 1291 if (tmp->above == tmp)
1280 tmp->above = NULL; 1292 tmp->above = NULL;
1293
1281 last = tmp; 1294 last = tmp;
1282 } 1295 }
1296
1283 /* last == NULL of there are no objects on this space */ 1297 /* last == NULL of there are no objects on this space */
1284 if (last == NULL) 1298 if (last == NULL)
1285 { 1299 {
1286 /* set P_NEED_UPDATE, otherwise update_position will complain. In theory, 1300 /* set P_NEED_UPDATE, otherwise update_position will complain. In theory,
1287 * we could preserve the flags (GET_MAP_FLAGS), but update_position figures 1301 * we could preserve the flags (GET_MAP_FLAGS), but update_position figures
1294 else 1308 else
1295 update_object (last, UP_OBJ_REMOVE); 1309 update_object (last, UP_OBJ_REMOVE);
1296 1310
1297 if (QUERY_FLAG (op, FLAG_BLOCKSVIEW) || (op->glow_radius != 0)) 1311 if (QUERY_FLAG (op, FLAG_BLOCKSVIEW) || (op->glow_radius != 0))
1298 update_all_los (op->map, op->x, op->y); 1312 update_all_los (op->map, op->x, op->y);
1299
1300} 1313}
1301 1314
1302/* 1315/*
1303 * merge_ob(op,top): 1316 * merge_ob(op,top):
1304 * 1317 *
1375 */ 1388 */
1376 1389
1377object * 1390object *
1378insert_ob_in_map (object *op, mapstruct *m, object *originator, int flag) 1391insert_ob_in_map (object *op, mapstruct *m, object *originator, int flag)
1379{ 1392{
1380 object * 1393 object *tmp, *top, *floor = NULL;
1381 tmp, * 1394 sint16 x, y;
1382 top, *
1383 floor = NULL;
1384 sint16
1385 x,
1386 y;
1387 1395
1388 if (QUERY_FLAG (op, FLAG_FREED)) 1396 if (QUERY_FLAG (op, FLAG_FREED))
1389 { 1397 {
1390 LOG (llevError, "Trying to insert freed object!\n"); 1398 LOG (llevError, "Trying to insert freed object!\n");
1391 return NULL; 1399 return NULL;
1392 } 1400 }
1401
1393 if (m == NULL) 1402 if (m == NULL)
1394 { 1403 {
1395 dump_object (op); 1404 dump_object (op);
1396 LOG (llevError, "Trying to insert in null-map!\n%s\n", errmsg); 1405 LOG (llevError, "Trying to insert in null-map!\n%s\n", errmsg);
1397 return op; 1406 return op;
1398 } 1407 }
1408
1399 if (out_of_map (m, op->x, op->y)) 1409 if (out_of_map (m, op->x, op->y))
1400 { 1410 {
1401 dump_object (op); 1411 dump_object (op);
1402 LOG (llevError, "Trying to insert object outside the map.\n%s\n", errmsg); 1412 LOG (llevError, "Trying to insert object outside the map.\n%s\n", errmsg);
1403#ifdef MANY_CORES 1413#ifdef MANY_CORES
1407 */ 1417 */
1408 abort (); 1418 abort ();
1409#endif 1419#endif
1410 return op; 1420 return op;
1411 } 1421 }
1422
1412 if (!QUERY_FLAG (op, FLAG_REMOVED)) 1423 if (!QUERY_FLAG (op, FLAG_REMOVED))
1413 { 1424 {
1414 dump_object (op); 1425 dump_object (op);
1415 LOG (llevError, "Trying to insert (map) inserted object.\n%s\n", errmsg); 1426 LOG (llevError, "Trying to insert (map) inserted object.\n%s\n", errmsg);
1416 return op; 1427 return op;
1417 } 1428 }
1429
1418 if (op->more != NULL) 1430 if (op->more != NULL)
1419 { 1431 {
1420 /* The part may be on a different map. */ 1432 /* The part may be on a different map. */
1421 1433
1422 object *
1423 more = op->more; 1434 object *more = op->more;
1424 1435
1425 /* We really need the caller to normalize coordinates - if 1436 /* We really need the caller to normalize coordinates - if
1426 * we set the map, that doesn't work if the location is within 1437 * we set the map, that doesn't work if the location is within
1427 * a map and this is straddling an edge. So only if coordinate 1438 * a map and this is straddling an edge. So only if coordinate
1428 * is clear wrong do we normalize it. 1439 * is clear wrong do we normalize it.
1429 */ 1440 */
1430 if (OUT_OF_REAL_MAP (more->map, more->x, more->y)) 1441 if (OUT_OF_REAL_MAP (more->map, more->x, more->y))
1431 {
1432 more->map = get_map_from_coord (m, &more->x, &more->y); 1442 more->map = get_map_from_coord (m, &more->x, &more->y);
1433 }
1434 else if (!more->map) 1443 else if (!more->map)
1435 { 1444 {
1436 /* For backwards compatibility - when not dealing with tiled maps, 1445 /* For backwards compatibility - when not dealing with tiled maps,
1437 * more->map should always point to the parent. 1446 * more->map should always point to the parent.
1438 */ 1447 */
1441 1450
1442 if (insert_ob_in_map (more, more->map, originator, flag) == NULL) 1451 if (insert_ob_in_map (more, more->map, originator, flag) == NULL)
1443 { 1452 {
1444 if (!op->head) 1453 if (!op->head)
1445 LOG (llevError, "BUG: insert_ob_in_map(): inserting op->more killed op\n"); 1454 LOG (llevError, "BUG: insert_ob_in_map(): inserting op->more killed op\n");
1455
1446 return NULL; 1456 return NULL;
1447 } 1457 }
1448 } 1458 }
1459
1449 CLEAR_FLAG (op, FLAG_REMOVED); 1460 CLEAR_FLAG (op, FLAG_REMOVED);
1450 1461
1451 /* Ideally, the caller figures this out. However, it complicates a lot 1462 /* Ideally, the caller figures this out. However, it complicates a lot
1452 * of areas of callers (eg, anything that uses find_free_spot would now 1463 * of areas of callers (eg, anything that uses find_free_spot would now
1453 * need extra work 1464 * need extra work
1457 y = op->y; 1468 y = op->y;
1458 1469
1459 /* this has to be done after we translate the coordinates. 1470 /* this has to be done after we translate the coordinates.
1460 */ 1471 */
1461 if (op->nrof && !(flag & INS_NO_MERGE)) 1472 if (op->nrof && !(flag & INS_NO_MERGE))
1462 {
1463 for (tmp = GET_MAP_OB (op->map, x, y); tmp != NULL; tmp = tmp->above) 1473 for (tmp = GET_MAP_OB (op->map, x, y); tmp != NULL; tmp = tmp->above)
1464 if (CAN_MERGE (op, tmp)) 1474 if (CAN_MERGE (op, tmp))
1465 { 1475 {
1466 op->nrof += tmp->nrof; 1476 op->nrof += tmp->nrof;
1467 remove_ob (tmp); 1477 remove_ob (tmp);
1468 free_object (tmp); 1478 free_object (tmp);
1469 } 1479 }
1470 }
1471 1480
1472 CLEAR_FLAG (op, FLAG_APPLIED); /* hack for fixing F_APPLIED in items of dead people */ 1481 CLEAR_FLAG (op, FLAG_APPLIED); /* hack for fixing F_APPLIED in items of dead people */
1473 CLEAR_FLAG (op, FLAG_INV_LOCKED); 1482 CLEAR_FLAG (op, FLAG_INV_LOCKED);
1483
1474 if (!QUERY_FLAG (op, FLAG_ALIVE)) 1484 if (!QUERY_FLAG (op, FLAG_ALIVE))
1475 CLEAR_FLAG (op, FLAG_NO_STEAL); 1485 CLEAR_FLAG (op, FLAG_NO_STEAL);
1476 1486
1477 if (flag & INS_BELOW_ORIGINATOR) 1487 if (flag & INS_BELOW_ORIGINATOR)
1478 { 1488 {
1479 if (originator->map != op->map || originator->x != op->x || originator->y != op->y) 1489 if (originator->map != op->map || originator->x != op->x || originator->y != op->y)
1480 { 1490 {
1481 LOG (llevError, "insert_ob_in_map called with INS_BELOW_ORIGINATOR when originator not on same space!\n"); 1491 LOG (llevError, "insert_ob_in_map called with INS_BELOW_ORIGINATOR when originator not on same space!\n");
1482 abort (); 1492 abort ();
1483 } 1493 }
1494
1484 op->above = originator; 1495 op->above = originator;
1485 op->below = originator->below; 1496 op->below = originator->below;
1497
1486 if (op->below) 1498 if (op->below)
1487 op->below->above = op; 1499 op->below->above = op;
1488 else 1500 else
1489 SET_MAP_OB (op->map, op->x, op->y, op); 1501 SET_MAP_OB (op->map, op->x, op->y, op);
1502
1490 /* since *below* originator, no need to update top */ 1503 /* since *below* originator, no need to update top */
1491 originator->below = op; 1504 originator->below = op;
1492 } 1505 }
1493 else 1506 else
1494 { 1507 {
1495 /* If there are other objects, then */ 1508 /* If there are other objects, then */
1496 if ((!(flag & INS_MAP_LOAD)) && ((top = GET_MAP_OB (op->map, op->x, op->y)) != NULL)) 1509 if ((!(flag & INS_MAP_LOAD)) && ((top = GET_MAP_OB (op->map, op->x, op->y)) != NULL))
1497 { 1510 {
1498 object *
1499 last = NULL; 1511 object *last = NULL;
1500 1512
1501 /* 1513 /*
1502 * If there are multiple objects on this space, we do some trickier handling. 1514 * If there are multiple objects on this space, we do some trickier handling.
1503 * We've already dealt with merging if appropriate. 1515 * We've already dealt with merging if appropriate.
1504 * Generally, we want to put the new object on top. But if 1516 * Generally, we want to put the new object on top. But if
1513 1525
1514 while (top != NULL) 1526 while (top != NULL)
1515 { 1527 {
1516 if (QUERY_FLAG (top, FLAG_IS_FLOOR) || QUERY_FLAG (top, FLAG_OVERLAY_FLOOR)) 1528 if (QUERY_FLAG (top, FLAG_IS_FLOOR) || QUERY_FLAG (top, FLAG_OVERLAY_FLOOR))
1517 floor = top; 1529 floor = top;
1530
1518 if (QUERY_FLAG (top, FLAG_NO_PICK) && (top->move_type & (MOVE_FLY_LOW | MOVE_FLY_HIGH)) && !QUERY_FLAG (top, FLAG_IS_FLOOR)) 1531 if (QUERY_FLAG (top, FLAG_NO_PICK) && (top->move_type & (MOVE_FLY_LOW | MOVE_FLY_HIGH)) && !QUERY_FLAG (top, FLAG_IS_FLOOR))
1519 { 1532 {
1520 /* We insert above top, so we want this object below this */ 1533 /* We insert above top, so we want this object below this */
1521 top = top->below; 1534 top = top->below;
1522 break; 1535 break;
1523 } 1536 }
1537
1524 last = top; 1538 last = top;
1525 top = top->above; 1539 top = top->above;
1526 } 1540 }
1541
1527 /* Don't want top to be NULL, so set it to the last valid object */ 1542 /* Don't want top to be NULL, so set it to the last valid object */
1528 top = last; 1543 top = last;
1529 1544
1530 /* We let update_position deal with figuring out what the space 1545 /* We let update_position deal with figuring out what the space
1531 * looks like instead of lots of conditions here. 1546 * looks like instead of lots of conditions here.
1551 */ 1566 */
1552 if (last && last->below && last != floor) 1567 if (last && last->below && last != floor)
1553 top = last->below; 1568 top = last->below;
1554 } 1569 }
1555 } /* If objects on this space */ 1570 } /* If objects on this space */
1571
1556 if (flag & INS_MAP_LOAD) 1572 if (flag & INS_MAP_LOAD)
1557 top = GET_MAP_TOP (op->map, op->x, op->y); 1573 top = GET_MAP_TOP (op->map, op->x, op->y);
1574
1558 if (flag & INS_ABOVE_FLOOR_ONLY) 1575 if (flag & INS_ABOVE_FLOOR_ONLY)
1559 top = floor; 1576 top = floor;
1560 1577
1561 /* Top is the object that our object (op) is going to get inserted above. 1578 /* Top is the object that our object (op) is going to get inserted above.
1562 */ 1579 */
1563 1580
1564 /* First object on this space */ 1581 /* First object on this space */
1565 if (!top) 1582 if (!top)
1566 { 1583 {
1567 op->above = GET_MAP_OB (op->map, op->x, op->y); 1584 op->above = GET_MAP_OB (op->map, op->x, op->y);
1585
1568 if (op->above) 1586 if (op->above)
1569 op->above->below = op; 1587 op->above->below = op;
1588
1570 op->below = NULL; 1589 op->below = NULL;
1571 SET_MAP_OB (op->map, op->x, op->y, op); 1590 SET_MAP_OB (op->map, op->x, op->y, op);
1572 } 1591 }
1573 else 1592 else
1574 { /* get inserted into the stack above top */ 1593 { /* get inserted into the stack above top */
1575 op->above = top->above; 1594 op->above = top->above;
1595
1576 if (op->above) 1596 if (op->above)
1577 op->above->below = op; 1597 op->above->below = op;
1598
1578 op->below = top; 1599 op->below = top;
1579 top->above = op; 1600 top->above = op;
1580 } 1601 }
1602
1581 if (op->above == NULL) 1603 if (op->above == NULL)
1582 SET_MAP_TOP (op->map, op->x, op->y, op); 1604 SET_MAP_TOP (op->map, op->x, op->y, op);
1583 } /* else not INS_BELOW_ORIGINATOR */ 1605 } /* else not INS_BELOW_ORIGINATOR */
1584 1606
1585 if (op->type == PLAYER) 1607 if (op->type == PLAYER)
1588 /* If we have a floor, we know the player, if any, will be above 1610 /* If we have a floor, we know the player, if any, will be above
1589 * it, so save a few ticks and start from there. 1611 * it, so save a few ticks and start from there.
1590 */ 1612 */
1591 if (!(flag & INS_MAP_LOAD)) 1613 if (!(flag & INS_MAP_LOAD))
1592 for (tmp = floor ? floor : GET_MAP_OB (op->map, op->x, op->y); tmp != NULL; tmp = tmp->above) 1614 for (tmp = floor ? floor : GET_MAP_OB (op->map, op->x, op->y); tmp != NULL; tmp = tmp->above)
1593 {
1594 if (tmp->type == PLAYER) 1615 if (tmp->type == PLAYER)
1595 tmp->contr->socket.update_look = 1; 1616 tmp->contr->socket.update_look = 1;
1596 }
1597 1617
1598 /* If this object glows, it may affect lighting conditions that are 1618 /* If this object glows, it may affect lighting conditions that are
1599 * visible to others on this map. But update_all_los is really 1619 * visible to others on this map. But update_all_los is really
1600 * an inefficient way to do this, as it means los for all players 1620 * an inefficient way to do this, as it means los for all players
1601 * on the map will get recalculated. The players could very well 1621 * on the map will get recalculated. The players could very well
1605 * of effect may be sufficient. 1625 * of effect may be sufficient.
1606 */ 1626 */
1607 if (MAP_DARKNESS (op->map) && (op->glow_radius != 0)) 1627 if (MAP_DARKNESS (op->map) && (op->glow_radius != 0))
1608 update_all_los (op->map, op->x, op->y); 1628 update_all_los (op->map, op->x, op->y);
1609 1629
1610
1611 /* updates flags (blocked, alive, no magic, etc) for this map space */ 1630 /* updates flags (blocked, alive, no magic, etc) for this map space */
1612 update_object (op, UP_OBJ_INSERT); 1631 update_object (op, UP_OBJ_INSERT);
1613
1614 1632
1615 /* Don't know if moving this to the end will break anything. However, 1633 /* Don't know if moving this to the end will break anything. However,
1616 * we want to have update_look set above before calling this. 1634 * we want to have update_look set above before calling this.
1617 * 1635 *
1618 * check_move_on() must be after this because code called from 1636 * check_move_on() must be after this because code called from
1620 * blocked() and wall() work properly), and these flags are updated by 1638 * blocked() and wall() work properly), and these flags are updated by
1621 * update_object(). 1639 * update_object().
1622 */ 1640 */
1623 1641
1624 /* if this is not the head or flag has been passed, don't check walk on status */ 1642 /* if this is not the head or flag has been passed, don't check walk on status */
1625
1626 if (!(flag & INS_NO_WALK_ON) && !op->head) 1643 if (!(flag & INS_NO_WALK_ON) && !op->head)
1627 { 1644 {
1628 if (check_move_on (op, originator)) 1645 if (check_move_on (op, originator))
1629 return NULL; 1646 return NULL;
1630 1647
1633 */ 1650 */
1634 for (tmp = op->more; tmp != NULL; tmp = tmp->more) 1651 for (tmp = op->more; tmp != NULL; tmp = tmp->more)
1635 if (check_move_on (tmp, originator)) 1652 if (check_move_on (tmp, originator))
1636 return NULL; 1653 return NULL;
1637 } 1654 }
1655
1638 return op; 1656 return op;
1639} 1657}
1640 1658
1641/* this function inserts an object in the map, but if it 1659/* this function inserts an object in the map, but if it
1642 * finds an object of its own type, it'll remove that one first. 1660 * finds an object of its own type, it'll remove that one first.
1643 * op is the object to insert it under: supplies x and the map. 1661 * op is the object to insert it under: supplies x and the map.
1644 */ 1662 */
1645void 1663void
1646replace_insert_ob_in_map (const char *arch_string, object *op) 1664replace_insert_ob_in_map (const char *arch_string, object *op)
1647{ 1665{
1648 object * 1666 object *tmp;
1649 tmp;
1650 object * 1667 object *tmp1;
1651 tmp1;
1652 1668
1653 /* first search for itself and remove any old instances */ 1669 /* first search for itself and remove any old instances */
1654 1670
1655 for (tmp = GET_MAP_OB (op->map, op->x, op->y); tmp != NULL; tmp = tmp->above) 1671 for (tmp = GET_MAP_OB (op->map, op->x, op->y); tmp != NULL; tmp = tmp->above)
1656 { 1672 {
1660 free_object (tmp); 1676 free_object (tmp);
1661 } 1677 }
1662 } 1678 }
1663 1679
1664 tmp1 = arch_to_object (find_archetype (arch_string)); 1680 tmp1 = arch_to_object (find_archetype (arch_string));
1665
1666 1681
1667 tmp1->x = op->x; 1682 tmp1->x = op->x;
1668 tmp1->y = op->y; 1683 tmp1->y = op->y;
1669 insert_ob_in_map (tmp1, op->map, op, 0); 1684 insert_ob_in_map (tmp1, op->map, op, 0);
1670} 1685}
1971 */ 1986 */
1972 1987
1973int 1988int
1974check_move_on (object *op, object *originator) 1989check_move_on (object *op, object *originator)
1975{ 1990{
1976 object * 1991 object *tmp;
1977 tmp; 1992 tag_t tag;
1978 tag_t 1993 mapstruct *m = op->map;
1979 tag;
1980 mapstruct *
1981 m = op->map;
1982 int
1983 x = op->x, y = op->y; 1994 int x = op->x, y = op->y;
1984 MoveType 1995
1985 move_on, 1996 MoveType move_on, move_slow, move_block;
1986 move_slow,
1987 move_block;
1988 1997
1989 if (QUERY_FLAG (op, FLAG_NO_APPLY)) 1998 if (QUERY_FLAG (op, FLAG_NO_APPLY))
1990 return 0; 1999 return 0;
1991 2000
1992 tag = op->count; 2001 tag = op->count;
2022 * we don't need to check all of them. 2031 * we don't need to check all of them.
2023 */ 2032 */
2024 if ((tmp->move_type & MOVE_FLY_LOW) && QUERY_FLAG (tmp, FLAG_NO_PICK)) 2033 if ((tmp->move_type & MOVE_FLY_LOW) && QUERY_FLAG (tmp, FLAG_NO_PICK))
2025 break; 2034 break;
2026 } 2035 }
2036
2027 for (; tmp != NULL; tmp = tmp->below) 2037 for (; tmp; tmp = tmp->below)
2028 { 2038 {
2029 if (tmp == op) 2039 if (tmp == op)
2030 continue; /* Can't apply yourself */ 2040 continue; /* Can't apply yourself */
2031 2041
2032 /* Check to see if one of the movement types should be slowed down. 2042 /* Check to see if one of the movement types should be slowed down.
2039 { 2049 {
2040 if ((!op->move_type && tmp->move_slow & MOVE_WALK) || 2050 if ((!op->move_type && tmp->move_slow & MOVE_WALK) ||
2041 ((op->move_type & tmp->move_slow) && (op->move_type & ~tmp->move_slow & ~tmp->move_block) == 0)) 2051 ((op->move_type & tmp->move_slow) && (op->move_type & ~tmp->move_slow & ~tmp->move_block) == 0))
2042 { 2052 {
2043 2053
2044 float
2045 diff;
2046
2047 diff = tmp->move_slow_penalty * FABS (op->speed); 2054 float diff = tmp->move_slow_penalty * FABS (op->speed);
2055
2048 if (op->type == PLAYER) 2056 if (op->type == PLAYER)
2049 {
2050 if ((QUERY_FLAG (tmp, FLAG_IS_HILLY) && find_skill_by_number (op, SK_CLIMBING)) || 2057 if ((QUERY_FLAG (tmp, FLAG_IS_HILLY) && find_skill_by_number (op, SK_CLIMBING)) ||
2051 (QUERY_FLAG (tmp, FLAG_IS_WOODED) && find_skill_by_number (op, SK_WOODSMAN))) 2058 (QUERY_FLAG (tmp, FLAG_IS_WOODED) && find_skill_by_number (op, SK_WOODSMAN)))
2052 {
2053 diff /= 4.0; 2059 diff /= 4.0;
2054 } 2060
2055 }
2056 op->speed_left -= diff; 2061 op->speed_left -= diff;
2057 } 2062 }
2058 } 2063 }
2059 2064
2060 /* Basically same logic as above, except now for actual apply. */ 2065 /* Basically same logic as above, except now for actual apply. */
2061 if ((!op->move_type && tmp->move_on & MOVE_WALK) || 2066 if ((!op->move_type && tmp->move_on & MOVE_WALK) ||
2062 ((op->move_type & tmp->move_on) && (op->move_type & ~tmp->move_on & ~tmp->move_block) == 0)) 2067 ((op->move_type & tmp->move_on) && (op->move_type & ~tmp->move_on & ~tmp->move_block) == 0))
2063 { 2068 {
2064
2065 move_apply (tmp, op, originator); 2069 move_apply (tmp, op, originator);
2070
2066 if (was_destroyed (op, tag)) 2071 if (was_destroyed (op, tag))
2067 return 1; 2072 return 1;
2068 2073
2069 /* what the person/creature stepped onto has moved the object 2074 /* what the person/creature stepped onto has moved the object
2070 * someplace new. Don't process any further - if we did, 2075 * someplace new. Don't process any further - if we did,
2072 */ 2077 */
2073 if (op->map != m || op->x != x || op->y != y) 2078 if (op->map != m || op->x != x || op->y != y)
2074 return 0; 2079 return 0;
2075 } 2080 }
2076 } 2081 }
2082
2077 return 0; 2083 return 0;
2078} 2084}
2079 2085
2080/* 2086/*
2081 * present_arch(arch, map, x, y) searches for any objects with 2087 * present_arch(arch, map, x, y) searches for any objects with

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines