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())