Core/RestState: Check area trigger radius instead of 1.0f distance

Closes #15016
Closes #15052

Signed-off-by: jackpoz <[email protected]>
(cherry picked from commit 12931f4762d2592e4b28c6e6bf137b3348230c45)

Conflicts:
	src/server/game/Entities/Player/Player.h
	src/server/game/Handlers/MiscHandler.cpp
This commit is contained in:
Rochet2
2015-09-24 20:29:55 +02:00
committed by Carbenium
parent bfb373ef22
commit c3c7ab6ec7
5 changed files with 79 additions and 72 deletions
@@ -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
@@ -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;
+42 -13
View File
@@ -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);
+4 -9
View File
@@ -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/////////////////////
+4 -50
View File
@@ -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())