--- deliantra/server/common/map.C 2009/11/10 05:06:02 1.175 +++ deliantra/server/common/map.C 2010/04/16 02:32:25 1.188 @@ -1,9 +1,9 @@ /* * This file is part of Deliantra, the Roguelike Realtime MMORPG. * - * Copyright (©) 2005,2006,2007,2008,2009 Marc Alexander Lehmann / Robin Redeker / the Deliantra team - * Copyright (©) 2001-2003,2007 Mark Wedel & Crossfire Development Team - * Copyright (©) 1992,2007 Frank Tore Johansen + * Copyright (©) 2005,2006,2007,2008,2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team + * Copyright (©) 2001-2003 Mark Wedel & Crossfire Development Team + * Copyright (©) 1992 Frank Tore Johansen * * Deliantra is free software: you can redistribute it and/or modify it under * the terms of the Affero GNU General Public License as published by the @@ -25,7 +25,6 @@ #include #include "global.h" -#include "loader.h" #include "path.h" //+GPL @@ -152,8 +151,7 @@ if (tmp->flag [FLAG_ALIVE] && tmp->head_ () != ob && tmp != ob - && tmp->type != DOOR - && !tmp->flag [FLAG_WIZPASS]) + && tmp->type != DOOR) return 1; } } @@ -245,6 +243,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 @@ -413,30 +424,35 @@ return freezer.save (path); } -maptile::maptile () +void +maptile::init () { in_memory = MAP_SWAPPED; /* The maps used to pick up default x and y values from the * map archetype. Mimic that behaviour. */ - width = 16; - height = 16; - timeout = 300; - max_items = MAX_ITEM_PER_ACTION; - max_volume = 2000000; // 2m³ + width = 16; + height = 16; + timeout = 300; + max_items = MAX_ITEM_PER_ACTION; + max_volume = 2000000; // 2m³ + reset_timeout = 0; + enter_x = 0; + enter_y = 0; +} + +maptile::maptile () +{ + init (); } maptile::maptile (int w, int h) { - in_memory = MAP_SWAPPED; + init (); - width = w; - height = h; - reset_timeout = 0; - timeout = 300; - enter_x = 0; - enter_y = 0; + width = w; + height = h; alloc (); } @@ -619,12 +635,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; @@ -659,7 +669,7 @@ return true; default: - if (!thawer.parse_error ("map", 0)) + if (!thawer.parse_error ("map")) return false; break; } @@ -687,10 +697,10 @@ { object *above = op->above; - if (QUERY_FLAG (op, FLAG_IS_FLOOR) && QUERY_FLAG (op, FLAG_UNIQUE)) + if (op->flag [FLAG_IS_FLOOR] && op->flag [FLAG_UNIQUE]) unique = 1; - if (op->head_ () == op && (QUERY_FLAG (op, FLAG_UNIQUE) || unique)) + if (op->head_ () == op && (op->flag [FLAG_UNIQUE] || unique)) op->destroy (); op = above; @@ -703,10 +713,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); @@ -724,22 +734,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); @@ -750,7 +753,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; } @@ -845,6 +848,7 @@ } /* decay and destroy perishable items in a map */ +// TODO: should be done regularly, not on map load? void maptile::do_decay_objects () { @@ -856,17 +860,17 @@ { 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)) + if (op->flag [FLAG_IS_FLOOR] && op->flag [FLAG_UNIQUE]) break; - if (QUERY_FLAG (op, FLAG_IS_FLOOR) - || QUERY_FLAG (op, FLAG_OBJ_ORIGINAL) - || QUERY_FLAG (op, FLAG_UNIQUE) - || QUERY_FLAG (op, FLAG_OVERLAY_FLOOR) - || QUERY_FLAG (op, FLAG_UNPAID) + bool destroy = 0; + + if (op->flag [FLAG_IS_FLOOR] + || op->flag [FLAG_OBJ_ORIGINAL] + || op->flag [FLAG_UNIQUE] + || op->flag [FLAG_OVERLAY_FLOOR] + || op->flag [FLAG_UNPAID] || op->is_alive ()) ; // do not decay else if (op->is_weapon ()) @@ -901,7 +905,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; } @@ -931,13 +936,13 @@ for (mapspace *ms = spaces + size (); ms-- > spaces; ) for (object *op = ms->bot; op; op = op->above) { - if (QUERY_FLAG (op, FLAG_MONSTER)) + if (op->flag [FLAG_MONSTER]) { total_exp += op->stats.exp; monster_cnt++; } - if (QUERY_FLAG (op, FLAG_GENERATOR)) + if (op->flag [FLAG_GENERATOR]) { total_exp += op->stats.exp; @@ -1129,7 +1134,7 @@ for (object *tmp = last; tmp; tmp = tmp->below) { /* Once we get to a floor, stop, since we already have a floor object */ - if (QUERY_FLAG (tmp, FLAG_IS_FLOOR)) + if (tmp->flag [FLAG_IS_FLOOR]) break; /* If two top faces are already set, quit processing */ @@ -1422,7 +1427,7 @@ * closest body part of 'op1' */ void -get_rangevector (object *op1, object *op2, rv_vector * retval, int flags) +get_rangevector (object *op1, object *op2, rv_vector *retval, int flags) { if (!adjacent_map (op1->map, op2->map, &retval->distance_x, &retval->distance_y)) { @@ -1435,14 +1440,13 @@ } else { - object *best; - retval->distance_x += op2->x - op1->x; retval->distance_y += op2->y - op1->y; - best = op1; + object *best = op1; + /* If this is multipart, find the closest part now */ - if (!(flags & 0x1) && op1->more) + if (!(flags & 1) && op1->more) { int best_distance = retval->distance_x * retval->distance_x + retval->distance_y * retval->distance_y, tmpi; @@ -1565,9 +1569,9 @@ { object *pick = at (gen (width), gen (height)).bot; - // do not prefer big monsters just because they are big. + // must be head: do not prefer big monsters just because they are big. if (pick && pick->is_head ()) - return pick->head_ (); + return pick; } // instead of crashing in the unlikely(?) case, try to return *something* @@ -1611,6 +1615,8 @@ } } +dynbuf mapwalk_buf (sizeof (maprect) * 25, sizeof (maprect) * 25); + static void split_to_tiles (dynbuf &buf, maptile *m, int x0, int y0, int x1, int y1, int dx, int dy) { @@ -1675,9 +1681,8 @@ } maprect * -maptile::split_to_tiles (int x0, int y0, int x1, int y1) +maptile::split_to_tiles (dynbuf &buf, int x0, int y0, int x1, int y1) { - static dynbuf buf (sizeof (maprect) * 8, sizeof (maprect) * 8); buf.clear (); ::split_to_tiles (buf, this, x0, y0, x1, y1, 0, 0);