diff --git a/zone/entity.cpp b/zone/entity.cpp index 6df61b95d..798e2704b 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -1595,7 +1595,7 @@ void EntityList::RefreshClientXTargets(Client *c) } void EntityList::QueueClientsByTarget(Mob *sender, const EQApplicationPacket *app, - bool iSendToSender, Mob *SkipThisMob, bool ackreq, bool HoTT, uint32 ClientVersionBits, bool inspect_buffs) + bool iSendToSender, Mob *SkipThisMob, bool ackreq, bool HoTT, uint32 ClientVersionBits, bool inspect_buffs, bool clear_target_window) { auto it = client_list.begin(); while (it != client_list.end()) { @@ -1611,7 +1611,7 @@ void EntityList::QueueClientsByTarget(Mob *sender, const EQApplicationPacket *ap TargetsTarget = Target->GetTarget(); - bool Send = false; + bool Send = clear_target_window; if (c == SkipThisMob) continue; @@ -1624,22 +1624,23 @@ void EntityList::QueueClientsByTarget(Mob *sender, const EQApplicationPacket *ap if (Target == sender) { if (inspect_buffs) { // if inspect_buffs is true we're sending a mob's buffs to those with the LAA if (c->GetGM() || RuleB(Spells, AlwaysSendTargetsBuffs)) { - Send = true; + Send = !clear_target_window; } else if (c->IsRaidGrouped()) { Raid *raid = c->GetRaid(); - if (!raid) - continue; - uint32 gid = raid->GetGroup(c); - if (gid > 11 || raid->GroupCount(gid) < 3) - continue; - if (raid->GetLeadershipAA(groupAAInspectBuffs, gid)) - Send = true; + if (raid) { + uint32 gid = raid->GetGroup(c); + if (gid < MAX_RAID_GROUPS && raid->GroupCount(gid) >= 3) { + if (raid->GetLeadershipAA(groupAAInspectBuffs, gid)) + Send = !clear_target_window; + } + } } else { Group *group = c->GetGroup(); - if (!group || group->GroupCount() < 3) - continue; - if (group->GetLeadershipAA(groupAAInspectBuffs)) - Send = true; + if (group && group->GroupCount() >= 3) { + if (group->GetLeadershipAA(groupAAInspectBuffs)) { + Send = !clear_target_window; + } + } } } else { Send = true; @@ -1649,8 +1650,9 @@ void EntityList::QueueClientsByTarget(Mob *sender, const EQApplicationPacket *ap } } - if (Send && (c->ClientVersionBit() & ClientVersionBits)) + if (Send && (c->ClientVersionBit() & ClientVersionBits)) { c->QueuePacket(app, ackreq); + } } } diff --git a/zone/entity.h b/zone/entity.h index 672a4f31f..27c749efb 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -413,8 +413,7 @@ public: void QueueClientsStatus(Mob* sender, const EQApplicationPacket* app, bool ignore_sender = false, uint8 minstatus = AccountStatus::Player, uint8 maxstatus = AccountStatus::Player); void QueueClientsGuild(Mob* sender, const EQApplicationPacket* app, bool ignore_sender = false, uint32 guildeqid = 0); void QueueClientsGuildBankItemUpdate(const GuildBankItemUpdate_Struct *gbius, uint32 GuildID); - void QueueClientsByTarget(Mob* sender, const EQApplicationPacket* app, bool iSendToSender = true, Mob* SkipThisMob = 0, bool ackreq = true, - bool HoTT = true, uint32 ClientVersionBits = 0xFFFFFFFF, bool inspect_buffs = false); + void QueueClientsByTarget(Mob* sender, const EQApplicationPacket* app, bool iSendToSender = true, Mob* SkipThisMob = 0, bool ackreq = true, bool HoTT = true, uint32 ClientVersionBits = 0xFFFFFFFF, bool inspect_buffs = false, bool clear_target_window = false); void QueueClientsByXTarget(Mob* sender, const EQApplicationPacket* app, bool iSendToSender = true, EQ::versions::ClientVersionBitmask client_version_bits = EQ::versions::ClientVersionBitmask::maskAllClients); void QueueToGroupsForNPCHealthAA(Mob* sender, const EQApplicationPacket* app); diff --git a/zone/mob.h b/zone/mob.h index d1673ea8e..9cae8ab59 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -457,7 +457,7 @@ public: virtual uint32 GetLastBuffSlot(bool disc, bool song); virtual void InitializeBuffSlots() { buffs = nullptr; } virtual void UninitializeBuffSlots() { } - EQApplicationPacket *MakeBuffsPacket(bool for_target = true); + EQApplicationPacket *MakeBuffsPacket(bool for_target = true, bool clear_buffs = false); void SendBuffsToClient(Client *c); inline Buffs_Struct* GetBuffs() { return buffs; } void DoGravityEffect(); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 9b3116942..488e20609 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -799,6 +799,12 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove SetPetType(petCharmed); + // This was done in AddBuff, but we were not a pet yet, so + // the target windows didn't get updated. + EQApplicationPacket *outapp = MakeBuffsPacket(); + entity_list.QueueClientsByTarget(this, outapp, false, nullptr, true, false, EQ::versions::maskSoDAndLater); + safe_delete(outapp); + if(caster->IsClient()){ auto app = new EQApplicationPacket(OP_Charm, sizeof(Charm_Struct)); Charm_Struct *ps = (Charm_Struct*)app->pBuffer; @@ -4355,6 +4361,15 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) { owner->SetPet(0); } + + // Any client that has a previous charmed pet targetted shouldo + // no longer see the buffs on the old pet. + // QueueClientsByTarget preserves GM and leadership cases. + + EQApplicationPacket *outapp = MakeBuffsPacket(true, true); + + entity_list.QueueClientsByTarget(this, outapp, false, nullptr, true, false, EQ::versions::maskSoDAndLater, true, true); + if (IsAIControlled()) { //Remove damage over time effects on charmed pet and those applied by charmed pet. diff --git a/zone/spells.cpp b/zone/spells.cpp index 872b3698a..07a40ffd9 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -6258,16 +6258,22 @@ void Mob::SendBuffsToClient(Client *c) } } -EQApplicationPacket *Mob::MakeBuffsPacket(bool for_target) +EQApplicationPacket *Mob::MakeBuffsPacket(bool for_target, bool clear_buffs) { uint32 count = 0; + uint32 buff_count; + // for self we want all buffs, for target, we want to skip song window buffs // since NPCs and pets don't have a song window, we still see it for them :P - uint32 buff_count = for_target ? GetMaxBuffSlots() : GetMaxTotalSlots(); - for(int i = 0; i < buff_count; ++i) - { - if (IsValidSpell(buffs[i].spellid)) - { + if (for_target) { + buff_count = (clear_buffs) ? 0 : GetMaxBuffSlots(); + } + else { + buff_count = GetMaxTotalSlots(); + } + + for(int i = 0; i < buff_count; ++i) { + if (IsValidSpell(buffs[i].spellid)) { ++count; } } @@ -6275,12 +6281,10 @@ EQApplicationPacket *Mob::MakeBuffsPacket(bool for_target) EQApplicationPacket* outapp = nullptr; //Create it for a targeting window, else create it for a create buff packet. - if(for_target) - { + if(for_target) { outapp = new EQApplicationPacket(OP_TargetBuffs, sizeof(BuffIcon_Struct) + sizeof(BuffIconEntry_Struct) * count); } - else - { + else { outapp = new EQApplicationPacket(OP_BuffCreate, sizeof(BuffIcon_Struct) + sizeof(BuffIconEntry_Struct) * count); } BuffIcon_Struct *buff = (BuffIcon_Struct*)outapp->pBuffer; @@ -6297,10 +6301,8 @@ EQApplicationPacket *Mob::MakeBuffsPacket(bool for_target) buff->name_lengths = 0; // hacky shit uint32 index = 0; - for(int i = 0; i < buff_count; ++i) - { - if (IsValidSpell(buffs[i].spellid)) - { + for(int i = 0; i < buff_count; ++i) { + if (IsValidSpell(buffs[i].spellid)) { buff->entries[index].buff_slot = i; buff->entries[index].spell_id = buffs[i].spellid; buff->entries[index].tics_remaining = buffs[i].ticsremaining;