--- deliantra/server/common/object.C 2008/05/03 11:14:50 1.228 +++ deliantra/server/common/object.C 2008/05/06 20:08:37 1.236 @@ -356,7 +356,7 @@ // adjust weight per container type ("of holding") static sint32 -weight_adjust (object *op, sint32 weight) +weight_adjust_for (object *op, sint32 weight) { return op->type == CONTAINER ? lerp (weight, 0, 100, 0, 100 - op->stats.Str) @@ -372,7 +372,10 @@ { while (op) { - weight = weight_adjust (op, weight); + // adjust by actual difference to account for rounding errors + // i.e. (w2 - w1) / f != w2 / f - w1 / f and the latter is correct + weight = weight_adjust_for (op, op->carrying) + - weight_adjust_for (op, op->carrying - weight); if (!weight) return; @@ -405,7 +408,7 @@ sum += op->total_weight (); } - sum = weight_adjust (this, sum); + sum = weight_adjust_for (this, sum); if (sum != carrying) { @@ -951,6 +954,11 @@ alloc (); in_memory = MAP_ACTIVE; } + + ~freed_map () + { + destroy (); + } } freed_map; // freed objects are moved here to avoid crashes void @@ -1051,10 +1059,13 @@ adjust_weight (env, -total_weight ()); + // make sure cmov optimisation is applicable *(above ? &above->below : &env->inv) = below; + *(below ? &below->above : &above ) = above; // &above is just a dummy - if (below) - below->above = above; + above = 0; + below = 0; + env = 0; /* we set up values so that it could be inserted into * the map, but we don't actually do that - it is up @@ -1063,9 +1074,6 @@ map = env->map; x = env->x; y = env->y; - above = 0; - below = 0; - env = 0; /* NO_FIX_PLAYER is set when a great many changes are being * made to players inventory. If set, avoiding the call @@ -1102,25 +1110,9 @@ } /* link the object above us */ - if (above) - above->below = below; - else - ms.top = below; /* we were top, set new top */ - - /* Relink the object below us, if there is one */ - if (below) - below->above = above; - else - { - /* Nothing below, which means we need to relink map object for this space - * use translated coordinates in case some oddness with map tiling is - * evident - */ - if (GET_MAP_OB (map, x, y) != this) - LOG (llevError, "remove_ob: GET_MAP_OB does not return object to be removed even though it appears to be on the bottom? %s\n", debug_desc ()); - - ms.bot = above; /* goes on above it. */ - } + // re-link, make sure compiler can easily use cmove + *(above ? &above->below : &ms.top) = below; + *(below ? &below->above : &ms.bot) = above; above = 0; below = 0; @@ -1287,7 +1279,7 @@ */ if (!xy_normalise (m, op->x, op->y)) { - op->destroy (1); + op->head_ ()->destroy (1);// remove head_ once all tail object destroyers found return 0; } @@ -1584,7 +1576,7 @@ { decrease (nr); - object *op = object_create_clone (this); + object *op = deep_clone (); op->nrof = nr; return op; } @@ -1815,7 +1807,7 @@ } for (object *tmp = m->at (x, y).bot; tmp; tmp = tmp->above) - if (tmp->arch == at) + if (tmp->arch->archname == at->archname) return tmp; return NULL; @@ -1889,8 +1881,8 @@ object * present_arch_in_ob (const archetype *at, const object *op) { - for (object *tmp = op->inv; tmp != NULL; tmp = tmp->below) - if (tmp->arch == at) + for (object *tmp = op->inv; tmp; tmp = tmp->below) + if (tmp->arch->archname == at->archname) return tmp; return NULL; @@ -2309,41 +2301,23 @@ * create clone from object to another */ object * -object_create_clone (object *asrc) +object::deep_clone () { - object *dst = 0; + assert (("deep_clone called on non-head object", is_head ())); - if (!asrc) - return 0; - - object *src = asrc->head_ (); + object *dst = clone (); - object *prev = 0; - for (object *part = src; part; part = part->more) + object *prev = dst; + for (object *part = this->more; part; part = part->more) { object *tmp = part->clone (); - - tmp->x -= src->x; - tmp->y -= src->y; - - if (!part->head) - { - dst = tmp; - tmp->head = 0; - } - else - tmp->head = dst; - - tmp->more = 0; - - if (prev) - prev->more = tmp; - + tmp->head = dst; + prev->more = tmp; prev = tmp; } - for (object *item = src->inv; item; item = item->below) - insert_ob_in_ob (object_create_clone (item), dst); + for (object *item = inv; item; item = item->below) + insert_ob_in_ob (item->deep_clone (), dst); return dst; }