--- deliantra/server/common/map.C 2010/04/29 12:24:04 1.198 +++ deliantra/server/common/map.C 2012/01/03 11:25:31 1.217 @@ -1,7 +1,7 @@ /* * This file is part of Deliantra, the Roguelike Realtime MMORPG. * - * Copyright (©) 2005,2006,2007,2008,2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team + * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012 Marc Alexander Lehmann / Robin Redeker / the Deliantra team * Copyright (©) 2001-2003 Mark Wedel & Crossfire Development Team * Copyright (©) 1992 Frank Tore Johansen * @@ -313,7 +313,10 @@ { // TODO: why? if (op->inv) - op->update_weight (); + { + op->carrying = 0; + op->update_weight (); + } if (IN_RANGE_EXC (op->x, 0, width) && IN_RANGE_EXC (op->y, 0, height)) { @@ -360,19 +363,29 @@ void maptile::activate () { - if (spaces) - for (mapspace *ms = spaces + size (); ms-- > spaces; ) - for (object *op = ms->bot; op; op = op->above) - op->activate_recursive (); + if (state != MAP_INACTIVE) + return; + + for (mapspace *ms = spaces + size (); ms-- > spaces; ) + for (object *op = ms->bot; op; op = op->above) + op->activate_recursive (); + + state = MAP_ACTIVE; + + activate_physics (); } void maptile::deactivate () { - if (spaces) - for (mapspace *ms = spaces + size (); ms-- > spaces; ) - for (object *op = ms->bot; op; op = op->above) - op->deactivate_recursive (); + if (state != MAP_ACTIVE) + return; + + for (mapspace *ms = spaces + size (); ms-- > spaces; ) + for (object *op = ms->bot; op; op = op->above) + op->deactivate_recursive (); + + state = MAP_INACTIVE; } bool @@ -426,7 +439,7 @@ void maptile::init () { - in_memory = MAP_SWAPPED; + state = MAP_SWAPPED; /* The maps used to pick up default x and y values from the * map archetype. Mimic that behaviour. @@ -532,7 +545,7 @@ current_type = get_typedata_by_name (p); if (current_type) { - items[i].name = current_type->name; + items[i].name = current_type->name; items[i].typenum = current_type->number; items[i].name_pl = current_type->name_pl; } @@ -613,7 +626,7 @@ thawer.get_ml (KW_endmsg, msg); break; - case KW_lore: // CF+ extension + case KW_lore: // deliantra extension thawer.get_ml (KW_endlore, maplore); break; @@ -660,10 +673,12 @@ case KW_invisible: case KW_darkness: thawer.get (darkness); break; case KW_stand_still: case KW_fixed_resettime: thawer.get (fixed_resettime); break; - case KW_tile_path_1: thawer.get (tile_path [0]); break; - case KW_tile_path_2: thawer.get (tile_path [1]); break; - case KW_tile_path_3: thawer.get (tile_path [2]); break; - case KW_tile_path_4: thawer.get (tile_path [3]); break; + case KW_tile_path_1: thawer.get (tile_path [TILE_NORTH]); break; + case KW_tile_path_2: thawer.get (tile_path [TILE_EAST ]); break; + case KW_tile_path_3: thawer.get (tile_path [TILE_SOUTH]); break; + case KW_tile_path_4: thawer.get (tile_path [TILE_WEST ]); break; + case KW_tile_path_5: thawer.get (tile_path [TILE_UP ]); break; + case KW_tile_path_6: thawer.get (tile_path [TILE_DOWN ]); break; case KW_ERROR: set_key_text (thawer.kw_str, thawer.value); @@ -752,10 +767,12 @@ MAP_OUT (per_player); MAP_OUT (per_party); - if (tile_path [0]) MAP_OUT2 (tile_path_1, tile_path [0]); - if (tile_path [1]) MAP_OUT2 (tile_path_2, tile_path [1]); - if (tile_path [2]) MAP_OUT2 (tile_path_3, tile_path [2]); - if (tile_path [3]) MAP_OUT2 (tile_path_4, tile_path [3]); + if (tile_path [TILE_NORTH]) MAP_OUT2 (tile_path_1, tile_path [TILE_NORTH]); + if (tile_path [TILE_EAST ]) MAP_OUT2 (tile_path_2, tile_path [TILE_EAST ]); + if (tile_path [TILE_SOUTH]) MAP_OUT2 (tile_path_3, tile_path [TILE_SOUTH]); + if (tile_path [TILE_WEST ]) MAP_OUT2 (tile_path_4, tile_path [TILE_WEST ]); + if (tile_path [TILE_UP ]) MAP_OUT2 (tile_path_5, tile_path [TILE_UP ]); + if (tile_path [TILE_DOWN ]) MAP_OUT2 (tile_path_6, tile_path [TILE_DOWN ]); freezer.put (this); freezer.put (KW(end)); @@ -822,7 +839,7 @@ shoprace = 0; delete [] shopitems, shopitems = 0; - for (int i = 0; i < 4; i++) + for (int i = 0; i < array_length (tile_path); i++) tile_path [i] = 0; } @@ -839,7 +856,7 @@ * tiling can be asymetric, we just can not look to see which * maps this map tiles with and clears those. */ - for (int i = 0; i < 4; i++) + for (int i = 0; i < array_length (tile_path); i++) if (tile_map[i] == m) tile_map[i] = 0; } @@ -1180,6 +1197,29 @@ if (top == middle) middle = 0; + // set lower map transparent floor flag if applicable + if (floor && floor->flag [FLAG_IS_TRANSPARENT_FLOOR] && !middle && !top) + { + floor->set_anim_frame (0); + + if (maptile *m = floor->map->tile_map [TILE_DOWN]) + { + mapspace &ms = m->at (floor->x, floor->y); + ms.update (); + + if (object *floor2 = ms.faces_obj [2]) + if (!floor2->flag [FLAG_IS_TRANSPARENT_FLOOR]) + { + floor->set_anim_frame (1); + top = floor; + middle = ms.faces_obj [0]; + floor = floor2; + } + + ms.pflags |= PF_VIS_UP; + } + } + #if 0 faces_obj [0] = top; faces_obj [1] = middle; @@ -1187,16 +1227,63 @@ #endif } +void +mapspace::update_up () +{ + // invalidate up + if (!(pflags & PF_VIS_UP)) + return; + + pflags &= ~PF_VIS_UP; + + if (bot) + if (maptile *m = bot->map->tile_map [TILE_UP]) + m->at (bot->x, bot->y).invalidate (); +} + maptile * maptile::tile_available (int dir, bool load) { - if (tile_path[dir]) - { - if (tile_map[dir] && (!load || tile_map[dir]->in_memory == MAP_ACTIVE)) - return tile_map[dir]; + // map is there and we don't need to load it OR it's loaded => return what we have + if (tile_map [dir] && (!load || tile_map [dir]->linkable ())) + return tile_map [dir]; + + if (tile_path [dir]) + { + // well, try to locate it then, if possible - maybe it's there already + // this is the ONLY place in the server that links maps with each other, + // so any kind of inter-map stuff has to be initiated here. + if (maptile *m = find_async (tile_path [dir], this, load)) + { + bool mismatch = false; + + if (dir == TILE_NORTH || dir == TILE_SOUTH || dir == TILE_UP || dir == TILE_DOWN) + if (width != m->width) + mismatch = true; + + if (dir == TILE_EAST || dir == TILE_WEST || dir == TILE_UP || dir == TILE_DOWN) + if (height != m->height) + mismatch = true; + + if (mismatch) + { + LOG (llevError, "tile dimension mismatch for direction %d from %s to %s\n", + dir, &path, &m->path); + m = 0; + } + else if (0)//D + { + // as an optimisation, link us against the other map if the other map + // has us as neighbour, which is very common, but not guaranteed. + int dir2 = REVERSE_TILE_DIR (dir); + + if (m->tile_path [dir2] == path) + m->tile_map [dir2] = this; + } + - if ((tile_map[dir] = find_async (tile_path[dir], this, load))) - return tile_map[dir]; + return tile_map [dir] = m; + } } return 0; @@ -1222,34 +1309,34 @@ if (x < 0) { - if (!m->tile_available (3)) + if (!m->tile_available (TILE_WEST)) return 1; - return out_of_map (m->tile_map[3], x + m->tile_map[3]->width, y); + return out_of_map (m->tile_map [TILE_WEST], x + m->tile_map [TILE_WEST]->width, y); } if (x >= m->width) { - if (!m->tile_available (1)) + if (!m->tile_available (TILE_EAST)) return 1; - return out_of_map (m->tile_map[1], x - m->width, y); + return out_of_map (m->tile_map [TILE_EAST], x - m->width, y); } if (y < 0) { - if (!m->tile_available (0)) + if (!m->tile_available (TILE_NORTH)) return 1; - return out_of_map (m->tile_map[0], x, y + m->tile_map[0]->height); + return out_of_map (m->tile_map [TILE_NORTH], x, y + m->tile_map [TILE_NORTH]->height); } if (y >= m->height) { - if (!m->tile_available (2)) + if (!m->tile_available (TILE_SOUTH)) return 1; - return out_of_map (m->tile_map[2], x, y - m->height); + return out_of_map (m->tile_map [TILE_SOUTH], x, y - m->height); } /* Simple case - coordinates are within this local @@ -1271,38 +1358,38 @@ { if (x < 0) { - if (!tile_available (3)) + if (!tile_available (TILE_WEST)) return 0; - x += tile_map[3]->width; - return tile_map[3]->xy_find (x, y); + x += tile_map [TILE_WEST]->width; + return tile_map [TILE_WEST]->xy_find (x, y); } if (x >= width) { - if (!tile_available (1)) + if (!tile_available (TILE_EAST)) return 0; x -= width; - return tile_map[1]->xy_find (x, y); + return tile_map [TILE_EAST]->xy_find (x, y); } if (y < 0) { - if (!tile_available (0)) + if (!tile_available (TILE_NORTH)) return 0; - y += tile_map[0]->height; - return tile_map[0]->xy_find (x, y); + y += tile_map [TILE_NORTH]->height; + return tile_map [TILE_NORTH]->xy_find (x, y); } if (y >= height) { - if (!tile_available (2)) + if (!tile_available (TILE_SOUTH)) return 0; y -= height; - return tile_map[2]->xy_find (x, y); + return tile_map [TILE_SOUTH]->xy_find (x, y); } /* Simple case - coordinates are within this local @@ -1316,7 +1403,7 @@ * map1 to map2 in dx/dy. */ int -adjacent_map (const maptile *map1, const maptile *map2, int *dx, int *dy) +adjacent_map (maptile *map1, maptile *map2, int *dx, int *dy) { if (!map1 || !map2) return 0; @@ -1328,65 +1415,65 @@ *dx = 0; *dy = 0; } - else if (map1->tile_map[0] == map2) - { /* up */ + else if (map1->tile_available (TILE_NORTH, false) == map2) + { *dx = 0; *dy = -map2->height; } - else if (map1->tile_map[1] == map2) - { /* right */ + else if (map1->tile_available (TILE_EAST , false) == map2) + { *dx = map1->width; *dy = 0; } - else if (map1->tile_map[2] == map2) - { /* down */ + else if (map1->tile_available (TILE_SOUTH, false) == map2) + { *dx = 0; *dy = map1->height; } - else if (map1->tile_map[3] == map2) - { /* left */ + else if (map1->tile_available (TILE_WEST , false) == map2) + { *dx = -map2->width; *dy = 0; } - else if (map1->tile_map[0] && map1->tile_map[0]->tile_map[1] == map2) + else if (map1->tile_map[TILE_NORTH] && map1->tile_map[TILE_NORTH]->tile_available (TILE_EAST , false) == map2) { /* up right */ - *dx = map1->tile_map[0]->width; - *dy = -map1->tile_map[0]->height; + *dx = +map1->tile_map[TILE_NORTH]->width; + *dy = -map1->tile_map[TILE_NORTH]->height; } - else if (map1->tile_map[0] && map1->tile_map[0]->tile_map[3] == map2) + else if (map1->tile_map[TILE_NORTH] && map1->tile_map[TILE_NORTH]->tile_available (TILE_WEST , false) == map2) { /* up left */ *dx = -map2->width; - *dy = -map1->tile_map[0]->height; + *dy = -map1->tile_map[TILE_NORTH]->height; } - else if (map1->tile_map[1] && map1->tile_map[1]->tile_map[0] == map2) + else if (map1->tile_map[TILE_EAST ] && map1->tile_map[TILE_EAST ]->tile_available (TILE_NORTH, false) == map2) { /* right up */ - *dx = map1->width; + *dx = +map1->width; *dy = -map2->height; } - else if (map1->tile_map[1] && map1->tile_map[1]->tile_map[2] == map2) + else if (map1->tile_map[TILE_EAST ] && map1->tile_map[TILE_EAST ]->tile_available (TILE_SOUTH, false) == map2) { /* right down */ - *dx = map1->width; - *dy = map1->tile_map[1]->height; + *dx = +map1->width; + *dy = +map1->tile_map[TILE_EAST]->height; } - else if (map1->tile_map[2] && map1->tile_map[2]->tile_map[1] == map2) + else if (map1->tile_map[TILE_SOUTH] && map1->tile_map[TILE_SOUTH]->tile_available (TILE_EAST , false) == map2) { /* down right */ - *dx = map1->tile_map[2]->width; - *dy = map1->height; + *dx = +map1->tile_map[TILE_SOUTH]->width; + *dy = +map1->height; } - else if (map1->tile_map[2] && map1->tile_map[2]->tile_map[3] == map2) + else if (map1->tile_map[TILE_SOUTH] && map1->tile_map[TILE_SOUTH]->tile_available (TILE_WEST , false) == map2) { /* down left */ *dx = -map2->width; - *dy = map1->height; + *dy = +map1->height; } - else if (map1->tile_map[3] && map1->tile_map[3]->tile_map[0] == map2) + else if (map1->tile_map[TILE_WEST ] && map1->tile_map[TILE_WEST ]->tile_available (TILE_NORTH, false) == map2) { /* left up */ - *dx = -map1->tile_map[3]->width; + *dx = -map1->tile_map[TILE_WEST]->width; *dy = -map2->height; } - else if (map1->tile_map[3] && map1->tile_map[3]->tile_map[2] == map2) + else if (map1->tile_map[TILE_WEST ] && map1->tile_map[TILE_WEST ]->tile_available (TILE_SOUTH, false) == map2) { /* left down */ - *dx = -map1->tile_map[3]->width; - *dy = map1->tile_map[3]->height; + *dx = -map1->tile_map[TILE_WEST]->width; + *dy = +map1->tile_map[TILE_WEST]->height; } else return 0; @@ -1496,7 +1583,7 @@ * field of the rv_vector is set to NULL. */ void -get_rangevector_from_mapcoord (const maptile *m, int x, int y, const object *op2, rv_vector *retval, int flags) +get_rangevector_from_mapcoord (maptile *m, int x, int y, const object *op2, rv_vector *retval, int flags) { if (!adjacent_map (m, op2->map, &retval->distance_x, &retval->distance_y)) { @@ -1628,7 +1715,7 @@ // clip to map to the left if (x0 < 0) { - if (maptile *tile = m->tile_available (TILE_LEFT, 1)) + if (maptile *tile = m->tile_available (TILE_WEST, 1)) split_to_tiles (buf, tile, x0 + tile->width, y0, min (x1 + tile->width, tile->width), y1, dx - tile->width, dy); if (x1 < 0) // entirely to the left @@ -1640,34 +1727,34 @@ // clip to map to the right if (x1 > m->width) { - if (maptile *tile = m->tile_available (TILE_RIGHT, 1)) + if (maptile *tile = m->tile_available (TILE_EAST, 1)) split_to_tiles (buf, tile, max (x0 - m->width, 0), y0, x1 - m->width, y1, dx + m->width, dy); - if (x0 > m->width) // entirely to the right + if (x0 >= m->width) // entirely to the right return; x1 = m->width; } - // clip to map above + // clip to map to the north if (y0 < 0) { - if (maptile *tile = m->tile_available (TILE_UP, 1)) + if (maptile *tile = m->tile_available (TILE_NORTH, 1)) split_to_tiles (buf, tile, x0, y0 + tile->height, x1, min (y1 + tile->height, tile->height), dx, dy - tile->height); - if (y1 < 0) // entirely above + if (y1 < 0) // entirely to the north return; y0 = 0; } - // clip to map below + // clip to map to the south if (y1 > m->height) { - if (maptile *tile = m->tile_available (TILE_DOWN, 1)) + if (maptile *tile = m->tile_available (TILE_SOUTH, 1)) split_to_tiles (buf, tile, x0, max (y0 - m->height, 0), x1, y1 - m->height, dx, dy + m->height); - if (y0 > m->height) // entirely below + if (y0 >= m->height) // entirely to the south return; y1 = m->height;