--- deliantra/server/common/map.C 2011/05/07 14:13:48 1.211
+++ deliantra/server/common/map.C 2012/10/29 23:55:52 1.218
@@ -1,24 +1,24 @@
/*
* This file is part of Deliantra, the Roguelike Realtime MMORPG.
- *
- * Copyright (©) 2005,2006,2007,2008,2009,2010,2011 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
- *
+ *
* 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
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the Affero GNU General Public License
* and the GNU General Public License along with this program. If not, see
* .
- *
+ *
* The authors can be reached via e-mail to
*/
@@ -545,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;
}
@@ -673,12 +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_5: thawer.get (tile_path [4]); break;
- case KW_tile_path_6: thawer.get (tile_path [5]); 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);
@@ -767,12 +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 [4]) MAP_OUT2 (tile_path_5, tile_path [4]);
- if (tile_path [5]) MAP_OUT2 (tile_path_6, tile_path [5]);
+ 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));
@@ -1197,25 +1197,26 @@
if (top == middle)
middle = 0;
- // dire hack to handle "transparent" floors - currently only open_space
- if (floor && floor->arch->archname == shstr_quad_open_space)
+ // 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])
{
- // mirror the floor - very unreliable because usually outdated,
- // but somewhta works because floors do not change often :/
mapspace &ms = m->at (floor->x, floor->y);
ms.update ();
if (object *floor2 = ms.faces_obj [2])
- if (floor2->arch->archname != shstr_quad_open_space && !middle)
+ if (!floor2->flag [FLAG_IS_TRANSPARENT_FLOOR])
{
floor->set_anim_frame (1);
- middle = floor;
+ top = floor;
+ middle = ms.faces_obj [0];
floor = floor2;
}
+
+ ms.pflags |= PF_VIS_UP;
}
}
@@ -1226,18 +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])
- {
- // 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];
+ // 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
- if ((tile_map[dir] = find_async (tile_path[dir], this, load)))
- return tile_map[dir];
+ // 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;
+ }
+
+
+ return tile_map [dir] = m;
+ }
}
return 0;
@@ -1263,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
@@ -1312,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
@@ -1460,7 +1506,7 @@
* can be negative. direction is the crossfire direction scheme
* that the creature should head. part is the part of the
* monster that is closest.
- *
+ *
* get_rangevector looks at op1 and op2, and fills in the
* structure for op1 to get to op2.
* We already trust that the caller has verified that the
@@ -1684,31 +1730,31 @@
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_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_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;