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 | */ |
… | |
… | |
561 | void object::clear () |
560 | void 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 | |
917 | static |
912 | static unordered_vector<object *> mortals; |
918 | std::vector < object *> |
913 | static std::vector<object *> freed; |
919 | mortals; |
|
|
920 | |
914 | |
921 | void object::free_mortals () |
915 | void 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 | |
930 | object::object () |
927 | object::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 | |
970 | object *object::create () |
975 | object *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 | |
1106 | void |
1122 | void |
1107 | remove_ob (object *op) |
1123 | remove_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 | |
1377 | object * |
1390 | object * |
1378 | insert_ob_in_map (object *op, mapstruct *m, object *originator, int flag) |
1391 | insert_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 | */ |
1645 | void |
1663 | void |
1646 | replace_insert_ob_in_map (const char *arch_string, object *op) |
1664 | replace_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 | |
1973 | int |
1988 | int |
1974 | check_move_on (object *op, object *originator) |
1989 | check_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 |