--- deliantra/server/common/object.C 2006/12/25 11:25:49 1.82 +++ deliantra/server/common/object.C 2006/12/26 20:04:09 1.93 @@ -143,7 +143,7 @@ */ /* For each field in wants, */ - for (wants_field = wants->key_values; wants_field != NULL; wants_field = wants_field->next) + for (wants_field = wants->key_values; wants_field; wants_field = wants_field->next) { key_value *has_field; @@ -366,7 +366,7 @@ return strdup ("[NULLOBJ]"); object_freezer freezer; - save_object (freezer, op, 3); + save_object (freezer, op, 1); return freezer.as_string (); } @@ -524,7 +524,7 @@ } } - update_ob_speed (dst); + dst->set_speed (dst->speed); } object * @@ -556,65 +556,62 @@ * This function needs to be called whenever the speed of an object changes. */ void -update_ob_speed (object *op) +object::set_speed (float speed) { extern int arch_init; /* No reason putting the archetypes objects on the speed list, * since they never really need to be updated. */ - - if (QUERY_FLAG (op, FLAG_FREED) && op->speed) + if (flag [FLAG_FREED] && speed) { - LOG (llevError, "Object %s is freed but has speed.\n", &op->name); -#ifdef MANY_CORES - abort (); -#else - op->speed = 0; -#endif + LOG (llevError, "Object %s is freed but has speed.\n", &name); + speed = 0; } + this->speed = speed; + if (arch_init) return; - if (FABS (op->speed) > MIN_ACTIVE_SPEED) + if (FABS (speed) > MIN_ACTIVE_SPEED) { /* If already on active list, don't do anything */ - if (op->active_next || op->active_prev || op == active_objects) + if (active_next || active_prev || this == active_objects) return; /* process_events() expects us to insert the object at the beginning * of the list. */ - op->active_next = active_objects; + active_next = active_objects; - if (op->active_next != NULL) - op->active_next->active_prev = op; + if (active_next) + active_next->active_prev = this; - active_objects = op; + active_objects = this; } else { /* If not on the active list, nothing needs to be done */ - if (!op->active_next && !op->active_prev && op != active_objects) + if (!active_next && !active_prev && this != active_objects) return; - if (op->active_prev == NULL) + if (!active_prev) { - active_objects = op->active_next; + active_objects = active_next; - if (op->active_next != NULL) - op->active_next->active_prev = NULL; + if (active_next) + active_next->active_prev = 0; } else { - op->active_prev->active_next = op->active_next; + active_prev->active_next = active_next; - if (op->active_next) - op->active_next->active_prev = op->active_prev; + if (active_next) + active_next->active_prev = active_prev; } - op->active_next = NULL; - op->active_prev = NULL; + active_next = 0; + active_prev = 0; } } @@ -693,7 +690,7 @@ return; /* make sure the object is within map boundaries */ - if (op->x < 0 || op->x >= MAP_WIDTH (op->map) || op->y < 0 || op->y >= MAP_HEIGHT (op->map)) + if (op->x < 0 || op->x >= op->map->width || op->y < 0 || op->y >= op->map->height) { LOG (llevError, "update_object() called for object out of map!\n"); #ifdef MANY_CORES @@ -783,6 +780,46 @@ next = 0; } +/* + * Remove and free all objects in the inventory of the given object. + * object.c ? + */ +void +object::destroy_inv (bool drop_to_ground) +{ + /* 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 + || map->at (x, y).move_block == 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 + map->insert (op, x, y); + } + } +} + object *object::create () { object *op = new object; @@ -790,21 +827,9 @@ return op; } -/* - * free_object() frees everything allocated by an object, removes - * it from the list of used objects, and puts it on the list of - * free objects. The IS_FREED() flag is set in the object. - * The object must have been removed by remove_ob() first for - * this function to succeed. - * - * If destroy_inventory is set, free inventory as well. Else drop items in - * inventory to the ground. - */ void object::do_destroy () { - attachable::do_destroy (); - if (flag [FLAG_IS_LINKED]) remove_button_link (this); @@ -817,8 +842,15 @@ if (flag [FLAG_FREED]) return; + set_speed (0); + flag [FLAG_FREED] = 1; + attachable::do_destroy (); + + destroy_inv (true); + unlink (); + // hack to ensure that freed objects still have a valid map { static maptile *freed_map; // freed objects are moved here to avoid crashes @@ -839,9 +871,13 @@ y = 1; } - more = 0; head = 0; - inv = 0; + + if (more) + { + more->destroy (); + more = 0; + } // clear those pointers that likely might have circular references to us owner = 0; @@ -850,57 +886,6 @@ // only relevant for players(?), but make sure of it anyways contr = 0; - - /* Remove object from the active list */ - speed = 0; - 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 @@ -909,15 +894,8 @@ 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); + destroy_inv (false); attachable::destroy (); } @@ -1029,7 +1007,7 @@ free (dump); } - map->at (x, y).bottom = above; /* goes on above it. */ + map->at (x, y).bot = above; /* goes on above it. */ } above = 0; @@ -1040,7 +1018,7 @@ int check_walk_off = !flag [FLAG_NO_APPLY]; - for (tmp = GET_MAP_OB (map, x, y); tmp; tmp = tmp->above) + for (tmp = map->at (x, y).bot; tmp; tmp = tmp->above) { /* No point updating the players look faces if he is the object * being removed. @@ -1136,12 +1114,7 @@ object * insert_ob_in_map_at (object *op, maptile *m, object *originator, int flag, int x, int y) { - object *tmp; - - if (op->head) - op = op->head; - - for (tmp = op; tmp; tmp = tmp->more) + for (object *tmp = op->head_ (); tmp; tmp = tmp->more) { tmp->x = x + tmp->arch->clone.x; tmp->y = y + tmp->arch->clone.y; @@ -1283,7 +1256,7 @@ if (op->below) op->below->above = op; else - op->ms ().bottom = op; + op->ms ().bot = op; /* since *below* originator, no need to update top */ originator->below = op; @@ -1372,7 +1345,7 @@ op->above->below = op; op->below = NULL; - op->ms ().bottom = op; + op->ms ().bot = op; } else { /* get inserted into the stack above top */ @@ -1409,7 +1382,7 @@ * or just updating the P_NEED_UPDATE for spaces within this area * of effect may be sufficient. */ - if (MAP_DARKNESS (op->map) && (op->glow_radius != 0)) + if (op->map->darkness && (op->glow_radius != 0)) update_all_los (op->map, op->x, op->y); /* updates flags (blocked, alive, no magic, etc) for this map space */ @@ -1465,6 +1438,12 @@ insert_ob_in_map (tmp1, op->map, op, 0); } +object * +object::insert_at (object *where, object *originator, int flags) +{ + where->map->insert (this, where->x, where->y, originator, flags); +} + /* * get_split_ob(ob,nr) splits up ob into two parts. The part which * is returned contains nr objects, and the remaining parts contains @@ -1472,7 +1451,6 @@ * On failure, NULL is returned, and the reason put into the * global static errmsg array. */ - object * get_split_ob (object *orig_ob, uint32 nr) { @@ -1705,7 +1683,7 @@ #ifdef DEBUG_LIGHTS LOG (llevDebug, " insert_ob_in_ob(): got %s to insert in map/op\n", op->name); #endif /* DEBUG_LIGHTS */ - if (MAP_DARKNESS (map)) + if (map->darkness) update_all_los (map, x, y); } @@ -1746,7 +1724,6 @@ * object being inserted. insert_ob_in_map may not put new objects * on top. */ - int check_move_on (object *op, object *originator) { @@ -1783,7 +1760,7 @@ * Hence, we first go to the top: */ - for (tmp = GET_MAP_OB (op->map, op->x, op->y); tmp != NULL && tmp->above != NULL; tmp = tmp->above) + for (tmp = GET_MAP_OB (op->map, op->x, op->y); tmp && tmp->above; tmp = tmp->above) { /* Trim the search when we find the first other spell effect * this helps performance so that if a space has 50 spell objects, @@ -1848,21 +1825,19 @@ * a matching archetype at the given map and coordinates. * The first matching object is returned, or NULL if none. */ - object * present_arch (const archetype *at, maptile *m, int x, int y) { - object * - tmp; - if (m == NULL || out_of_map (m, x, y)) { LOG (llevError, "Present_arch called outside map.\n"); return NULL; } - for (tmp = GET_MAP_OB (m, x, y); tmp != NULL; tmp = tmp->above) + + for (object *tmp = GET_MAP_OB (m, x, y); tmp != NULL; tmp = tmp->above) if (tmp->arch == at) return tmp; + return NULL; } @@ -1871,21 +1846,19 @@ * a matching type variable at the given map and coordinates. * The first matching object is returned, or NULL if none. */ - object * present (unsigned char type, maptile *m, int x, int y) { - object * - tmp; - if (out_of_map (m, x, y)) { LOG (llevError, "Present called outside map.\n"); return NULL; } - for (tmp = GET_MAP_OB (m, x, y); tmp != NULL; tmp = tmp->above) + + for (object *tmp = GET_MAP_OB (m, x, y); tmp != NULL; tmp = tmp->above) if (tmp->type == type) return tmp; + return NULL; } @@ -1894,16 +1867,13 @@ * a matching type variable in the inventory of the given object. * The first matching object is returned, or NULL if none. */ - object * present_in_ob (unsigned char type, 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->type == type) return tmp; + return NULL; } @@ -1924,9 +1894,7 @@ object * present_in_ob_by_name (int type, const char *str, const object *op) { - object *tmp; - - for (tmp = op->inv; tmp; tmp = tmp->below) + for (object *tmp = op->inv; tmp; tmp = tmp->below) if ((type == -1 || tmp->type == type) && (!strcmp (str, tmp->name))) return tmp; @@ -2145,7 +2113,7 @@ max = maxfree[i]; else if (mflags & P_IS_ALIVE) { - for (tmp = ms.bottom; tmp; tmp = tmp->above) + for (tmp = ms.bot; tmp; tmp = tmp->above) if ((tmp->flag [FLAG_MONSTER] || tmp->type == PLAYER) && (tmp != exclude || (tmp->head && tmp->head != exclude))) break;