diff options
Diffstat (limited to 'src/game/Map.cpp')
-rw-r--r-- | src/game/Map.cpp | 120 |
1 files changed, 73 insertions, 47 deletions
diff --git a/src/game/Map.cpp b/src/game/Map.cpp index a17604f5dd5..06685247688 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <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()); } @@ -300,7 +300,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()); } @@ -1082,8 +1082,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)); @@ -1095,15 +1095,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]; @@ -1113,7 +1133,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]; @@ -1126,7 +1146,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]; @@ -1136,7 +1156,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]; @@ -1145,32 +1165,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; @@ -1246,7 +1243,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; @@ -1264,11 +1261,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 @@ -1655,10 +1671,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; } @@ -1968,6 +1984,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) @@ -2023,12 +2047,14 @@ void BattleGroundMap::UnloadAll(bool pForce) { 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(pForce); |