diff options
Diffstat (limited to 'src/server')
| -rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 7 | ||||
| -rw-r--r-- | src/server/game/Handlers/MovementHandler.cpp | 3 | ||||
| -rw-r--r-- | src/server/game/Maps/Map.cpp | 62 | ||||
| -rw-r--r-- | src/server/game/Maps/Map.h | 11 |
4 files changed, 64 insertions, 19 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 76c610596c0..9ae9f21c967 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -4682,6 +4682,7 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness) // remove death flag + set aura SetByteValue(UNIT_FIELD_BYTES_1, 3, 0x00); + RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_IS_OUT_OF_BOUNDS); // This must be called always even on Players with race != RACE_NIGHTELF in case of faction change RemoveAurasDueToSpell(20584); // RACE_NIGHTELF speed bonuses @@ -5105,7 +5106,7 @@ void Player::RepopAtGraveyard() AreaTableEntry const* zone = sAreaTableStore.LookupEntry(GetAreaId()); // Such zones are considered unreachable as a ghost and the player must be automatically revived - if ((!IsAlive() && zone && zone->flags & AREA_FLAG_NEED_FLY) || GetTransport() || GetPositionZ() < -500.0f) + if ((!IsAlive() && zone && zone->flags & AREA_FLAG_NEED_FLY) || GetTransport() || GetPositionZ() < GetMap()->GetMinHeight(GetPositionX(), GetPositionY())) { ResurrectPlayer(0.5f); SpawnCorpseBones(); @@ -5142,8 +5143,10 @@ void Player::RepopAtGraveyard() GetSession()->SendPacket(&data); } } - else if (GetPositionZ() < -500.0f) + else if (GetPositionZ() < GetMap()->GetMinHeight(GetPositionX(), GetPositionY())) TeleportTo(m_homebindMapId, m_homebindX, m_homebindY, m_homebindZ, GetOrientation()); + + RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_IS_OUT_OF_BOUNDS); } bool Player::CanJoinConstantChannelInZone(ChatChannelsEntry const* channel, AreaTableEntry const* zone) diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index eea5c62fbd1..02702fc5622 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -386,7 +386,7 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData) plrMover->UpdateFallInformationIfNeed(movementInfo, opcode); - if (movementInfo.pos.GetPositionZ() < -500.0f) + if (movementInfo.pos.GetPositionZ() < plrMover->GetMap()->GetMinHeight(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY())) { if (!(plrMover->GetBattleground() && plrMover->GetBattleground()->HandlePlayerUnderMap(_player))) { @@ -395,6 +395,7 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData) /// @todo discard movement packets after the player is rooted if (plrMover->IsAlive()) { + plrMover->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_IS_OUT_OF_BOUNDS); plrMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth()); // player can be alive if GM/etc // change the death state to CORPSE to prevent the death timer from diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index edf7227746a..1560d4bdd08 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -37,7 +37,7 @@ #include "VMapFactory.h" u_map_magic MapMagic = { {'M','A','P','S'} }; -u_map_magic MapVersionMagic = { {'v','1','.','6'} }; +u_map_magic MapVersionMagic = { {'v','1','.','7'} }; u_map_magic MapAreaMagic = { {'A','R','E','A'} }; u_map_magic MapHeightMagic = { {'M','H','G','T'} }; u_map_magic MapLiquidMagic = { {'M','L','I','Q'} }; @@ -1644,13 +1644,15 @@ GridMap::GridMap() _flags = 0; // Area data _gridArea = 0; - _areaMap = NULL; + _areaMap = nullptr; // Height level data _gridHeight = INVALID_HEIGHT; _gridGetHeight = &GridMap::getHeightFromFlat; _gridIntHeightMultiplier = 0; - m_V9 = NULL; - m_V8 = NULL; + m_V9 = nullptr; + m_V8 = nullptr; + _maxHeight = nullptr; + _minHeight = nullptr; // Liquid data _liquidType = 0; _liquidOffX = 0; @@ -1658,9 +1660,9 @@ GridMap::GridMap() _liquidWidth = 0; _liquidHeight = 0; _liquidLevel = INVALID_HEIGHT; - _liquidEntry = NULL; - _liquidFlags = NULL; - _liquidMap = NULL; + _liquidEntry = nullptr; + _liquidFlags = nullptr; + _liquidMap = nullptr; } GridMap::~GridMap() @@ -1723,15 +1725,19 @@ void GridMap::unloadData() delete[] _areaMap; delete[] m_V9; delete[] m_V8; + delete[] _maxHeight; + delete[] _minHeight; delete[] _liquidEntry; delete[] _liquidFlags; delete[] _liquidMap; - _areaMap = NULL; - m_V9 = NULL; - m_V8 = NULL; - _liquidEntry = NULL; - _liquidFlags = NULL; - _liquidMap = NULL; + _areaMap = nullptr; + m_V9 = nullptr; + m_V8 = nullptr; + _maxHeight = nullptr; + _minHeight = nullptr; + _liquidEntry = nullptr; + _liquidFlags = nullptr; + _liquidMap = nullptr; _gridGetHeight = &GridMap::getHeightFromFlat; } @@ -1796,6 +1802,16 @@ bool GridMap::loadHeightData(FILE* in, uint32 offset, uint32 /*size*/) } else _gridGetHeight = &GridMap::getHeightFromFlat; + + if (header.flags & MAP_HEIGHT_HAS_FLIGHT_BOUNDS) + { + _maxHeight = new float[16 * 16]; + _minHeight = new float[16 * 16]; + if (fread(_maxHeight, sizeof(float), 16 * 16, in) != 16 * 16 || + fread(_minHeight, sizeof(float), 16 * 16, in) != 16 * 16) + return false; + } + return true; } @@ -2066,6 +2082,18 @@ float GridMap::getHeightFromUint16(float x, float y) const return (float)((a * x) + (b * y) + c)*_gridIntHeightMultiplier + _gridHeight; } +float GridMap::getMinHeight(float x, float y) const +{ + if (!_minHeight) + return -500.0f; + + x = 16 * (CENTER_GRID_ID - x / SIZE_OF_GRIDS); + y = 16 * (CENTER_GRID_ID - y / SIZE_OF_GRIDS); + int lx = (int)x & 15; + int ly = (int)y & 15; + return _minHeight[lx * 16 + ly]; +} + float GridMap::getLiquidLevel(float x, float y) const { if (!_liquidMap) @@ -2266,6 +2294,14 @@ float Map::GetHeight(float x, float y, float z, bool checkVMap /*= true*/, float return mapHeight; // explicitly use map data } +float Map::GetMinHeight(float x, float y) const +{ + if (GridMap const* grid = const_cast<Map*>(this)->GetGrid(x, y)) + return grid->getMinHeight(x, y); + + return -500.0f; +} + inline bool IsOutdoorWMO(uint32 mogpFlags, int32 /*adtId*/, int32 /*rootId*/, int32 /*groupId*/, WMOAreaTableEntry const* wmoEntry, AreaTableEntry const* atEntry) { bool outdoor = true; diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index 46eede09948..13d48db0f9d 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -98,9 +98,10 @@ struct map_areaHeader uint16 gridArea; }; -#define MAP_HEIGHT_NO_HEIGHT 0x0001 -#define MAP_HEIGHT_AS_INT16 0x0002 -#define MAP_HEIGHT_AS_INT8 0x0004 +#define MAP_HEIGHT_NO_HEIGHT 0x0001 +#define MAP_HEIGHT_AS_INT16 0x0002 +#define MAP_HEIGHT_AS_INT8 0x0004 +#define MAP_HEIGHT_HAS_FLIGHT_BOUNDS 0x0008 struct map_heightHeader { @@ -166,6 +167,8 @@ class GridMap uint16* m_uint16_V8; uint8* m_uint8_V8; }; + float* _maxHeight; + float* _minHeight; // Height level data float _gridHeight; float _gridIntHeightMultiplier; @@ -206,6 +209,7 @@ public: uint16 getArea(float x, float y) const; inline float getHeight(float x, float y) const {return (this->*_gridGetHeight)(x, y);} + float getMinHeight(float x, float y) const; float getLiquidLevel(float x, float y) const; uint8 getTerrainType(float x, float y) const; ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = 0); @@ -326,6 +330,7 @@ class Map : public GridRefManager<NGridType> // some calls like isInWater should not use vmaps due to processor power // can return INVALID_HEIGHT if under z+2 z coord not found height float GetHeight(float x, float y, float z, bool checkVMap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const; + float GetMinHeight(float x, float y) const; ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = nullptr) const; |
