--- deliantra/server/common/map.C 2009/11/08 15:11:22 1.170 +++ deliantra/server/common/map.C 2010/01/14 23:46:14 1.180 @@ -152,8 +152,7 @@ if (tmp->flag [FLAG_ALIVE] && tmp->head_ () != ob && tmp != ob - && tmp->type != DOOR - && !tmp->flag [FLAG_WIZPASS]) + && tmp->type != DOOR) return 1; } } @@ -219,33 +218,6 @@ return 0; } -/* When the map is loaded, load_object does not actually insert objects - * into inventory, but just links them. What this does is go through - * and insert them properly. - * The object 'container' is the object that contains the inventory. - * This is needed so that we can update the containers weight. - */ -static void -fix_container (object *container) -{ - object *tmp = container->inv, *next; - - container->inv = 0; - while (tmp) - { - next = tmp->below; - if (tmp->inv) - fix_container (tmp); - - insert_ob_in_ob (tmp, container); - tmp = next; - } - - // go through and calculate what all the containers are carrying. - //TODO: remove - container->update_weight (); -} - //-GPL void @@ -272,6 +244,19 @@ INVOKE_OBJECT (RESET, tmp); } +void +maptile::post_load () +{ +#if 0 + if (!spaces) + return; + + for (mapspace *ms = spaces + size (); ms-- > spaces; ) + for (object *tmp = ms->bot; tmp; tmp = tmp->above) + ; // nop +#endif +} + //+GPL /* link_multipart_objects go through all the objects on the map looking @@ -450,8 +435,7 @@ width = 16; height = 16; timeout = 300; - max_nrof = 1000; // 1000 items of anything - max_items = 25; + max_items = MAX_ITEM_PER_ACTION; max_volume = 2000000; // 2m³ } @@ -647,12 +631,6 @@ case KW_shopmax: thawer.get (shopmax); break; case KW_shoprace: thawer.get (shoprace); break; case KW_outdoor: thawer.get (outdoor); break; - case KW_temp: thawer.get (temp); break; - case KW_pressure: thawer.get (pressure); break; - case KW_humid: thawer.get (humid); break; - case KW_windspeed: thawer.get (windspeed); break; - case KW_winddir: thawer.get (winddir); break; - case KW_sky: thawer.get (sky); break; case KW_per_player: thawer.get (per_player); break; case KW_per_party: thawer.get (per_party); break; @@ -731,10 +709,10 @@ bool maptile::_save_header (object_freezer &freezer) { -#define MAP_OUT(k) freezer.put (KW_ ## k, k) -#define MAP_OUT2(k,v) freezer.put (KW_ ## k, v) +#define MAP_OUT(k) freezer.put (KW(k), k) +#define MAP_OUT2(k,v) freezer.put (KW(k), v) - MAP_OUT2 (arch, "map"); + MAP_OUT2 (arch, CS(map)); if (name) MAP_OUT (name); MAP_OUT (swap_time); @@ -752,22 +730,15 @@ MAP_OUT (shopmax); if (shoprace) MAP_OUT (shoprace); - MAP_OUT (darkness); MAP_OUT (width); MAP_OUT (height); MAP_OUT (enter_x); MAP_OUT (enter_y); - - if (msg) freezer.put (KW_msg , KW_endmsg , msg); - if (maplore) freezer.put (KW_maplore, KW_endmaplore, maplore); - + MAP_OUT (darkness); MAP_OUT (outdoor); - MAP_OUT (temp); - MAP_OUT (pressure); - MAP_OUT (humid); - MAP_OUT (windspeed); - MAP_OUT (winddir); - MAP_OUT (sky); + + if (msg) freezer.put (KW(msg) , KW(endmsg) , msg); + if (maplore) freezer.put (KW(maplore), KW(endmaplore), maplore); MAP_OUT (per_player); MAP_OUT (per_party); @@ -778,7 +749,7 @@ if (tile_path [3]) MAP_OUT2 (tile_path_4, tile_path [3]); freezer.put (this); - freezer.put (KW_end); + freezer.put (KW(end)); return true; } @@ -873,6 +844,7 @@ } /* decay and destroy perishable items in a map */ +// TODO: should be done regularly, not on map load? void maptile::do_decay_objects () { @@ -884,12 +856,12 @@ { above = op->above; - bool destroy = 0; - // do not decay anything above unique floor tiles (yet :) if (QUERY_FLAG (op, FLAG_IS_FLOOR) && QUERY_FLAG (op, FLAG_UNIQUE)) break; + bool destroy = 0; + if (QUERY_FLAG (op, FLAG_IS_FLOOR) || QUERY_FLAG (op, FLAG_OBJ_ORIGINAL) || QUERY_FLAG (op, FLAG_UNIQUE) @@ -929,7 +901,8 @@ || (mat & M_GLASS && rndm (1, 2) == 1) || ((mat & M_STONE || mat & M_ADAMANT) && rndm (1, 10) == 1) || ((mat & M_SOFT_METAL || mat & M_BONE) && rndm (1, 3) == 1) - || (mat & M_ICE && temp > 32)) + //|| (mat & M_ICE && temp > 32) + ) destroy = 1; } @@ -1030,11 +1003,13 @@ mapspace::update_ () { object *last = 0; - uint8 flags = P_UPTODATE, anywhere = 0; + uint8 flags = P_UPTODATE; sint8 light = 0; MoveType move_block = 0, move_slow = 0, move_on = 0, move_off = 0, move_allow = 0; uint64_t volume = 0; - uint32_t nrof = 0; + uint32_t items = 0; + object *anywhere = 0; + uint8_t middle_visibility = 0; //object *middle = 0; //object *top = 0; @@ -1044,10 +1019,10 @@ object *&middle = faces_obj[1] = 0; object *&floor = faces_obj[2] = 0; + object::flags_t allflags; // all flags of all objects or'ed together + for (object *tmp = bot; tmp; last = tmp, tmp = tmp->above) { - ++nrof; - // Lights are additive, up to MAX_LIGHT_RADIUS, see los.C) light += tmp->glow_radius; @@ -1059,38 +1034,41 @@ * * Always put the player down for drawing. */ - if (!tmp->invisible) + if (expect_true (!tmp->invisible)) { - if (tmp->type == PLAYER || tmp->flag [FLAG_MONSTER]) + if (expect_false (tmp->type == PLAYER || tmp->flag [FLAG_MONSTER])) top = tmp; + else if (expect_false (tmp->flag [FLAG_IS_FLOOR])) + { + /* If we got a floor, that means middle and top were below it, + * so should not be visible, so we clear them. + */ + middle = 0; + top = 0; + floor = tmp; + volume = 0; + items = 0; + } else { - if (tmp->flag [FLAG_IS_FLOOR]) + if (expect_true (!tmp->flag [FLAG_NO_PICK])) { - /* If we got a floor, that means middle and top were below it, - * so should not be visible, so we clear them. - */ - middle = 0; - top = 0; - floor = tmp; + ++items; + volume += tmp->volume (); } - else - { - if (!tmp->flag [FLAG_NO_PICK]) - volume += tmp->volume (); - /* Flag anywhere have high priority */ - if (tmp->flag [FLAG_SEE_ANYWHERE]) - { - middle = tmp; - anywhere = 1; - } - /* Find the highest visible face around. If equal - * visibilities, we still want the one nearer to the - * top - */ - else if (!middle || (::faces [tmp->face].visibility > ::faces [middle->face].visibility && !anywhere)) - middle = tmp; + /* Flag anywhere have high priority */ + if (expect_false (tmp->flag [FLAG_SEE_ANYWHERE])) + anywhere = tmp; + + /* Find the highest visible face around. If equal + * visibilities, we still want the one nearer to the + * top + */ + if (expect_false (::faces [tmp->face].visibility >= middle_visibility)) + { + middle_visibility = ::faces [tmp->face].visibility; + middle = tmp; } } } @@ -1101,22 +1079,30 @@ move_off |= tmp->move_off; move_allow |= tmp->move_allow; - if (QUERY_FLAG (tmp, FLAG_BLOCKSVIEW)) flags |= P_BLOCKSVIEW; - if (QUERY_FLAG (tmp, FLAG_NO_MAGIC)) flags |= P_NO_MAGIC; - if (tmp->type == PLAYER) flags |= P_PLAYER; - if (tmp->type == SAFE_GROUND) flags |= P_SAFE; - if (QUERY_FLAG (tmp, FLAG_ALIVE)) flags |= P_IS_ALIVE; - if (QUERY_FLAG (tmp, FLAG_DAMNED)) flags |= P_NO_CLERIC; + allflags |= tmp->flag; + + if (tmp->type == PLAYER) flags |= P_PLAYER; + if (tmp->type == SAFE_GROUND) flags |= P_SAFE; } + // FLAG_SEE_ANYWHERE takes precedence + if (anywhere) + middle = anywhere; + + // ORing all flags together and checking them here is much faster + if (allflags [FLAG_BLOCKSVIEW]) flags |= P_BLOCKSVIEW; + if (allflags [FLAG_NO_MAGIC] ) flags |= P_NO_MAGIC; + if (allflags [FLAG_ALIVE] ) flags |= P_IS_ALIVE; + if (allflags [FLAG_DAMNED] ) flags |= P_NO_CLERIC; + this->light = min (light, MAX_LIGHT_RADIUS); this->flags_ = flags; this->move_block = move_block & ~move_allow; this->move_on = move_on; this->move_off = move_off; this->move_slow = move_slow; - this->volume_ = volume / 1024; - this->nrof_ = min (65535, nrof); + this->volume_ = (volume + 1023) / 1024; + this->items_ = upos_min (items, 65535); // assume nrof <= 2**31 /* At this point, we have a floor face (if there is a floor), * and the floor is set - we are not going to touch it at