Core/Players: Improve rest state handling, allow several rest states to be active

Fixes https://github.com/TrinityCore/TrinityCore/issues/15325

(cherry picked from commit c14b66c24c)

Conflicts:
	src/server/game/Entities/Player/Player.cpp
	src/server/game/Handlers/MiscHandler.cpp
This commit is contained in:
Trisjdc
2015-08-23 10:47:16 +01:00
committed by Carbenium
parent e5eea44e0a
commit 93e77bfc7b
3 changed files with 60 additions and 87 deletions

View File

@@ -603,7 +603,6 @@ Player::Player(WorldSession* session) : Unit(true)
m_MirrorTimerFlagsLast = UNDERWATER_NONE;
m_isInWater = false;
m_drunkTimer = 0;
m_restTime = 0;
m_deathTimer = 0;
m_deathExpireTime = 0;
@@ -634,10 +633,10 @@ Player::Player(WorldSession* session) : Unit(true)
m_lastpetnumber = 0;
////////////////////Rest System/////////////////////
time_inn_enter = 0;
_restTime = 0;
inn_triggerId = 0;
m_rest_bonus = 0;
rest_type = REST_TYPE_NO;
_restFlagMask = 0;
////////////////////Rest System/////////////////////
m_mailsLoaded = false;
@@ -1569,15 +1568,20 @@ void Player::Update(uint32 p_time)
if (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING))
{
if (roll_chance_i(3) && GetTimeInnEnter() > 0) // freeze update
if (roll_chance_i(3) && _restTime > 0) // freeze update
{
time_t time_inn = time(NULL)-GetTimeInnEnter();
if (time_inn >= 10) // freeze update
time_t currTime = time(nullptr);
time_t timeDiff = currTime - _restTime;
if (timeDiff >= 10) // freeze update
{
float bubble = 0.125f*sWorld->getRate(RATE_REST_INGAME);
// speed collect rest bonus (section/in hour)
SetRestBonus(GetRestBonus()+ time_inn*((float)GetUInt32Value(PLAYER_NEXT_LEVEL_XP)/72000)*bubble);
UpdateInnerTime(time(NULL));
_restTime = currTime;
float bubble = 0.125f * sWorld->getRate(RATE_REST_INGAME);
float extraPerSec = ((float)GetUInt32Value(PLAYER_NEXT_LEVEL_XP) / 72000.0f) * bubble;
// speed collect rest bonus (section/in hour)
float currRestBonus = GetRestBonus();
SetRestBonus(currRestBonus + timeDiff * extraPerSec);
}
}
}
@@ -1595,14 +1599,11 @@ 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)
if (HasRestFlag(REST_FLAG_IN_TAVERN))
{
AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(GetInnTriggerId());
if (!atEntry || !IsInAreaTriggerRadius(atEntry))
{
RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
SetRestType(REST_TYPE_NO);
}
RemoveRestFlag(REST_FLAG_IN_TAVERN);
}
uint32 newzone, newarea;
@@ -1795,12 +1796,6 @@ void Player::setDeathState(DeathState s)
SetUInt32Value(PLAYER_SELF_RES_SPELL, 0);
}
void Player::InnEnter(time_t time, uint32 triggerId)
{
inn_triggerId = triggerId;
time_inn_enter = time;
}
void Player::ToggleAFK()
{
ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_AFK);
@@ -7216,7 +7211,7 @@ void Player::UpdateArea(uint32 newArea)
{
// FFA_PVP flags are area and not zone id dependent
// so apply them accordingly
m_areaUpdateId = newArea;
m_areaUpdateId = newArea;
AreaTableEntry const* area = GetAreaEntryByAreaID(newArea);
pvpInfo.IsInFFAPvPArea = area && (area->Flags[0] & AREA_FLAG_ARENA);
@@ -7238,16 +7233,9 @@ void Player::UpdateArea(uint32 newArea)
uint32 const areaRestFlag = (GetTeam() == ALLIANCE) ? AREA_FLAG_REST_ZONE_ALLIANCE : AREA_FLAG_REST_ZONE_HORDE;
if (area && area->Flags[0] & areaRestFlag)
{
SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
SetRestType(REST_TYPE_IN_FACTION_AREA);
InnEnter(time(nullptr), 0);
}
else if (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) && GetRestType() == REST_TYPE_IN_FACTION_AREA)
{
RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
SetRestType(REST_TYPE_NO);
}
SetRestFlag(REST_FLAG_IN_FACTION_AREA);
else
RemoveRestFlag(REST_FLAG_IN_FACTION_AREA);
}
void Player::UpdateZone(uint32 newZone, uint32 newArea)
@@ -7317,36 +7305,11 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
if (zone->Flags[0] & AREA_FLAG_CAPITAL) // Is in a capital city
{
if (!pvpInfo.IsHostile || zone->IsSanctuary())
{
SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
SetRestType(REST_TYPE_IN_CITY);
InnEnter(time(nullptr), 0);
}
SetRestFlag(REST_FLAG_IN_CITY);
pvpInfo.IsInNoPvPArea = true;
}
else
{
if (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING))
{
if (GetRestType() == REST_TYPE_IN_TAVERN) // Still inside a tavern or has recently left
{
// 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);
}
}
else if (GetRestType() != REST_TYPE_IN_FACTION_AREA) // handled in UpdateArea
{
// Recently left a capital city
RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
SetRestType(REST_TYPE_NO);
}
}
}
RemoveRestFlag(REST_FLAG_IN_CITY);
UpdatePvPState();
@@ -26663,3 +26626,30 @@ void Player::SendRaidGroupOnlyMessage(RaidGroupReason reason, int32 delay)
GetSession()->SendPacket(raidGroupOnly.Write());
}
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)
inn_triggerId = 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);
}
}

View File

@@ -907,12 +907,11 @@ enum ArenaTeamInfoType
class InstanceSave;
enum RestType
enum RestFlag
{
REST_TYPE_NO = 0,
REST_TYPE_IN_TAVERN = 1,
REST_TYPE_IN_CITY = 2,
REST_TYPE_IN_FACTION_AREA = 3 // used with AREA_FLAG_REST_ZONE_*
REST_FLAG_IN_TAVERN = 0x1,
REST_FLAG_IN_CITY = 0x2,
REST_FLAG_IN_FACTION_AREA = 0x4, // used with AREA_FLAG_REST_ZONE_*
};
enum TeleportToOptions
@@ -1368,19 +1367,16 @@ class Player : public Unit, public GridObject<Player>
void setDeathState(DeathState s) override; // overwrite Unit::setDeathState
void InnEnter(time_t time, uint32 triggerId);
float GetRestBonus() const { return m_rest_bonus; }
void SetRestBonus(float rest_bonus_new);
RestType GetRestType() const { return rest_type; }
void SetRestType(RestType n_r_type) { rest_type = n_r_type; }
bool HasRestFlag(RestFlag restFlag) const { return (_restFlagMask & restFlag) != 0; }
void SetRestFlag(RestFlag restFlag, uint32 triggerId = 0);
void RemoveRestFlag(RestFlag restFlag);
uint32 GetXPRestBonus(uint32 xp);
uint32 GetInnTriggerId() const { return inn_triggerId; }
time_t GetTimeInnEnter() const { return time_inn_enter; }
void UpdateInnerTime (time_t time) { time_inn_enter = time; }
Pet* GetPet() const;
Pet* SummonPet(uint32 entry, float x, float y, float z, float ang, PetType petType, uint32 despwtime);
void RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent = false);
@@ -2316,15 +2312,6 @@ class Player : public Unit, public GridObject<Player>
// returns true if the player is in active state for outdoor pvp objective capturing, false otherwise
bool IsOutdoorPvPActive();
/*********************************************************/
/*** REST SYSTEM ***/
/*********************************************************/
bool isRested() const { return GetRestTime() >= 10*IN_MILLISECONDS; }
uint32 GetXPRestBonus(uint32 xp);
uint32 GetRestTime() const { return m_restTime;}
void SetRestTime(uint32 v) { m_restTime = v;}
/*********************************************************/
/*** ENVIROMENTAL SYSTEM ***/
/*********************************************************/
@@ -2810,8 +2797,6 @@ class Player : public Unit, public GridObject<Player>
uint32 m_deathTimer;
time_t m_deathExpireTime;
uint32 m_restTime;
uint32 m_WeaponProficiency;
uint32 m_ArmorProficiency;
bool m_canParry;
@@ -2820,10 +2805,10 @@ class Player : public Unit, public GridObject<Player>
uint8 m_swingErrorMsg;
////////////////////Rest System/////////////////////
time_t time_inn_enter;
time_t _restTime;
uint32 inn_triggerId;
float m_rest_bonus;
RestType rest_type;
uint32 _restFlagMask;
////////////////////Rest System/////////////////////
// Social

View File

@@ -509,9 +509,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPackets::Misc::AreaTrigger& pack
if (sObjectMgr->IsTavernAreaTrigger(packet.AreaTriggerID))
{
// set resting flag we are in the inn
player->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
player->InnEnter(time(nullptr), atEntry->ID);
player->SetRestType(REST_TYPE_IN_TAVERN);
player->SetRestFlag(REST_FLAG_IN_TAVERN, atEntry->ID);
if (sWorld->IsFFAPvPRealm())
player->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);