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.28 by root, Mon Sep 11 12:10:21 2006 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines