--- deliantra/server/common/object.C 2007/01/15 01:39:42 1.115 +++ deliantra/server/common/object.C 2007/01/24 22:42:48 1.122 @@ -1,26 +1,26 @@ /* - CrossFire, A Multiplayer game for X-windows - - Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team - Copyright (C) 2001 Mark Wedel & Crossfire Development Team - Copyright (C) 1992 Frank Tore Johansen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - The authors can be reached via e-mail at -*/ + * CrossFire, A Multiplayer game for X-windows + * + * Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team + * Copyright (C) 2001 Mark Wedel & Crossfire Development Team + * Copyright (C) 1992 Frank Tore Johansen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * The authors can be reached via e-mail at + */ /* Eneq(@csd.uu.se): Added weight-modifiers in environment of objects. sub/add_weight will transcend the environment updating the carrying @@ -491,7 +491,7 @@ SET_FLAG (dst, FLAG_REMOVED); if (speed < 0) - dst->speed_left = speed_left - RANDOM () % 200 / 100.0; + dst->speed_left = speed_left - rndm (); /* Copy over key_values, if any. */ if (key_values) @@ -672,6 +672,8 @@ object::~object () { + unlink (); + free_key_values (this); } @@ -689,7 +691,9 @@ void object::unlink () { - assert (index);//D + if (!index) + return; + objects.erase (this); refcnt_dec (); } @@ -773,6 +777,7 @@ if (!drop_to_ground || !map || map->in_memory != MAP_IN_MEMORY + || map->nodrop || ms ().move_block == MOVE_ALL) { while (inv) @@ -901,7 +906,7 @@ * Beware: This function is called from the editor as well! */ void -object::remove () +object::remove_slow () { object *tmp, *last = 0; object *otmp; @@ -959,12 +964,13 @@ } map->dirty = true; + mapspace &ms = this->ms (); /* link the object above us */ if (above) above->below = below; else - map->at (x, y).top = below; /* we were top, set new top */ + ms.top = below; /* we were top, set new top */ /* Relink the object below us, if there is one */ if (below) @@ -976,17 +982,9 @@ * evident */ if (GET_MAP_OB (map, x, y) != this) - { - char *dump = dump_object (this); - 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", dump); - free (dump); - dump = dump_object (GET_MAP_OB (map, x, y)); - LOG (llevError, "%s\n", dump); - free (dump); - } + 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 ()); - map->at (x, y).bot = above; /* goes on above it. */ + ms.bot = above; /* goes on above it. */ } above = 0; @@ -997,7 +995,7 @@ int check_walk_off = !flag [FLAG_NO_APPLY]; - for (tmp = map->at (x, y).bot; tmp; tmp = tmp->above) + for (tmp = ms.bot; tmp; tmp = tmp->above) { /* No point updating the players look faces if he is the object * being removed. @@ -1088,8 +1086,8 @@ } /* - * same as insert_ob_in_map except it handle separate coordinates and do a clean - * job preparing multi-part monsters + * same as insert_ob_in_map except it handles separate coordinates and does a clean + * job preparing multi-part monsters. */ object * insert_ob_in_map_at (object *op, maptile *m, object *originator, int flag, int x, int y) @@ -1127,7 +1125,6 @@ insert_ob_in_map (object *op, maptile *m, object *originator, int flag) { object *tmp, *top, *floor = NULL; - sint16 x, y; if (QUERY_FLAG (op, FLAG_FREED)) { @@ -1135,6 +1132,11 @@ return NULL; } + if (!QUERY_FLAG (op, FLAG_REMOVED)) + LOG (llevError, "Trying to insert already inserted object %s\n", op->debug_desc ()); + + op->remove (); + if (!m) { char *dump = dump_object (op); @@ -1158,36 +1160,9 @@ return op; } - if (!QUERY_FLAG (op, FLAG_REMOVED)) + if (object *more = op->more) { - char *dump = dump_object (op); - LOG (llevError, "Trying to insert (map) inserted object.\n%s\n", dump); - free (dump); - return op; - } - - if (op->more) - { - /* The part may be on a different map. */ - - object *more = op->more; - - /* We really need the caller to normalise coordinates - if - * we set the map, that doesn't work if the location is within - * a map and this is straddling an edge. So only if coordinate - * is clear wrong do we normalise it. - */ - if (OUT_OF_REAL_MAP (more->map, 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, - * more->map should always point to the parent. - */ - more->map = m; - } - - if (insert_ob_in_map (more, more->map, originator, flag) == NULL) + if (!insert_ob_in_map (more, m, originator, flag)) { if (!op->head) LOG (llevError, "BUG: insert_ob_in_map(): inserting op->more killed op\n"); @@ -1202,14 +1177,16 @@ * of areas of callers (eg, anything that uses find_free_spot would now * need extra work */ - op->map = get_map_from_coord (m, &op->x, &op->y); - x = op->x; - y = op->y; + if (!xy_normalise (m, op->x, op->y)) + return 0; + + op->map = m; + mapspace &ms = op->ms (); /* 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; tmp = tmp->above) + for (tmp = ms.bot; tmp; tmp = tmp->above) if (object::can_merge (op, tmp)) { op->nrof += tmp->nrof; @@ -1236,15 +1213,17 @@ if (op->below) op->below->above = op; else - op->ms ().bot = op; + ms.bot = op; /* since *below* originator, no need to update top */ originator->below = op; } else { + top = ms.bot; + /* If there are other objects, then */ - if ((!(flag & INS_MAP_LOAD)) && ((top = GET_MAP_OB (op->map, op->x, op->y)) != NULL)) + if ((!(flag & INS_MAP_LOAD)) && top) { object *last = 0; @@ -1260,7 +1239,7 @@ * when lots of spells are cast in one area. Currently, it is presumed * that flying non pickable objects are spell objects. */ - while (top) + for (top = ms.bot; top; top = top->above) { if (QUERY_FLAG (top, FLAG_IS_FLOOR) || QUERY_FLAG (top, FLAG_OVERLAY_FLOOR)) floor = top; @@ -1273,7 +1252,6 @@ } last = top; - top = top->above; } /* Don't want top to be NULL, so set it to the last valid object */ @@ -1290,12 +1268,14 @@ * Need to find the object that in fact blocks view, otherwise * stacking is a bit odd. */ - if (!(flag & INS_ON_TOP) && - (get_map_flags (op->map, 0, op->x, op->y, 0, 0) & P_BLOCKSVIEW) && (op->face && !op->face->visibility)) + if (!(flag & INS_ON_TOP) + && ms.flags () & P_BLOCKSVIEW + && (op->face && !op->face->visibility)) { for (last = top; last != floor; last = last->below) if (QUERY_FLAG (last, FLAG_BLOCKSVIEW) && (last->type != EXIT)) break; + /* Check to see if we found the object that blocks view, * and make sure we have a below pointer for it so that * we can get inserted below this one, which requires we @@ -1307,7 +1287,7 @@ } /* If objects on this space */ if (flag & INS_MAP_LOAD) - top = GET_MAP_TOP (op->map, op->x, op->y); + top = ms.top; if (flag & INS_ABOVE_FLOOR_ONLY) top = floor; @@ -1318,13 +1298,13 @@ /* First object on this space */ if (!top) { - op->above = GET_MAP_OB (op->map, op->x, op->y); + op->above = ms.bot; if (op->above) op->above->below = op; op->below = 0; - op->ms ().bot = op; + ms.bot = op; } else { /* get inserted into the stack above top */ @@ -1338,7 +1318,7 @@ } if (!op->above) - op->ms ().top = op; + ms.top = op; } /* else not INS_BELOW_ORIGINATOR */ if (op->type == PLAYER) @@ -1354,7 +1334,7 @@ * it, so save a few ticks and start from there. */ if (!(flag & INS_MAP_LOAD)) - if (object *pl = op->ms ().player ()) + if (object *pl = ms.player ()) if (pl->contr->ns) pl->contr->ns->floorbox_update (); @@ -1773,7 +1753,7 @@ { 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)) || @@ -2593,10 +2573,10 @@ char info2[256 * 4]; char *p = info; - p += snprintf (p, 512, "{cnt:%d,uuid:<1,%" PRIx64 ">,name:\"%s%s%s\",flags:[%s],type:%d}", + p += snprintf (p, 512, "{cnt:%d,uuid:<1,%" PRIx64 ">,name:\"%s\"%s%s,flags:[%s],type:%d}", count, uuid.seq, &name, - title ? "\",title:" : "", + title ? "\",title:\"" : "", title ? (const char *)title : "", flag_desc (flagdesc, 512), type);