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 b3006709556..fe060d14dff 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);  | 
