Core/Objects: ported Heartbeat implementation fron master branch

This commit is contained in:
Ovahlord committed 2025-03-09 02:40:05 +01:00
1 parent 352ce7e1b3
commit e8588fd5ba
30 files changed
+257 -184

No files matched your search

+55 -88
View File
@@ -118,8 +118,6 @@
#include "WorldStatePackets.h"
#include <G3D/g3dmath.h>
#define ZONE_UPDATE_INTERVAL (1*IN_MILLISECONDS)
// corpse reclaim times
#define DEATH_EXPIRE_STEP (5*MINUTE)
#define MAX_DEATH_COUNT 3
@@ -171,11 +169,9 @@ Player::Player(WorldSession* session): Unit(true)
m_comboPoints = 0;
m_foodEmoteTimerCount = 0;
m_weaponChangeTimer = 0;
m_zoneUpdateId = uint32(-1);
m_zoneUpdateTimer = 0;
m_areaUpdateId = 0;
m_team = 0;
@@ -355,7 +351,6 @@ Player::Player(WorldSession* session): Unit(true)
_hasValidLFGLeavePoint = false;
_archaeology = std::make_unique<Archaeology>(this);
m_petScalingSynchTimer.Reset(1000);
m_groupUpdateTimer.Reset(5000);
}
Player::~Player()
@@ -1133,37 +1128,6 @@ void Player::Update(uint32 p_time)
m_weaponChangeTimer -= p_time;
}
if (m_zoneUpdateTimer > 0)
{
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))
{
AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(GetInnTriggerId());
if (!atEntry || !IsInAreaTriggerRadius(atEntry))
RemoveRestFlag(REST_FLAG_IN_TAVERN);
}
uint32 newzone, newarea;
GetZoneAndAreaId(newzone, newarea);
if (m_zoneUpdateId != newzone)
UpdateZone(newzone, newarea); // also update area
else
{
// use area updates as well
// needed for free far all arenas for example
if (m_areaUpdateId != newarea)
UpdateArea(newarea);
m_zoneUpdateTimer = ZONE_UPDATE_INTERVAL;
}
}
else
m_zoneUpdateTimer -= p_time;
}
// Power regeneration update
_powerUpdateTimer -= p_time;
if (IsAlive())
@@ -1267,14 +1231,6 @@ void Player::Update(uint32 p_time)
}
}
// group update
m_groupUpdateTimer.Update(p_time);
if (m_groupUpdateTimer.Passed())
{
SendUpdateToOutOfRangeGroupMembers();
m_groupUpdateTimer.Reset(5000);
}
Pet* pet = GetPet();
if (pet && !pet->IsWithinDistInMap(this, GetMap()->GetVisibilityRange()) && !pet->isPossessed())
//if (pet && !pet->IsWithinDistInMap(this, GetMap()->GetVisibilityDistance()) && (GetCharmGUID() && (pet->GetGUID() != GetCharmGUID())))
@@ -1311,6 +1267,24 @@ void Player::Update(uint32 p_time)
}
void Player::Heartbeat()
{
Unit::Heartbeat();
// Group update
SendUpdateToOutOfRangeGroupMembers();
// Updating Zone and AreaId. This will also trigger spell_area and phasing related updates
UpdateZoneAndAreaId();
// Updating auras which can only be used inside or outside (such as Mounts)
UpdateIndoorsOutdoorsAuras();
// Updating the resting state when entering resting places
UpdateTavernRestingState();
}
void Player::setDeathState(DeathState s)
{
uint32 ressSpellId = 0;
@@ -1808,8 +1782,6 @@ bool Player::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, Wo
void Player::RegenerateAll(uint32 diff)
{
m_foodEmoteTimerCount += diff;
Regenerate(POWER_ENERGY, diff);
Regenerate(POWER_MANA, diff);
Regenerate(POWER_FOCUS, diff);
@@ -1838,37 +1810,6 @@ void Player::RegenerateAll(uint32 diff)
SetRuneCooldown(runeToRegen, (cd > (diff * cdmod)) ? cd - (diff * cdmod) : 0);
}
}
// Handles the emotes for drinking and eating.
// According to sniffs there is a background timer going on that repeats independed from the time window where the aura applies.
// That's why we dont need to reset the timer on apply. In sniffs I have seen that the first call for the spell visual is totally random, then after
// 5 seconds over and over again which confirms my theory that we have a independed timer.
if (m_foodEmoteTimerCount >= 5000)
{
std::vector<AuraEffect*> auraList;
AuraEffectList const& ModRegenAuras = GetAuraEffectsByType(SPELL_AURA_MOD_REGEN);
AuraEffectList const& ModPowerRegenAuras = GetAuraEffectsByType(SPELL_AURA_MOD_POWER_REGEN);
auraList.reserve(ModRegenAuras.size() + ModPowerRegenAuras.size());
auraList.insert(auraList.end(), ModRegenAuras.begin(), ModRegenAuras.end());
auraList.insert(auraList.end(), ModPowerRegenAuras.begin(), ModPowerRegenAuras.end());
for (auto itr = auraList.begin(); itr != auraList.end(); ++itr)
{
// Food emote comes above drinking emote if we have to decide (mage regen food for example)
if ((*itr)->GetBase()->HasEffectType(SPELL_AURA_MOD_REGEN) && (*itr)->GetSpellInfo()->HasAuraInterruptFlag(SpellAuraInterruptFlags::Standing))
{
SendPlaySpellVisualKit(SPELL_VISUAL_KIT_FOOD, 0, 0);
break;
}
else if ((*itr)->GetBase()->HasEffectType(SPELL_AURA_MOD_POWER_REGEN) && (*itr)->GetSpellInfo()->HasAuraInterruptFlag(SpellAuraInterruptFlags::Standing))
{
SendPlaySpellVisualKit(SPELL_VISUAL_KIT_DRINK, 0, 0);
break;
}
}
m_foodEmoteTimerCount -= 5000;
}
}
void Player::RegenerateHealth()
@@ -5913,7 +5854,7 @@ bool Player::UpdatePosition(float x, float y, float z, float orientation, bool t
SetGroupUpdateFlag(GROUP_UPDATE_FLAG_WMO_GROUP_ID);
}
CheckAreaExploreAndOutdoor();
CheckAreaExplore();
return true;
}
@@ -5969,7 +5910,7 @@ void Player::SendMovieStart(uint32 movieId)
SendDirectMessage(packet.Write());
}
void Player::CheckAreaExploreAndOutdoor()
void Player::CheckAreaExplore()
{
if (!IsAlive())
return;
@@ -5977,9 +5918,6 @@ void Player::CheckAreaExploreAndOutdoor()
if (IsInFlight())
return;
if (sWorld->getBoolConfig(CONFIG_VMAP_INDOOR_CHECK) && !IsOutdoors())
RemoveAurasWithAttribute(SPELL_ATTR0_ONLY_OUTDOORS);
uint32 const areaId = GetAreaId();
SetAreaExplored(areaId);
}
@@ -6052,6 +5990,39 @@ void Player::SetAreaExplored(uint32 areaId)
}
}
void Player::UpdateZoneAndAreaId()
{
uint32 newzone = 0, newarea = 0;
GetZoneAndAreaId(newzone, newarea);
if (m_zoneUpdateId != newzone)
UpdateZone(newzone, newarea); // also update area
else
{
// use area updates as well
// needed for free far all arenas for example
if (m_areaUpdateId != newarea)
UpdateArea(newarea);
}
}
void Player::UpdateIndoorsOutdoorsAuras()
{
if (sWorld->getBoolConfig(CONFIG_VMAP_INDOOR_CHECK))
RemoveAurasWithAttribute(IsOutdoors() ? SPELL_ATTR0_ONLY_INDOORS : SPELL_ATTR0_ONLY_OUTDOORS);
}
void Player::UpdateTavernRestingState()
{
AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(GetInnTriggerId());
if (HasRestFlag(REST_FLAG_IN_TAVERN) && (!atEntry || !IsInAreaTriggerRadius(atEntry)))
RemoveRestFlag(REST_FLAG_IN_TAVERN);
else if (!HasRestFlag(REST_FLAG_IN_TAVERN) && IsInAreaTriggerRadius(atEntry))
SetRestFlag(REST_FLAG_IN_TAVERN);
}
uint32 Player::TeamForRace(uint8 race)
{
if (ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(race))
@@ -7032,7 +7003,6 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
uint32 const oldZone = m_zoneUpdateId;
m_zoneUpdateId = newZone;
m_zoneUpdateTimer = ZONE_UPDATE_INTERVAL;
GetMap()->UpdatePlayerZoneStats(oldZone, newZone);
@@ -27629,7 +27599,7 @@ void Player::SetActiveSpec(uint8 spec)
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags2::ChangeSpec);
}
void Player::SetRestFlag(RestFlag restFlag, uint32 triggerId /*= 0*/)
void Player::SetRestFlag(RestFlag restFlag)
{
uint32 oldRestMask = _restFlagMask;
_restFlagMask |= restFlag;
@@ -27639,10 +27609,7 @@ void Player::SetRestFlag(RestFlag restFlag, uint32 triggerId /*= 0*/)
_restTime = GameTime::GetGameTime();
SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
}
if (triggerId)
inn_triggerId = triggerId;
}
}
void Player::RemoveRestFlag(RestFlag restFlag)
{