From 855796448cb1405f8b1910132a172af4620d25d5 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 11 Jul 2017 17:54:46 -0500 Subject: [PATCH] Raid/Group/XTarget HP/Mana/Endurance updates now only send when percentage changes Raid/Group Mana/Endurance updates should now update real-time once again Fixed an issue with clients looking like they are 'skipping' when they are moving in view of another client Fixed an issue with NPC's who are ghosted in plain view of a client when they are not really there --- changelog.txt | 6 ++ zone/bot.cpp | 12 ++-- zone/client.cpp | 129 +++++++++++++++++++++++----------------- zone/client.h | 13 ++-- zone/client_mods.cpp | 16 ++--- zone/client_packet.cpp | 4 +- zone/client_process.cpp | 8 +-- zone/command.cpp | 2 +- zone/groups.cpp | 71 +++++++++++++++++----- zone/groups.h | 6 +- zone/merc.cpp | 10 ++-- zone/mob.cpp | 36 +++++++---- zone/mob.h | 10 ++-- zone/npc.cpp | 2 +- zone/perl_groups.cpp | 2 +- zone/raids.cpp | 104 ++++++++++++++++++++++++-------- zone/raids.h | 6 +- zone/worldserver.cpp | 2 +- 18 files changed, 289 insertions(+), 150 deletions(-) diff --git a/changelog.txt b/changelog.txt index 3ab8093cc..51011d64b 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,11 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 7/11/2017 == +Akkadius: Raid/Group/XTarget HP/Mana/Endurance updates now only send when percentage changes +Akkadius: Raid/Group Mana/Endurance updates should now update real-time once again +Akkadius: Fixed an issue with clients looking like they are 'skipping' when they are moving in view of another client +Akkadius: Fixed an issue with NPC's who are ghosted in plain view of a client when they are not really there + == 7/9/2017 == Akkadius: Fix HP update issues, rework logic for more accurate HP updates Akkadius: Massive reductions in unnecessary network traffic especially during high spam combat fights diff --git a/zone/bot.cpp b/zone/bot.cpp index fbed35a06..129cdb9b3 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -84,7 +84,7 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm GenerateBaseStats(); // Calculate HitPoints Last As It Uses Base Stats cur_hp = GenerateBaseHitPoints(); - cur_mana = GenerateBaseManaPoints(); + current_mana = GenerateBaseManaPoints(); cur_end = CalcBaseEndurance(); hp_regen = CalcHPRegen(); mana_regen = CalcManaRegen(); @@ -129,7 +129,7 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to _baseRace = npcTypeData.race; _baseGender = npcTypeData.gender; cur_hp = npcTypeData.cur_hp; - cur_mana = npcTypeData.Mana; + current_mana = npcTypeData.Mana; RestRegenHP = 0; RestRegenMana = 0; RestRegenEndurance = 0; @@ -206,8 +206,8 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to SpellOnTarget(756, this); // Rezz effects } - if(cur_mana > max_mana) - cur_mana = max_mana; + if(current_mana > max_mana) + current_mana = max_mana; cur_end = max_end; } @@ -5557,8 +5557,8 @@ int32 Bot::CalcMaxMana() { } } - if(cur_mana > max_mana) - cur_mana = max_mana; + if(current_mana > max_mana) + current_mana = max_mana; else if(max_mana < 0) max_mana = 0; diff --git a/zone/client.cpp b/zone/client.cpp index 986c2b582..0bcbb4ec2 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -161,8 +161,10 @@ Client::Client(EQStreamInterface* ieqs) npc_close_scan_timer(6000), hp_self_update_throttle_timer(500) { + for(int cf=0; cf < _FilterCount; cf++) ClientFilters[cf] = FilterShow; + character_id = 0; conn_state = NoPacketsReceived; client_data_loaded = false; @@ -191,7 +193,9 @@ Client::Client(EQStreamInterface* ieqs) strcpy(account_name, ""); tellsoff = false; last_reported_mana = 0; - last_reported_endur = 0; + last_reported_endurance = 0; + last_reported_endurance_percent = 0; + last_reported_mana_percent = 0; gmhideme = false; AFK = false; LFG = false; @@ -269,7 +273,7 @@ Client::Client(EQStreamInterface* ieqs) RestRegenMana = 0; RestRegenEndurance = 0; XPRate = 100; - cur_end = 0; + current_endurance = 0; m_TimeSinceLastPositionCheck = 0; m_DistanceSinceLastPositionCheck = 0.0f; @@ -287,7 +291,7 @@ Client::Client(EQStreamInterface* ieqs) HideCorpseMode = HideCorpseNone; PendingGuildInvitation = false; - cur_end = 0; + current_endurance = 0; InitializeBuffSlots(); @@ -599,8 +603,8 @@ bool Client::Save(uint8 iCommitNow) { m_pp.cur_hp = GetHP(); } - m_pp.mana = cur_mana; - m_pp.endurance = cur_end; + m_pp.mana = current_mana; + m_pp.endurance = current_endurance; /* Save Character Currency */ database.SaveCharacterCurrency(CharacterID(), &m_pp); @@ -1820,20 +1824,20 @@ const int32& Client::SetMana(int32 amount) { amount = 0; if (amount > GetMaxMana()) amount = GetMaxMana(); - if (amount != cur_mana) + if (amount != current_mana) update = true; - cur_mana = amount; + current_mana = amount; if (update) Mob::SetMana(amount); - SendManaUpdatePacket(); - return cur_mana; + CheckManaEndUpdate(); + return current_mana; } -void Client::SendManaUpdatePacket() { +void Client::CheckManaEndUpdate() { if (!Connected()) return; - if (last_reported_mana != cur_mana || last_reported_endur != cur_end) { + if (last_reported_mana != current_mana || last_reported_endurance != current_endurance) { if (ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { SendManaUpdate(); @@ -1841,46 +1845,65 @@ void Client::SendManaUpdatePacket() { } auto outapp = new EQApplicationPacket(OP_ManaChange, sizeof(ManaChange_Struct)); - ManaChange_Struct* manachange = (ManaChange_Struct*)outapp->pBuffer; - manachange->new_mana = cur_mana; - manachange->stamina = cur_end; - manachange->spell_id = casting_spell_id; - manachange->keepcasting = 1; + ManaChange_Struct* mana_change = (ManaChange_Struct*)outapp->pBuffer; + mana_change->new_mana = current_mana; + mana_change->stamina = current_endurance; + mana_change->spell_id = casting_spell_id; + mana_change->keepcasting = 1; outapp->priority = 6; QueuePacket(outapp); safe_delete(outapp); - Group *g = GetGroup(); + /* Let others know when our mana percent has changed */ + if (this->GetManaPercent() != last_reported_mana_percent) { + Group *group = this->GetGroup(); + Raid *raid = this->GetRaid(); - if(g) - { - outapp = new EQApplicationPacket(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct)); - auto outapp2 = - new EQApplicationPacket(OP_MobEnduranceUpdate, sizeof(MobEnduranceUpdate_Struct)); + if (raid) { + raid->SendManaPacketFrom(this); + } + else if (group) { + group->SendManaPacketFrom(this); + } - MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp->pBuffer; - MobEnduranceUpdate_Struct *meus = (MobEnduranceUpdate_Struct *)outapp2->pBuffer; + auto mana_packet = new EQApplicationPacket(OP_ManaUpdate, sizeof(ManaUpdate_Struct)); + ManaUpdate_Struct* mana_update = (ManaUpdate_Struct*)mana_packet->pBuffer; + mana_update->cur_mana = GetMana(); + mana_update->max_mana = GetMaxMana(); + mana_update->spawn_id = GetID(); + QueuePacket(mana_packet); + entity_list.QueueClientsByXTarget(this, mana_packet, false); + safe_delete(mana_packet); - mmus->spawn_id = meus->spawn_id = GetID(); - - mmus->mana = GetManaPercent(); - meus->endurance = GetEndurancePercent(); - - - for(int i = 0; i < MAX_GROUP_MEMBERS; ++i) - if (g->members[i] && g->members[i]->IsClient() && (g->members[i] != this) && (g->members[i]->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoD)) - { - g->members[i]->CastToClient()->QueuePacket(outapp); - g->members[i]->CastToClient()->QueuePacket(outapp2); - } - - safe_delete(outapp); - safe_delete(outapp2); + last_reported_mana_percent = this->GetManaPercent(); } + /* Let others know when our endurance percent has changed */ + if (this->GetEndurancePercent() != last_reported_endurance_percent) { + Group *group = this->GetGroup(); + Raid *raid = this->GetRaid(); - last_reported_mana = cur_mana; - last_reported_endur = cur_end; + if (raid) { + raid->SendEndurancePacketFrom(this); + } + else if (group) { + group->SendEndurancePacketFrom(this); + } + + auto endurance_packet = new EQApplicationPacket(OP_EnduranceUpdate, sizeof(EnduranceUpdate_Struct)); + EnduranceUpdate_Struct* endurance_update = (EnduranceUpdate_Struct*)endurance_packet->pBuffer; + endurance_update->cur_end = GetEndurance(); + endurance_update->max_end = GetMaxEndurance(); + endurance_update->spawn_id = GetID(); + QueuePacket(endurance_packet); + entity_list.QueueClientsByXTarget(this, endurance_packet, false); + safe_delete(endurance_packet); + + last_reported_endurance_percent = this->GetEndurancePercent(); + } + + last_reported_mana = current_mana; + last_reported_endurance = current_endurance; } } @@ -1888,12 +1911,11 @@ void Client::SendManaUpdatePacket() { void Client::SendManaUpdate() { auto mana_app = new EQApplicationPacket(OP_ManaUpdate, sizeof(ManaUpdate_Struct)); - ManaUpdate_Struct* mus = (ManaUpdate_Struct*)mana_app->pBuffer; - mus->cur_mana = GetMana(); - mus->max_mana = GetMaxMana(); - mus->spawn_id = GetID(); + ManaUpdate_Struct* mana_update = (ManaUpdate_Struct*)mana_app->pBuffer; + mana_update->cur_mana = GetMana(); + mana_update->max_mana = GetMaxMana(); + mana_update->spawn_id = GetID(); QueuePacket(mana_app); - entity_list.QueueClientsByXTarget(this, mana_app, false); safe_delete(mana_app); } @@ -1901,12 +1923,11 @@ void Client::SendManaUpdate() void Client::SendEnduranceUpdate() { auto end_app = new EQApplicationPacket(OP_EnduranceUpdate, sizeof(EnduranceUpdate_Struct)); - EnduranceUpdate_Struct* eus = (EnduranceUpdate_Struct*)end_app->pBuffer; - eus->cur_end = GetEndurance(); - eus->max_end = GetMaxEndurance(); - eus->spawn_id = GetID(); + EnduranceUpdate_Struct* endurance_update = (EnduranceUpdate_Struct*)end_app->pBuffer; + endurance_update->cur_end = GetEndurance(); + endurance_update->max_end = GetMaxEndurance(); + endurance_update->spawn_id = GetID(); QueuePacket(end_app); - entity_list.QueueClientsByXTarget(this, end_app, false); safe_delete(end_app); } @@ -3769,8 +3790,8 @@ void Client::SetEndurance(int32 newEnd) newEnd = GetMaxEndurance(); } - cur_end = newEnd; - SendManaUpdatePacket(); + current_endurance = newEnd; + CheckManaEndUpdate(); } void Client::SacrificeConfirm(Client *caster) @@ -4376,7 +4397,7 @@ bool Client::GroupFollow(Client* inviter) { } database.RefreshGroupFromDB(this); - group->SendHPPacketsTo(this); + group->SendHPManaEndPacketsTo(this); //send updates to clients out of zone... group->SendGroupJoinOOZ(this); return true; diff --git a/zone/client.h b/zone/client.h index 7bd02c46c..ff617f009 100644 --- a/zone/client.h +++ b/zone/client.h @@ -540,11 +540,11 @@ public: void CalcMaxEndurance(); //This calculates the maximum endurance we can have int32 CalcBaseEndurance(); //Calculates Base End int32 CalcEnduranceRegen(); //Calculates endurance regen used in DoEnduranceRegen() - int32 GetEndurance() const {return cur_end;} //This gets our current endurance + int32 GetEndurance() const {return current_endurance;} //This gets our current endurance int32 GetMaxEndurance() const {return max_end;} //This gets our endurance from the last CalcMaxEndurance() call int32 CalcEnduranceRegenCap(); int32 CalcHPRegenCap(); - inline uint8 GetEndurancePercent() { return (uint8)((float)cur_end / (float)max_end * 100.0f); } + inline uint8 GetEndurancePercent() { return (uint8)((float)current_endurance / (float)max_end * 100.0f); } void SetEndurance(int32 newEnd); //This sets the current endurance to the new value void DoEnduranceRegen(); //This Regenerates endurance void DoEnduranceUpkeep(); //does the endurance upkeep @@ -661,7 +661,7 @@ public: void RefreshGuildInfo(); - void SendManaUpdatePacket(); + void CheckManaEndUpdate(); void SendManaUpdate(); void SendEnduranceUpdate(); uint8 GetFace() const { return m_pp.face; } @@ -1411,7 +1411,7 @@ private: int Haste; //precalced value int32 max_end; - int32 cur_end; + int32 current_endurance; PlayerProfile_Struct m_pp; ExtendedProfile_Struct m_epp; @@ -1502,7 +1502,10 @@ private: bool tgb; bool instalog; int32 last_reported_mana; - int32 last_reported_endur; + int32 last_reported_endurance; + + int8 last_reported_mana_percent; + int8 last_reported_endurance_percent; unsigned int AggroCount; // How many mobs are aggro on us. diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index ad6a8e7a2..6db0437c5 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -1046,14 +1046,14 @@ int32 Client::CalcMaxMana() if (max_mana < 0) { max_mana = 0; } - if (cur_mana > max_mana) { - cur_mana = max_mana; + if (current_mana > max_mana) { + current_mana = max_mana; } int mana_perc_cap = spellbonuses.ManaPercCap[0]; if (mana_perc_cap) { int curMana_cap = (max_mana * mana_perc_cap) / 100; - if (cur_mana > curMana_cap || (spellbonuses.ManaPercCap[1] && cur_mana > spellbonuses.ManaPercCap[1])) { - cur_mana = curMana_cap; + if (current_mana > curMana_cap || (spellbonuses.ManaPercCap[1] && current_mana > spellbonuses.ManaPercCap[1])) { + current_mana = curMana_cap; } } Log(Logs::Detail, Logs::Spells, "Client::CalcMaxMana() called for %s - returning %d", GetName(), max_mana); @@ -2034,14 +2034,14 @@ void Client::CalcMaxEndurance() if (max_end < 0) { max_end = 0; } - if (cur_end > max_end) { - cur_end = max_end; + if (current_endurance > max_end) { + current_endurance = max_end; } int end_perc_cap = spellbonuses.EndPercCap[0]; if (end_perc_cap) { int curEnd_cap = (max_end * end_perc_cap) / 100; - if (cur_end > curEnd_cap || (spellbonuses.EndPercCap[1] && cur_end > spellbonuses.EndPercCap[1])) { - cur_end = curEnd_cap; + if (current_endurance > curEnd_cap || (spellbonuses.EndPercCap[1] && current_endurance > spellbonuses.EndPercCap[1])) { + current_endurance = curEnd_cap; } } } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index e4891b999..5e1bcc8ca 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -584,14 +584,14 @@ void Client::CompleteConnect() if (raid->IsLocked()) raid->SendRaidLockTo(this); - raid->SendHPPacketsTo(this); + raid->SendHPManaEndPacketsTo(this); } } else { Group *group = nullptr; group = this->GetGroup(); if (group) - group->SendHPPacketsTo(this); + group->SendHPManaEndPacketsTo(this); } diff --git a/zone/client_process.cpp b/zone/client_process.cpp index a346b7ce3..2bf1d5818 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -135,7 +135,7 @@ bool Client::Process() { SendHPUpdate(); if (mana_timer.Check()) - SendManaUpdatePacket(); + CheckManaEndUpdate(); if (dead && dead_timer.Check()) { database.MoveCharacterToZone(GetName(), database.GetZoneName(m_pp.binds[0].zoneId)); @@ -273,10 +273,10 @@ bool Client::Process() { } /* Clients need to be kept up to date for position updates more often otherwise they disappear */ - if (mob->IsClient() && this != mob && distance <= client_update_range) { + if (mob->IsClient() && this != mob && !mob->IsMoving() && distance <= client_update_range) { auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); PlayerPositionUpdateServer_Struct* spawn_update = (PlayerPositionUpdateServer_Struct*)app->pBuffer; - mob->MakeSpawnUpdateNoDelta(spawn_update); + mob->MakeSpawnUpdate(spawn_update); this->FastQueuePacket(&app, false); safe_delete(app); } @@ -1832,7 +1832,7 @@ void Client::DoManaRegen() { return; SetMana(GetMana() + CalcManaRegen() + RestRegenMana); - SendManaUpdatePacket(); + CheckManaEndUpdate(); } diff --git a/zone/command.cpp b/zone/command.cpp index b6c79e235..cbcdf6bb3 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -7197,7 +7197,7 @@ void command_ginfo(Client *c, const Seperator *sep) void command_hp(Client *c, const Seperator *sep) { c->SendHPUpdate(); - c->SendManaUpdatePacket(); + c->CheckManaEndUpdate(); } void command_aggro(Client *c, const Seperator *sep) diff --git a/zone/groups.cpp b/zone/groups.cpp index 28b4abd6a..c6fa6a978 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -341,7 +341,7 @@ bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 Characte Group* group = newmember->CastToClient()->GetGroup(); if (group) { - group->SendHPPacketsTo(newmember); + group->SendHPManaEndPacketsTo(newmember); group->SendHPPacketsFrom(newmember); } @@ -394,7 +394,7 @@ void Group::QueuePacket(const EQApplicationPacket *app, bool ack_req) // Sends the rest of the group's hps to member. this is useful when someone // first joins a group, but otherwise there shouldn't be a need to call it -void Group::SendHPPacketsTo(Mob *member) +void Group::SendHPManaEndPacketsTo(Mob *member) { if(member && member->IsClient()) { EQApplicationPacket hpapp; @@ -410,14 +410,14 @@ void Group::SendHPPacketsTo(Mob *member) if (member->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { outapp.SetOpcode(OP_MobManaUpdate); - MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp.pBuffer; - mmus->spawn_id = members[i]->GetID(); - mmus->mana = members[i]->GetManaPercent(); + MobManaUpdate_Struct *mana_update = (MobManaUpdate_Struct *)outapp.pBuffer; + mana_update->spawn_id = members[i]->GetID(); + mana_update->mana = members[i]->GetManaPercent(); member->CastToClient()->QueuePacket(&outapp, false); - MobEnduranceUpdate_Struct *meus = (MobEnduranceUpdate_Struct *)outapp.pBuffer; + MobEnduranceUpdate_Struct *endurance_update = (MobEnduranceUpdate_Struct *)outapp.pBuffer; outapp.SetOpcode(OP_MobEnduranceUpdate); - meus->endurance = members[i]->GetEndurancePercent(); + endurance_update->endurance = members[i]->GetEndurancePercent(); member->CastToClient()->QueuePacket(&outapp, false); } } @@ -436,19 +436,58 @@ void Group::SendHPPacketsFrom(Mob *member) uint32 i; for(i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(members[i] && members[i] != member && members[i]->IsClient()) - { + if(members[i] && members[i] != member && members[i]->IsClient()) { members[i]->CastToClient()->QueuePacket(&hp_app); - if (members[i]->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) - { + if (members[i]->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { outapp.SetOpcode(OP_MobManaUpdate); - MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp.pBuffer; - mmus->spawn_id = member->GetID(); - mmus->mana = member->GetManaPercent(); + MobManaUpdate_Struct *mana_update = (MobManaUpdate_Struct *)outapp.pBuffer; + mana_update->spawn_id = member->GetID(); + mana_update->mana = member->GetManaPercent(); members[i]->CastToClient()->QueuePacket(&outapp, false); - MobEnduranceUpdate_Struct *meus = (MobEnduranceUpdate_Struct *)outapp.pBuffer; + + MobEnduranceUpdate_Struct *endurance_update = (MobEnduranceUpdate_Struct *)outapp.pBuffer; outapp.SetOpcode(OP_MobEnduranceUpdate); - meus->endurance = member->GetEndurancePercent(); + endurance_update->endurance = member->GetEndurancePercent(); + members[i]->CastToClient()->QueuePacket(&outapp, false); + } + } + } +} + +void Group::SendManaPacketFrom(Mob *member) +{ + if (!member) + return; + EQApplicationPacket outapp(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct)); + + uint32 i; + for (i = 0; i < MAX_GROUP_MEMBERS; i++) { + if (members[i] && members[i] != member && members[i]->IsClient()) { + if (members[i]->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { + outapp.SetOpcode(OP_MobManaUpdate); + MobManaUpdate_Struct *mana_update = (MobManaUpdate_Struct *)outapp.pBuffer; + mana_update->spawn_id = member->GetID(); + mana_update->mana = member->GetManaPercent(); + members[i]->CastToClient()->QueuePacket(&outapp, false); + } + } + } +} + +void Group::SendEndurancePacketFrom(Mob* member) +{ + if (!member) + return; + + EQApplicationPacket outapp(OP_MobEnduranceUpdate, sizeof(MobManaUpdate_Struct)); + + uint32 i; + for (i = 0; i < MAX_GROUP_MEMBERS; i++) { + if (members[i] && members[i] != member && members[i]->IsClient()) { + if (members[i]->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { + MobEnduranceUpdate_Struct *endurance_update = (MobEnduranceUpdate_Struct *)outapp.pBuffer; + endurance_update->spawn_id = member->GetID(); + endurance_update->endurance = member->GetEndurancePercent(); members[i]->CastToClient()->QueuePacket(&outapp, false); } } diff --git a/zone/groups.h b/zone/groups.h index 6de364d93..79fb0d8b6 100644 --- a/zone/groups.h +++ b/zone/groups.h @@ -80,8 +80,10 @@ public: inline void SetLeader(Mob* newleader){ leader=newleader; }; inline Mob* GetLeader() { return leader; }; const char* GetLeaderName() { return membername[0]; }; - void SendHPPacketsTo(Mob* newmember); - void SendHPPacketsFrom(Mob* newmember); + void SendHPManaEndPacketsTo(Mob* newmember); + void SendHPPacketsFrom(Mob* member); + void SendManaPacketFrom(Mob* member); + void SendEndurancePacketFrom(Mob* member); bool UpdatePlayer(Mob* update); void MemberZoned(Mob* removemob); inline bool IsLeader(Mob* leadertest) { return leadertest==leader; }; diff --git a/zone/merc.cpp b/zone/merc.cpp index 90d287152..2b1ef7098 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -906,15 +906,15 @@ int32 Merc::CalcMaxMana() max_mana = 0; } - if (cur_mana > max_mana) { - cur_mana = max_mana; + if (current_mana > max_mana) { + current_mana = max_mana; } int mana_perc_cap = spellbonuses.ManaPercCap[0]; if(mana_perc_cap) { int curMana_cap = (max_mana * mana_perc_cap) / 100; - if (cur_mana > curMana_cap || (spellbonuses.ManaPercCap[1] && cur_mana > spellbonuses.ManaPercCap[1])) - cur_mana = curMana_cap; + if (current_mana > curMana_cap || (spellbonuses.ManaPercCap[1] && current_mana > spellbonuses.ManaPercCap[1])) + current_mana = curMana_cap; } #if EQDEBUG >= 11 @@ -4987,7 +4987,7 @@ void Merc::ScaleStats(int scalepercent, bool setmax) { max_mana = (int)((float)base_mana * scalerate); base_mana = max_mana; if (setmax) - cur_mana = max_mana; + current_mana = max_mana; } if (base_end) diff --git a/zone/mob.cpp b/zone/mob.cpp index 256fd7df7..eebb9798f 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -125,7 +125,7 @@ Mob::Mob(const char* in_name, last_z = 0; - + last_major_update_position = m_Position; AI_Init(); SetMoving(false); @@ -249,7 +249,7 @@ Mob::Mob(const char* in_name, bEnraged = false; shield_target = nullptr; - cur_mana = 0; + current_mana = 0; max_mana = 0; hp_regen = in_hp_regen; mana_regen = in_mana_regen; @@ -1357,24 +1357,24 @@ void Mob::SendHPUpdate(bool skip_self) last_hp_percent = current_hp_percent; } - EQApplicationPacket hp_app; + EQApplicationPacket hp_packet; Group *group = nullptr; - CreateHPPacket(&hp_app); + CreateHPPacket(&hp_packet); /* Update those who have use targeted */ - entity_list.QueueClientsByTarget(this, &hp_app, false, 0, false, true, EQEmu::versions::bit_AllClients); + entity_list.QueueClientsByTarget(this, &hp_packet, false, 0, false, true, EQEmu::versions::bit_AllClients); /* Update those who have us on x-target */ - entity_list.QueueClientsByXTarget(this, &hp_app, false); + entity_list.QueueClientsByXTarget(this, &hp_packet, false); /* Update groups using Group LAA health name tag counter */ - entity_list.QueueToGroupsForNPCHealthAA(this, &hp_app); + entity_list.QueueToGroupsForNPCHealthAA(this, &hp_packet); /* Update group */ if(IsGrouped()) { group = entity_list.GetGroupByMob(this); - if(group) //not sure why this might be null, but it happens + if(group) group->SendHPPacketsFrom(this); } @@ -1387,7 +1387,7 @@ void Mob::SendHPUpdate(bool skip_self) /* Pet - Update master - group and raid if exists */ if(GetOwner() && GetOwner()->IsClient()) { - GetOwner()->CastToClient()->QueuePacket(&hp_app, false); + GetOwner()->CastToClient()->QueuePacket(&hp_packet, false); group = entity_list.GetGroupByClient(GetOwner()->CastToClient()); if(group) @@ -1400,7 +1400,7 @@ void Mob::SendHPUpdate(bool skip_self) /* Send to pet */ if(GetPet() && GetPet()->IsClient()) { - GetPet()->CastToClient()->QueuePacket(&hp_app, false); + GetPet()->CastToClient()->QueuePacket(&hp_packet, false); } /* Destructible objects */ @@ -1439,10 +1439,20 @@ void Mob::SendHPUpdate(bool skip_self) // this one just warps the mob to the current location void Mob::SendPosition() { + auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)app->pBuffer; MakeSpawnUpdateNoDelta(spu); - entity_list.QueueCloseClients(this, app, true, RuleI(Range, MobPositionUpdates), nullptr, false); + + /* When an NPC has made a large distance change - we should update all clients to prevent "ghosts" */ + if (DistanceNoZ(last_major_update_position, m_Position) > 100) { + entity_list.QueueClients(this, app, true, true); + last_major_update_position = m_Position; + } + else { + entity_list.QueueCloseClients(this, app, true, RuleI(Range, MobPositionUpdates), nullptr, false); + } + safe_delete(app); } @@ -2270,13 +2280,13 @@ const int32& Mob::SetMana(int32 amount) { CalcMaxMana(); int32 mmana = GetMaxMana(); - cur_mana = amount < 0 ? 0 : (amount > mmana ? mmana : amount); + current_mana = amount < 0 ? 0 : (amount > mmana ? mmana : amount); /* if(IsClient()) LogFile->write(EQEMuLog::Debug, "Setting mana for %s to %d (%4.1f%%)", GetName(), amount, GetManaRatio()); */ - return cur_mana; + return current_mana; } diff --git a/zone/mob.h b/zone/mob.h index 27ea48d4f..5292aff00 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -466,14 +466,14 @@ public: inline int32 GetMaxHP() const { return max_hp; } virtual int32 CalcMaxHP(); inline int32 GetMaxMana() const { return max_mana; } - inline int32 GetMana() const { return cur_mana; } + inline int32 GetMana() const { return current_mana; } virtual int32 GetEndurance() const { return 0; } virtual void SetEndurance(int32 newEnd) { return; } int32 GetItemHPBonuses(); int32 GetSpellHPBonuses(); virtual const int32& SetMana(int32 amount); inline float GetManaRatio() const { return max_mana == 0 ? 100 : - ((static_cast(cur_mana) / max_mana) * 100); } + ((static_cast(current_mana) / max_mana) * 100); } virtual int32 CalcMaxMana(); uint32 GetNPCTypeID() const { return npctype_id; } void SetNPCTypeID(uint32 npctypeid) { npctype_id = npctypeid; } @@ -998,7 +998,7 @@ public: Timer GetAttackTimer() { return attack_timer; } Timer GetAttackDWTimer() { return attack_dw_timer; } inline bool IsFindable() { return findable; } - inline uint8 GetManaPercent() { return (uint8)((float)cur_mana / (float)max_mana * 100.0f); } + inline uint8 GetManaPercent() { return (uint8)((float)current_mana / (float)max_mana * 100.0f); } virtual uint8 GetEndurancePercent() { return 0; } inline virtual bool IsBlockedBuff(int16 SpellID) { return false; } @@ -1145,7 +1145,7 @@ protected: int32 cur_hp; int32 max_hp; int32 base_hp; - int32 cur_mana; + int32 current_mana; int32 max_mana; int32 hp_regen; int32 mana_regen; @@ -1184,6 +1184,8 @@ protected: uint8 orig_level; uint32 npctype_id; glm::vec4 m_Position; + /* Used to determine when an NPC has traversed so many units - to send a zone wide pos update */ + glm::vec4 last_major_update_position; uint16 animation; float base_size; float size; diff --git a/zone/npc.cpp b/zone/npc.cpp index 97dd647ec..8ddd9b2e3 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -1990,7 +1990,7 @@ void NPC::ModifyNPCStat(const char *identifier, const char *newValue) else if(id == "int" || id == "_int") { INT = atoi(val.c_str()); CalcMaxMana(); return; } else if(id == "cha") { CHA = atoi(val.c_str()); return; } else if(id == "max_hp") { base_hp = atoi(val.c_str()); CalcMaxHP(); if (cur_hp > max_hp) { cur_hp = max_hp; } return; } - else if(id == "max_mana") { npc_mana = atoi(val.c_str()); CalcMaxMana(); if (cur_mana > max_mana){ cur_mana = max_mana; } return; } + else if(id == "max_mana") { npc_mana = atoi(val.c_str()); CalcMaxMana(); if (current_mana > max_mana){ current_mana = max_mana; } return; } else if(id == "mr") { MR = atoi(val.c_str()); return; } else if(id == "fr") { FR = atoi(val.c_str()); return; } else if(id == "cr") { CR = atoi(val.c_str()); return; } diff --git a/zone/perl_groups.cpp b/zone/perl_groups.cpp index cdbffdd1c..e264b7d7a 100644 --- a/zone/perl_groups.cpp +++ b/zone/perl_groups.cpp @@ -389,7 +389,7 @@ XS(XS_Group_SendHPPacketsTo) if(newmember == nullptr) Perl_croak(aTHX_ "newmember is nullptr, avoiding crash."); - THIS->SendHPPacketsTo(newmember); + THIS->SendHPManaEndPacketsTo(newmember); } XSRETURN_EMPTY; } diff --git a/zone/raids.cpp b/zone/raids.cpp index d32ad4def..baf2d71b0 100644 --- a/zone/raids.cpp +++ b/zone/raids.cpp @@ -145,11 +145,11 @@ void Raid::AddMember(Client *c, uint32 group, bool rleader, bool groupleader, bo } } - Group *group_update = nullptr; - group_update = c->GetGroup(); - if (group_update) { - group_update->SendHPPacketsTo(c); - group_update->SendHPPacketsFrom(c); + Raid *raid_update = nullptr; + raid_update = c->GetRaid(); + if (raid_update) { + raid_update->SendHPManaEndPacketsTo(c); + raid_update->SendHPPacketsFrom(c); } auto pack = new ServerPacket(ServerOP_RaidAdd, sizeof(ServerRaidGeneralAction_Struct)); @@ -1546,7 +1546,7 @@ void Raid::MemberZoned(Client *c) group_mentor[gid].mentoree = nullptr; } -void Raid::SendHPPacketsTo(Client *client) +void Raid::SendHPManaEndPacketsTo(Client *client) { if(!client) return; @@ -1583,35 +1583,89 @@ void Raid::SendHPPacketsTo(Client *client) } } -void Raid::SendHPPacketsFrom(Mob *m) +void Raid::SendHPPacketsFrom(Mob *mob) { - if(!m) + if(!mob) return; - uint32 gid = 0; - if(m->IsClient()) - gid = this->GetGroup(m->CastToClient()); + uint32 group_id = 0; + + if(mob->IsClient()) + group_id = this->GetGroup(mob->CastToClient()); + EQApplicationPacket hpapp; EQApplicationPacket outapp(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct)); - m->CreateHPPacket(&hpapp); - for(int x = 0; x < MAX_RAID_MEMBERS; x++) - { - if(members[x].member) - { - if(!m->IsClient() || ((members[x].member != m->CastToClient()) && (members[x].GroupNumber == gid))) - { + mob->CreateHPPacket(&hpapp); + + for(int x = 0; x < MAX_RAID_MEMBERS; x++) { + if(members[x].member) { + if(!mob->IsClient() || ((members[x].member != mob->CastToClient()) && (members[x].GroupNumber == group_id))) { members[x].member->QueuePacket(&hpapp, false); - if (members[x].member->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) - { + if (members[x].member->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { outapp.SetOpcode(OP_MobManaUpdate); - MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp.pBuffer; - mmus->spawn_id = m->GetID(); - mmus->mana = m->GetManaPercent(); + MobManaUpdate_Struct *mana_update = (MobManaUpdate_Struct *)outapp.pBuffer; + mana_update->spawn_id = mob->GetID(); + mana_update->mana = mob->GetManaPercent(); members[x].member->QueuePacket(&outapp, false); + outapp.SetOpcode(OP_MobEnduranceUpdate); - MobEnduranceUpdate_Struct *meus = (MobEnduranceUpdate_Struct *)outapp.pBuffer; - meus->endurance = m->GetEndurancePercent(); + MobEnduranceUpdate_Struct *endurance_update = (MobEnduranceUpdate_Struct *)outapp.pBuffer; + endurance_update->endurance = mob->GetEndurancePercent(); + members[x].member->QueuePacket(&outapp, false); + } + } + } + } +} + +void Raid::SendManaPacketFrom(Mob *mob) +{ + if (!mob) + return; + + uint32 group_id = 0; + + if (mob->IsClient()) + group_id = this->GetGroup(mob->CastToClient()); + + EQApplicationPacket outapp(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct)); + + for (int x = 0; x < MAX_RAID_MEMBERS; x++) { + if (members[x].member) { + if (!mob->IsClient() || ((members[x].member != mob->CastToClient()) && (members[x].GroupNumber == group_id))) { + if (members[x].member->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { + outapp.SetOpcode(OP_MobManaUpdate); + MobManaUpdate_Struct *mana_update = (MobManaUpdate_Struct *)outapp.pBuffer; + mana_update->spawn_id = mob->GetID(); + mana_update->mana = mob->GetManaPercent(); + members[x].member->QueuePacket(&outapp, false); + } + } + } + } +} + +void Raid::SendEndurancePacketFrom(Mob *mob) +{ + if (!mob) + return; + + uint32 group_id = 0; + + if (mob->IsClient()) + group_id = this->GetGroup(mob->CastToClient()); + + EQApplicationPacket outapp(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct)); + + for (int x = 0; x < MAX_RAID_MEMBERS; x++) { + if (members[x].member) { + if (!mob->IsClient() || ((members[x].member != mob->CastToClient()) && (members[x].GroupNumber == group_id))) { + if (members[x].member->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { + outapp.SetOpcode(OP_MobEnduranceUpdate); + MobEnduranceUpdate_Struct *endurance_update = (MobEnduranceUpdate_Struct *)outapp.pBuffer; + endurance_update->spawn_id = mob->GetID(); + endurance_update->endurance = mob->GetEndurancePercent(); members[x].member->QueuePacket(&outapp, false); } } diff --git a/zone/raids.h b/zone/raids.h index 9e681153c..232a0057f 100644 --- a/zone/raids.h +++ b/zone/raids.h @@ -172,8 +172,10 @@ public: bool LearnMembers(); void VerifyRaid(); void MemberZoned(Client *c); - void SendHPPacketsTo(Client *c); - void SendHPPacketsFrom(Mob *m); + void SendHPManaEndPacketsTo(Client *c); + void SendHPPacketsFrom(Mob *mob); + void SendManaPacketFrom(Mob *mob); + void SendEndurancePacketFrom(Mob *mob); void RaidSay(const char *msg, Client *c); void RaidGroupSay(const char *msg, Client *c); diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 99f748d51..18730bb55 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -989,7 +989,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) } database.RefreshGroupFromDB(client); - group->SendHPPacketsTo(client); + group->SendHPManaEndPacketsTo(client); // If the group leader is not set, pull the group leader information from the database. if (!group->GetLeader())