--- deliantra/server/common/object.C 2006/09/10 16:00:23 1.24 +++ deliantra/server/common/object.C 2006/09/11 12:08:45 1.27 @@ -1,7 +1,7 @@ /* * static char *rcsid_object_c = - * "$Id: object.C,v 1.24 2006/09/10 16:00:23 root Exp $"; + * "$Id: object.C,v 1.27 2006/09/11 12:08:45 root Exp $"; */ /* @@ -509,7 +509,6 @@ op->ownercount = owner->count; owner->refcount++; - } /* Set the owner to clone's current owner and set the skill and experience @@ -537,8 +536,8 @@ else return; } - set_owner (op, owner); + set_owner (op, owner); } /* Zero the key_values on op, decrementing the shared-string @@ -564,6 +563,8 @@ free_key_values (this); + clear_owner (this); + name = 0; name_pl = 0; title = 0; @@ -892,17 +893,11 @@ * that is being removed. */ else if (action == UP_OBJ_CHANGE || action == UP_OBJ_REMOVE) - { - update_now = 1; - } + update_now = 1; else if (action == UP_OBJ_FACE) - { - /* Nothing to do for that case */ - } + /* Nothing to do for that case */; else - { - LOG (llevError, "update_object called with invalid action: %d\n", action); - } + LOG (llevError, "update_object called with invalid action: %d\n", action); if (update_now) { @@ -914,17 +909,19 @@ update_object (op->more, action); } -static -std::vector < object *> - mortals; +static unordered_vector mortals; +static std::vector freed; void object::free_mortals () { - for (std::vector < object *>::iterator i = mortals.begin (); i != mortals.end (); ++i) - delete * - i; - - mortals.clear (); + for (unordered_vector::iterator i = mortals.begin (); i != mortals.end (); ) + if (!(*i)->refcount) + { + freed.push_back (*i); + mortals.erase (i); + } + else + ++i; } object::object () @@ -960,17 +957,34 @@ /* Remove this object from the list of used objects */ if (prev) - prev->next = next; + { + prev->next = next; + prev = 0; + } + if (next) - next->prev = prev; + { + next->prev = prev; + next = 0; + } + if (this == objects) objects = next; } object *object::create () { - object * + object *op; + + if (freed.empty ()) op = new object; + else + { + // highly annoying, but the only way to get it stable right now + op = freed.back (); freed.pop_back (); + op->~object (); + new ((void *)op) object; + } op->link (); return op; @@ -1064,6 +1078,8 @@ } } + clear_owner (this); + /* Remove object from the active list */ speed = 0; update_ob_speed (this); @@ -1106,21 +1122,14 @@ void remove_ob (object *op) { - object * - tmp, * - last = NULL; - object * - otmp; - tag_t - tag; - int - check_walk_off; - mapstruct * - m; - sint16 - x, - y; + object *tmp, *last = NULL; + object *otmp; + + tag_t tag; + int check_walk_off; + mapstruct *m; + sint16 x, y; if (QUERY_FLAG (op, FLAG_REMOVED)) { @@ -1139,6 +1148,7 @@ */ abort (); } + if (op->more != NULL) remove_ob (op->more); @@ -1217,9 +1227,7 @@ /* Relink the object below us, if there is one */ if (op->below) - { - op->below->above = op->above; - } + op->below->above = op->above; else { /* Nothing below, which means we need to relink map object for this space @@ -1234,8 +1242,10 @@ dump_object (GET_MAP_OB (m, x, y)); LOG (llevError, "%s\n", errmsg); } + SET_MAP_OB (m, x, y, op->above); /* goes on above it. */ } + op->above = NULL; op->below = NULL; @@ -1244,6 +1254,7 @@ tag = op->count; check_walk_off = !QUERY_FLAG (op, FLAG_NO_APPLY); + for (tmp = GET_MAP_OB (m, x, y); tmp != NULL; tmp = tmp->above) { /* No point updating the players look faces if he is the object @@ -1261,13 +1272,14 @@ CLEAR_FLAG (op, FLAG_APPLIED); tmp->container = NULL; } + tmp->contr->socket.update_look = 1; } /* See if player moving off should effect something */ if (check_walk_off && ((op->move_type & tmp->move_off) && (op->move_type & ~tmp->move_off & ~tmp->move_block) == 0)) { - move_apply (tmp, op, NULL); + if (was_destroyed (op, tag)) { LOG (llevError, "BUG: remove_ob(): name %s, archname %s destroyed " "leaving object\n", &tmp->name, &tmp->arch->name); @@ -1278,8 +1290,10 @@ if (tmp->above == tmp) tmp->above = NULL; + last = tmp; } + /* last == NULL of there are no objects on this space */ if (last == NULL) { @@ -1296,7 +1310,6 @@ if (QUERY_FLAG (op, FLAG_BLOCKSVIEW) || (op->glow_radius != 0)) update_all_los (op->map, op->x, op->y); - } /* @@ -1377,25 +1390,22 @@ object * insert_ob_in_map (object *op, mapstruct *m, object *originator, int flag) { - object * - tmp, * - top, * - floor = NULL; - sint16 - x, - y; + object *tmp, *top, *floor = NULL; + sint16 x, y; if (QUERY_FLAG (op, FLAG_FREED)) { LOG (llevError, "Trying to insert freed object!\n"); return NULL; } + if (m == NULL) { dump_object (op); LOG (llevError, "Trying to insert in null-map!\n%s\n", errmsg); return op; } + if (out_of_map (m, op->x, op->y)) { dump_object (op); @@ -1409,18 +1419,19 @@ #endif return op; } + if (!QUERY_FLAG (op, FLAG_REMOVED)) { dump_object (op); LOG (llevError, "Trying to insert (map) inserted object.\n%s\n", errmsg); return op; } + if (op->more != NULL) { /* The part may be on a different map. */ - object * - more = op->more; + object *more = op->more; /* We really need the caller to normalize coordinates - if * we set the map, that doesn't work if the location is within @@ -1428,9 +1439,7 @@ * is clear wrong do we normalize it. */ if (OUT_OF_REAL_MAP (more->map, more->x, more->y)) - { - more->map = get_map_from_coord (m, &more->x, &more->y); - } + more->map = get_map_from_coord (m, &more->x, &more->y); else if (!more->map) { /* For backwards compatibility - when not dealing with tiled maps, @@ -1443,9 +1452,11 @@ { if (!op->head) LOG (llevError, "BUG: insert_ob_in_map(): inserting op->more killed op\n"); + return NULL; } } + CLEAR_FLAG (op, FLAG_REMOVED); /* Ideally, the caller figures this out. However, it complicates a lot @@ -1459,18 +1470,17 @@ /* this has to be done after we translate the coordinates. */ if (op->nrof && !(flag & INS_NO_MERGE)) - { - for (tmp = GET_MAP_OB (op->map, x, y); tmp != NULL; tmp = tmp->above) - if (CAN_MERGE (op, tmp)) - { - op->nrof += tmp->nrof; - remove_ob (tmp); - free_object (tmp); - } - } + for (tmp = GET_MAP_OB (op->map, x, y); tmp != NULL; tmp = tmp->above) + if (CAN_MERGE (op, tmp)) + { + op->nrof += tmp->nrof; + remove_ob (tmp); + free_object (tmp); + } CLEAR_FLAG (op, FLAG_APPLIED); /* hack for fixing F_APPLIED in items of dead people */ CLEAR_FLAG (op, FLAG_INV_LOCKED); + if (!QUERY_FLAG (op, FLAG_ALIVE)) CLEAR_FLAG (op, FLAG_NO_STEAL); @@ -1481,12 +1491,15 @@ LOG (llevError, "insert_ob_in_map called with INS_BELOW_ORIGINATOR when originator not on same space!\n"); abort (); } + op->above = originator; op->below = originator->below; + if (op->below) op->below->above = op; else SET_MAP_OB (op->map, op->x, op->y, op); + /* since *below* originator, no need to update top */ originator->below = op; } @@ -1495,8 +1508,7 @@ /* If there are other objects, then */ if ((!(flag & INS_MAP_LOAD)) && ((top = GET_MAP_OB (op->map, op->x, op->y)) != NULL)) { - object * - last = NULL; + object *last = NULL; /* * If there are multiple objects on this space, we do some trickier handling. @@ -1515,15 +1527,18 @@ { if (QUERY_FLAG (top, FLAG_IS_FLOOR) || QUERY_FLAG (top, FLAG_OVERLAY_FLOOR)) floor = top; + if (QUERY_FLAG (top, FLAG_NO_PICK) && (top->move_type & (MOVE_FLY_LOW | MOVE_FLY_HIGH)) && !QUERY_FLAG (top, FLAG_IS_FLOOR)) { /* We insert above top, so we want this object below this */ top = top->below; break; } + last = top; top = top->above; } + /* Don't want top to be NULL, so set it to the last valid object */ top = last; @@ -1553,8 +1568,10 @@ top = last->below; } } /* If objects on this space */ + if (flag & INS_MAP_LOAD) top = GET_MAP_TOP (op->map, op->x, op->y); + if (flag & INS_ABOVE_FLOOR_ONLY) top = floor; @@ -1565,19 +1582,24 @@ if (!top) { op->above = GET_MAP_OB (op->map, op->x, op->y); + if (op->above) op->above->below = op; + op->below = NULL; SET_MAP_OB (op->map, op->x, op->y, op); } else { /* get inserted into the stack above top */ op->above = top->above; + if (op->above) op->above->below = op; + op->below = top; top->above = op; } + if (op->above == NULL) SET_MAP_TOP (op->map, op->x, op->y, op); } /* else not INS_BELOW_ORIGINATOR */ @@ -1590,10 +1612,8 @@ */ if (!(flag & INS_MAP_LOAD)) for (tmp = floor ? floor : GET_MAP_OB (op->map, op->x, op->y); tmp != NULL; tmp = tmp->above) - { - if (tmp->type == PLAYER) - tmp->contr->socket.update_look = 1; - } + if (tmp->type == PLAYER) + tmp->contr->socket.update_look = 1; /* If this object glows, it may affect lighting conditions that are * visible to others on this map. But update_all_los is really @@ -1607,11 +1627,9 @@ if (MAP_DARKNESS (op->map) && (op->glow_radius != 0)) update_all_los (op->map, op->x, op->y); - /* updates flags (blocked, alive, no magic, etc) for this map space */ update_object (op, UP_OBJ_INSERT); - /* Don't know if moving this to the end will break anything. However, * we want to have update_look set above before calling this. * @@ -1622,7 +1640,6 @@ */ /* if this is not the head or flag has been passed, don't check walk on status */ - if (!(flag & INS_NO_WALK_ON) && !op->head) { if (check_move_on (op, originator)) @@ -1635,6 +1652,7 @@ if (check_move_on (tmp, originator)) return NULL; } + return op; } @@ -1645,10 +1663,8 @@ void replace_insert_ob_in_map (const char *arch_string, object *op) { - object * - tmp; - object * - tmp1; + object *tmp; + object *tmp1; /* first search for itself and remove any old instances */ @@ -1663,7 +1679,6 @@ tmp1 = arch_to_object (find_archetype (arch_string)); - tmp1->x = op->x; tmp1->y = op->y; insert_ob_in_map (tmp1, op->map, op, 0); @@ -1973,18 +1988,12 @@ int check_move_on (object *op, object *originator) { - object * - tmp; - tag_t - tag; - mapstruct * - m = op->map; - int - x = op->x, y = op->y; - MoveType - move_on, - move_slow, - move_block; + object *tmp; + tag_t tag; + mapstruct *m = op->map; + int x = op->x, y = op->y; + + MoveType move_on, move_slow, move_block; if (QUERY_FLAG (op, FLAG_NO_APPLY)) return 0; @@ -2024,7 +2033,8 @@ if ((tmp->move_type & MOVE_FLY_LOW) && QUERY_FLAG (tmp, FLAG_NO_PICK)) break; } - for (; tmp != NULL; tmp = tmp->below) + + for (; tmp; tmp = tmp->below) { if (tmp == op) continue; /* Can't apply yourself */ @@ -2041,18 +2051,13 @@ ((op->move_type & tmp->move_slow) && (op->move_type & ~tmp->move_slow & ~tmp->move_block) == 0)) { - float - diff; + float diff = tmp->move_slow_penalty * FABS (op->speed); - diff = tmp->move_slow_penalty * FABS (op->speed); if (op->type == PLAYER) - { - if ((QUERY_FLAG (tmp, FLAG_IS_HILLY) && find_skill_by_number (op, SK_CLIMBING)) || - (QUERY_FLAG (tmp, FLAG_IS_WOODED) && find_skill_by_number (op, SK_WOODSMAN))) - { - diff /= 4.0; - } - } + if ((QUERY_FLAG (tmp, FLAG_IS_HILLY) && find_skill_by_number (op, SK_CLIMBING)) || + (QUERY_FLAG (tmp, FLAG_IS_WOODED) && find_skill_by_number (op, SK_WOODSMAN))) + diff /= 4.0; + op->speed_left -= diff; } } @@ -2061,8 +2066,8 @@ if ((!op->move_type && tmp->move_on & MOVE_WALK) || ((op->move_type & tmp->move_on) && (op->move_type & ~tmp->move_on & ~tmp->move_block) == 0)) { - move_apply (tmp, op, originator); + if (was_destroyed (op, tag)) return 1; @@ -2074,6 +2079,7 @@ return 0; } } + return 0; }