--- deliantra/server/common/object.C 2007/09/04 08:42:55 1.187 +++ deliantra/server/common/object.C 2007/10/16 00:30:24 1.194 @@ -256,13 +256,14 @@ */ if (ob1->inv || ob2->inv) { - /* if one object has inventory but the other doesn't, not equiv */ - if ((ob1->inv && !ob2->inv) || (ob2->inv && !ob1->inv)) - return 0; + if (!(ob1->inv && ob2->inv)) + return 0; /* inventories differ in length */ + + if (ob1->inv->below || ob2->inv->below) + return 0; /* more than one object in inv */ - /* Now check to see if the two inventory objects could merge */ if (!object::can_merge (ob1->inv, ob2->inv)) - return 0; + return 0; /* inventory objexts differ */ /* inventory ok - still need to check rest of this object to see * if it is valid. @@ -307,8 +308,17 @@ ob2->optimise (); if (ob1->self || ob2->self) - if (!cfperl_can_merge (ob1, ob2)) - return 0; + { + int k1 = ob1->self ? HvTOTALKEYS (SvRV (ob1->self)) : 0; + int k2 = ob2->self ? HvTOTALKEYS (SvRV (ob2->self)) : 0; + + if (k1 != k2) + return 0; + else if (k1 == 0) + return 1; + else if (!cfperl_can_merge (ob1, ob2)) + return 0; + } } /* Everything passes, must be OK. */ @@ -1142,7 +1152,7 @@ if (!op->nrof) return 0; - if (top) + if (!top) for (top = op; top && top->above; top = top->above) ; @@ -1292,7 +1302,7 @@ top = ms.bot; /* If there are other objects, then */ - if ((!(flag & INS_MAP_LOAD)) && top) + if (top) { object *last = 0; @@ -1354,8 +1364,6 @@ top = last->below; } } /* If objects on this space */ - if (flag & INS_MAP_LOAD) - top = ms.top; if (flag & INS_ABOVE_FLOOR_ONLY) top = floor; @@ -1398,9 +1406,8 @@ op->map->dirty = true; - if (!(flag & INS_MAP_LOAD)) - if (object *pl = ms.player ()) - pl->contr->ns->floorbox_update (); + if (object *pl = ms.player ()) + pl->contr->ns->floorbox_update (); /* If this object glows, it may affect lighting conditions that are * visible to others on this map. But update_all_los is really @@ -1993,14 +2000,30 @@ int find_free_spot (const object *ob, maptile *m, int x, int y, int start, int stop) { - int index = 0, flag; int altern[SIZEOFFREE]; + int index = 0, flag; for (int i = start; i < stop; i++) { - flag = ob_blocked (ob, m, x + freearr_x[i], y + freearr_y[i]); - if (!flag) - altern [index++] = i; + mapxy pos (m, x, y); pos.move (i); + + if (!pos.normalise ()) + continue; + + mapspace &ms = *pos; + + if (ms.flags () & P_IS_ALIVE) + continue; + + /* However, often + * ob doesn't have any move type (when used to place exits) + * so the AND operation in OB_TYPE_MOVE_BLOCK doesn't work. + */ + if (ob->move_type == 0 && ms.move_block != MOVE_ALL) + { + altern [index++] = i; + continue; + } /* Basically, if we find a wall on a space, we cut down the search size. * In this way, we won't return spaces that are on another side of a wall. @@ -2010,8 +2033,19 @@ * to only the spaces immediately surrounding the target area, and * won't look 2 spaces south of the target space. */ - else if ((flag & P_NO_PASS) && maxfree[i] < stop) - stop = maxfree[i]; + if (ms.move_block == MOVE_ALL && maxfree[i] < stop) + { + stop = maxfree[i]; + 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)) + continue; + + altern [index++] = i; } if (!index) @@ -2030,7 +2064,7 @@ find_first_free_spot (const object *ob, maptile *m, int x, int y) { for (int i = 0; i < SIZEOFFREE; i++) - if (!ob_blocked (ob, m, x + freearr_x[i], y + freearr_y[i])) + if (!ob->blocked (m, x + freearr_x[i], y + freearr_y[i])) return i; return -1;