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
This commit is contained in:
Akkadius 2017-07-11 17:54:46 -05:00
parent d47daa2857
commit 855796448c
18 changed files with 289 additions and 150 deletions

View File

@ -1,5 +1,11 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50) 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 == == 7/9/2017 ==
Akkadius: Fix HP update issues, rework logic for more accurate HP updates 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 Akkadius: Massive reductions in unnecessary network traffic especially during high spam combat fights

View File

@ -84,7 +84,7 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm
GenerateBaseStats(); GenerateBaseStats();
// Calculate HitPoints Last As It Uses Base Stats // Calculate HitPoints Last As It Uses Base Stats
cur_hp = GenerateBaseHitPoints(); cur_hp = GenerateBaseHitPoints();
cur_mana = GenerateBaseManaPoints(); current_mana = GenerateBaseManaPoints();
cur_end = CalcBaseEndurance(); cur_end = CalcBaseEndurance();
hp_regen = CalcHPRegen(); hp_regen = CalcHPRegen();
mana_regen = CalcManaRegen(); mana_regen = CalcManaRegen();
@ -129,7 +129,7 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to
_baseRace = npcTypeData.race; _baseRace = npcTypeData.race;
_baseGender = npcTypeData.gender; _baseGender = npcTypeData.gender;
cur_hp = npcTypeData.cur_hp; cur_hp = npcTypeData.cur_hp;
cur_mana = npcTypeData.Mana; current_mana = npcTypeData.Mana;
RestRegenHP = 0; RestRegenHP = 0;
RestRegenMana = 0; RestRegenMana = 0;
RestRegenEndurance = 0; RestRegenEndurance = 0;
@ -206,8 +206,8 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to
SpellOnTarget(756, this); // Rezz effects SpellOnTarget(756, this); // Rezz effects
} }
if(cur_mana > max_mana) if(current_mana > max_mana)
cur_mana = max_mana; current_mana = max_mana;
cur_end = max_end; cur_end = max_end;
} }
@ -5557,8 +5557,8 @@ int32 Bot::CalcMaxMana() {
} }
} }
if(cur_mana > max_mana) if(current_mana > max_mana)
cur_mana = max_mana; current_mana = max_mana;
else if(max_mana < 0) else if(max_mana < 0)
max_mana = 0; max_mana = 0;

View File

@ -161,8 +161,10 @@ Client::Client(EQStreamInterface* ieqs)
npc_close_scan_timer(6000), npc_close_scan_timer(6000),
hp_self_update_throttle_timer(500) hp_self_update_throttle_timer(500)
{ {
for(int cf=0; cf < _FilterCount; cf++) for(int cf=0; cf < _FilterCount; cf++)
ClientFilters[cf] = FilterShow; ClientFilters[cf] = FilterShow;
character_id = 0; character_id = 0;
conn_state = NoPacketsReceived; conn_state = NoPacketsReceived;
client_data_loaded = false; client_data_loaded = false;
@ -191,7 +193,9 @@ Client::Client(EQStreamInterface* ieqs)
strcpy(account_name, ""); strcpy(account_name, "");
tellsoff = false; tellsoff = false;
last_reported_mana = 0; last_reported_mana = 0;
last_reported_endur = 0; last_reported_endurance = 0;
last_reported_endurance_percent = 0;
last_reported_mana_percent = 0;
gmhideme = false; gmhideme = false;
AFK = false; AFK = false;
LFG = false; LFG = false;
@ -269,7 +273,7 @@ Client::Client(EQStreamInterface* ieqs)
RestRegenMana = 0; RestRegenMana = 0;
RestRegenEndurance = 0; RestRegenEndurance = 0;
XPRate = 100; XPRate = 100;
cur_end = 0; current_endurance = 0;
m_TimeSinceLastPositionCheck = 0; m_TimeSinceLastPositionCheck = 0;
m_DistanceSinceLastPositionCheck = 0.0f; m_DistanceSinceLastPositionCheck = 0.0f;
@ -287,7 +291,7 @@ Client::Client(EQStreamInterface* ieqs)
HideCorpseMode = HideCorpseNone; HideCorpseMode = HideCorpseNone;
PendingGuildInvitation = false; PendingGuildInvitation = false;
cur_end = 0; current_endurance = 0;
InitializeBuffSlots(); InitializeBuffSlots();
@ -599,8 +603,8 @@ bool Client::Save(uint8 iCommitNow) {
m_pp.cur_hp = GetHP(); m_pp.cur_hp = GetHP();
} }
m_pp.mana = cur_mana; m_pp.mana = current_mana;
m_pp.endurance = cur_end; m_pp.endurance = current_endurance;
/* Save Character Currency */ /* Save Character Currency */
database.SaveCharacterCurrency(CharacterID(), &m_pp); database.SaveCharacterCurrency(CharacterID(), &m_pp);
@ -1820,20 +1824,20 @@ const int32& Client::SetMana(int32 amount) {
amount = 0; amount = 0;
if (amount > GetMaxMana()) if (amount > GetMaxMana())
amount = GetMaxMana(); amount = GetMaxMana();
if (amount != cur_mana) if (amount != current_mana)
update = true; update = true;
cur_mana = amount; current_mana = amount;
if (update) if (update)
Mob::SetMana(amount); Mob::SetMana(amount);
SendManaUpdatePacket(); CheckManaEndUpdate();
return cur_mana; return current_mana;
} }
void Client::SendManaUpdatePacket() { void Client::CheckManaEndUpdate() {
if (!Connected()) if (!Connected())
return; 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) { if (ClientVersion() >= EQEmu::versions::ClientVersion::SoD) {
SendManaUpdate(); SendManaUpdate();
@ -1841,46 +1845,65 @@ void Client::SendManaUpdatePacket() {
} }
auto outapp = new EQApplicationPacket(OP_ManaChange, sizeof(ManaChange_Struct)); auto outapp = new EQApplicationPacket(OP_ManaChange, sizeof(ManaChange_Struct));
ManaChange_Struct* manachange = (ManaChange_Struct*)outapp->pBuffer; ManaChange_Struct* mana_change = (ManaChange_Struct*)outapp->pBuffer;
manachange->new_mana = cur_mana; mana_change->new_mana = current_mana;
manachange->stamina = cur_end; mana_change->stamina = current_endurance;
manachange->spell_id = casting_spell_id; mana_change->spell_id = casting_spell_id;
manachange->keepcasting = 1; mana_change->keepcasting = 1;
outapp->priority = 6; outapp->priority = 6;
QueuePacket(outapp); QueuePacket(outapp);
safe_delete(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) if (raid) {
{ raid->SendManaPacketFrom(this);
outapp = new EQApplicationPacket(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct)); }
auto outapp2 = else if (group) {
new EQApplicationPacket(OP_MobEnduranceUpdate, sizeof(MobEnduranceUpdate_Struct)); group->SendManaPacketFrom(this);
MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp->pBuffer;
MobEnduranceUpdate_Struct *meus = (MobEnduranceUpdate_Struct *)outapp2->pBuffer;
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); auto mana_packet = new EQApplicationPacket(OP_ManaUpdate, sizeof(ManaUpdate_Struct));
safe_delete(outapp2); 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);
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; if (raid) {
last_reported_endur = cur_end; 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() void Client::SendManaUpdate()
{ {
auto mana_app = new EQApplicationPacket(OP_ManaUpdate, sizeof(ManaUpdate_Struct)); auto mana_app = new EQApplicationPacket(OP_ManaUpdate, sizeof(ManaUpdate_Struct));
ManaUpdate_Struct* mus = (ManaUpdate_Struct*)mana_app->pBuffer; ManaUpdate_Struct* mana_update = (ManaUpdate_Struct*)mana_app->pBuffer;
mus->cur_mana = GetMana(); mana_update->cur_mana = GetMana();
mus->max_mana = GetMaxMana(); mana_update->max_mana = GetMaxMana();
mus->spawn_id = GetID(); mana_update->spawn_id = GetID();
QueuePacket(mana_app); QueuePacket(mana_app);
entity_list.QueueClientsByXTarget(this, mana_app, false);
safe_delete(mana_app); safe_delete(mana_app);
} }
@ -1901,12 +1923,11 @@ void Client::SendManaUpdate()
void Client::SendEnduranceUpdate() void Client::SendEnduranceUpdate()
{ {
auto end_app = new EQApplicationPacket(OP_EnduranceUpdate, sizeof(EnduranceUpdate_Struct)); auto end_app = new EQApplicationPacket(OP_EnduranceUpdate, sizeof(EnduranceUpdate_Struct));
EnduranceUpdate_Struct* eus = (EnduranceUpdate_Struct*)end_app->pBuffer; EnduranceUpdate_Struct* endurance_update = (EnduranceUpdate_Struct*)end_app->pBuffer;
eus->cur_end = GetEndurance(); endurance_update->cur_end = GetEndurance();
eus->max_end = GetMaxEndurance(); endurance_update->max_end = GetMaxEndurance();
eus->spawn_id = GetID(); endurance_update->spawn_id = GetID();
QueuePacket(end_app); QueuePacket(end_app);
entity_list.QueueClientsByXTarget(this, end_app, false);
safe_delete(end_app); safe_delete(end_app);
} }
@ -3769,8 +3790,8 @@ void Client::SetEndurance(int32 newEnd)
newEnd = GetMaxEndurance(); newEnd = GetMaxEndurance();
} }
cur_end = newEnd; current_endurance = newEnd;
SendManaUpdatePacket(); CheckManaEndUpdate();
} }
void Client::SacrificeConfirm(Client *caster) void Client::SacrificeConfirm(Client *caster)
@ -4376,7 +4397,7 @@ bool Client::GroupFollow(Client* inviter) {
} }
database.RefreshGroupFromDB(this); database.RefreshGroupFromDB(this);
group->SendHPPacketsTo(this); group->SendHPManaEndPacketsTo(this);
//send updates to clients out of zone... //send updates to clients out of zone...
group->SendGroupJoinOOZ(this); group->SendGroupJoinOOZ(this);
return true; return true;

View File

@ -540,11 +540,11 @@ public:
void CalcMaxEndurance(); //This calculates the maximum endurance we can have void CalcMaxEndurance(); //This calculates the maximum endurance we can have
int32 CalcBaseEndurance(); //Calculates Base End int32 CalcBaseEndurance(); //Calculates Base End
int32 CalcEnduranceRegen(); //Calculates endurance regen used in DoEnduranceRegen() 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 GetMaxEndurance() const {return max_end;} //This gets our endurance from the last CalcMaxEndurance() call
int32 CalcEnduranceRegenCap(); int32 CalcEnduranceRegenCap();
int32 CalcHPRegenCap(); 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 SetEndurance(int32 newEnd); //This sets the current endurance to the new value
void DoEnduranceRegen(); //This Regenerates endurance void DoEnduranceRegen(); //This Regenerates endurance
void DoEnduranceUpkeep(); //does the endurance upkeep void DoEnduranceUpkeep(); //does the endurance upkeep
@ -661,7 +661,7 @@ public:
void RefreshGuildInfo(); void RefreshGuildInfo();
void SendManaUpdatePacket(); void CheckManaEndUpdate();
void SendManaUpdate(); void SendManaUpdate();
void SendEnduranceUpdate(); void SendEnduranceUpdate();
uint8 GetFace() const { return m_pp.face; } uint8 GetFace() const { return m_pp.face; }
@ -1411,7 +1411,7 @@ private:
int Haste; //precalced value int Haste; //precalced value
int32 max_end; int32 max_end;
int32 cur_end; int32 current_endurance;
PlayerProfile_Struct m_pp; PlayerProfile_Struct m_pp;
ExtendedProfile_Struct m_epp; ExtendedProfile_Struct m_epp;
@ -1502,7 +1502,10 @@ private:
bool tgb; bool tgb;
bool instalog; bool instalog;
int32 last_reported_mana; 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. unsigned int AggroCount; // How many mobs are aggro on us.

View File

@ -1046,14 +1046,14 @@ int32 Client::CalcMaxMana()
if (max_mana < 0) { if (max_mana < 0) {
max_mana = 0; max_mana = 0;
} }
if (cur_mana > max_mana) { if (current_mana > max_mana) {
cur_mana = max_mana; current_mana = max_mana;
} }
int mana_perc_cap = spellbonuses.ManaPercCap[0]; int mana_perc_cap = spellbonuses.ManaPercCap[0];
if (mana_perc_cap) { if (mana_perc_cap) {
int curMana_cap = (max_mana * mana_perc_cap) / 100; int curMana_cap = (max_mana * mana_perc_cap) / 100;
if (cur_mana > curMana_cap || (spellbonuses.ManaPercCap[1] && cur_mana > spellbonuses.ManaPercCap[1])) { if (current_mana > curMana_cap || (spellbonuses.ManaPercCap[1] && current_mana > spellbonuses.ManaPercCap[1])) {
cur_mana = curMana_cap; current_mana = curMana_cap;
} }
} }
Log(Logs::Detail, Logs::Spells, "Client::CalcMaxMana() called for %s - returning %d", GetName(), max_mana); 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) { if (max_end < 0) {
max_end = 0; max_end = 0;
} }
if (cur_end > max_end) { if (current_endurance > max_end) {
cur_end = max_end; current_endurance = max_end;
} }
int end_perc_cap = spellbonuses.EndPercCap[0]; int end_perc_cap = spellbonuses.EndPercCap[0];
if (end_perc_cap) { if (end_perc_cap) {
int curEnd_cap = (max_end * end_perc_cap) / 100; int curEnd_cap = (max_end * end_perc_cap) / 100;
if (cur_end > curEnd_cap || (spellbonuses.EndPercCap[1] && cur_end > spellbonuses.EndPercCap[1])) { if (current_endurance > curEnd_cap || (spellbonuses.EndPercCap[1] && current_endurance > spellbonuses.EndPercCap[1])) {
cur_end = curEnd_cap; current_endurance = curEnd_cap;
} }
} }
} }

View File

@ -584,14 +584,14 @@ void Client::CompleteConnect()
if (raid->IsLocked()) if (raid->IsLocked())
raid->SendRaidLockTo(this); raid->SendRaidLockTo(this);
raid->SendHPPacketsTo(this); raid->SendHPManaEndPacketsTo(this);
} }
} }
else { else {
Group *group = nullptr; Group *group = nullptr;
group = this->GetGroup(); group = this->GetGroup();
if (group) if (group)
group->SendHPPacketsTo(this); group->SendHPManaEndPacketsTo(this);
} }

View File

@ -135,7 +135,7 @@ bool Client::Process() {
SendHPUpdate(); SendHPUpdate();
if (mana_timer.Check()) if (mana_timer.Check())
SendManaUpdatePacket(); CheckManaEndUpdate();
if (dead && dead_timer.Check()) { if (dead && dead_timer.Check()) {
database.MoveCharacterToZone(GetName(), database.GetZoneName(m_pp.binds[0].zoneId)); 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 */ /* 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)); auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
PlayerPositionUpdateServer_Struct* spawn_update = (PlayerPositionUpdateServer_Struct*)app->pBuffer; PlayerPositionUpdateServer_Struct* spawn_update = (PlayerPositionUpdateServer_Struct*)app->pBuffer;
mob->MakeSpawnUpdateNoDelta(spawn_update); mob->MakeSpawnUpdate(spawn_update);
this->FastQueuePacket(&app, false); this->FastQueuePacket(&app, false);
safe_delete(app); safe_delete(app);
} }
@ -1832,7 +1832,7 @@ void Client::DoManaRegen() {
return; return;
SetMana(GetMana() + CalcManaRegen() + RestRegenMana); SetMana(GetMana() + CalcManaRegen() + RestRegenMana);
SendManaUpdatePacket(); CheckManaEndUpdate();
} }

View File

@ -7197,7 +7197,7 @@ void command_ginfo(Client *c, const Seperator *sep)
void command_hp(Client *c, const Seperator *sep) void command_hp(Client *c, const Seperator *sep)
{ {
c->SendHPUpdate(); c->SendHPUpdate();
c->SendManaUpdatePacket(); c->CheckManaEndUpdate();
} }
void command_aggro(Client *c, const Seperator *sep) void command_aggro(Client *c, const Seperator *sep)

View File

@ -341,7 +341,7 @@ bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 Characte
Group* group = newmember->CastToClient()->GetGroup(); Group* group = newmember->CastToClient()->GetGroup();
if (group) { if (group) {
group->SendHPPacketsTo(newmember); group->SendHPManaEndPacketsTo(newmember);
group->SendHPPacketsFrom(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 // 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 // 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()) { if(member && member->IsClient()) {
EQApplicationPacket hpapp; EQApplicationPacket hpapp;
@ -410,14 +410,14 @@ void Group::SendHPPacketsTo(Mob *member)
if (member->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { if (member->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) {
outapp.SetOpcode(OP_MobManaUpdate); outapp.SetOpcode(OP_MobManaUpdate);
MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp.pBuffer; MobManaUpdate_Struct *mana_update = (MobManaUpdate_Struct *)outapp.pBuffer;
mmus->spawn_id = members[i]->GetID(); mana_update->spawn_id = members[i]->GetID();
mmus->mana = members[i]->GetManaPercent(); mana_update->mana = members[i]->GetManaPercent();
member->CastToClient()->QueuePacket(&outapp, false); member->CastToClient()->QueuePacket(&outapp, false);
MobEnduranceUpdate_Struct *meus = (MobEnduranceUpdate_Struct *)outapp.pBuffer; MobEnduranceUpdate_Struct *endurance_update = (MobEnduranceUpdate_Struct *)outapp.pBuffer;
outapp.SetOpcode(OP_MobEnduranceUpdate); outapp.SetOpcode(OP_MobEnduranceUpdate);
meus->endurance = members[i]->GetEndurancePercent(); endurance_update->endurance = members[i]->GetEndurancePercent();
member->CastToClient()->QueuePacket(&outapp, false); member->CastToClient()->QueuePacket(&outapp, false);
} }
} }
@ -436,19 +436,58 @@ void Group::SendHPPacketsFrom(Mob *member)
uint32 i; uint32 i;
for(i = 0; i < MAX_GROUP_MEMBERS; 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); 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); outapp.SetOpcode(OP_MobManaUpdate);
MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp.pBuffer; MobManaUpdate_Struct *mana_update = (MobManaUpdate_Struct *)outapp.pBuffer;
mmus->spawn_id = member->GetID(); mana_update->spawn_id = member->GetID();
mmus->mana = member->GetManaPercent(); mana_update->mana = member->GetManaPercent();
members[i]->CastToClient()->QueuePacket(&outapp, false); 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); 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); members[i]->CastToClient()->QueuePacket(&outapp, false);
} }
} }

View File

@ -80,8 +80,10 @@ public:
inline void SetLeader(Mob* newleader){ leader=newleader; }; inline void SetLeader(Mob* newleader){ leader=newleader; };
inline Mob* GetLeader() { return leader; }; inline Mob* GetLeader() { return leader; };
const char* GetLeaderName() { return membername[0]; }; const char* GetLeaderName() { return membername[0]; };
void SendHPPacketsTo(Mob* newmember); void SendHPManaEndPacketsTo(Mob* newmember);
void SendHPPacketsFrom(Mob* newmember); void SendHPPacketsFrom(Mob* member);
void SendManaPacketFrom(Mob* member);
void SendEndurancePacketFrom(Mob* member);
bool UpdatePlayer(Mob* update); bool UpdatePlayer(Mob* update);
void MemberZoned(Mob* removemob); void MemberZoned(Mob* removemob);
inline bool IsLeader(Mob* leadertest) { return leadertest==leader; }; inline bool IsLeader(Mob* leadertest) { return leadertest==leader; };

View File

@ -906,15 +906,15 @@ int32 Merc::CalcMaxMana()
max_mana = 0; max_mana = 0;
} }
if (cur_mana > max_mana) { if (current_mana > max_mana) {
cur_mana = max_mana; current_mana = max_mana;
} }
int mana_perc_cap = spellbonuses.ManaPercCap[0]; int mana_perc_cap = spellbonuses.ManaPercCap[0];
if(mana_perc_cap) { if(mana_perc_cap) {
int curMana_cap = (max_mana * mana_perc_cap) / 100; int curMana_cap = (max_mana * mana_perc_cap) / 100;
if (cur_mana > curMana_cap || (spellbonuses.ManaPercCap[1] && cur_mana > spellbonuses.ManaPercCap[1])) if (current_mana > curMana_cap || (spellbonuses.ManaPercCap[1] && current_mana > spellbonuses.ManaPercCap[1]))
cur_mana = curMana_cap; current_mana = curMana_cap;
} }
#if EQDEBUG >= 11 #if EQDEBUG >= 11
@ -4987,7 +4987,7 @@ void Merc::ScaleStats(int scalepercent, bool setmax) {
max_mana = (int)((float)base_mana * scalerate); max_mana = (int)((float)base_mana * scalerate);
base_mana = max_mana; base_mana = max_mana;
if (setmax) if (setmax)
cur_mana = max_mana; current_mana = max_mana;
} }
if (base_end) if (base_end)

View File

@ -125,7 +125,7 @@ Mob::Mob(const char* in_name,
last_z = 0; last_z = 0;
last_major_update_position = m_Position;
AI_Init(); AI_Init();
SetMoving(false); SetMoving(false);
@ -249,7 +249,7 @@ Mob::Mob(const char* in_name,
bEnraged = false; bEnraged = false;
shield_target = nullptr; shield_target = nullptr;
cur_mana = 0; current_mana = 0;
max_mana = 0; max_mana = 0;
hp_regen = in_hp_regen; hp_regen = in_hp_regen;
mana_regen = in_mana_regen; mana_regen = in_mana_regen;
@ -1357,24 +1357,24 @@ void Mob::SendHPUpdate(bool skip_self)
last_hp_percent = current_hp_percent; last_hp_percent = current_hp_percent;
} }
EQApplicationPacket hp_app; EQApplicationPacket hp_packet;
Group *group = nullptr; Group *group = nullptr;
CreateHPPacket(&hp_app); CreateHPPacket(&hp_packet);
/* Update those who have use targeted */ /* 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 */ /* 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 */ /* Update groups using Group LAA health name tag counter */
entity_list.QueueToGroupsForNPCHealthAA(this, &hp_app); entity_list.QueueToGroupsForNPCHealthAA(this, &hp_packet);
/* Update group */ /* Update group */
if(IsGrouped()) { if(IsGrouped()) {
group = entity_list.GetGroupByMob(this); group = entity_list.GetGroupByMob(this);
if(group) //not sure why this might be null, but it happens if(group)
group->SendHPPacketsFrom(this); group->SendHPPacketsFrom(this);
} }
@ -1387,7 +1387,7 @@ void Mob::SendHPUpdate(bool skip_self)
/* Pet - Update master - group and raid if exists */ /* Pet - Update master - group and raid if exists */
if(GetOwner() && GetOwner()->IsClient()) { if(GetOwner() && GetOwner()->IsClient()) {
GetOwner()->CastToClient()->QueuePacket(&hp_app, false); GetOwner()->CastToClient()->QueuePacket(&hp_packet, false);
group = entity_list.GetGroupByClient(GetOwner()->CastToClient()); group = entity_list.GetGroupByClient(GetOwner()->CastToClient());
if(group) if(group)
@ -1400,7 +1400,7 @@ void Mob::SendHPUpdate(bool skip_self)
/* Send to pet */ /* Send to pet */
if(GetPet() && GetPet()->IsClient()) { if(GetPet() && GetPet()->IsClient()) {
GetPet()->CastToClient()->QueuePacket(&hp_app, false); GetPet()->CastToClient()->QueuePacket(&hp_packet, false);
} }
/* Destructible objects */ /* Destructible objects */
@ -1439,10 +1439,20 @@ void Mob::SendHPUpdate(bool skip_self)
// this one just warps the mob to the current location // this one just warps the mob to the current location
void Mob::SendPosition() void Mob::SendPosition()
{ {
auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)app->pBuffer; PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)app->pBuffer;
MakeSpawnUpdateNoDelta(spu); MakeSpawnUpdateNoDelta(spu);
/* 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); entity_list.QueueCloseClients(this, app, true, RuleI(Range, MobPositionUpdates), nullptr, false);
}
safe_delete(app); safe_delete(app);
} }
@ -2270,13 +2280,13 @@ const int32& Mob::SetMana(int32 amount)
{ {
CalcMaxMana(); CalcMaxMana();
int32 mmana = GetMaxMana(); int32 mmana = GetMaxMana();
cur_mana = amount < 0 ? 0 : (amount > mmana ? mmana : amount); current_mana = amount < 0 ? 0 : (amount > mmana ? mmana : amount);
/* /*
if(IsClient()) if(IsClient())
LogFile->write(EQEMuLog::Debug, "Setting mana for %s to %d (%4.1f%%)", GetName(), amount, GetManaRatio()); LogFile->write(EQEMuLog::Debug, "Setting mana for %s to %d (%4.1f%%)", GetName(), amount, GetManaRatio());
*/ */
return cur_mana; return current_mana;
} }

View File

@ -466,14 +466,14 @@ public:
inline int32 GetMaxHP() const { return max_hp; } inline int32 GetMaxHP() const { return max_hp; }
virtual int32 CalcMaxHP(); virtual int32 CalcMaxHP();
inline int32 GetMaxMana() const { return max_mana; } 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 int32 GetEndurance() const { return 0; }
virtual void SetEndurance(int32 newEnd) { return; } virtual void SetEndurance(int32 newEnd) { return; }
int32 GetItemHPBonuses(); int32 GetItemHPBonuses();
int32 GetSpellHPBonuses(); int32 GetSpellHPBonuses();
virtual const int32& SetMana(int32 amount); virtual const int32& SetMana(int32 amount);
inline float GetManaRatio() const { return max_mana == 0 ? 100 : inline float GetManaRatio() const { return max_mana == 0 ? 100 :
((static_cast<float>(cur_mana) / max_mana) * 100); } ((static_cast<float>(current_mana) / max_mana) * 100); }
virtual int32 CalcMaxMana(); virtual int32 CalcMaxMana();
uint32 GetNPCTypeID() const { return npctype_id; } uint32 GetNPCTypeID() const { return npctype_id; }
void SetNPCTypeID(uint32 npctypeid) { npctype_id = npctypeid; } void SetNPCTypeID(uint32 npctypeid) { npctype_id = npctypeid; }
@ -998,7 +998,7 @@ public:
Timer GetAttackTimer() { return attack_timer; } Timer GetAttackTimer() { return attack_timer; }
Timer GetAttackDWTimer() { return attack_dw_timer; } Timer GetAttackDWTimer() { return attack_dw_timer; }
inline bool IsFindable() { return findable; } 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; } virtual uint8 GetEndurancePercent() { return 0; }
inline virtual bool IsBlockedBuff(int16 SpellID) { return false; } inline virtual bool IsBlockedBuff(int16 SpellID) { return false; }
@ -1145,7 +1145,7 @@ protected:
int32 cur_hp; int32 cur_hp;
int32 max_hp; int32 max_hp;
int32 base_hp; int32 base_hp;
int32 cur_mana; int32 current_mana;
int32 max_mana; int32 max_mana;
int32 hp_regen; int32 hp_regen;
int32 mana_regen; int32 mana_regen;
@ -1184,6 +1184,8 @@ protected:
uint8 orig_level; uint8 orig_level;
uint32 npctype_id; uint32 npctype_id;
glm::vec4 m_Position; 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; uint16 animation;
float base_size; float base_size;
float size; float size;

View File

@ -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 == "int" || id == "_int") { INT = atoi(val.c_str()); CalcMaxMana(); return; }
else if(id == "cha") { CHA = atoi(val.c_str()); 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_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 == "mr") { MR = atoi(val.c_str()); return; }
else if(id == "fr") { FR = 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; } else if(id == "cr") { CR = atoi(val.c_str()); return; }

View File

@ -389,7 +389,7 @@ XS(XS_Group_SendHPPacketsTo)
if(newmember == nullptr) if(newmember == nullptr)
Perl_croak(aTHX_ "newmember is nullptr, avoiding crash."); Perl_croak(aTHX_ "newmember is nullptr, avoiding crash.");
THIS->SendHPPacketsTo(newmember); THIS->SendHPManaEndPacketsTo(newmember);
} }
XSRETURN_EMPTY; XSRETURN_EMPTY;
} }

View File

@ -145,11 +145,11 @@ void Raid::AddMember(Client *c, uint32 group, bool rleader, bool groupleader, bo
} }
} }
Group *group_update = nullptr; Raid *raid_update = nullptr;
group_update = c->GetGroup(); raid_update = c->GetRaid();
if (group_update) { if (raid_update) {
group_update->SendHPPacketsTo(c); raid_update->SendHPManaEndPacketsTo(c);
group_update->SendHPPacketsFrom(c); raid_update->SendHPPacketsFrom(c);
} }
auto pack = new ServerPacket(ServerOP_RaidAdd, sizeof(ServerRaidGeneralAction_Struct)); auto pack = new ServerPacket(ServerOP_RaidAdd, sizeof(ServerRaidGeneralAction_Struct));
@ -1546,7 +1546,7 @@ void Raid::MemberZoned(Client *c)
group_mentor[gid].mentoree = nullptr; group_mentor[gid].mentoree = nullptr;
} }
void Raid::SendHPPacketsTo(Client *client) void Raid::SendHPManaEndPacketsTo(Client *client)
{ {
if(!client) if(!client)
return; 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; return;
uint32 gid = 0; uint32 group_id = 0;
if(m->IsClient())
gid = this->GetGroup(m->CastToClient()); if(mob->IsClient())
group_id = this->GetGroup(mob->CastToClient());
EQApplicationPacket hpapp; EQApplicationPacket hpapp;
EQApplicationPacket outapp(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct)); EQApplicationPacket outapp(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct));
m->CreateHPPacket(&hpapp); mob->CreateHPPacket(&hpapp);
for(int x = 0; x < MAX_RAID_MEMBERS; x++)
{ for(int x = 0; x < MAX_RAID_MEMBERS; x++) {
if(members[x].member) if(members[x].member) {
{ if(!mob->IsClient() || ((members[x].member != mob->CastToClient()) && (members[x].GroupNumber == group_id))) {
if(!m->IsClient() || ((members[x].member != m->CastToClient()) && (members[x].GroupNumber == gid)))
{
members[x].member->QueuePacket(&hpapp, false); 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); outapp.SetOpcode(OP_MobManaUpdate);
MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp.pBuffer; MobManaUpdate_Struct *mana_update = (MobManaUpdate_Struct *)outapp.pBuffer;
mmus->spawn_id = m->GetID(); mana_update->spawn_id = mob->GetID();
mmus->mana = m->GetManaPercent(); mana_update->mana = mob->GetManaPercent();
members[x].member->QueuePacket(&outapp, false); members[x].member->QueuePacket(&outapp, false);
outapp.SetOpcode(OP_MobEnduranceUpdate); outapp.SetOpcode(OP_MobEnduranceUpdate);
MobEnduranceUpdate_Struct *meus = (MobEnduranceUpdate_Struct *)outapp.pBuffer; MobEnduranceUpdate_Struct *endurance_update = (MobEnduranceUpdate_Struct *)outapp.pBuffer;
meus->endurance = m->GetEndurancePercent(); 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); members[x].member->QueuePacket(&outapp, false);
} }
} }

View File

@ -172,8 +172,10 @@ public:
bool LearnMembers(); bool LearnMembers();
void VerifyRaid(); void VerifyRaid();
void MemberZoned(Client *c); void MemberZoned(Client *c);
void SendHPPacketsTo(Client *c); void SendHPManaEndPacketsTo(Client *c);
void SendHPPacketsFrom(Mob *m); void SendHPPacketsFrom(Mob *mob);
void SendManaPacketFrom(Mob *mob);
void SendEndurancePacketFrom(Mob *mob);
void RaidSay(const char *msg, Client *c); void RaidSay(const char *msg, Client *c);
void RaidGroupSay(const char *msg, Client *c); void RaidGroupSay(const char *msg, Client *c);

View File

@ -989,7 +989,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
} }
database.RefreshGroupFromDB(client); 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 the group leader is not set, pull the group leader information from the database.
if (!group->GetLeader()) if (!group->GetLeader())