1 | |
|
|
2 | /* |
|
|
3 | * static char *rcsid_object_c = |
|
|
4 | * "$Id: object.C,v 1.25 2006/09/11 01:16:20 root Exp $"; |
|
|
5 | */ |
|
|
6 | |
|
|
7 | /* |
1 | /* |
8 | CrossFire, A Multiplayer game for X-windows |
2 | CrossFire, A Multiplayer game for X-windows |
9 | |
3 | |
10 | Copyright (C) 2001 Mark Wedel & Crossfire Development Team |
4 | Copyright (C) 2001 Mark Wedel & Crossfire Development Team |
11 | Copyright (C) 1992 Frank Tore Johansen |
5 | Copyright (C) 1992 Frank Tore Johansen |
… | |
… | |
29 | |
23 | |
30 | /* Eneq(@csd.uu.se): Added weight-modifiers in environment of objects. |
24 | /* Eneq(@csd.uu.se): Added weight-modifiers in environment of objects. |
31 | sub/add_weight will transcend the environment updating the carrying |
25 | sub/add_weight will transcend the environment updating the carrying |
32 | variable. */ |
26 | variable. */ |
33 | #include <global.h> |
27 | #include <global.h> |
34 | #ifndef WIN32 /* ---win32 exclude headers */ |
|
|
35 | # include <stdio.h> |
28 | #include <stdio.h> |
36 | # include <sys/types.h> |
29 | #include <sys/types.h> |
37 | # include <sys/uio.h> |
30 | #include <sys/uio.h> |
38 | #endif /* win32 */ |
|
|
39 | #include <object.h> |
31 | #include <object.h> |
40 | #include <funcpoint.h> |
32 | #include <funcpoint.h> |
41 | #include <skills.h> |
33 | #include <skills.h> |
42 | #include <loader.h> |
34 | #include <loader.h> |
|
|
35 | |
43 | int nrofallocobjects = 0; |
36 | int nrofallocobjects = 0; |
44 | |
37 | |
45 | object *objects; /* Pointer to the list of used objects */ |
38 | object *objects; /* Pointer to the list of used objects */ |
46 | object *active_objects; /* List of active objects that need to be processed */ |
39 | object *active_objects; /* List of active objects that need to be processed */ |
47 | |
40 | |
… | |
… | |
249 | /* |
242 | /* |
250 | * sum_weight() is a recursive function which calculates the weight |
243 | * sum_weight() is a recursive function which calculates the weight |
251 | * an object is carrying. It goes through in figures out how much |
244 | * an object is carrying. It goes through in figures out how much |
252 | * containers are carrying, and sums it up. |
245 | * containers are carrying, and sums it up. |
253 | */ |
246 | */ |
254 | signed long |
247 | long |
255 | sum_weight (object *op) |
248 | sum_weight (object *op) |
256 | { |
249 | { |
257 | signed long sum; |
250 | long sum; |
258 | object *inv; |
251 | object *inv; |
259 | |
252 | |
260 | for (sum = 0, inv = op->inv; inv != NULL; inv = inv->below) |
253 | for (sum = 0, inv = op->inv; inv != NULL; inv = inv->below) |
261 | { |
254 | { |
262 | if (inv->inv) |
255 | if (inv->inv) |
… | |
… | |
891 | /* if the object is being removed, we can't make intelligent |
884 | /* if the object is being removed, we can't make intelligent |
892 | * decisions, because remove_ob can't really pass the object |
885 | * decisions, because remove_ob can't really pass the object |
893 | * that is being removed. |
886 | * that is being removed. |
894 | */ |
887 | */ |
895 | else if (action == UP_OBJ_CHANGE || action == UP_OBJ_REMOVE) |
888 | else if (action == UP_OBJ_CHANGE || action == UP_OBJ_REMOVE) |
896 | { |
|
|
897 | update_now = 1; |
889 | update_now = 1; |
898 | } |
|
|
899 | else if (action == UP_OBJ_FACE) |
890 | else if (action == UP_OBJ_FACE) |
900 | { |
|
|
901 | /* Nothing to do for that case */ |
891 | /* Nothing to do for that case */; |
902 | } |
|
|
903 | else |
892 | else |
904 | { |
|
|
905 | LOG (llevError, "update_object called with invalid action: %d\n", action); |
893 | LOG (llevError, "update_object called with invalid action: %d\n", action); |
906 | } |
|
|
907 | |
894 | |
908 | if (update_now) |
895 | if (update_now) |
909 | { |
896 | { |
910 | SET_MAP_FLAGS (op->map, op->x, op->y, flags | P_NO_ERROR | P_NEED_UPDATE); |
897 | SET_MAP_FLAGS (op->map, op->x, op->y, flags | P_NO_ERROR | P_NEED_UPDATE); |
911 | update_position (op->map, op->x, op->y); |
898 | update_position (op->map, op->x, op->y); |
… | |
… | |
1126 | */ |
1113 | */ |
1127 | |
1114 | |
1128 | void |
1115 | void |
1129 | remove_ob (object *op) |
1116 | remove_ob (object *op) |
1130 | { |
1117 | { |
|
|
1118 | object *tmp, *last = NULL; |
1131 | object * |
1119 | object *otmp; |
1132 | tmp, * |
1120 | |
1133 | last = NULL; |
1121 | tag_t tag; |
1134 | object * |
|
|
1135 | otmp; |
|
|
1136 | tag_t |
|
|
1137 | tag; |
|
|
1138 | int |
|
|
1139 | check_walk_off; |
1122 | int check_walk_off; |
1140 | mapstruct * |
1123 | mapstruct *m; |
1141 | m; |
|
|
1142 | sint16 |
|
|
1143 | x, |
|
|
1144 | y; |
|
|
1145 | |
1124 | |
|
|
1125 | sint16 x, y; |
1146 | |
1126 | |
1147 | if (QUERY_FLAG (op, FLAG_REMOVED)) |
1127 | if (QUERY_FLAG (op, FLAG_REMOVED)) |
1148 | { |
1128 | { |
1149 | dump_object (op); |
1129 | dump_object (op); |
1150 | LOG (llevError, "Trying to remove removed object.\n%s\n", errmsg); |
1130 | LOG (llevError, "Trying to remove removed object.\n%s\n", errmsg); |
… | |
… | |
1159 | * so is easily enough restarted without any real problems. |
1139 | * so is easily enough restarted without any real problems. |
1160 | * MSW 2001-07-01 |
1140 | * MSW 2001-07-01 |
1161 | */ |
1141 | */ |
1162 | abort (); |
1142 | abort (); |
1163 | } |
1143 | } |
|
|
1144 | |
1164 | if (op->more != NULL) |
1145 | if (op->more != NULL) |
1165 | remove_ob (op->more); |
1146 | remove_ob (op->more); |
1166 | |
1147 | |
1167 | SET_FLAG (op, FLAG_REMOVED); |
1148 | SET_FLAG (op, FLAG_REMOVED); |
1168 | |
1149 | |
… | |
… | |
1237 | else |
1218 | else |
1238 | SET_MAP_TOP (m, x, y, op->below); /* we were top, set new top */ |
1219 | SET_MAP_TOP (m, x, y, op->below); /* we were top, set new top */ |
1239 | |
1220 | |
1240 | /* Relink the object below us, if there is one */ |
1221 | /* Relink the object below us, if there is one */ |
1241 | if (op->below) |
1222 | if (op->below) |
1242 | { |
|
|
1243 | op->below->above = op->above; |
1223 | op->below->above = op->above; |
1244 | } |
|
|
1245 | else |
1224 | else |
1246 | { |
1225 | { |
1247 | /* Nothing below, which means we need to relink map object for this space |
1226 | /* Nothing below, which means we need to relink map object for this space |
1248 | * use translated coordinates in case some oddness with map tiling is |
1227 | * use translated coordinates in case some oddness with map tiling is |
1249 | * evident |
1228 | * evident |
… | |
… | |
1254 | 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 | 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", |
1255 | errmsg); |
1234 | errmsg); |
1256 | dump_object (GET_MAP_OB (m, x, y)); |
1235 | dump_object (GET_MAP_OB (m, x, y)); |
1257 | LOG (llevError, "%s\n", errmsg); |
1236 | LOG (llevError, "%s\n", errmsg); |
1258 | } |
1237 | } |
|
|
1238 | |
1259 | SET_MAP_OB (m, x, y, op->above); /* goes on above it. */ |
1239 | SET_MAP_OB (m, x, y, op->above); /* goes on above it. */ |
1260 | } |
1240 | } |
|
|
1241 | |
1261 | op->above = NULL; |
1242 | op->above = NULL; |
1262 | op->below = NULL; |
1243 | op->below = NULL; |
1263 | |
1244 | |
1264 | if (op->map->in_memory == MAP_SAVING) |
1245 | if (op->map->in_memory == MAP_SAVING) |
1265 | return; |
1246 | return; |
1266 | |
1247 | |
1267 | tag = op->count; |
1248 | tag = op->count; |
1268 | check_walk_off = !QUERY_FLAG (op, FLAG_NO_APPLY); |
1249 | check_walk_off = !QUERY_FLAG (op, FLAG_NO_APPLY); |
|
|
1250 | |
1269 | for (tmp = GET_MAP_OB (m, x, y); tmp != NULL; tmp = tmp->above) |
1251 | for (tmp = GET_MAP_OB (m, x, y); tmp != NULL; tmp = tmp->above) |
1270 | { |
1252 | { |
1271 | /* No point updating the players look faces if he is the object |
1253 | /* No point updating the players look faces if he is the object |
1272 | * being removed. |
1254 | * being removed. |
1273 | */ |
1255 | */ |
… | |
… | |
1281 | if (tmp->container == op) |
1263 | if (tmp->container == op) |
1282 | { |
1264 | { |
1283 | CLEAR_FLAG (op, FLAG_APPLIED); |
1265 | CLEAR_FLAG (op, FLAG_APPLIED); |
1284 | tmp->container = NULL; |
1266 | tmp->container = NULL; |
1285 | } |
1267 | } |
|
|
1268 | |
1286 | tmp->contr->socket.update_look = 1; |
1269 | tmp->contr->socket.update_look = 1; |
1287 | } |
1270 | } |
1288 | /* See if player moving off should effect something */ |
1271 | /* See if player moving off should effect something */ |
1289 | if (check_walk_off && ((op->move_type & tmp->move_off) && (op->move_type & ~tmp->move_off & ~tmp->move_block) == 0)) |
1272 | if (check_walk_off && ((op->move_type & tmp->move_off) && (op->move_type & ~tmp->move_off & ~tmp->move_block) == 0)) |
1290 | { |
1273 | { |
1291 | |
|
|
1292 | move_apply (tmp, op, NULL); |
1274 | move_apply (tmp, op, NULL); |
|
|
1275 | |
1293 | if (was_destroyed (op, tag)) |
1276 | if (was_destroyed (op, tag)) |
1294 | { |
1277 | { |
1295 | LOG (llevError, "BUG: remove_ob(): name %s, archname %s destroyed " "leaving object\n", &tmp->name, &tmp->arch->name); |
1278 | LOG (llevError, "BUG: remove_ob(): name %s, archname %s destroyed " "leaving object\n", &tmp->name, &tmp->arch->name); |
1296 | } |
1279 | } |
1297 | } |
1280 | } |
1298 | |
1281 | |
1299 | /* Eneq(@csd.uu.se): Fixed this to skip tmp->above=tmp */ |
1282 | /* Eneq(@csd.uu.se): Fixed this to skip tmp->above=tmp */ |
1300 | |
1283 | |
1301 | if (tmp->above == tmp) |
1284 | if (tmp->above == tmp) |
1302 | tmp->above = NULL; |
1285 | tmp->above = NULL; |
|
|
1286 | |
1303 | last = tmp; |
1287 | last = tmp; |
1304 | } |
1288 | } |
|
|
1289 | |
1305 | /* last == NULL of there are no objects on this space */ |
1290 | /* last == NULL of there are no objects on this space */ |
1306 | if (last == NULL) |
1291 | if (last == NULL) |
1307 | { |
1292 | { |
1308 | /* set P_NEED_UPDATE, otherwise update_position will complain. In theory, |
1293 | /* set P_NEED_UPDATE, otherwise update_position will complain. In theory, |
1309 | * we could preserve the flags (GET_MAP_FLAGS), but update_position figures |
1294 | * we could preserve the flags (GET_MAP_FLAGS), but update_position figures |
… | |
… | |
1316 | else |
1301 | else |
1317 | update_object (last, UP_OBJ_REMOVE); |
1302 | update_object (last, UP_OBJ_REMOVE); |
1318 | |
1303 | |
1319 | if (QUERY_FLAG (op, FLAG_BLOCKSVIEW) || (op->glow_radius != 0)) |
1304 | if (QUERY_FLAG (op, FLAG_BLOCKSVIEW) || (op->glow_radius != 0)) |
1320 | update_all_los (op->map, op->x, op->y); |
1305 | update_all_los (op->map, op->x, op->y); |
1321 | |
|
|
1322 | } |
1306 | } |
1323 | |
1307 | |
1324 | /* |
1308 | /* |
1325 | * merge_ob(op,top): |
1309 | * merge_ob(op,top): |
1326 | * |
1310 | * |
… | |
… | |
1438 | |
1422 | |
1439 | if (op->more != NULL) |
1423 | if (op->more != NULL) |
1440 | { |
1424 | { |
1441 | /* The part may be on a different map. */ |
1425 | /* The part may be on a different map. */ |
1442 | |
1426 | |
1443 | object * |
|
|
1444 | more = op->more; |
1427 | object *more = op->more; |
1445 | |
1428 | |
1446 | /* We really need the caller to normalize coordinates - if |
1429 | /* We really need the caller to normalize coordinates - if |
1447 | * we set the map, that doesn't work if the location is within |
1430 | * we set the map, that doesn't work if the location is within |
1448 | * a map and this is straddling an edge. So only if coordinate |
1431 | * a map and this is straddling an edge. So only if coordinate |
1449 | * is clear wrong do we normalize it. |
1432 | * is clear wrong do we normalize it. |
1450 | */ |
1433 | */ |
1451 | if (OUT_OF_REAL_MAP (more->map, more->x, more->y)) |
1434 | if (OUT_OF_REAL_MAP (more->map, more->x, more->y)) |
1452 | { |
|
|
1453 | more->map = get_map_from_coord (m, &more->x, &more->y); |
1435 | more->map = get_map_from_coord (m, &more->x, &more->y); |
1454 | } |
|
|
1455 | else if (!more->map) |
1436 | else if (!more->map) |
1456 | { |
1437 | { |
1457 | /* For backwards compatibility - when not dealing with tiled maps, |
1438 | /* For backwards compatibility - when not dealing with tiled maps, |
1458 | * more->map should always point to the parent. |
1439 | * more->map should always point to the parent. |
1459 | */ |
1440 | */ |
… | |
… | |
1462 | |
1443 | |
1463 | if (insert_ob_in_map (more, more->map, originator, flag) == NULL) |
1444 | if (insert_ob_in_map (more, more->map, originator, flag) == NULL) |
1464 | { |
1445 | { |
1465 | if (!op->head) |
1446 | if (!op->head) |
1466 | LOG (llevError, "BUG: insert_ob_in_map(): inserting op->more killed op\n"); |
1447 | LOG (llevError, "BUG: insert_ob_in_map(): inserting op->more killed op\n"); |
|
|
1448 | |
1467 | return NULL; |
1449 | return NULL; |
1468 | } |
1450 | } |
1469 | } |
1451 | } |
1470 | |
1452 | |
1471 | CLEAR_FLAG (op, FLAG_REMOVED); |
1453 | CLEAR_FLAG (op, FLAG_REMOVED); |
… | |
… | |
1536 | |
1518 | |
1537 | while (top != NULL) |
1519 | while (top != NULL) |
1538 | { |
1520 | { |
1539 | if (QUERY_FLAG (top, FLAG_IS_FLOOR) || QUERY_FLAG (top, FLAG_OVERLAY_FLOOR)) |
1521 | if (QUERY_FLAG (top, FLAG_IS_FLOOR) || QUERY_FLAG (top, FLAG_OVERLAY_FLOOR)) |
1540 | floor = top; |
1522 | floor = top; |
|
|
1523 | |
1541 | if (QUERY_FLAG (top, FLAG_NO_PICK) && (top->move_type & (MOVE_FLY_LOW | MOVE_FLY_HIGH)) && !QUERY_FLAG (top, FLAG_IS_FLOOR)) |
1524 | if (QUERY_FLAG (top, FLAG_NO_PICK) && (top->move_type & (MOVE_FLY_LOW | MOVE_FLY_HIGH)) && !QUERY_FLAG (top, FLAG_IS_FLOOR)) |
1542 | { |
1525 | { |
1543 | /* We insert above top, so we want this object below this */ |
1526 | /* We insert above top, so we want this object below this */ |
1544 | top = top->below; |
1527 | top = top->below; |
1545 | break; |
1528 | break; |
1546 | } |
1529 | } |
|
|
1530 | |
1547 | last = top; |
1531 | last = top; |
1548 | top = top->above; |
1532 | top = top->above; |
1549 | } |
1533 | } |
|
|
1534 | |
1550 | /* Don't want top to be NULL, so set it to the last valid object */ |
1535 | /* Don't want top to be NULL, so set it to the last valid object */ |
1551 | top = last; |
1536 | top = last; |
1552 | |
1537 | |
1553 | /* We let update_position deal with figuring out what the space |
1538 | /* We let update_position deal with figuring out what the space |
1554 | * looks like instead of lots of conditions here. |
1539 | * looks like instead of lots of conditions here. |
… | |
… | |
1633 | * of effect may be sufficient. |
1618 | * of effect may be sufficient. |
1634 | */ |
1619 | */ |
1635 | if (MAP_DARKNESS (op->map) && (op->glow_radius != 0)) |
1620 | if (MAP_DARKNESS (op->map) && (op->glow_radius != 0)) |
1636 | update_all_los (op->map, op->x, op->y); |
1621 | update_all_los (op->map, op->x, op->y); |
1637 | |
1622 | |
1638 | |
|
|
1639 | /* updates flags (blocked, alive, no magic, etc) for this map space */ |
1623 | /* updates flags (blocked, alive, no magic, etc) for this map space */ |
1640 | update_object (op, UP_OBJ_INSERT); |
1624 | update_object (op, UP_OBJ_INSERT); |
1641 | |
|
|
1642 | |
1625 | |
1643 | /* Don't know if moving this to the end will break anything. However, |
1626 | /* Don't know if moving this to the end will break anything. However, |
1644 | * we want to have update_look set above before calling this. |
1627 | * we want to have update_look set above before calling this. |
1645 | * |
1628 | * |
1646 | * check_move_on() must be after this because code called from |
1629 | * check_move_on() must be after this because code called from |
… | |
… | |
1996 | */ |
1979 | */ |
1997 | |
1980 | |
1998 | int |
1981 | int |
1999 | check_move_on (object *op, object *originator) |
1982 | check_move_on (object *op, object *originator) |
2000 | { |
1983 | { |
2001 | object * |
1984 | object *tmp; |
2002 | tmp; |
1985 | tag_t tag; |
2003 | tag_t |
1986 | mapstruct *m = op->map; |
2004 | tag; |
|
|
2005 | mapstruct * |
|
|
2006 | m = op->map; |
|
|
2007 | int |
|
|
2008 | x = op->x, y = op->y; |
1987 | int x = op->x, y = op->y; |
2009 | MoveType |
1988 | |
2010 | move_on, |
1989 | MoveType move_on, move_slow, move_block; |
2011 | move_slow, |
|
|
2012 | move_block; |
|
|
2013 | |
1990 | |
2014 | if (QUERY_FLAG (op, FLAG_NO_APPLY)) |
1991 | if (QUERY_FLAG (op, FLAG_NO_APPLY)) |
2015 | return 0; |
1992 | return 0; |
2016 | |
1993 | |
2017 | tag = op->count; |
1994 | tag = op->count; |
… | |
… | |
2047 | * we don't need to check all of them. |
2024 | * we don't need to check all of them. |
2048 | */ |
2025 | */ |
2049 | if ((tmp->move_type & MOVE_FLY_LOW) && QUERY_FLAG (tmp, FLAG_NO_PICK)) |
2026 | if ((tmp->move_type & MOVE_FLY_LOW) && QUERY_FLAG (tmp, FLAG_NO_PICK)) |
2050 | break; |
2027 | break; |
2051 | } |
2028 | } |
|
|
2029 | |
2052 | for (; tmp != NULL; tmp = tmp->below) |
2030 | for (; tmp; tmp = tmp->below) |
2053 | { |
2031 | { |
2054 | if (tmp == op) |
2032 | if (tmp == op) |
2055 | continue; /* Can't apply yourself */ |
2033 | continue; /* Can't apply yourself */ |
2056 | |
2034 | |
2057 | /* Check to see if one of the movement types should be slowed down. |
2035 | /* Check to see if one of the movement types should be slowed down. |
… | |
… | |
2064 | { |
2042 | { |
2065 | if ((!op->move_type && tmp->move_slow & MOVE_WALK) || |
2043 | if ((!op->move_type && tmp->move_slow & MOVE_WALK) || |
2066 | ((op->move_type & tmp->move_slow) && (op->move_type & ~tmp->move_slow & ~tmp->move_block) == 0)) |
2044 | ((op->move_type & tmp->move_slow) && (op->move_type & ~tmp->move_slow & ~tmp->move_block) == 0)) |
2067 | { |
2045 | { |
2068 | |
2046 | |
2069 | float |
|
|
2070 | diff; |
|
|
2071 | |
|
|
2072 | diff = tmp->move_slow_penalty * FABS (op->speed); |
2047 | float diff = tmp->move_slow_penalty * FABS (op->speed); |
|
|
2048 | |
2073 | if (op->type == PLAYER) |
2049 | if (op->type == PLAYER) |
2074 | { |
|
|
2075 | if ((QUERY_FLAG (tmp, FLAG_IS_HILLY) && find_skill_by_number (op, SK_CLIMBING)) || |
2050 | if ((QUERY_FLAG (tmp, FLAG_IS_HILLY) && find_skill_by_number (op, SK_CLIMBING)) || |
2076 | (QUERY_FLAG (tmp, FLAG_IS_WOODED) && find_skill_by_number (op, SK_WOODSMAN))) |
2051 | (QUERY_FLAG (tmp, FLAG_IS_WOODED) && find_skill_by_number (op, SK_WOODSMAN))) |
2077 | { |
|
|
2078 | diff /= 4.0; |
2052 | diff /= 4.0; |
2079 | } |
2053 | |
2080 | } |
|
|
2081 | op->speed_left -= diff; |
2054 | op->speed_left -= diff; |
2082 | } |
2055 | } |
2083 | } |
2056 | } |
2084 | |
2057 | |
2085 | /* Basically same logic as above, except now for actual apply. */ |
2058 | /* Basically same logic as above, except now for actual apply. */ |
2086 | if ((!op->move_type && tmp->move_on & MOVE_WALK) || |
2059 | if ((!op->move_type && tmp->move_on & MOVE_WALK) || |
2087 | ((op->move_type & tmp->move_on) && (op->move_type & ~tmp->move_on & ~tmp->move_block) == 0)) |
2060 | ((op->move_type & tmp->move_on) && (op->move_type & ~tmp->move_on & ~tmp->move_block) == 0)) |
2088 | { |
2061 | { |
2089 | |
|
|
2090 | move_apply (tmp, op, originator); |
2062 | move_apply (tmp, op, originator); |
|
|
2063 | |
2091 | if (was_destroyed (op, tag)) |
2064 | if (was_destroyed (op, tag)) |
2092 | return 1; |
2065 | return 1; |
2093 | |
2066 | |
2094 | /* what the person/creature stepped onto has moved the object |
2067 | /* what the person/creature stepped onto has moved the object |
2095 | * someplace new. Don't process any further - if we did, |
2068 | * someplace new. Don't process any further - if we did, |
… | |
… | |
2097 | */ |
2070 | */ |
2098 | if (op->map != m || op->x != x || op->y != y) |
2071 | if (op->map != m || op->x != x || op->y != y) |
2099 | return 0; |
2072 | return 0; |
2100 | } |
2073 | } |
2101 | } |
2074 | } |
|
|
2075 | |
2102 | return 0; |
2076 | return 0; |
2103 | } |
2077 | } |
2104 | |
2078 | |
2105 | /* |
2079 | /* |
2106 | * present_arch(arch, map, x, y) searches for any objects with |
2080 | * present_arch(arch, map, x, y) searches for any objects with |