1 | |
1 | |
2 | /* |
2 | /* |
3 | * static char *rcsid_object_c = |
3 | * static char *rcsid_object_c = |
4 | * "$Id: object.C,v 1.25 2006/09/11 01:16:20 root Exp $"; |
4 | * "$Id: object.C,v 1.26 2006/09/11 11:46:52 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 | |
… | |
… | |
1126 | */ |
1126 | */ |
1127 | |
1127 | |
1128 | void |
1128 | void |
1129 | remove_ob (object *op) |
1129 | remove_ob (object *op) |
1130 | { |
1130 | { |
|
|
1131 | object *tmp, *last = NULL; |
1131 | object * |
1132 | object *otmp; |
1132 | tmp, * |
1133 | |
1133 | last = NULL; |
1134 | tag_t tag; |
1134 | object * |
|
|
1135 | otmp; |
|
|
1136 | tag_t |
|
|
1137 | tag; |
|
|
1138 | int |
|
|
1139 | check_walk_off; |
1135 | int check_walk_off; |
1140 | mapstruct * |
1136 | mapstruct *m; |
1141 | m; |
|
|
1142 | sint16 |
|
|
1143 | x, |
|
|
1144 | y; |
|
|
1145 | |
1137 | |
|
|
1138 | sint16 x, y; |
1146 | |
1139 | |
1147 | if (QUERY_FLAG (op, FLAG_REMOVED)) |
1140 | if (QUERY_FLAG (op, FLAG_REMOVED)) |
1148 | { |
1141 | { |
1149 | dump_object (op); |
1142 | dump_object (op); |
1150 | LOG (llevError, "Trying to remove removed object.\n%s\n", errmsg); |
1143 | LOG (llevError, "Trying to remove removed object.\n%s\n", errmsg); |
… | |
… | |
1159 | * so is easily enough restarted without any real problems. |
1152 | * so is easily enough restarted without any real problems. |
1160 | * MSW 2001-07-01 |
1153 | * MSW 2001-07-01 |
1161 | */ |
1154 | */ |
1162 | abort (); |
1155 | abort (); |
1163 | } |
1156 | } |
|
|
1157 | |
1164 | if (op->more != NULL) |
1158 | if (op->more != NULL) |
1165 | remove_ob (op->more); |
1159 | remove_ob (op->more); |
1166 | |
1160 | |
1167 | SET_FLAG (op, FLAG_REMOVED); |
1161 | SET_FLAG (op, FLAG_REMOVED); |
1168 | |
1162 | |
… | |
… | |
1237 | else |
1231 | else |
1238 | SET_MAP_TOP (m, x, y, op->below); /* we were top, set new top */ |
1232 | SET_MAP_TOP (m, x, y, op->below); /* we were top, set new top */ |
1239 | |
1233 | |
1240 | /* Relink the object below us, if there is one */ |
1234 | /* Relink the object below us, if there is one */ |
1241 | if (op->below) |
1235 | if (op->below) |
1242 | { |
|
|
1243 | op->below->above = op->above; |
1236 | op->below->above = op->above; |
1244 | } |
|
|
1245 | else |
1237 | else |
1246 | { |
1238 | { |
1247 | /* Nothing below, which means we need to relink map object for this space |
1239 | /* 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 |
1240 | * use translated coordinates in case some oddness with map tiling is |
1249 | * evident |
1241 | * 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", |
1246 | 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); |
1247 | errmsg); |
1256 | dump_object (GET_MAP_OB (m, x, y)); |
1248 | dump_object (GET_MAP_OB (m, x, y)); |
1257 | LOG (llevError, "%s\n", errmsg); |
1249 | LOG (llevError, "%s\n", errmsg); |
1258 | } |
1250 | } |
|
|
1251 | |
1259 | SET_MAP_OB (m, x, y, op->above); /* goes on above it. */ |
1252 | SET_MAP_OB (m, x, y, op->above); /* goes on above it. */ |
1260 | } |
1253 | } |
|
|
1254 | |
1261 | op->above = NULL; |
1255 | op->above = NULL; |
1262 | op->below = NULL; |
1256 | op->below = NULL; |
1263 | |
1257 | |
1264 | if (op->map->in_memory == MAP_SAVING) |
1258 | if (op->map->in_memory == MAP_SAVING) |
1265 | return; |
1259 | return; |
1266 | |
1260 | |
1267 | tag = op->count; |
1261 | tag = op->count; |
1268 | check_walk_off = !QUERY_FLAG (op, FLAG_NO_APPLY); |
1262 | check_walk_off = !QUERY_FLAG (op, FLAG_NO_APPLY); |
|
|
1263 | |
1269 | for (tmp = GET_MAP_OB (m, x, y); tmp != NULL; tmp = tmp->above) |
1264 | for (tmp = GET_MAP_OB (m, x, y); tmp != NULL; tmp = tmp->above) |
1270 | { |
1265 | { |
1271 | /* No point updating the players look faces if he is the object |
1266 | /* No point updating the players look faces if he is the object |
1272 | * being removed. |
1267 | * being removed. |
1273 | */ |
1268 | */ |
… | |
… | |
1281 | if (tmp->container == op) |
1276 | if (tmp->container == op) |
1282 | { |
1277 | { |
1283 | CLEAR_FLAG (op, FLAG_APPLIED); |
1278 | CLEAR_FLAG (op, FLAG_APPLIED); |
1284 | tmp->container = NULL; |
1279 | tmp->container = NULL; |
1285 | } |
1280 | } |
|
|
1281 | |
1286 | tmp->contr->socket.update_look = 1; |
1282 | tmp->contr->socket.update_look = 1; |
1287 | } |
1283 | } |
1288 | /* See if player moving off should effect something */ |
1284 | /* 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)) |
1285 | if (check_walk_off && ((op->move_type & tmp->move_off) && (op->move_type & ~tmp->move_off & ~tmp->move_block) == 0)) |
1290 | { |
1286 | { |
1291 | |
|
|
1292 | move_apply (tmp, op, NULL); |
1287 | move_apply (tmp, op, NULL); |
|
|
1288 | |
1293 | if (was_destroyed (op, tag)) |
1289 | if (was_destroyed (op, tag)) |
1294 | { |
1290 | { |
1295 | LOG (llevError, "BUG: remove_ob(): name %s, archname %s destroyed " "leaving object\n", &tmp->name, &tmp->arch->name); |
1291 | LOG (llevError, "BUG: remove_ob(): name %s, archname %s destroyed " "leaving object\n", &tmp->name, &tmp->arch->name); |
1296 | } |
1292 | } |
1297 | } |
1293 | } |
1298 | |
1294 | |
1299 | /* Eneq(@csd.uu.se): Fixed this to skip tmp->above=tmp */ |
1295 | /* Eneq(@csd.uu.se): Fixed this to skip tmp->above=tmp */ |
1300 | |
1296 | |
1301 | if (tmp->above == tmp) |
1297 | if (tmp->above == tmp) |
1302 | tmp->above = NULL; |
1298 | tmp->above = NULL; |
|
|
1299 | |
1303 | last = tmp; |
1300 | last = tmp; |
1304 | } |
1301 | } |
|
|
1302 | |
1305 | /* last == NULL of there are no objects on this space */ |
1303 | /* last == NULL of there are no objects on this space */ |
1306 | if (last == NULL) |
1304 | if (last == NULL) |
1307 | { |
1305 | { |
1308 | /* set P_NEED_UPDATE, otherwise update_position will complain. In theory, |
1306 | /* set P_NEED_UPDATE, otherwise update_position will complain. In theory, |
1309 | * we could preserve the flags (GET_MAP_FLAGS), but update_position figures |
1307 | * we could preserve the flags (GET_MAP_FLAGS), but update_position figures |
… | |
… | |
1316 | else |
1314 | else |
1317 | update_object (last, UP_OBJ_REMOVE); |
1315 | update_object (last, UP_OBJ_REMOVE); |
1318 | |
1316 | |
1319 | if (QUERY_FLAG (op, FLAG_BLOCKSVIEW) || (op->glow_radius != 0)) |
1317 | if (QUERY_FLAG (op, FLAG_BLOCKSVIEW) || (op->glow_radius != 0)) |
1320 | update_all_los (op->map, op->x, op->y); |
1318 | update_all_los (op->map, op->x, op->y); |
1321 | |
|
|
1322 | } |
1319 | } |
1323 | |
1320 | |
1324 | /* |
1321 | /* |
1325 | * merge_ob(op,top): |
1322 | * merge_ob(op,top): |
1326 | * |
1323 | * |
… | |
… | |
1438 | |
1435 | |
1439 | if (op->more != NULL) |
1436 | if (op->more != NULL) |
1440 | { |
1437 | { |
1441 | /* The part may be on a different map. */ |
1438 | /* The part may be on a different map. */ |
1442 | |
1439 | |
1443 | object * |
|
|
1444 | more = op->more; |
1440 | object *more = op->more; |
1445 | |
1441 | |
1446 | /* We really need the caller to normalize coordinates - if |
1442 | /* We really need the caller to normalize coordinates - if |
1447 | * we set the map, that doesn't work if the location is within |
1443 | * 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 |
1444 | * a map and this is straddling an edge. So only if coordinate |
1449 | * is clear wrong do we normalize it. |
1445 | * is clear wrong do we normalize it. |
1450 | */ |
1446 | */ |
1451 | if (OUT_OF_REAL_MAP (more->map, more->x, more->y)) |
1447 | if (OUT_OF_REAL_MAP (more->map, more->x, more->y)) |
1452 | { |
|
|
1453 | more->map = get_map_from_coord (m, &more->x, &more->y); |
1448 | more->map = get_map_from_coord (m, &more->x, &more->y); |
1454 | } |
|
|
1455 | else if (!more->map) |
1449 | else if (!more->map) |
1456 | { |
1450 | { |
1457 | /* For backwards compatibility - when not dealing with tiled maps, |
1451 | /* For backwards compatibility - when not dealing with tiled maps, |
1458 | * more->map should always point to the parent. |
1452 | * more->map should always point to the parent. |
1459 | */ |
1453 | */ |
… | |
… | |
1462 | |
1456 | |
1463 | if (insert_ob_in_map (more, more->map, originator, flag) == NULL) |
1457 | if (insert_ob_in_map (more, more->map, originator, flag) == NULL) |
1464 | { |
1458 | { |
1465 | if (!op->head) |
1459 | if (!op->head) |
1466 | LOG (llevError, "BUG: insert_ob_in_map(): inserting op->more killed op\n"); |
1460 | LOG (llevError, "BUG: insert_ob_in_map(): inserting op->more killed op\n"); |
|
|
1461 | |
1467 | return NULL; |
1462 | return NULL; |
1468 | } |
1463 | } |
1469 | } |
1464 | } |
1470 | |
1465 | |
1471 | CLEAR_FLAG (op, FLAG_REMOVED); |
1466 | CLEAR_FLAG (op, FLAG_REMOVED); |
… | |
… | |
1536 | |
1531 | |
1537 | while (top != NULL) |
1532 | while (top != NULL) |
1538 | { |
1533 | { |
1539 | if (QUERY_FLAG (top, FLAG_IS_FLOOR) || QUERY_FLAG (top, FLAG_OVERLAY_FLOOR)) |
1534 | if (QUERY_FLAG (top, FLAG_IS_FLOOR) || QUERY_FLAG (top, FLAG_OVERLAY_FLOOR)) |
1540 | floor = top; |
1535 | floor = top; |
|
|
1536 | |
1541 | if (QUERY_FLAG (top, FLAG_NO_PICK) && (top->move_type & (MOVE_FLY_LOW | MOVE_FLY_HIGH)) && !QUERY_FLAG (top, FLAG_IS_FLOOR)) |
1537 | if (QUERY_FLAG (top, FLAG_NO_PICK) && (top->move_type & (MOVE_FLY_LOW | MOVE_FLY_HIGH)) && !QUERY_FLAG (top, FLAG_IS_FLOOR)) |
1542 | { |
1538 | { |
1543 | /* We insert above top, so we want this object below this */ |
1539 | /* We insert above top, so we want this object below this */ |
1544 | top = top->below; |
1540 | top = top->below; |
1545 | break; |
1541 | break; |
1546 | } |
1542 | } |
|
|
1543 | |
1547 | last = top; |
1544 | last = top; |
1548 | top = top->above; |
1545 | top = top->above; |
1549 | } |
1546 | } |
|
|
1547 | |
1550 | /* Don't want top to be NULL, so set it to the last valid object */ |
1548 | /* Don't want top to be NULL, so set it to the last valid object */ |
1551 | top = last; |
1549 | top = last; |
1552 | |
1550 | |
1553 | /* We let update_position deal with figuring out what the space |
1551 | /* We let update_position deal with figuring out what the space |
1554 | * looks like instead of lots of conditions here. |
1552 | * looks like instead of lots of conditions here. |
… | |
… | |
1633 | * of effect may be sufficient. |
1631 | * of effect may be sufficient. |
1634 | */ |
1632 | */ |
1635 | if (MAP_DARKNESS (op->map) && (op->glow_radius != 0)) |
1633 | if (MAP_DARKNESS (op->map) && (op->glow_radius != 0)) |
1636 | update_all_los (op->map, op->x, op->y); |
1634 | update_all_los (op->map, op->x, op->y); |
1637 | |
1635 | |
1638 | |
|
|
1639 | /* updates flags (blocked, alive, no magic, etc) for this map space */ |
1636 | /* updates flags (blocked, alive, no magic, etc) for this map space */ |
1640 | update_object (op, UP_OBJ_INSERT); |
1637 | update_object (op, UP_OBJ_INSERT); |
1641 | |
|
|
1642 | |
1638 | |
1643 | /* Don't know if moving this to the end will break anything. However, |
1639 | /* 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. |
1640 | * we want to have update_look set above before calling this. |
1645 | * |
1641 | * |
1646 | * check_move_on() must be after this because code called from |
1642 | * check_move_on() must be after this because code called from |
… | |
… | |
1996 | */ |
1992 | */ |
1997 | |
1993 | |
1998 | int |
1994 | int |
1999 | check_move_on (object *op, object *originator) |
1995 | check_move_on (object *op, object *originator) |
2000 | { |
1996 | { |
2001 | object * |
1997 | object *tmp; |
2002 | tmp; |
1998 | tag_t tag; |
2003 | tag_t |
1999 | mapstruct *m = op->map; |
2004 | tag; |
|
|
2005 | mapstruct * |
|
|
2006 | m = op->map; |
|
|
2007 | int |
|
|
2008 | x = op->x, y = op->y; |
2000 | int x = op->x, y = op->y; |
2009 | MoveType |
2001 | |
2010 | move_on, |
2002 | MoveType move_on, move_slow, move_block; |
2011 | move_slow, |
|
|
2012 | move_block; |
|
|
2013 | |
2003 | |
2014 | if (QUERY_FLAG (op, FLAG_NO_APPLY)) |
2004 | if (QUERY_FLAG (op, FLAG_NO_APPLY)) |
2015 | return 0; |
2005 | return 0; |
2016 | |
2006 | |
2017 | tag = op->count; |
2007 | tag = op->count; |
… | |
… | |
2047 | * we don't need to check all of them. |
2037 | * we don't need to check all of them. |
2048 | */ |
2038 | */ |
2049 | if ((tmp->move_type & MOVE_FLY_LOW) && QUERY_FLAG (tmp, FLAG_NO_PICK)) |
2039 | if ((tmp->move_type & MOVE_FLY_LOW) && QUERY_FLAG (tmp, FLAG_NO_PICK)) |
2050 | break; |
2040 | break; |
2051 | } |
2041 | } |
|
|
2042 | |
2052 | for (; tmp != NULL; tmp = tmp->below) |
2043 | for (; tmp; tmp = tmp->below) |
2053 | { |
2044 | { |
2054 | if (tmp == op) |
2045 | if (tmp == op) |
2055 | continue; /* Can't apply yourself */ |
2046 | continue; /* Can't apply yourself */ |
2056 | |
2047 | |
2057 | /* Check to see if one of the movement types should be slowed down. |
2048 | /* Check to see if one of the movement types should be slowed down. |
… | |
… | |
2064 | { |
2055 | { |
2065 | if ((!op->move_type && tmp->move_slow & MOVE_WALK) || |
2056 | 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)) |
2057 | ((op->move_type & tmp->move_slow) && (op->move_type & ~tmp->move_slow & ~tmp->move_block) == 0)) |
2067 | { |
2058 | { |
2068 | |
2059 | |
2069 | float |
|
|
2070 | diff; |
|
|
2071 | |
|
|
2072 | diff = tmp->move_slow_penalty * FABS (op->speed); |
2060 | float diff = tmp->move_slow_penalty * FABS (op->speed); |
|
|
2061 | |
2073 | if (op->type == PLAYER) |
2062 | if (op->type == PLAYER) |
2074 | { |
|
|
2075 | if ((QUERY_FLAG (tmp, FLAG_IS_HILLY) && find_skill_by_number (op, SK_CLIMBING)) || |
2063 | 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))) |
2064 | (QUERY_FLAG (tmp, FLAG_IS_WOODED) && find_skill_by_number (op, SK_WOODSMAN))) |
2077 | { |
|
|
2078 | diff /= 4.0; |
2065 | diff /= 4.0; |
2079 | } |
2066 | |
2080 | } |
|
|
2081 | op->speed_left -= diff; |
2067 | op->speed_left -= diff; |
2082 | } |
2068 | } |
2083 | } |
2069 | } |
2084 | |
2070 | |
2085 | /* Basically same logic as above, except now for actual apply. */ |
2071 | /* Basically same logic as above, except now for actual apply. */ |
2086 | if ((!op->move_type && tmp->move_on & MOVE_WALK) || |
2072 | 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)) |
2073 | ((op->move_type & tmp->move_on) && (op->move_type & ~tmp->move_on & ~tmp->move_block) == 0)) |
2088 | { |
2074 | { |
2089 | |
|
|
2090 | move_apply (tmp, op, originator); |
2075 | move_apply (tmp, op, originator); |
|
|
2076 | |
2091 | if (was_destroyed (op, tag)) |
2077 | if (was_destroyed (op, tag)) |
2092 | return 1; |
2078 | return 1; |
2093 | |
2079 | |
2094 | /* what the person/creature stepped onto has moved the object |
2080 | /* what the person/creature stepped onto has moved the object |
2095 | * someplace new. Don't process any further - if we did, |
2081 | * someplace new. Don't process any further - if we did, |
… | |
… | |
2097 | */ |
2083 | */ |
2098 | if (op->map != m || op->x != x || op->y != y) |
2084 | if (op->map != m || op->x != x || op->y != y) |
2099 | return 0; |
2085 | return 0; |
2100 | } |
2086 | } |
2101 | } |
2087 | } |
|
|
2088 | |
2102 | return 0; |
2089 | return 0; |
2103 | } |
2090 | } |
2104 | |
2091 | |
2105 | /* |
2092 | /* |
2106 | * present_arch(arch, map, x, y) searches for any objects with |
2093 | * present_arch(arch, map, x, y) searches for any objects with |