diff options
-rw-r--r-- | src/server/game/Entities/Object/Position.cpp | 28 | ||||
-rw-r--r-- | src/server/game/Entities/Object/Position.h | 1 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 55 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 13 | ||||
-rw-r--r-- | src/server/game/Handlers/MiscHandler.cpp | 54 |
5 files changed, 79 insertions, 72 deletions
diff --git a/src/server/game/Entities/Object/Position.cpp b/src/server/game/Entities/Object/Position.cpp index 8f8e5743f8c..ae559cbac3a 100644 --- a/src/server/game/Entities/Object/Position.cpp +++ b/src/server/game/Entities/Object/Position.cpp @@ -98,6 +98,34 @@ void Position::GetSinCos(const float x, const float y, float &vsin, float &vcos) } } +bool Position::IsWithinBox(const Position& center, float xradius, float yradius, float zradius) const +{ + // rotate the WorldObject position instead of rotating the whole cube, that way we can make a simplified + // is-in-cube check and we have to calculate only one point instead of 4 + + // 2PI = 360*, keep in mind that ingame orientation is counter-clockwise + double rotation = 2 * M_PI - center.GetOrientation(); + double sinVal = std::sin(rotation); + double cosVal = std::cos(rotation); + + float BoxDistX = GetPositionX() - center.GetPositionX(); + float BoxDistY = GetPositionY() - center.GetPositionY(); + + float rotX = float(center.GetPositionX() + BoxDistX * cosVal - BoxDistY*sinVal); + float rotY = float(center.GetPositionY() + BoxDistY * cosVal + BoxDistX*sinVal); + + // box edges are parallel to coordiante axis, so we can treat every dimension independently :D + float dz = GetPositionZ() - center.GetPositionZ(); + float dx = rotX - center.GetPositionX(); + float dy = rotY - center.GetPositionY(); + if ((std::fabs(dx) > xradius) || + (std::fabs(dy) > yradius) || + (std::fabs(dz) > zradius)) + return false; + + return true; +} + bool Position::HasInArc(float arc, const Position* obj, float border) const { // always have self in arc diff --git a/src/server/game/Entities/Object/Position.h b/src/server/game/Entities/Object/Position.h index 109ff09d66c..98dbf1ca628 100644 --- a/src/server/game/Entities/Object/Position.h +++ b/src/server/game/Entities/Object/Position.h @@ -195,6 +195,7 @@ public: return GetExactDistSq(pos) < dist * dist; } + bool IsWithinBox(const Position& center, float xradius, float yradius, float zradius) const; bool HasInArc(float arcangle, Position const* pos, float border = 2.0f) const; bool HasInLine(Position const* pos, float width) const; std::string ToString() const; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 049db9251f5..5d84f587648 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -635,10 +635,7 @@ Player::Player(WorldSession* session) : Unit(true) ////////////////////Rest System///////////////////// time_inn_enter = 0; - inn_pos_mapid = 0; - inn_pos_x = 0.0f; - inn_pos_y = 0.0f; - inn_pos_z = 0.0f; + inn_triggerId = 0; m_rest_bonus = 0; rest_type = REST_TYPE_NO; ////////////////////Rest System///////////////////// @@ -1597,6 +1594,17 @@ void Player::Update(uint32 p_time) { if (p_time >= m_zoneUpdateTimer) { + // On zone update tick check if we are still in an inn if we are supposed to be in one + if (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) && GetRestType() == REST_TYPE_IN_TAVERN) + { + AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(GetInnTriggerId()); + if (!atEntry || !IsInAreaTriggerRadius(atEntry)) + { + RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING); + SetRestType(REST_TYPE_NO); + } + } + uint32 newzone, newarea; GetZoneAndAreaId(newzone, newarea); @@ -1787,12 +1795,9 @@ void Player::setDeathState(DeathState s) SetUInt32Value(PLAYER_SELF_RES_SPELL, 0); } -void Player::InnEnter(time_t time, uint32 mapid, float x, float y, float z) +void Player::InnEnter(time_t time, uint32 triggerId) { - inn_pos_mapid = mapid; - inn_pos_x = x; - inn_pos_y = y; - inn_pos_z = z; + inn_triggerId = triggerId; time_inn_enter = time; } @@ -2573,6 +2578,28 @@ void Player::SetInWater(bool apply) getHostileRefManager().updateThreatTables(); } +bool Player::IsInAreaTriggerRadius(const AreaTriggerEntry* trigger) const +{ + if (!trigger || GetMapId() != trigger->MapID) + return false; + + if (trigger->Radius > 0.f) + { + // if we have radius check it + float dist = GetDistance(trigger->Pos.X, trigger->Pos.Y, trigger->Pos.Z); + if (dist > trigger->Radius) + return false; + } + else + { + Position center(trigger->Pos.X, trigger->Pos.Y, trigger->Pos.Z, trigger->BoxYaw); + if (!IsWithinBox(center, trigger->BoxLength / 2.f, trigger->BoxWidth / 2.f, trigger->BoxHeight / 2.f)) + return false; + } + + return true; +} + void Player::SetGameMaster(bool on) { if (on) @@ -7214,7 +7241,7 @@ void Player::UpdateArea(uint32 newArea) { SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING); SetRestType(REST_TYPE_IN_FACTION_AREA); - InnEnter(time(0), GetMapId(), 0, 0, 0); + InnEnter(time(nullptr), 0); } else if (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) && GetRestType() == REST_TYPE_IN_FACTION_AREA) { @@ -7293,7 +7320,7 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea) { SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING); SetRestType(REST_TYPE_IN_CITY); - InnEnter(time(0), GetMapId(), 0, 0, 0); + InnEnter(time(nullptr), 0); } pvpInfo.IsInNoPvPArea = true; } @@ -7303,8 +7330,10 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea) { if (GetRestType() == REST_TYPE_IN_TAVERN) // Still inside a tavern or has recently left { - // Remove rest state if we have recently left a tavern. - if (GetMapId() != GetInnPosMapId() || GetExactDist(GetInnPosX(), GetInnPosY(), GetInnPosZ()) > 1.0f) + // check that we are still inside the tavern (in areatrigger radius) + + AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(GetInnTriggerId()); + if (!atEntry || !IsInAreaTriggerRadius(atEntry)) { RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING); SetRestType(REST_TYPE_NO); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index d16fc7a1fc1..db8a6170e9b 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1306,6 +1306,7 @@ class Player : public Unit, public GridObject<Player> bool IsInWater() const override { return m_isInWater; } bool IsUnderWater() const override; + bool IsInAreaTriggerRadius(const AreaTriggerEntry* trigger) const; void SendInitialPacketsBeforeAddToMap(); void SendInitialPacketsAfterAddToMap(); @@ -1367,7 +1368,7 @@ class Player : public Unit, public GridObject<Player> void setDeathState(DeathState s) override; // overwrite Unit::setDeathState - void InnEnter(time_t time, uint32 mapid, float x, float y, float z); + void InnEnter(time_t time, uint32 triggerId); float GetRestBonus() const { return m_rest_bonus; } void SetRestBonus(float rest_bonus_new); @@ -1375,10 +1376,7 @@ class Player : public Unit, public GridObject<Player> RestType GetRestType() const { return rest_type; } void SetRestType(RestType n_r_type) { rest_type = n_r_type; } - uint32 GetInnPosMapId() const { return inn_pos_mapid; } - float GetInnPosX() const { return inn_pos_x; } - float GetInnPosY() const { return inn_pos_y; } - float GetInnPosZ() const { return inn_pos_z; } + uint32 GetInnTriggerId() const { return inn_triggerId; } time_t GetTimeInnEnter() const { return time_inn_enter; } void UpdateInnerTime (time_t time) { time_inn_enter = time; } @@ -2823,10 +2821,7 @@ class Player : public Unit, public GridObject<Player> ////////////////////Rest System///////////////////// time_t time_inn_enter; - uint32 inn_pos_mapid; - float inn_pos_x; - float inn_pos_y; - float inn_pos_z; + uint32 inn_triggerId; float m_rest_bonus; RestType rest_type; ////////////////////Rest System///////////////////// diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index c1762421956..8151ff70248 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -471,59 +471,13 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPackets::Misc::AreaTrigger& pack return; } - if (player->GetMapId() != atEntry->MapID) + if (!player->IsInAreaTriggerRadius(atEntry)) { - TC_LOG_DEBUG("network", "HandleAreaTriggerOpcode: Player '%s' (%s) too far (trigger map: %u player map: %u), ignore Area Trigger ID: %u", - player->GetName().c_str(), player->GetGUID().ToString().c_str(), atEntry->MapID, player->GetMapId(), packet.AreaTriggerID); + TC_LOG_DEBUG("network", "HandleAreaTriggerOpcode: Player '%s' (%s) too far, ignore Area Trigger ID: %u", + player->GetName().c_str(), player->GetGUID().ToString().c_str(), packet.AreaTriggerID); return; } - // delta is safe radius - const float delta = 5.0f; - - if (atEntry->Radius > 0) - { - // if we have radius check it - float dist = player->GetDistance(atEntry->Pos.X, atEntry->Pos.Y, atEntry->Pos.Z); - if (dist > atEntry->Radius + delta) - { - TC_LOG_DEBUG("network", "HandleAreaTriggerOpcode: Player '%s' (%s) too far (radius: %f distance: %f), ignore Area Trigger ID: %u", - player->GetName().c_str(), player->GetGUID().ToString().c_str(), atEntry->Radius, dist, packet.AreaTriggerID); - return; - } - } - else - { - // we have only extent - - // rotate the players position instead of rotating the whole cube, that way we can make a simplified - // is-in-cube check and we have to calculate only one point instead of 4 - - // 2PI = 360°, keep in mind that ingame orientation is counter-clockwise - double rotation = 2 * M_PI - atEntry->BoxYaw; - double sinVal = std::sin(rotation); - double cosVal = std::cos(rotation); - - float playerBoxDistX = player->GetPositionX() - atEntry->Pos.X; - float playerBoxDistY = player->GetPositionY() - atEntry->Pos.Y; - - float rotPlayerX = float(atEntry->Pos.X + playerBoxDistX * cosVal - playerBoxDistY*sinVal); - float rotPlayerY = float(atEntry->Pos.Y + playerBoxDistY * cosVal + playerBoxDistX*sinVal); - - // box edges are parallel to coordiante axis, so we can treat every dimension independently :D - float dz = player->GetPositionZ() - atEntry->Pos.Z; - float dx = rotPlayerX - atEntry->Pos.X; - float dy = rotPlayerY - atEntry->Pos.Y; - if ((std::fabs(dx) > atEntry->BoxLength / 2 + delta) || - (std::fabs(dy) > atEntry->BoxWidth / 2 + delta) || - (std::fabs(dz) > atEntry->BoxHeight / 2 + delta)) - { - TC_LOG_DEBUG("network", "HandleAreaTriggerOpcode: Player '%s' (%s) too far (1/2 box X: %f 1/2 box Y: %f 1/2 box Z: %f rotatedPlayerX: %f rotatedPlayerY: %f dZ:%f), ignore Area Trigger ID: %u", - player->GetName().c_str(), player->GetGUID().ToString().c_str(), atEntry->BoxLength / 2, atEntry->BoxWidth / 2, atEntry->BoxHeight / 2, rotPlayerX, rotPlayerY, dz, packet.AreaTriggerID); - return; - } - } - if (player->isDebugAreaTriggers) ChatHandler(player->GetSession()).PSendSysMessage(packet.Entered ? LANG_DEBUG_AREATRIGGER_ENTERED : LANG_DEBUG_AREATRIGGER_LEFT, packet.AreaTriggerID); @@ -556,7 +510,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPackets::Misc::AreaTrigger& pack { // set resting flag we are in the inn player->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING); - player->InnEnter(time(NULL), atEntry->MapID, atEntry->Pos.X, atEntry->Pos.Y, atEntry->Pos.Z); + player->InnEnter(time(nullptr), atEntry->ID); player->SetRestType(REST_TYPE_IN_TAVERN); if (sWorld->IsFFAPvPRealm()) |