--- deliantra/server/common/map.C 2007/09/04 05:43:20 1.124 +++ deliantra/server/common/map.C 2007/09/30 20:22:14 1.130 @@ -168,11 +168,11 @@ } /* - * Returns true if the given object can't fit in the given spot. - * This is meant for multi space objects - for single space objecs, + * Returns qthe blocking object if the given object can't fit in the given + * spot. This is meant for multi space objects - for single space objecs, * just calling get_map_blocked and checking that against movement type - * of object. This function goes through all the parts of the - * multipart object and makes sure they can be inserted. + * of object. This function goes through all the parts of the multipart + * object and makes sure they can be inserted. * * While this doesn't call out of map, the get_map_flags does. * @@ -193,48 +193,33 @@ * code, we need to have actual object to check its move_type * against the move_block values. */ -int -ob_blocked (const object *ob, maptile *m, sint16 x, sint16 y) +bool +object::blocked (maptile *m, int x, int y) const { - archetype *tmp; - int flag; - maptile *m1; - sint16 sx, sy; - - if (!ob) + for (archetype *tmp = arch; tmp; tmp = (archetype *)tmp->more) { - flag = get_map_flags (m, &m1, x, y, &sx, &sy); - if (flag & P_OUT_OF_MAP) - return P_OUT_OF_MAP; + mapxy pos (m, x + tmp->x, y + tmp->y); - /* don't have object, so don't know what types would block */ - return m1->at (sx, sy).move_block; - } - - for (tmp = ob->arch; tmp; tmp = (archetype *)tmp->more) - { - flag = get_map_flags (m, &m1, x + tmp->x, y + tmp->y, &sx, &sy); + if (!pos.normalise ()) + return 1; - if (flag & P_OUT_OF_MAP) - return P_OUT_OF_MAP; - if (flag & P_IS_ALIVE) - return P_IS_ALIVE; + mapspace &ms = *pos; - mapspace &ms = m1->at (sx, sy); + if (ms.flags () & P_IS_ALIVE) + return 1; - /* find_first_free_spot() calls this function. However, often - * ob doesn't have any move type (when used to place exits) + /* However, often ob doesn't have any move type + * (signifying non-moving objects) * so the AND operation in OB_TYPE_MOVE_BLOCK doesn't work. */ - - if (ob->move_type == 0 && ms.move_block != MOVE_ALL) + if (!move_type && ms.move_block != MOVE_ALL) continue; /* Note it is intentional that we check ob - the movement type of the * head of the object should correspond for the entire object. */ - if (OB_TYPE_MOVE_BLOCK (ob, ms.move_block)) - return P_NO_PASS; + if (ms.blocks (move_type)) + return 1; } return 0; @@ -334,7 +319,32 @@ if (op->inv) sum_weight (op); - insert_ob_in_map (op, this, op, INS_NO_MERGE | INS_NO_WALK_ON | INS_ON_TOP | INS_MAP_LOAD); + if (IN_RANGE_EXC (op->x, 0, width) && IN_RANGE_EXC (op->y, 0, height)) + { + // we insert manually because + // a) its way faster + // b) we remove manually, too, and there are good reasons for that + // c) its correct + mapspace &ms = at (op->x, op->y); + + op->flag [FLAG_REMOVED] = false; + + op->above = 0; + op->below = ms.top; + + if (ms.top) + ms.top->above = op; + else + ms.bot = op; + + ms.top = op; + ms.flags_ = 0; + } + else + { + f.parse_warn (format ("object %s out of range", op->debug_desc ())); + op->destroy (); + } } continue; @@ -780,17 +790,28 @@ void maptile::clear () { - sfree (regions, size ()); regions = 0; - delete [] regionmap; regionmap = 0; - if (spaces) { for (mapspace *ms = spaces + size (); ms-- > spaces; ) while (object *op = ms->bot) { - op = op->head_ (); - op->destroy_inv (false); - op->destroy (); + // manually remove, as to not trigger anything + if (ms->bot = op->above) + ms->bot->below = 0; + + op->flag [FLAG_REMOVED] = true; + + object *head = op->head_ (); + if (op == head) + { + op->destroy_inv (false); + op->destroy (); + } + else if (head->map != op->map) + { + LOG (llevDebug, "bad luck for object crossing map borders: %s", head->debug_desc ()); + head->destroy (); + } } sfree (spaces, size ()), spaces = 0; @@ -798,6 +819,9 @@ if (buttons) free_objectlinkpt (buttons), buttons = 0; + + sfree (regions, size ()); regions = 0; + delete [] regionmap; regionmap = 0; } void @@ -1598,11 +1622,11 @@ return; for_all_players (pl) - if (pl->ob->map == this) + if (pl->observe->map == this) if (client *ns = pl->ns) { - int dx = x - pl->ob->x; - int dy = y - pl->ob->y; + int dx = x - pl->observe->x; + int dy = y - pl->observe->y; int distance = idistance (dx, dy);