mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/Auras: implemented PROC_FLAG_HEARTBEAT and moved food/drink emote mechanic into heartbeat handling (#29943)
* also fixed an false assumption that only one of the food emotes can be played. They can in fact be both done at the same time.
This commit is contained in:
@@ -182,7 +182,6 @@ Player::Player(WorldSession* session) : Unit(true), m_sceneMgr(this)
|
||||
m_regenInterruptTimestamp = GameTime::Now();
|
||||
m_regenTimer = 0;
|
||||
m_regenTimerCount = 0;
|
||||
m_foodEmoteTimerCount = 0;
|
||||
m_weaponChangeTimer = 0;
|
||||
|
||||
m_zoneUpdateId = uint32(-1);
|
||||
@@ -1624,7 +1623,6 @@ bool Player::IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo
|
||||
void Player::RegenerateAll()
|
||||
{
|
||||
m_regenTimerCount += m_regenTimer;
|
||||
m_foodEmoteTimerCount += m_regenTimer;
|
||||
|
||||
for (Powers power = POWER_MANA; power < MAX_POWERS; power = Powers(power + 1))
|
||||
if (power != POWER_RUNES)
|
||||
@@ -1661,35 +1659,6 @@ void Player::RegenerateAll()
|
||||
}
|
||||
|
||||
m_regenTimer = 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)
|
||||
{
|
||||
auto findInterruptibleEffect = [](AuraEffect const* aurEff)
|
||||
{
|
||||
return aurEff->GetSpellInfo()->HasAuraInterruptFlag(SpellAuraInterruptFlags::Standing);
|
||||
};
|
||||
|
||||
// Food emote comes above drinking emote if we have to decide (mage regen food for example)
|
||||
AuraEffectList const& ModRegenAuras = GetAuraEffectsByType(SPELL_AURA_MOD_REGEN);
|
||||
auto itr = std::find_if(ModRegenAuras.cbegin(), ModRegenAuras.cend(), findInterruptibleEffect);
|
||||
if (itr != ModRegenAuras.end())
|
||||
{
|
||||
SendPlaySpellVisualKit(SPELL_VISUAL_KIT_FOOD, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
AuraEffectList const& ModPowerRegenAuras = GetAuraEffectsByType(SPELL_AURA_MOD_POWER_REGEN);
|
||||
itr = std::find_if(ModPowerRegenAuras.cbegin(), ModPowerRegenAuras.cend(), findInterruptibleEffect);
|
||||
if (itr != ModPowerRegenAuras.end())
|
||||
SendPlaySpellVisualKit(SPELL_VISUAL_KIT_DRINK, 0, 0);
|
||||
}
|
||||
|
||||
m_foodEmoteTimerCount -= 5000;
|
||||
}
|
||||
}
|
||||
|
||||
void Player::Regenerate(Powers power)
|
||||
|
||||
@@ -2884,7 +2884,6 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
|
||||
GuidList WhisperList;
|
||||
TimePoint m_regenInterruptTimestamp;
|
||||
uint32 m_regenTimerCount;
|
||||
uint32 m_foodEmoteTimerCount;
|
||||
std::array<float, MAX_POWERS_PER_CLASS> m_powerFraction;
|
||||
uint32 m_contestedPvPTimer;
|
||||
|
||||
|
||||
@@ -501,6 +501,17 @@ void Unit::Heartbeat()
|
||||
|
||||
// SMSG_FLIGHT_SPLINE_SYNC for cyclic splines
|
||||
SendFlightSplineSyncUpdate();
|
||||
|
||||
// Trigger heartbeat procs and generic aura behavior such as food emotes
|
||||
TriggerAuraHeartbeat();
|
||||
}
|
||||
|
||||
void Unit::TriggerAuraHeartbeat()
|
||||
{
|
||||
for (auto const& [_, auraApplication] : m_appliedAuras)
|
||||
auraApplication->GetBase()->Heartbeat();
|
||||
|
||||
Unit::ProcSkillsAndAuras(this, nullptr, PROC_FLAG_HEARTBEAT, PROC_FLAG_NONE, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_NONE, PROC_HIT_NONE, nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
bool Unit::haveOffhandWeapon() const
|
||||
|
||||
@@ -685,6 +685,7 @@ class TC_GAME_API Unit : public WorldObject
|
||||
virtual void Update(uint32 time) override;
|
||||
|
||||
void Heartbeat() override;
|
||||
void TriggerAuraHeartbeat();
|
||||
|
||||
void setAttackTimer(WeaponAttackType type, uint32 time) { m_attackTimer[type] = time; }
|
||||
void resetAttackTimer(WeaponAttackType type = BASE_ATTACK);
|
||||
|
||||
@@ -2614,6 +2614,28 @@ void UnitAura::AddStaticApplication(Unit* target, uint32 effMask)
|
||||
_staticApplications[target->GetGUID()] |= effMask;
|
||||
}
|
||||
|
||||
void UnitAura::Heartbeat()
|
||||
{
|
||||
Aura::Heartbeat();
|
||||
|
||||
// Periodic food and drink emote animation
|
||||
HandlePeriodicFoodSpellVisualKit();
|
||||
}
|
||||
|
||||
void UnitAura::HandlePeriodicFoodSpellVisualKit()
|
||||
{
|
||||
SpellSpecificType specificType = GetSpellInfo()->GetSpellSpecific();
|
||||
|
||||
bool food = specificType == SPELL_SPECIFIC_FOOD || specificType == SPELL_SPECIFIC_FOOD_AND_DRINK;
|
||||
bool drink = specificType == SPELL_SPECIFIC_DRINK || specificType == SPELL_SPECIFIC_FOOD_AND_DRINK;
|
||||
|
||||
if (food)
|
||||
GetUnitOwner()->SendPlaySpellVisualKit(SPELL_VISUAL_KIT_FOOD, 0, 0);
|
||||
|
||||
if (drink)
|
||||
GetUnitOwner()->SendPlaySpellVisualKit(SPELL_VISUAL_KIT_DRINK, 0, 0);
|
||||
}
|
||||
|
||||
DynObjAura::DynObjAura(AuraCreateInfo const& createInfo)
|
||||
: Aura(createInfo)
|
||||
{
|
||||
|
||||
@@ -257,6 +257,7 @@ class TC_GAME_API Aura
|
||||
float CalcPPMProcChance(Unit* actor) const;
|
||||
void SetLastProcAttemptTime(TimePoint lastProcAttemptTime) { m_lastProcAttemptTime = lastProcAttemptTime; }
|
||||
void SetLastProcSuccessTime(TimePoint lastProcSuccessTime) { m_lastProcSuccessTime = lastProcSuccessTime; }
|
||||
virtual void Heartbeat() { }
|
||||
|
||||
// AuraScript
|
||||
void LoadScripts();
|
||||
@@ -383,6 +384,9 @@ class TC_GAME_API UnitAura : public Aura
|
||||
|
||||
void AddStaticApplication(Unit* target, uint32 effMask);
|
||||
|
||||
void Heartbeat() override;
|
||||
void HandlePeriodicFoodSpellVisualKit();
|
||||
|
||||
private:
|
||||
DiminishingGroup m_AuraDRGroup; // Diminishing
|
||||
std::unordered_map<ObjectGuid, uint32> _staticApplications; // non-area auras
|
||||
|
||||
@@ -134,7 +134,7 @@ enum ProcFlags : uint32
|
||||
{
|
||||
PROC_FLAG_NONE = 0x00000000,
|
||||
|
||||
PROC_FLAG_HEARTBEAT = 0x00000001, // 00 Killed by agressor - not sure about this flag
|
||||
PROC_FLAG_HEARTBEAT = 0x00000001, // 00 Heartbeat
|
||||
PROC_FLAG_KILL = 0x00000002, // 01 Kill target (in most cases need XP/Honor reward)
|
||||
|
||||
PROC_FLAG_DEAL_MELEE_SWING = 0x00000004, // 02 Done melee auto attack
|
||||
|
||||
Reference in New Issue
Block a user