Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions src/server/game/Entities/Creature/TemporarySummon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ void TempSummon::UnSummon(uint32 msTime)
return;
}

if (WorldObject * owner = GetSummoner())
if (WorldObject* owner = GetSummoner())
{
if (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->IsAIEnabled())
owner->ToCreature()->AI()->SummonedCreatureDespawn(this);
Expand Down Expand Up @@ -354,8 +354,7 @@ std::string TempSummon::GetDebugInfo() const
return sstr.str();
}

Minion::Minion(SummonPropertiesEntry const* properties, Unit* owner, bool isWorldObject)
: TempSummon(properties, owner, isWorldObject), m_owner(owner)
Minion::Minion(SummonPropertiesEntry const* properties, Unit* owner, bool isWorldObject) : TempSummon(properties, owner, isWorldObject), m_owner(owner)
{
ASSERT(m_owner);
m_unitTypeMask |= UNIT_MASK_MINION;
Expand All @@ -379,7 +378,9 @@ void Minion::RemoveFromWorld()
if (!IsInWorld())
return;

GetOwner()->SetMinion(this, false);
if (GetOwner())
GetOwner()->SetMinion(this, false);

TempSummon::RemoveFromWorld();
}

Expand Down Expand Up @@ -419,8 +420,7 @@ std::string Minion::GetDebugInfo() const
return sstr.str();
}

Guardian::Guardian(SummonPropertiesEntry const* properties, Unit* owner, bool isWorldObject) : Minion(properties, owner, isWorldObject)
, m_bonusSpellDamage(0)
Guardian::Guardian(SummonPropertiesEntry const* properties, Unit* owner, bool isWorldObject) : Minion(properties, owner, isWorldObject), m_bonusSpellDamage(0)
{
memset(m_statFromOwner, 0, sizeof(float)*MAX_STATS);
m_unitTypeMask |= UNIT_MASK_GUARDIAN;
Expand Down Expand Up @@ -462,8 +462,7 @@ std::string Guardian::GetDebugInfo() const
return sstr.str();
}

Puppet::Puppet(SummonPropertiesEntry const* properties, Unit* owner)
: Minion(properties, owner, false) //maybe true?
Puppet::Puppet(SummonPropertiesEntry const* properties, Unit* owner) : Minion(properties, owner, false) //maybe true?
{
ASSERT(m_owner->GetTypeId() == TYPEID_PLAYER);
m_unitTypeMask |= UNIT_MASK_PUPPET;
Expand Down
1 change: 1 addition & 0 deletions src/server/game/Entities/Creature/TemporarySummon.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class TC_GAME_API TempSummon : public Creature
ObjectGuid GetSummonerGUID() const { return m_summonerGUID; }
TempSummonType GetSummonType() const { return m_type; }
uint32 GetTimer() const { return m_timer; }
void SetTimer(uint32 timer) { m_timer = timer; m_lifetime = timer; }
bool CanFollowOwner() const { return m_canFollowOwner; }
void SetCanFollowOwner(bool can) { m_canFollowOwner = can; }
bool IsFollowerDespawnActive() const { return _followerDespawnActive; }
Expand Down
58 changes: 44 additions & 14 deletions src/server/game/Entities/Unit/Unit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6251,28 +6251,44 @@ Unit* Unit::GetFirstControlled() const
return unit;
}

void Unit::RemoveAllControlled()
void Unit::RemoveAllControlled(bool onDeath/* = false*/)
{
// possessed pet and vehicle
if (GetTypeId() == TYPEID_PLAYER)
ToPlayer()->StopCastingCharm();

while (!m_Controlled.empty())
bool exception = false;
for (auto itr = m_Controlled.begin(); itr != m_Controlled.end();)
{
Unit* target = *m_Controlled.begin();
m_Controlled.erase(m_Controlled.begin());
Unit* target = *itr;
itr = m_Controlled.erase(itr);
if (target->GetCharmerGUID() == GetGUID())
target->RemoveCharmAuras();
else if (target->GetOwnerGUID() == GetGUID() && target->IsSummon())
target->ToTempSummon()->UnSummon();
{
TempSummon* summon = target->ToTempSummon();
if (onDeath && GetTypeId() == TYPEID_UNIT && summon->HasUnitTypeMask(UNIT_MASK_GUARDIAN | UNIT_MASK_MINION) && TempSummon::ShouldFollowOnSpawn(summon->m_Properties))
{
if (summon->IsInCombat() && summon->CanHaveThreatList() && summon->GetCombatManager().HasPvECombatWithPlayers())
{
summon->SetTimer(1000);
summon->SetTempSummonType(TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT);
exception = true;
}
else
summon->UnSummon();
}
else
summon->UnSummon();
}
else
TC_LOG_ERROR("entities.unit", "Unit {} is trying to release unit {} which is neither charmed nor owned by it", GetEntry(), target->GetEntry());
}
if (!GetPetGUID().IsEmpty())
if (!exception && !GetPetGUID().IsEmpty())
TC_LOG_FATAL("entities.unit", "Unit {} is not able to release its pet {}", GetEntry(), GetPetGUID().ToString());
if (!GetMinionGUID().IsEmpty())
if (!exception && !GetMinionGUID().IsEmpty())
TC_LOG_FATAL("entities.unit", "Unit {} is not able to release its minion {}", GetEntry(), GetMinionGUID().ToString());
if (!GetCharmedGUID().IsEmpty())
if (!exception && !GetCharmedGUID().IsEmpty())
TC_LOG_FATAL("entities.unit", "Unit {} is not able to release its charm {}", GetEntry(), GetCharmedGUID().ToString());
if (!IsPet()) // pets don't use the flag for this
RemoveUnitFlag(UNIT_FLAG_PET_IN_COMBAT); // m_controlled is now empty, so we know none of our minions are in combat
Expand Down Expand Up @@ -6390,16 +6406,30 @@ void Unit::RemoveCharmAuras()
RemoveAurasByType(SPELL_AURA_AOE_CHARM);
}

void Unit::UnsummonAllTotems()
void Unit::UnsummonAllTotems(bool onDeath/* = false*/)
{
for (uint8 i = 0; i < MAX_SUMMON_SLOT; ++i)
{
if (!m_SummonSlot[i])
continue;

if (Creature* OldTotem = GetMap()->GetCreature(m_SummonSlot[i]))
if (OldTotem->IsSummon())
OldTotem->ToTempSummon()->UnSummon();
if (Creature* summonCreature = GetMap()->GetCreature(m_SummonSlot[i]))
if (summonCreature->IsSummon())
{
TempSummon* summon = summonCreature->ToTempSummon();
if (onDeath && GetTypeId() == TYPEID_UNIT && i == SUMMON_SLOT_PET && summon->HasUnitTypeMask(UNIT_MASK_GUARDIAN | UNIT_MASK_MINION) && TempSummon::ShouldFollowOnSpawn(summon->m_Properties))
{
if (summon->IsInCombat() && summon->CanHaveThreatList() && summon->GetCombatManager().HasPvECombatWithPlayers())
{
summon->SetTimer(1000);
summon->SetTempSummonType(TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT);
}
else
summon->UnSummon();
}
else
summon->UnSummon();
}
}
}

Expand Down Expand Up @@ -8744,8 +8774,8 @@ void Unit::setDeathState(DeathState s)
ExitVehicle(); // Exit vehicle before calling RemoveAllControlled
// vehicles use special type of charm that is not removed by the next function
// triggering an assert
UnsummonAllTotems();
RemoveAllControlled();
UnsummonAllTotems(true);
RemoveAllControlled(true);
RemoveAllAurasOnDeath();
}

Expand Down
4 changes: 2 additions & 2 deletions src/server/game/Entities/Unit/Unit.h
Original file line number Diff line number Diff line change
Expand Up @@ -1279,7 +1279,7 @@ class TC_GAME_API Unit : public WorldObject

ControlList m_Controlled;
Unit* GetFirstControlled() const;
void RemoveAllControlled();
void RemoveAllControlled(bool onDeath = false);

bool IsCharmed() const { return !GetCharmerGUID().IsEmpty(); }
bool IsCharming() const { return !GetCharmedGUID().IsEmpty(); }
Expand Down Expand Up @@ -1609,7 +1609,7 @@ class TC_GAME_API Unit : public WorldObject
void ModifyAuraState(AuraStateType flag, bool apply);
uint32 BuildAuraStateUpdateForTarget(Unit const* target) const;
bool HasAuraState(AuraStateType flag, SpellInfo const* spellProto = nullptr, Unit const* Caster = nullptr) const;
void UnsummonAllTotems();
void UnsummonAllTotems(bool onDeath = false);
bool IsMagnet() const;
Unit* GetMeleeHitRedirectTarget(Unit* victim, SpellInfo const* spellInfo = nullptr);

Expand Down