fix(Core/Game): Rest & Inn Improvements (#3780)
This commit is contained in:
@@ -1335,7 +1335,7 @@ bool Position::IsWithinBox(const Position& center, float xradius, float yradius,
|
|||||||
// is-in-cube check and we have to calculate only one point instead of 4
|
// 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
|
// 2PI = 360*, keep in mind that ingame orientation is counter-clockwise
|
||||||
double rotation = 2 * M_PI - center.GetOrientation();
|
double rotation = 2 * M_PI - GetOrientation();
|
||||||
double sinVal = std::sin(rotation);
|
double sinVal = std::sin(rotation);
|
||||||
double cosVal = std::cos(rotation);
|
double cosVal = std::cos(rotation);
|
||||||
|
|
||||||
@@ -1347,13 +1347,14 @@ bool Position::IsWithinBox(const Position& center, float xradius, float yradius,
|
|||||||
|
|
||||||
// box edges are parallel to coordiante axis, so we can treat every dimension independently :D
|
// box edges are parallel to coordiante axis, so we can treat every dimension independently :D
|
||||||
float dz = GetPositionZ() - center.GetPositionZ();
|
float dz = GetPositionZ() - center.GetPositionZ();
|
||||||
float dx = rotX - center.GetPositionX();
|
float dx = rotX - GetPositionX();
|
||||||
float dy = rotY - center.GetPositionY();
|
float dy = rotY - GetPositionY();
|
||||||
if ((std::fabs(dx) > xradius) ||
|
if ((std::fabs(dx) > xradius) ||
|
||||||
(std::fabs(dy) > yradius) ||
|
(std::fabs(dy) > yradius) ||
|
||||||
(std::fabs(dz) > zradius))
|
(std::fabs(dz) > zradius))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -82,7 +82,8 @@
|
|||||||
#include "LuaEngine.h"
|
#include "LuaEngine.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ZONE_UPDATE_INTERVAL (2*IN_MILLISECONDS)
|
// Zone Interval should be 1 second
|
||||||
|
#define ZONE_UPDATE_INTERVAL (1*IN_MILLISECONDS)
|
||||||
|
|
||||||
#define PLAYER_SKILL_INDEX(x) (PLAYER_SKILL_INFO_1_1 + ((x)*3))
|
#define PLAYER_SKILL_INDEX(x) (PLAYER_SKILL_INFO_1_1 + ((x)*3))
|
||||||
#define PLAYER_SKILL_VALUE_INDEX(x) (PLAYER_SKILL_INDEX(x)+1)
|
#define PLAYER_SKILL_VALUE_INDEX(x) (PLAYER_SKILL_INDEX(x)+1)
|
||||||
@@ -824,6 +825,7 @@ Player::Player(WorldSession* session): Unit(true), m_mover(this)
|
|||||||
_restTime = 0;
|
_restTime = 0;
|
||||||
_innTriggerId = 0;
|
_innTriggerId = 0;
|
||||||
_restBonus = 0;
|
_restBonus = 0;
|
||||||
|
_restFlagMask = 0;
|
||||||
////////////////////Rest System/////////////////////
|
////////////////////Rest System/////////////////////
|
||||||
|
|
||||||
m_mailsUpdated = false;
|
m_mailsUpdated = false;
|
||||||
@@ -1776,6 +1778,14 @@ void Player::Update(uint32 p_time)
|
|||||||
{
|
{
|
||||||
if (p_time >= m_zoneUpdateTimer)
|
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 (HasRestFlag(REST_FLAG_IN_TAVERN))
|
||||||
|
{
|
||||||
|
AreaTrigger const* atEntry = sObjectMgr->GetAreaTrigger(GetInnTriggerId());
|
||||||
|
if (!atEntry || !IsInAreaTriggerRadius(atEntry))
|
||||||
|
RemoveRestFlag(REST_FLAG_IN_TAVERN);
|
||||||
|
}
|
||||||
|
|
||||||
uint32 newzone, newarea;
|
uint32 newzone, newarea;
|
||||||
GetZoneAndAreaId(newzone, newarea, true);
|
GetZoneAndAreaId(newzone, newarea, true);
|
||||||
m_last_zone_id = newzone;
|
m_last_zone_id = newzone;
|
||||||
@@ -3023,20 +3033,22 @@ void Player::SetInWater(bool apply)
|
|||||||
|
|
||||||
bool Player::IsInAreaTriggerRadius(const AreaTrigger* trigger) const
|
bool Player::IsInAreaTriggerRadius(const AreaTrigger* trigger) const
|
||||||
{
|
{
|
||||||
|
static const float delta = 5.0f;
|
||||||
|
|
||||||
if (!trigger || GetMapId() != trigger->map)
|
if (!trigger || GetMapId() != trigger->map)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (trigger->radius > 0.f)
|
if (trigger->radius > 0)
|
||||||
{
|
{
|
||||||
// if we have radius check it
|
// if we have radius check it
|
||||||
float dist = GetDistance(trigger->x, trigger->y, trigger->z);
|
float dist = GetDistance(trigger->x, trigger->y, trigger->z);
|
||||||
if (dist > trigger->radius)
|
if (dist > trigger->radius + delta)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Position center = {trigger->x, trigger->y, trigger->z, trigger->orientation};
|
Position center(trigger->x, trigger->y, trigger->z, trigger->orientation);
|
||||||
if (!IsWithinBox(center, trigger->length / 2.f, trigger->width / 2.f, trigger->height / 2.f))
|
if (IsWithinBox(center, trigger->length / 2 + delta, trigger->width / 2 + delta, trigger->height / 2 + delta))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7673,27 +7685,7 @@ void Player::UpdateArea(uint32 newArea)
|
|||||||
UpdateAreaDependentAuras(newArea);
|
UpdateAreaDependentAuras(newArea);
|
||||||
|
|
||||||
pvpInfo.IsInNoPvPArea = false;
|
pvpInfo.IsInNoPvPArea = false;
|
||||||
if (!area)
|
if (area && area->IsSanctuary())
|
||||||
{
|
|
||||||
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY);
|
|
||||||
RemoveRestState();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Xinef: area should inherit zone flags
|
|
||||||
AreaTableEntry const* zone = sAreaTableStore.LookupEntry(area->zone);
|
|
||||||
uint32 areaFlags = area->flags;
|
|
||||||
bool isSanctuary = area->IsSanctuary();
|
|
||||||
bool isInn = area->IsInn(GetTeamId(true));
|
|
||||||
if (zone)
|
|
||||||
{
|
|
||||||
areaFlags |= zone->flags;
|
|
||||||
isSanctuary |= zone->IsSanctuary();
|
|
||||||
isInn |= zone->IsInn(GetTeamId(true));
|
|
||||||
}
|
|
||||||
|
|
||||||
// previously this was in UpdateZone (but after UpdateArea) so nothing will break
|
|
||||||
if (isSanctuary) // in sanctuary
|
|
||||||
{
|
{
|
||||||
SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY);
|
SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY);
|
||||||
pvpInfo.IsInNoPvPArea = true;
|
pvpInfo.IsInNoPvPArea = true;
|
||||||
@@ -7702,18 +7694,11 @@ void Player::UpdateArea(uint32 newArea)
|
|||||||
else
|
else
|
||||||
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY);
|
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY);
|
||||||
|
|
||||||
if (isInn)
|
uint32 const areaRestFlag = (GetTeamId(true) == TEAM_ALLIANCE) ? AREA_FLAG_REST_ZONE_ALLIANCE : AREA_FLAG_REST_ZONE_HORDE;
|
||||||
{
|
if (area && area->flags & areaRestFlag)
|
||||||
SetRestState(0);
|
SetRestFlag(REST_FLAG_IN_FACTION_AREA);
|
||||||
if (sWorld->IsFFAPvPRealm())
|
else
|
||||||
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
|
RemoveRestFlag(REST_FLAG_IN_FACTION_AREA);
|
||||||
}
|
|
||||||
else if (!(areaFlags & AREA_FLAG_CAPITAL))
|
|
||||||
{
|
|
||||||
AreaTrigger const* atEntry = sObjectMgr->GetAreaTrigger(GetInnTriggerId());
|
|
||||||
if (!atEntry || !IsInAreaTriggerRadius(atEntry))
|
|
||||||
RemoveRestState();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 Player::GetZoneId(bool forceRecalc) const
|
uint32 Player::GetZoneId(bool forceRecalc) const
|
||||||
@@ -7809,10 +7794,12 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
|
|||||||
if (zone->flags & AREA_FLAG_CAPITAL) // Is in a capital city
|
if (zone->flags & AREA_FLAG_CAPITAL) // Is in a capital city
|
||||||
{
|
{
|
||||||
if (!pvpInfo.IsHostile || zone->IsSanctuary())
|
if (!pvpInfo.IsHostile || zone->IsSanctuary())
|
||||||
SetRestState(0);
|
SetRestFlag(REST_FLAG_IN_CITY);
|
||||||
|
|
||||||
pvpInfo.IsInNoPvPArea = true;
|
pvpInfo.IsInNoPvPArea = true;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
RemoveRestFlag(REST_FLAG_IN_CITY); // Recently left a capital city
|
||||||
|
|
||||||
UpdatePvPState();
|
UpdatePvPState();
|
||||||
|
|
||||||
@@ -27855,3 +27842,30 @@ bool Player::HasHealSpec()
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<int, bgZoneRef> Player::bgZoneIdToFillWorldStates = {};
|
std::unordered_map<int, bgZoneRef> Player::bgZoneIdToFillWorldStates = {};
|
||||||
|
|
||||||
|
void Player::SetRestFlag(RestFlag restFlag, uint32 triggerId /*= 0*/)
|
||||||
|
{
|
||||||
|
uint32 oldRestMask = _restFlagMask;
|
||||||
|
_restFlagMask |= restFlag;
|
||||||
|
|
||||||
|
if (!oldRestMask && _restFlagMask) // only set flag/time on the first rest state
|
||||||
|
{
|
||||||
|
_restTime = time(nullptr);
|
||||||
|
SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (triggerId)
|
||||||
|
_innTriggerId = triggerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::RemoveRestFlag(RestFlag restFlag)
|
||||||
|
{
|
||||||
|
uint32 oldRestMask = _restFlagMask;
|
||||||
|
_restFlagMask &= ~restFlag;
|
||||||
|
|
||||||
|
if (oldRestMask && !_restFlagMask) // only remove flag/time on the last rest state remove
|
||||||
|
{
|
||||||
|
_restTime = 0;
|
||||||
|
RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -766,6 +766,13 @@ enum ArenaTeamInfoType
|
|||||||
|
|
||||||
class InstanceSave;
|
class InstanceSave;
|
||||||
|
|
||||||
|
enum RestFlag
|
||||||
|
{
|
||||||
|
REST_FLAG_IN_TAVERN = 0x1,
|
||||||
|
REST_FLAG_IN_CITY = 0x2,
|
||||||
|
REST_FLAG_IN_FACTION_AREA = 0x4, // used with AREA_FLAG_REST_ZONE_*
|
||||||
|
};
|
||||||
|
|
||||||
enum TeleportToOptions
|
enum TeleportToOptions
|
||||||
{
|
{
|
||||||
TELE_TO_GM_MODE = 0x01,
|
TELE_TO_GM_MODE = 0x01,
|
||||||
@@ -1251,6 +1258,10 @@ public:
|
|||||||
uint32 GetXPRestBonus(uint32 xp);
|
uint32 GetXPRestBonus(uint32 xp);
|
||||||
[[nodiscard]] float GetRestBonus() const { return _restBonus; }
|
[[nodiscard]] float GetRestBonus() const { return _restBonus; }
|
||||||
void SetRestBonus(float rest_bonus_new);
|
void SetRestBonus(float rest_bonus_new);
|
||||||
|
|
||||||
|
bool HasRestFlag(RestFlag restFlag) const { return (_restFlagMask & restFlag) != 0; }
|
||||||
|
void SetRestFlag(RestFlag restFlag, uint32 triggerId = 0);
|
||||||
|
void RemoveRestFlag(RestFlag restFlag);
|
||||||
[[nodiscard]] uint32 GetInnTriggerId() const { return _innTriggerId; }
|
[[nodiscard]] uint32 GetInnTriggerId() const { return _innTriggerId; }
|
||||||
|
|
||||||
[[nodiscard]] Pet* GetPet() const;
|
[[nodiscard]] Pet* GetPet() const;
|
||||||
@@ -2901,6 +2912,7 @@ protected:
|
|||||||
time_t _restTime;
|
time_t _restTime;
|
||||||
uint32 _innTriggerId;
|
uint32 _innTriggerId;
|
||||||
float _restBonus;
|
float _restBonus;
|
||||||
|
uint32 _restFlagMask;
|
||||||
////////////////////Rest System/////////////////////
|
////////////////////Rest System/////////////////////
|
||||||
uint32 m_resetTalentsCost;
|
uint32 m_resetTalentsCost;
|
||||||
time_t m_resetTalentsTime;
|
time_t m_resetTalentsTime;
|
||||||
|
|||||||
@@ -766,7 +766,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket& recv_data)
|
|||||||
if (sObjectMgr->IsTavernAreaTrigger(triggerId))
|
if (sObjectMgr->IsTavernAreaTrigger(triggerId))
|
||||||
{
|
{
|
||||||
// set resting flag we are in the inn
|
// set resting flag we are in the inn
|
||||||
player->SetRestState(atEntry->entry);
|
player->SetRestFlag(REST_FLAG_IN_TAVERN, atEntry->entry);
|
||||||
|
|
||||||
if (sWorld->IsFFAPvPRealm())
|
if (sWorld->IsFFAPvPRealm())
|
||||||
player->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
|
player->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
|
||||||
|
|||||||
@@ -522,16 +522,6 @@ struct AreaTableEntry
|
|||||||
return true;
|
return true;
|
||||||
return (flags & AREA_FLAG_SANCTUARY);
|
return (flags & AREA_FLAG_SANCTUARY);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Xinef: mark some zones / areas as inns
|
|
||||||
[[nodiscard]] bool IsInn(TeamId teamId) const
|
|
||||||
{
|
|
||||||
if (teamId == TEAM_ALLIANCE)
|
|
||||||
return flags & AREA_FLAG_REST_ZONE_ALLIANCE;
|
|
||||||
else if (teamId == TEAM_HORDE)
|
|
||||||
return flags & AREA_FLAG_REST_ZONE_HORDE;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_GROUP_AREA_IDS 6
|
#define MAX_GROUP_AREA_IDS 6
|
||||||
|
|||||||
Reference in New Issue
Block a user