diff --git a/common/timer.cpp b/common/timer.cpp index 3b5d8f15e..120e3dea7 100644 --- a/common/timer.cpp +++ b/common/timer.cpp @@ -129,7 +129,7 @@ void Timer::SetTimer(uint32 set_timer_time) { } } -uint32 Timer::GetRemainingTime() { +uint32 Timer::GetRemainingTime() const { if (enabled) { if (current_time - start_time > timer_time) return 0; diff --git a/common/timer.h b/common/timer.h index f06f5bbe4..6678be952 100644 --- a/common/timer.h +++ b/common/timer.h @@ -40,7 +40,7 @@ public: void Disable(); void Start(uint32 set_timer_time=0, bool ChangeResetTimer = true); void SetTimer(uint32 set_timer_time=0); - uint32 GetRemainingTime(); + uint32 GetRemainingTime() const; inline const uint32& GetTimerTime() { return timer_time; } inline const uint32& GetSetAtTrigger() { return set_at_trigger; } void Trigger(); diff --git a/zone/client.cpp b/zone/client.cpp index bbe2c2512..f50d60e8c 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -325,9 +325,6 @@ Client::Client(EQStreamInterface* ieqs) initial_respawn_selection = 0; alternate_currency_loaded = false; - EngagedRaidTarget = false; - SavedRaidRestTimer = 0; - interrogateinv_flag = false; trapid = 0; @@ -630,7 +627,7 @@ bool Client::Save(uint8 iCommitNow) { /* Total Time Played */ TotalSecondsPlayed += (time(nullptr) - m_pp.lastlogin); m_pp.timePlayedMin = (TotalSecondsPlayed / 60); - m_pp.RestTimer = rest_timer.GetRemainingTime() / 1000; + m_pp.RestTimer = GetRestTimer(); /* Save Mercs */ if (GetMercInfo().MercTimerRemaining > RuleI(Mercs, UpkeepIntervalMS)) { @@ -4594,29 +4591,31 @@ int Client::GetAggroCount() { return AggroCount; } -void Client::IncrementAggroCount() { - +// we pass in for book keeping if RestRegen is enabled +void Client::IncrementAggroCount(bool raid_target) +{ // This method is called when a client is added to a mob's hate list. It turns the clients aggro flag on so // rest state regen is stopped, and for SoF, it sends the opcode to show the crossed swords in-combat indicator. - // - // AggroCount++; if(!RuleB(Character, RestRegenEnabled)) return; + uint32 newtimer = raid_target ? RuleI(Character, RestRegenRaidTimeToActivate) : RuleI(Character, RestRegenTimeToActivate); + + 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, // so we don't need to send it again. // if(AggroCount > 1) return; - // Pause the rest timer + // Pause the rest timer, it's possible the new timer is a non-raid timer we're currently ticking down on a raid timer if (AggroCount == 1) - SavedRaidRestTimer = rest_timer.GetRemainingTime(); + m_pp.RestTimer = std::max(m_pp.RestTimer, rest_timer.GetRemainingTime() / 1000); if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { - auto outapp = new EQApplicationPacket(OP_RestState, 1); char *Buffer = (char *)outapp->pBuffer; VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0x01); @@ -4626,12 +4625,11 @@ void Client::IncrementAggroCount() { } -void Client::DecrementAggroCount() { - +void Client::DecrementAggroCount() +{ // This should be called when a client is removed from a mob's hate list (it dies or is memblurred). // It checks whether any other mob is aggro on the player, and if not, starts the rest timer. // For SoF, the opcode to start the rest state countdown timer in the UI is sent. - // // If we didn't have aggro before, this method should not have been called. if(!AggroCount) @@ -4643,29 +4641,16 @@ void Client::DecrementAggroCount() { return; // Something else is still aggro on us, can't rest yet. - if(AggroCount) return; + if (AggroCount) + return; - uint32 time_until_rest; - if (GetEngagedRaidTarget()) { - time_until_rest = RuleI(Character, RestRegenRaidTimeToActivate) * 1000; - SetEngagedRaidTarget(false); - } else { - if (SavedRaidRestTimer > (RuleI(Character, RestRegenTimeToActivate) * 1000)) { - time_until_rest = SavedRaidRestTimer; - SavedRaidRestTimer = 0; - } else { - time_until_rest = RuleI(Character, RestRegenTimeToActivate) * 1000; - } - } - - rest_timer.Start(time_until_rest); + rest_timer.Start(m_pp.RestTimer * 1000); 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, (uint32)(time_until_rest / 1000)); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, m_pp.RestTimer); QueuePacket(outapp); safe_delete(outapp); } diff --git a/zone/client.h b/zone/client.h index f058ee180..7d0982fc2 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1074,7 +1074,7 @@ public: void ClearPendingAdventureData(); int GetAggroCount(); - void IncrementAggroCount(); + void IncrementAggroCount(bool raid_target = false); void DecrementAggroCount(); void SendPVPStats(); void SendDisciplineTimers(); @@ -1278,9 +1278,6 @@ public: int mod_food_value(const EQEmu::ItemData *item, int change); int mod_drink_value(const EQEmu::ItemData *item, int change); - void SetEngagedRaidTarget(bool value) { EngagedRaidTarget = value; } - bool GetEngagedRaidTarget() const { return EngagedRaidTarget; } - void ShowNumHits(); // work around function for numhits not showing on buffs void TripInterrogateInvState() { interrogateinv_flag = true; } @@ -1398,6 +1395,8 @@ private: void DoManaRegen(); void DoStaminaHungerUpdate(); void CalcRestState(); + // 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; } uint32 pLastUpdate; uint32 pLastUpdateWZ; @@ -1565,9 +1564,6 @@ private: float AreaManaRegen; float AreaEndRegen; - bool EngagedRaidTarget; - uint32 SavedRaidRestTimer; - std::set zone_flags; ClientTaskState *taskstate; diff --git a/zone/client_process.cpp b/zone/client_process.cpp index ce5e6d5c9..bd14dc70a 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -1933,12 +1933,11 @@ void Client::DoEnduranceUpkeep() { SetEndurUpkeep(false); } -void Client::CalcRestState() { - +void Client::CalcRestState() +{ // This method calculates rest state HP and mana regeneration. // The client must have been out of combat for RuleI(Character, RestRegenTimeToActivate) seconds, // must be sitting down, and must not have any detrimental spells affecting them. - // if(!RuleB(Character, RestRegenEnabled)) return; @@ -1950,6 +1949,9 @@ void Client::CalcRestState() { if(!rest_timer.Check(false)) return; + // so we don't have aggro, our timer has expired, we do not want this to cause issues + m_pp.RestTimer = 0; + uint32 buff_count = GetMaxTotalSlots(); for (unsigned int j = 0; j < buff_count; j++) { if(buffs[j].spellid != SPELL_UNKNOWN) { @@ -1960,7 +1962,6 @@ void Client::CalcRestState() { } ooc_regen = true; - } void Client::DoTracking() diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index 5af9da7d9..f02cbe6b6 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -207,9 +207,7 @@ void HateList::AddEntToHateList(Mob *in_entity, int32 in_hate, int32 in_damage, parse->EventNPC(EVENT_HATE_LIST, hate_owner->CastToNPC(), in_entity, "1", 0); if (in_entity->IsClient()) { - if (hate_owner->CastToNPC()->IsRaidTarget()) - in_entity->CastToClient()->SetEngagedRaidTarget(true); - in_entity->CastToClient()->IncrementAggroCount(); + in_entity->CastToClient()->IncrementAggroCount(hate_owner->CastToNPC()->IsRaidTarget()); } } }