diff options
Diffstat (limited to 'src/game/Map.cpp')
-rw-r--r-- | src/game/Map.cpp | 127 |
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(); |