Beneficial spells will now correctly inherit targets RestTimer

Example PC A is fighting mob B. PC C casts a heal on PC A. PC C will
inherit the timer from PC A. This is done because beneficial spells have
a "witness" check from NPCs so there is a chance PC C would not gain
aggro and could just keep on going with no RestTimer which allows them
to fast regen while actively participating.
This commit is contained in:
Michael Cook (mackal) 2018-07-14 18:50:02 -04:00
parent 18005ac7a9
commit 6ab2871fd1
3 changed files with 34 additions and 0 deletions

View File

@ -4608,6 +4608,7 @@ void Client::IncrementAggroCount(bool raid_target)
uint32 newtimer = raid_target ? RuleI(Character, RestRegenRaidTimeToActivate) : RuleI(Character, RestRegenTimeToActivate); uint32 newtimer = raid_target ? RuleI(Character, RestRegenRaidTimeToActivate) : RuleI(Character, RestRegenTimeToActivate);
// save the new timer if it's higher
m_pp.RestTimer = std::max(m_pp.RestTimer, newtimer); m_pp.RestTimer = std::max(m_pp.RestTimer, newtimer);
// If we already had aggro before this method was called, the combat indicator should already be up for SoF clients, // If we already had aggro before this method was called, the combat indicator should already be up for SoF clients,
@ -4661,6 +4662,36 @@ void Client::DecrementAggroCount()
} }
} }
// when we cast a beneficial spell we need to steal our targets current timer
// That's what we use this for
void Client::UpdateRestTimer(uint32 new_timer)
{
// their timer was 0, so we don't do anything
if (new_timer == 0)
return;
if (!RuleB(Character, RestRegenEnabled))
return;
// so if we're currently on aggro, we check our saved timer
if (AggroCount) {
if (m_pp.RestTimer < new_timer) // our timer needs to be updated, don't need to update client here
m_pp.RestTimer = new_timer;
} else { // if we're not aggro, we need to check if current timer needs updating
if (rest_timer.GetRemainingTime() < new_timer) {
rest_timer.Start(new_timer);
if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) {
auto outapp = new EQApplicationPacket(OP_RestState, 5);
char *Buffer = (char *)outapp->pBuffer;
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0x00);
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, new_timer);
QueuePacket(outapp);
safe_delete(outapp);
}
}
}
}
void Client::SendPVPStats() void Client::SendPVPStats()
{ {
// This sends the data to the client to populate the PVP Stats Window. // This sends the data to the client to populate the PVP Stats Window.

View File

@ -1397,6 +1397,7 @@ private:
void CalcRestState(); void CalcRestState();
// if they have aggro (AggroCount != 0) their timer is saved in m_pp.RestTimer, else we need to get current timer // if they have aggro (AggroCount != 0) their timer is saved in m_pp.RestTimer, else we need to get current timer
inline uint32 GetRestTimer() const { return AggroCount ? m_pp.RestTimer : rest_timer.GetRemainingTime() / 1000; } inline uint32 GetRestTimer() const { return AggroCount ? m_pp.RestTimer : rest_timer.GetRemainingTime() / 1000; }
void UpdateRestTimer(uint32 new_timer);
uint32 pLastUpdate; uint32 pLastUpdate;
uint32 pLastUpdateWZ; uint32 pLastUpdateWZ;

View File

@ -3895,6 +3895,8 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r
spelltar->SetHateAmountOnEnt(this, std::max(newhate, 1)); spelltar->SetHateAmountOnEnt(this, std::max(newhate, 1));
} }
} else if (IsBeneficialSpell(spell_id) && !IsSummonPCSpell(spell_id)) { } else if (IsBeneficialSpell(spell_id) && !IsSummonPCSpell(spell_id)) {
if (spelltar->IsClient() && IsClient())
CastToClient()->UpdateRestTimer(spelltar->CastToClient()->GetRestTimer());
entity_list.AddHealAggro( entity_list.AddHealAggro(
spelltar, this, spelltar, this,
CheckHealAggroAmount(spell_id, spelltar, (spelltar->GetMaxHP() - spelltar->GetHP()))); CheckHealAggroAmount(spell_id, spelltar, (spelltar->GetMaxHP() - spelltar->GetHP())));