[Spells] Fix to prevent Charmed Pets from continuing fight target if owner is dead. (#1600)

* Fix for charm break if pet owner dead

* fix, can't check hatelist it is already wiped.

* Update spell_effects.cpp
This commit is contained in:
KayenEQ 2021-10-16 00:22:07 -04:00 committed by GitHub
parent 5235dcee95
commit af5cfb9bed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 53 additions and 19 deletions

View File

@ -1684,11 +1684,17 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, EQ::skills::Skill
// #2: figure out things that affect the player dying and mark them dead // #2: figure out things that affect the player dying and mark them dead
InterruptSpell(); InterruptSpell();
Mob* m_pet = GetPet();
SetPet(0); SetPet(0);
SetHorseId(0); SetHorseId(0);
ShieldAbilityClearVariables(); ShieldAbilityClearVariables();
dead = true; dead = true;
if (m_pet && m_pet->IsCharmed()) {
m_pet->BuffFadeByEffect(SE_Charm);
}
if (GetMerc()) { if (GetMerc()) {
GetMerc()->Suspend(); GetMerc()->Suspend();
} }

View File

@ -4291,7 +4291,7 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses)
} }
SendAppearancePacket(AT_Pet, 0, true, true); SendAppearancePacket(AT_Pet, 0, true, true);
Mob* tempmob = GetOwner(); Mob* owner = GetOwner();
SetOwnerID(0); SetOwnerID(0);
SetPetType(petNone); SetPetType(petNone);
SetHeld(false); SetHeld(false);
@ -4300,25 +4300,27 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses)
SetFocused(false); SetFocused(false);
SetPetStop(false); SetPetStop(false);
SetPetRegroup(false); SetPetRegroup(false);
if(tempmob) if(owner)
{ {
tempmob->SetPet(0); owner->SetPet(0);
} }
if (IsAIControlled()) if (IsAIControlled())
{ {
// clear the hate list of the mobs //Remove damage over time effects on charmed pet and those applied by charmed pet.
if (RuleB(Spells, PreventFactionWarOnCharmBreak)) { if (RuleB(Spells, PreventFactionWarOnCharmBreak)) {
for (auto mob : hate_list.GetHateList()) { for (auto mob : hate_list.GetHateList()) {
auto tar = mob->entity_on_hatelist; auto tar = mob->entity_on_hatelist;
if (tar->IsCasting()) { if (tar) {
tar->InterruptSpell(tar->CastingSpellID()); if (tar->IsCasting()) {
} tar->InterruptSpell(tar->CastingSpellID());
uint32 buff_count = tar->GetMaxTotalSlots(); }
for (unsigned int j = 0; j < buff_count; j++) { uint32 buff_count = tar->GetMaxTotalSlots();
if (tar->GetBuffs()[j].spellid != SPELL_UNKNOWN) { for (unsigned int j = 0; j < buff_count; j++) {
auto spell = spells[tar->GetBuffs()[j].spellid]; if (IsValidSpell(tar->GetBuffs()[j].spellid)) {
if (spell.goodEffect == 0 && IsEffectInSpell(spell.id, SE_CurrentHP) && tar->GetBuffs()[j].casterid == GetID()) { auto spell = spells[tar->GetBuffs()[j].spellid];
tar->BuffFadeBySpellID(spell.id); if (spell.goodEffect == 0 && IsEffectInSpell(spell.id, SE_CurrentHP) && tar->GetBuffs()[j].casterid == GetID()) {
tar->BuffFadeBySpellID(spell.id);
}
} }
} }
} }
@ -4328,7 +4330,7 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses)
} }
uint32 buff_count = GetMaxTotalSlots(); uint32 buff_count = GetMaxTotalSlots();
for (unsigned int j = 0; j < buff_count; j++) { for (unsigned int j = 0; j < buff_count; j++) {
if (GetBuffs()[j].spellid != SPELL_UNKNOWN) { if (IsValidSpell(GetBuffs()[j].spellid )) {
auto spell = spells[this->GetBuffs()[j].spellid]; auto spell = spells[this->GetBuffs()[j].spellid];
if (spell.goodEffect == 0 && IsEffectInSpell(spell.id, SE_CurrentHP)) { if (spell.goodEffect == 0 && IsEffectInSpell(spell.id, SE_CurrentHP)) {
BuffFadeBySpellID(spell.id); BuffFadeBySpellID(spell.id);
@ -4336,17 +4338,43 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses)
} }
} }
} }
entity_list.ReplaceWithTarget(this, tempmob);
// clear the hate list of the mobs
entity_list.ReplaceWithTarget(this, owner);
WipeHateList(); WipeHateList();
if(tempmob) if (owner) {
AddToHateList(tempmob, 1, 0); AddToHateList(owner, 1, 0);
}
//If owner dead, briefly setting Immmune Aggro while hatelists wipe for both pet and targets is needed to ensure no reaggroing.
else if (IsNPC()){
bool immune_aggro = GetSpecialAbility(IMMUNE_AGGRO); //check if already immune aggro
SetSpecialAbility(IMMUNE_AGGRO, 1);
WipeHateList();
if (IsCasting()) {
InterruptSpell(CastingSpellID());
}
entity_list.RemoveFromHateLists(this);
//If NPC targeting charmed pet are in process of casting on it after it is removed from hatelist, stop the cast to prevent reaggroing.
Mob *current_npc = nullptr;
for (auto &it : entity_list.GetNPCList()) {
current_npc = it.second;
if (current_npc && current_npc->IsCasting() && current_npc->GetTarget() == this) {
current_npc->InterruptSpell(current_npc->CastingSpellID());
}
}
if (!immune_aggro) {
SetSpecialAbility(IMMUNE_AGGRO, 0);
}
}
SendAppearancePacket(AT_Anim, ANIM_STAND); SendAppearancePacket(AT_Anim, ANIM_STAND);
} }
if(tempmob && tempmob->IsClient()) if(owner && owner->IsClient())
{ {
auto app = new EQApplicationPacket(OP_Charm, sizeof(Charm_Struct)); auto app = new EQApplicationPacket(OP_Charm, sizeof(Charm_Struct));
Charm_Struct *ps = (Charm_Struct*)app->pBuffer; Charm_Struct *ps = (Charm_Struct*)app->pBuffer;
ps->owner_id = tempmob->GetID(); ps->owner_id = owner->GetID();
ps->pet_id = GetID(); ps->pet_id = GetID();
ps->command = 0; ps->command = 0;
entity_list.QueueClients(this, app); entity_list.QueueClients(this, app);