--- deliantra/server/common/object.C 2006/12/23 13:56:25 1.81 +++ deliantra/server/common/object.C 2006/12/25 11:25:49 1.82 @@ -485,9 +485,6 @@ *(object_copy *)dst = *this; - if (self || cb) - INVOKE_OBJECT (CLONE, this, ARG_OBJECT (dst)); - if (is_freed) SET_FLAG (dst, FLAG_FREED); @@ -743,22 +740,9 @@ update_object (op->more, action); } -object::vector object::mortals; object::vector object::objects; // not yet used object *object::first; -void object::free_mortals () -{ - for (AUTODECL (i, mortals.begin ()); i != mortals.end ();) - if ((*i)->refcnt) - ++i; // further delay freeing - else - { - delete *i; - mortals.erase (i); - } -} - object::object () { SET_FLAG (this, FLAG_REMOVED); @@ -816,66 +800,24 @@ * If destroy_inventory is set, free inventory as well. Else drop items in * inventory to the ground. */ -void object::destroy (bool destroy_inventory) +void +object::do_destroy () { - if (QUERY_FLAG (this, FLAG_FREED)) - return; + attachable::do_destroy (); - if (QUERY_FLAG (this, FLAG_FRIENDLY)) + if (flag [FLAG_IS_LINKED]) + remove_button_link (this); + + if (flag [FLAG_FRIENDLY]) remove_friendly_object (this); - if (!QUERY_FLAG (this, FLAG_REMOVED)) + if (!flag [FLAG_REMOVED]) remove (); - SET_FLAG (this, FLAG_FREED); - - if (more) - { - more->destroy (destroy_inventory); - more = 0; - } - - if (inv) - { - /* Only if the space blocks everything do we not process - - * if some form of movement is allowed, let objects - * drop on that space. - */ - if (destroy_inventory || !map || map->in_memory != MAP_IN_MEMORY || GET_MAP_MOVE_BLOCK (map, x, y) == MOVE_ALL) - { - object *op = inv; - - while (op) - { - object *tmp = op->below; - op->destroy (destroy_inventory); - op = tmp; - } - } - else - { /* Put objects in inventory onto this space */ - object *op = inv; - - while (op) - { - object *tmp = op->below; + if (flag [FLAG_FREED]) + return; - op->remove (); - - if (QUERY_FLAG (op, FLAG_STARTEQUIP) - || QUERY_FLAG (op, FLAG_NO_DROP) || op->type == RUNE || op->type == TRAP || QUERY_FLAG (op, FLAG_IS_A_TEMPLATE)) - op->destroy (); - else - { - op->x = x; - op->y = y; - insert_ob_in_map (op, map, 0, 0); /* Insert in same map as the envir */ - } - - op = tmp; - } - } - } + flag [FLAG_FREED] = 1; // hack to ensure that freed objects still have a valid map { @@ -897,6 +839,10 @@ y = 1; } + more = 0; + head = 0; + inv = 0; + // clear those pointers that likely might have circular references to us owner = 0; enemy = 0; @@ -910,8 +856,70 @@ update_ob_speed (this); unlink (); +} + +/* + * Remove and free all objects in the inventory of the given object. + * object.c ? + */ +void +object::destroy_inv (bool drop_to_ground) +{ + if (!inv) + return; + + /* Only if the space blocks everything do we not process - + * if some form of movement is allowed, let objects + * drop on that space. + */ + if (!drop_to_ground || !map || map->in_memory != MAP_IN_MEMORY || GET_MAP_MOVE_BLOCK (map, x, y) == MOVE_ALL) + { + while (inv) + { + inv->destroy_inv (drop_to_ground); + inv->destroy (); + } + } + else + { /* Put objects in inventory onto this space */ + while (inv) + { + object *op = inv; + + if (op->flag [FLAG_STARTEQUIP] + || op->flag [FLAG_NO_DROP] + || op->type == RUNE + || op->type == TRAP + || op->flag [FLAG_IS_A_TEMPLATE]) + op->destroy (); + else + { + op->remove (); + op->x = x; + op->y = y; + insert_ob_in_map (op, map, 0, 0); /* Insert in same map as the envir */ + } + } + } +} + +void +object::destroy (bool destroy_inventory) +{ + if (destroyed ()) + return; + + if (more) + { + //TODO: non-head objects must not have inventory + more->destroy (destroy_inventory); + more = 0; + } + + if (destroy_inventory) + destroy_inv (true); - mortals.push_back (this); + attachable::destroy (); } /* @@ -945,12 +953,11 @@ object *tmp, *last = 0; object *otmp; - int check_walk_off; - if (QUERY_FLAG (this, FLAG_REMOVED)) return; SET_FLAG (this, FLAG_REMOVED); + INVOKE_OBJECT (REMOVE, this); if (more) more->remove (); @@ -1031,7 +1038,7 @@ if (map->in_memory == MAP_SAVING) return; - check_walk_off = !QUERY_FLAG (this, FLAG_NO_APPLY); + int check_walk_off = !flag [FLAG_NO_APPLY]; for (tmp = GET_MAP_OB (map, x, y); tmp; tmp = tmp->above) { @@ -1047,11 +1054,12 @@ */ if (tmp->container == this) { - CLEAR_FLAG (this, FLAG_APPLIED); + flag [FLAG_APPLIED] = 0; tmp->container = 0; } - tmp->contr->ns->floorbox_update (); + if (tmp->contr->ns) + tmp->contr->ns->floorbox_update (); } /* See if player moving off should effect something */ @@ -1079,7 +1087,7 @@ else update_object (last, UP_OBJ_REMOVE); - if (QUERY_FLAG (this, FLAG_BLOCKSVIEW) || glow_radius) + if (flag [FLAG_BLOCKSVIEW] || glow_radius) update_all_los (map, x, y); } } @@ -1098,10 +1106,11 @@ if (!op->nrof) return 0; - if (top == NULL) - for (top = op; top != NULL && top->above != NULL; top = top->above); + if (top) + for (top = op; top && top->above; top = top->above) + ; - for (; top != NULL; top = top->below) + for (; top; top = top->below) { if (top == op) continue; @@ -1161,7 +1170,6 @@ * NULL if 'op' was destroyed * just 'op' otherwise */ - object * insert_ob_in_map (object *op, maptile *m, object *originator, int flag) { @@ -1205,7 +1213,7 @@ return op; } - if (op->more != NULL) + if (op->more) { /* The part may be on a different map. */ @@ -1231,7 +1239,7 @@ if (!op->head) LOG (llevError, "BUG: insert_ob_in_map(): inserting op->more killed op\n"); - return NULL; + return 0; } } @@ -1389,7 +1397,8 @@ */ if (!(flag & INS_MAP_LOAD)) if (object *pl = op->ms ().player ()) - pl->contr->ns->floorbox_update (); + if (pl->contr->ns) + 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 @@ -1406,6 +1415,8 @@ /* updates flags (blocked, alive, no magic, etc) for this map space */ update_object (op, UP_OBJ_INSERT); + INVOKE_OBJECT (INSERT, op); + /* Don't know if moving this to the end will break anything. However, * we want to have floorbox_update called before calling this. * @@ -1419,14 +1430,14 @@ if (!(flag & INS_NO_WALK_ON) && !op->head) { if (check_move_on (op, originator)) - return NULL; + return 0; /* If we are a multi part object, lets work our way through the check * walk on's. */ for (tmp = op->more; tmp != NULL; tmp = tmp->more) if (check_move_on (tmp, originator)) - return NULL; + return 0; } return op; @@ -1710,6 +1721,8 @@ inv = op; } + INVOKE_OBJECT (INSERT, this); + return op; } @@ -1908,19 +1921,16 @@ * spell code can use one object type (force), but change it's name * to be unique. */ - object * present_in_ob_by_name (int type, const char *str, const object *op) { - object * - tmp; + object *tmp; - for (tmp = op->inv; tmp != NULL; tmp = tmp->below) - { - if ((type == -1 || tmp->type == type) && (!strcmp (str, tmp->name))) - return tmp; - } - return NULL; + for (tmp = op->inv; tmp; tmp = tmp->below) + if ((type == -1 || tmp->type == type) && (!strcmp (str, tmp->name))) + return tmp; + + return 0; } /* @@ -1928,16 +1938,13 @@ * a matching archetype in the inventory of the given object. * The first matching object is returned, or NULL if none. */ - object * present_arch_in_ob (const archetype *at, const object *op) { - object * - tmp; - - for (tmp = op->inv; tmp != NULL; tmp = tmp->below) + for (object *tmp = op->inv; tmp != NULL; tmp = tmp->below) if (tmp->arch == at) return tmp; + return NULL; } @@ -1947,26 +1954,22 @@ void flag_inv (object *op, int flag) { - object * - tmp; - if (op->inv) - for (tmp = op->inv; tmp != NULL; tmp = tmp->below) + for (object *tmp = op->inv; tmp != NULL; tmp = tmp->below) { SET_FLAG (tmp, flag); flag_inv (tmp, flag); } -} /* - * desactivate recursively a flag on an object inventory - */ +} + +/* + * deactivate recursively a flag on an object inventory + */ void unflag_inv (object *op, int flag) { - object * - tmp; - if (op->inv) - for (tmp = op->inv; tmp != NULL; tmp = tmp->below) + for (object *tmp = op->inv; tmp != NULL; tmp = tmp->below) { CLEAR_FLAG (tmp, flag); unflag_inv (tmp, flag); @@ -1979,7 +1982,6 @@ * If checksums are used, a player will get set_cheat called for * him/her-self and all object carried by a call to this function. */ - void set_cheat (object *op) { @@ -2008,21 +2010,17 @@ * the archetype because that isn't correct if the monster has been * customized, changed states, etc. */ - int find_free_spot (const object *ob, maptile *m, int x, int y, int start, int stop) { - int - i, - index = 0, flag; - static int - altern[SIZEOFFREE]; + int index = 0, flag; + int altern[SIZEOFFREE]; - for (i = start; i < stop; i++) + 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; + altern [index++] = i; /* 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. @@ -2048,43 +2046,29 @@ * But it will return the first available spot, not a random choice. * Changed 0.93.2: Have it return -1 if there is no free spot available. */ - int find_first_free_spot (const object *ob, maptile *m, int x, int y) { - int - i; + for (int i = 0; i < SIZEOFFREE; i++) + if (!ob_blocked (ob, m, x + freearr_x[i], y + freearr_y[i])) + return i; - for (i = 0; i < SIZEOFFREE; i++) - { - if (!ob_blocked (ob, m, x + freearr_x[i], y + freearr_y[i])) - return i; - } return -1; } /* * The function permute(arr, begin, end) randomly reorders the array * arr[begin..end-1]. + * now uses a fisher-yates shuffle, old permute was broken */ static void permute (int *arr, int begin, int end) { - int - i, - j, - tmp, - len; - - len = end - begin; - for (i = begin; i < end; i++) - { - j = begin + RANDOM () % len; - - tmp = arr[i]; - arr[i] = arr[j]; - arr[j] = tmp; - } + arr += begin; + end -= begin; + + while (--end) + swap (arr [end], arr [RANDOM () % (end + 1)]); } /* new function to make monster searching more efficient, and effective! @@ -2097,13 +2081,10 @@ void get_search_arr (int *search_arr) { - int - i; + int i; for (i = 0; i < SIZEOFFREE; i++) - { - search_arr[i] = i; - } + search_arr[i] = i; permute (search_arr, 1, SIZEOFFREE1 + 1); permute (search_arr, SIZEOFFREE1 + 1, SIZEOFFREE2 + 1); @@ -2122,19 +2103,14 @@ * because we have to know what movement the thing looking to move * there is capable of. */ - int find_dir (maptile *m, int x, int y, object *exclude) { - int - i, - max = SIZEOFFREE, mflags; + int i, max = SIZEOFFREE, mflags; sint16 nx, ny; - object * - tmp; - maptile * - mp; + object *tmp; + maptile *mp; MoveType blocked, move_type; @@ -2161,14 +2137,17 @@ max = maxfree[i]; else { - blocked = GET_MAP_MOVE_BLOCK (mp, nx, ny); + mapspace &ms = mp->at (nx, ny); + + blocked = ms.move_block; if ((move_type & blocked) == move_type) max = maxfree[i]; else if (mflags & P_IS_ALIVE) { - for (tmp = GET_MAP_OB (mp, nx, ny); tmp; tmp = tmp->above) - if ((QUERY_FLAG (tmp, FLAG_MONSTER) || tmp->type == PLAYER) && (tmp != exclude || (tmp->head && tmp->head != exclude))) + for (tmp = ms.bottom; tmp; tmp = tmp->above) + if ((tmp->flag [FLAG_MONSTER] || tmp->type == PLAYER) + && (tmp != exclude || (tmp->head && tmp->head != exclude))) break; if (tmp) @@ -2184,14 +2163,10 @@ * distance(object 1, object 2) will return the square of the * distance between the two given objects. */ - int distance (const object *ob1, const object *ob2) { - int i; - - i = (ob1->x - ob2->x) * (ob1->x - ob2->x) + (ob1->y - ob2->y) * (ob1->y - ob2->y); - return i; + return (ob1->x - ob2->x) * (ob1->x - ob2->x) + (ob1->y - ob2->y) * (ob1->y - ob2->y); } /* @@ -2199,7 +2174,6 @@ * an object which has subtracted the x and y coordinates of another * object, needs to travel toward it. */ - int find_dir_2 (int x, int y) { @@ -2248,8 +2222,10 @@ { while (d < 1) d += 8; + while (d > 8) d -= 8; + return d; } @@ -2261,12 +2237,12 @@ int dirdiff (int dir1, int dir2) { - int - d; + int d; d = abs (dir1 - dir2); if (d > 4) d = 8 - d; + return d; } @@ -2279,9 +2255,7 @@ * Moved from spell_util.c to object.c with the other related direction * functions. */ - -int - reduction_dir[SIZEOFFREE][3] = { +int reduction_dir[SIZEOFFREE][3] = { {0, 0, 0}, /* 0 */ {0, 0, 0}, /* 1 */ {0, 0, 0}, /* 2 */ @@ -2441,7 +2415,6 @@ /* but it was simple to make and allows reusing the load_object function. */ /* Remember not to use load_object_str in a time-critical situation. */ /* Also remember that multiparts objects are not supported for now. */ - object * load_object_str (const char *obstr) { @@ -2481,13 +2454,11 @@ object * find_obj_by_type_subtype (const object *who, int type, int subtype) { - object *tmp; - - for (tmp = who->inv; tmp; tmp = tmp->below) + for (object *tmp = who->inv; tmp; tmp = tmp->below) if (tmp->type == type && tmp->subtype == subtype) return tmp; - return NULL; + return 0; } /* If ob has a field named key, return the link from the list, @@ -2499,13 +2470,11 @@ key_value * get_ob_key_link (const object *ob, const char *key) { - key_value *link; - - for (link = ob->key_values; link != NULL; link = link->next) + for (key_value *link = ob->key_values; link; link = link->next) if (link->key == key) return link; - return NULL; + return 0; } /* @@ -2555,8 +2524,7 @@ int set_ob_key_value_s (object *op, const shstr & canonical_key, const char *value, int add_key) { - key_value * - field = NULL, *last = NULL; + key_value *field = NULL, *last = NULL; for (field = op->key_values; field != NULL; field = field->next) { @@ -2594,9 +2562,8 @@ /* No field, we'll have to add it. */ if (!add_key) - { - return FALSE; - } + return FALSE; + /* There isn't any good reason to store a null * value in the key/value list. If the archetype has * this key, then we should also have it, so shouldn't