Core/Entities: Handle partial state change for pets (#22014)

* handle partial state change

* range-based for loop

* fixes

* readability

* break

(cherry picked from commit ae22fd6d74)
This commit is contained in:
DanVS
2018-11-04 10:42:46 +00:00
committed by Shauren
parent afac2b1742
commit 0585032c90
3 changed files with 76 additions and 37 deletions

View File

@@ -305,6 +305,28 @@ void Minion::RemoveFromWorld()
TempSummon::RemoveFromWorld();
}
void Minion::setDeathState(DeathState s)
{
Creature::setDeathState(s);
if (s != JUST_DIED || !IsGuardianPet())
return;
Unit* owner = GetOwner();
if (!owner || owner->GetTypeId() != TYPEID_PLAYER || owner->GetMinionGUID() != GetGUID())
return;
for (Unit* controlled : owner->m_Controlled)
{
if (controlled->GetEntry() == GetEntry() && controlled->IsAlive())
{
owner->SetMinionGUID(controlled->GetGUID());
owner->SetPetGUID(controlled->GetGUID());
owner->ToPlayer()->CharmSpellInitialize();
break;
}
}
}
bool Minion::IsGuardianPet() const
{
return IsPet() || (m_Properties && m_Properties->Control == SUMMON_CATEGORY_PET);

View File

@@ -73,6 +73,7 @@ class TC_GAME_API Minion : public TempSummon
Minion(SummonPropertiesEntry const* properties, Unit* owner, bool isWorldObject);
void InitStats(uint32 duration) override;
void RemoveFromWorld() override;
void setDeathState(DeathState s) override;
Unit* GetOwner() const { return m_owner; }
float GetFollowAngle() const override { return m_followAngle; }
void SetFollowAngle(float angle) { m_followAngle = angle; }

View File

@@ -480,6 +480,11 @@ void WorldSession::HandlePetSetAction(WorldPackets::Pet::PetSetAction& packet)
return;
}
std::vector<Unit*> pets;
for (Unit* controlled : _player->m_Controlled)
if (controlled->GetEntry() == pet->GetEntry() && controlled->IsAlive())
pets.push_back(controlled);
uint32 position = packet.Index;
uint32 actionData = packet.Action;
@@ -489,34 +494,37 @@ void WorldSession::HandlePetSetAction(WorldPackets::Pet::PetSetAction& packet)
TC_LOG_DEBUG("entities.pet", "Player %s has changed pet spell action. Position: %u, Spell: %u, State: 0x%X",
_player->GetName().c_str(), position, spell_id, uint32(act_state));
//if it's act for spell (en/disable/cast) and there is a spell given (0 = remove spell) which pet doesn't know, don't add
if (!((act_state == ACT_ENABLED || act_state == ACT_DISABLED || act_state == ACT_PASSIVE) && spell_id && !pet->HasSpell(spell_id)))
for (Unit* petControlled : pets)
{
if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id, pet->GetMap()->GetDifficultyID()))
//if it's act for spell (en/disable/cast) and there is a spell given (0 = remove spell) which pet doesn't know, don't add
if (!((act_state == ACT_ENABLED || act_state == ACT_DISABLED || act_state == ACT_PASSIVE) && spell_id && !petControlled->HasSpell(spell_id)))
{
//sign for autocast
if (act_state == ACT_ENABLED)
if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id, petControlled->GetMap()->GetDifficultyID()))
{
if (pet->GetTypeId() == TYPEID_UNIT && pet->IsPet())
((Pet*)pet)->ToggleAutocast(spellInfo, true);
else
for (Unit::ControlList::iterator itr = GetPlayer()->m_Controlled.begin(); itr != GetPlayer()->m_Controlled.end(); ++itr)
if ((*itr)->GetEntry() == pet->GetEntry())
(*itr)->GetCharmInfo()->ToggleCreatureAutocast(spellInfo, true);
//sign for autocast
if (act_state == ACT_ENABLED)
{
if (petControlled->GetTypeId() == TYPEID_UNIT && petControlled->IsPet())
((Pet*)petControlled)->ToggleAutocast(spellInfo, true);
else
for (Unit::ControlList::iterator itr = GetPlayer()->m_Controlled.begin(); itr != GetPlayer()->m_Controlled.end(); ++itr)
if ((*itr)->GetEntry() == petControlled->GetEntry())
(*itr)->GetCharmInfo()->ToggleCreatureAutocast(spellInfo, true);
}
//sign for no/turn off autocast
else if (act_state == ACT_DISABLED)
{
if (petControlled->GetTypeId() == TYPEID_UNIT && petControlled->IsPet())
((Pet*)petControlled)->ToggleAutocast(spellInfo, false);
else
for (Unit::ControlList::iterator itr = GetPlayer()->m_Controlled.begin(); itr != GetPlayer()->m_Controlled.end(); ++itr)
if ((*itr)->GetEntry() == petControlled->GetEntry())
(*itr)->GetCharmInfo()->ToggleCreatureAutocast(spellInfo, false);
}
}
//sign for no/turn off autocast
else if (act_state == ACT_DISABLED)
{
if (pet->GetTypeId() == TYPEID_UNIT && pet->IsPet())
((Pet*)pet)->ToggleAutocast(spellInfo, false);
else
for (Unit::ControlList::iterator itr = GetPlayer()->m_Controlled.begin(); itr != GetPlayer()->m_Controlled.end(); ++itr)
if ((*itr)->GetEntry() == pet->GetEntry())
(*itr)->GetCharmInfo()->ToggleCreatureAutocast(spellInfo, false);
}
}
charmInfo->SetActionBar(position, spell_id, ActiveStates(act_state));
charmInfo->SetActionBar(position, spell_id, ActiveStates(act_state));
}
}
}
@@ -630,23 +638,31 @@ void WorldSession::HandlePetSpellAutocastOpcode(WorldPackets::Pet::PetSpellAutoc
return;
}
// do not add not learned spells/ passive spells
if (!pet->HasSpell(packet.SpellID) || !spellInfo->IsAutocastable())
return;
std::vector<Unit*> pets;
for (Unit* controlled : _player->m_Controlled)
if (controlled->GetEntry() == pet->GetEntry() && controlled->IsAlive())
pets.push_back(controlled);
CharmInfo* charmInfo = pet->GetCharmInfo();
if (!charmInfo)
for (Unit* pet : pets)
{
TC_LOG_ERROR("entities.pet", "WorldSession::HandlePetSpellAutocastOpcode: object (%s) is considered pet-like but doesn't have a charminfo!", pet->GetGUID().ToString().c_str());
return;
// do not add not learned spells/ passive spells
if (!pet->HasSpell(packet.SpellID) || !spellInfo->IsAutocastable())
return;
CharmInfo* charmInfo = pet->GetCharmInfo();
if (!charmInfo)
{
TC_LOG_ERROR("entities.pet", "WorldSession::HandlePetSpellAutocastOpcode: object (%s) is considered pet-like but doesn't have a charminfo!", pet->GetGUID().ToString().c_str());
return;
}
if (pet->IsPet())
pet->ToPet()->ToggleAutocast(spellInfo, packet.AutocastEnabled);
else
charmInfo->ToggleCreatureAutocast(spellInfo, packet.AutocastEnabled);
charmInfo->SetSpellAutocast(spellInfo, packet.AutocastEnabled);
}
if (pet->IsPet())
pet->ToPet()->ToggleAutocast(spellInfo, packet.AutocastEnabled);
else
charmInfo->ToggleCreatureAutocast(spellInfo, packet.AutocastEnabled);
charmInfo->SetSpellAutocast(spellInfo, packet.AutocastEnabled);
}
void WorldSession::HandlePetCastSpellOpcode(WorldPackets::Spells::PetCastSpell& petCastSpell)