aboutsummaryrefslogtreecommitdiff
path: root/src/game/Map.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/game/Map.cpp')
-rw-r--r--src/game/Map.cpp127
1 files changed, 77 insertions, 50 deletions
diff --git a/src/game/Map.cpp b/src/game/Map.cpp
index c6b0739b6bd..493e5b4b112 100644
--- a/src/game/Map.cpp
+++ b/src/game/Map.cpp
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2005-2008 Trinity <http://www.mangosproject.org/>
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*
- * Copyright (C) 2008 Trinity <http://www.trinitycore.org/>
+ * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -45,7 +45,7 @@
#define MAX_GRID_LOAD_TIME 50
// magic *.map header
-const char MAP_MAGIC[] = "MAP_2.50";
+const char MAP_MAGIC[] = "MAP_3.00";
GridState* si_GridStates[MAX_GRID_STATE];
@@ -257,7 +257,7 @@ template<>
void Map::AddToGrid(Creature* obj, NGridType *grid, Cell const& cell)
{
// add to world object registry in grid
- if(obj->isPet() || obj->HasSharedVision())
+ if(obj->isPet() || obj->HasSharedVision() || obj->isVehicle())
{
(*grid)(cell.CellX(), cell.CellY()).AddWorldObject<Creature>(obj, obj->GetGUID());
}
@@ -309,7 +309,7 @@ template<>
void Map::RemoveFromGrid(Creature* obj, NGridType *grid, Cell const& cell)
{
// remove from world object registry in grid
- if(obj->isPet() || obj->HasSharedVision())
+ if(obj->isPet() || obj->HasSharedVision() || obj->isVehicle())
{
(*grid)(cell.CellX(), cell.CellY()).RemoveWorldObject<Creature>(obj, obj->GetGUID());
}
@@ -1168,8 +1168,8 @@ float Map::GetHeight(float x, float y, float z, bool pUseVmaps) const
int gx=(int)(32-x/SIZE_OF_GRIDS); //grid x
int gy=(int)(32-y/SIZE_OF_GRIDS); //grid y
- float lx=128*(32 -x/SIZE_OF_GRIDS - gx);
- float ly=128*(32 -y/SIZE_OF_GRIDS - gy);
+ float lx=MAP_RESOLUTION*(32 -x/SIZE_OF_GRIDS - gx);
+ float ly=MAP_RESOLUTION*(32 -y/SIZE_OF_GRIDS - gy);
// ensure GridMap is loaded
const_cast<Map*>(this)->EnsureGridCreated(GridPair(63-gx,63-gy));
@@ -1181,15 +1181,35 @@ float Map::GetHeight(float x, float y, float z, bool pUseVmaps) const
int lx_int = (int)lx;
int ly_int = (int)ly;
+ // In some very rare case this will happen. Need find a better way.
+ //if(lx_int == MAP_RESOLUTION) --lx_int;
+ //if(ly_int == MAP_RESOLUTION) --ly_int;
+
lx -= lx_int;
ly -= ly_int;
+ // Height stored as: h5 - its v8 grid, h1-h4 - its v9 grid
+ // +--------------> X
+ // | h1-------h2 Coordinates is:
+ // | | \ 1 / | h1 0,0
+ // | | \ / | h2 0,1
+ // | | 2 h5 3 | h3 1,0
+ // | | / \ | h4 1,1
+ // | | / 4 \ | h5 1/2,1/2
+ // | h3-------h4
+ // V Y
+ // For find height need
+ // 1 - detect triangle
+ // 2 - solve linear equation from triangle points
+
+ // Calculate coefficients for solve h = a*x + b*y + c
float a,b,c;
+ // Select triangle:
if (lx+ly < 1)
{
if (lx > ly)
{
- // 1
+ // 1 triangle (h1, h2, h5 points)
float h1 = gmap->v9[lx_int][ly_int];
float h2 = gmap->v9[lx_int+1][ly_int];
float h5 = 2 * gmap->v8[lx_int][ly_int];
@@ -1199,7 +1219,7 @@ float Map::GetHeight(float x, float y, float z, bool pUseVmaps) const
}
else
{
- // 2
+ // 2 triangle (h1, h3, h5 points)
float h1 = gmap->v9[lx_int][ly_int];
float h3 = gmap->v9[lx_int][ly_int+1];
float h5 = 2 * gmap->v8[lx_int][ly_int];
@@ -1212,7 +1232,7 @@ float Map::GetHeight(float x, float y, float z, bool pUseVmaps) const
{
if (lx > ly)
{
- // 3
+ // 3 triangle (h2, h4, h5 points)
float h2 = gmap->v9[lx_int+1][ly_int];
float h4 = gmap->v9[lx_int+1][ly_int+1];
float h5 = 2 * gmap->v8[lx_int][ly_int];
@@ -1222,7 +1242,7 @@ float Map::GetHeight(float x, float y, float z, bool pUseVmaps) const
}
else
{
- // 4
+ // 4 triangle (h3, h4, h5 points)
float h3 = gmap->v9[lx_int][ly_int+1];
float h4 = gmap->v9[lx_int+1][ly_int+1];
float h5 = 2 * gmap->v8[lx_int][ly_int];
@@ -1231,32 +1251,9 @@ float Map::GetHeight(float x, float y, float z, bool pUseVmaps) const
c = h5 - h4;
}
}
+ // Calculate height
float _mapheight = a * lx + b * ly + c;
- // In some very rare case this will happen. Need find a better way.
- if(lx_int == MAP_RESOLUTION) --lx_int;
- if(ly_int == MAP_RESOLUTION) --ly_int;
-
- /*
- float zi[4];
- // Probe 4 nearest points (except border cases)
- zi[0] = gmap->Z[lx_int][ly_int];
- zi[1] = lx < MAP_RESOLUTION-1 ? gmap->Z[lx_int+1][ly_int] : zi[0];
- zi[2] = ly < MAP_RESOLUTION-1 ? gmap->Z[lx_int][ly_int+1] : zi[0];
- zi[3] = lx < MAP_RESOLUTION-1 && ly < MAP_RESOLUTION-1 ? gmap->Z[lx_int+1][ly_int+1] : zi[0];
- // Recalculate them like if their x,y positions were in the range 0,1
- float b[4];
- b[0] = zi[0];
- b[1] = zi[1]-zi[0];
- b[2] = zi[2]-zi[0];
- b[3] = zi[0]-zi[1]-zi[2]+zi[3];
- // Normalize the dx and dy to be in range 0..1
- float fact_x = lx - lx_int;
- float fact_y = ly - ly_int;
- // Use the simplified bilinear equation, as described in [url="http://en.wikipedia.org/wiki/Bilinear_interpolation"]http://en.wikipedia.org/wiki/Bilinear_interpolation[/url]
- float _mapheight = b[0] + (b[1]*fact_x) + (b[2]*fact_y) + (b[3]*fact_x*fact_y);
-
- */
// look from a bit higher pos to find the floor, ignore under surface case
if(z + 2.0f > _mapheight)
mapHeight = _mapheight;
@@ -1332,7 +1329,7 @@ float Map::GetVmapHeight(float x, float y, float z, bool useMaps) const
return vmapHeight;
}
-uint16 Map::GetAreaFlag(float x, float y ) const
+uint16 Map::GetAreaFlag(float x, float y, float z) const
{
//local x,y coords
float lx,ly;
@@ -1350,11 +1347,30 @@ uint16 Map::GetAreaFlag(float x, float y ) const
// ensure GridMap is loaded
const_cast<Map*>(this)->EnsureGridCreated(GridPair(63-gx,63-gy));
+ uint16 areaflag;
if(GridMaps[gx][gy])
- return GridMaps[gx][gy]->area_flag[(int)(lx)][(int)(ly)];
+ areaflag = GridMaps[gx][gy]->area_flag[(int)(lx)][(int)(ly)];
// this used while not all *.map files generated (instances)
else
- return GetAreaFlagByMapId(i_id);
+ areaflag = GetAreaFlagByMapId(i_id);
+
+ //FIXME: some hacks for areas above or underground for ground area
+ // required for area specific spells/etc, until map/vmap data
+ // not provided correct areaflag with this hacks
+ switch(areaflag)
+ {
+ // Acherus: The Ebon Hold (Plaguelands: The Scarlet Enclave)
+ case 1984: // Plaguelands: The Scarlet Enclave
+ case 2076: // Death's Breach (Plaguelands: The Scarlet Enclave)
+ case 2745: // The Noxious Pass (Plaguelands: The Scarlet Enclave)
+ if(z > 350.0f) areaflag = 2048; break;
+ // Acherus: The Ebon Hold (Eastern Plaguelands)
+ case 856: // The Noxious Glade (Eastern Plaguelands)
+ case 2456: // Death's Breach (Eastern Plaguelands)
+ if(z > 350.0f) areaflag = 1950; break;
+ }
+
+ return areaflag;
}
uint8 Map::GetTerrainType(float x, float y ) const
@@ -1614,7 +1630,7 @@ void Map::RemoveAllObjectsInRemoveList()
switch(obj->GetTypeId())
{
case TYPEID_UNIT:
- if(!((Creature*)obj)->isPet())
+ if(!((Creature*)obj)->isPet() && !((Creature*)obj)->isVehicle())
SwitchGridContainers((Creature*)obj, on);
break;
}
@@ -1759,8 +1775,9 @@ template void Map::Remove(DynamicObject *, bool);
/* ******* Dungeon Instance Maps ******* */
InstanceMap::InstanceMap(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode)
- : Map(id, expiry, InstanceId, SpawnMode), i_data(NULL),
- m_resetAfterUnload(false), m_unloadWhenEmpty(false)
+ : Map(id, expiry, InstanceId, SpawnMode),
+ m_resetAfterUnload(false), m_unloadWhenEmpty(false),
+ i_data(NULL), i_script_id(0)
{
// the timer is started by default, and stopped when the first player joins
// this make sure it gets unloaded if for some reason no player joins
@@ -1789,10 +1806,10 @@ bool InstanceMap::CanEnter(Player *player)
}
// cannot enter if the instance is full (player cap), GMs don't count
- InstanceTemplate const* iTemplate = objmgr.GetInstanceTemplate(GetId());
- if (!player->isGameMaster() && GetPlayersCountExceptGMs() >= iTemplate->maxPlayers)
+ uint32 maxPlayers = GetMaxPlayers();
+ if (!player->isGameMaster() && GetPlayersCountExceptGMs() >= maxPlayers)
{
- sLog.outDetail("MAP: Instance '%u' of map '%s' cannot have more than '%u' players. Player '%s' rejected", GetInstanceId(), GetMapName(), iTemplate->maxPlayers, player->GetName());
+ sLog.outDetail("MAP: Instance '%u' of map '%s' cannot have more than '%u' players. Player '%s' rejected", GetInstanceId(), GetMapName(), maxPlayers, player->GetName());
player->SendTransferAborted(GetId(), TRANSFER_ABORT_MAX_PLAYERS);
return false;
}
@@ -2102,6 +2119,14 @@ void InstanceMap::SetResetSchedule(bool on)
}
}
+uint32 InstanceMap::GetMaxPlayers() const
+{
+ InstanceTemplate const* iTemplate = objmgr.GetInstanceTemplate(GetId());
+ if(!iTemplate)
+ return 0;
+ return IsHeroic() ? iTemplate->maxPlayersHeroic : iTemplate->maxPlayers;
+}
+
/* ******* Battleground Instance Maps ******* */
BattleGroundMap::BattleGroundMap(uint32 id, time_t expiry, uint32 InstanceId)
@@ -2157,12 +2182,14 @@ void BattleGroundMap::UnloadAll()
{
while(HavePlayers())
{
- Player * plr = m_mapRefManager.getFirst()->getSource();
- if(plr) (plr)->TeleportTo(plr->m_homebindMapId, plr->m_homebindX, plr->m_homebindY, plr->m_homebindZ, plr->GetOrientation());
- // TeleportTo removes the player from this map (if the map exists) -> calls BattleGroundMap::Remove -> invalidates the iterator.
- // just in case, remove the player from the list explicitly here as well to prevent a possible infinite loop
- // note that this remove is not needed if the code works well in other places
- plr->GetMapRef().unlink();
+ if(Player * plr = m_mapRefManager.getFirst()->getSource())
+ {
+ plr->TeleportTo(plr->GetBattleGroundEntryPoint());
+ // TeleportTo removes the player from this map (if the map exists) -> calls BattleGroundMap::Remove -> invalidates the iterator.
+ // just in case, remove the player from the list explicitly here as well to prevent a possible infinite loop
+ // note that this remove is not needed if the code works well in other places
+ plr->GetMapRef().unlink();
+ }
}
Map::UnloadAll();