Core/Creatures: Allow summons to be initialized properly when summoner is not in world yet

This commit is contained in:
Shauren
2023-05-27 18:43:43 +02:00
parent 3d3e94d8e4
commit 7881f0ef5f
6 changed files with 46 additions and 50 deletions

View File

@@ -179,7 +179,7 @@ void TempSummon::Update(uint32 diff)
}
}
void TempSummon::InitStats(uint32 duration)
void TempSummon::InitStats(WorldObject* summoner, uint32 duration)
{
ASSERT(!IsPet());
@@ -189,14 +189,11 @@ void TempSummon::InitStats(uint32 duration)
if (m_type == TEMPSUMMON_MANUAL_DESPAWN)
m_type = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN;
Unit* owner = GetSummonerUnit();
if (owner && IsTrigger() && m_spells[0])
if (owner->GetTypeId() == TYPEID_PLAYER)
if (summoner && summoner->IsPlayer())
{
if (IsTrigger() && m_spells[0])
m_ControlledByPlayer = true;
if (owner && owner->IsPlayer())
{
if (CreatureSummonedData const* summonedData = sObjectMgr->GetCreatureSummonedData(GetEntry()))
{
m_creatureIdVisibleToSummoner = summonedData->CreatureIDVisibleToSummoner;
@@ -211,27 +208,27 @@ void TempSummon::InitStats(uint32 duration)
if (!m_Properties)
return;
if (owner)
if (Unit* unitSummoner = ToUnit(summoner))
{
int32 slot = m_Properties->Slot;
if (slot > 0)
{
if (!owner->m_SummonSlot[slot].IsEmpty() && owner->m_SummonSlot[slot] != GetGUID())
if (!unitSummoner->m_SummonSlot[slot].IsEmpty() && unitSummoner->m_SummonSlot[slot] != GetGUID())
{
Creature* oldSummon = GetMap()->GetCreature(owner->m_SummonSlot[slot]);
Creature* oldSummon = GetMap()->GetCreature(unitSummoner->m_SummonSlot[slot]);
if (oldSummon && oldSummon->IsSummon())
oldSummon->ToTempSummon()->UnSummon();
}
owner->m_SummonSlot[slot] = GetGUID();
unitSummoner->m_SummonSlot[slot] = GetGUID();
}
if (!m_Properties->GetFlags().HasFlag(SummonPropertiesFlags::UseCreatureLevel))
SetLevel(owner->GetLevel());
SetLevel(unitSummoner->GetLevel());
}
uint32 faction = m_Properties->Faction;
if (owner && m_Properties->GetFlags().HasFlag(SummonPropertiesFlags::UseSummonerFaction)) // TODO: Determine priority between faction and flag
faction = owner->GetFaction();
if (summoner && m_Properties->GetFlags().HasFlag(SummonPropertiesFlags::UseSummonerFaction)) // TODO: Determine priority between faction and flag
faction = summoner->GetFaction();
if (faction)
SetFaction(faction);
@@ -240,23 +237,22 @@ void TempSummon::InitStats(uint32 duration)
RemoveNpcFlag(UNIT_NPC_FLAG_WILD_BATTLE_PET);
}
void TempSummon::InitSummon()
void TempSummon::InitSummon(WorldObject* summoner)
{
WorldObject* owner = GetSummoner();
if (owner)
if (summoner)
{
if (owner->GetTypeId() == TYPEID_UNIT)
if (summoner->GetTypeId() == TYPEID_UNIT)
{
if (owner->ToCreature()->IsAIEnabled())
owner->ToCreature()->AI()->JustSummoned(this);
if (summoner->ToCreature()->IsAIEnabled())
summoner->ToCreature()->AI()->JustSummoned(this);
}
else if (owner->GetTypeId() == TYPEID_GAMEOBJECT)
else if (summoner->GetTypeId() == TYPEID_GAMEOBJECT)
{
if (owner->ToGameObject()->AI())
owner->ToGameObject()->AI()->JustSummoned(this);
if (summoner->ToGameObject()->AI())
summoner->ToGameObject()->AI()->JustSummoned(this);
}
if (IsAIEnabled())
AI()->IsSummonedBy(owner);
AI()->IsSummonedBy(summoner);
}
}
@@ -387,9 +383,9 @@ Minion::Minion(SummonPropertiesEntry const* properties, Unit* owner, bool isWorl
InitCharmInfo();
}
void Minion::InitStats(uint32 duration)
void Minion::InitStats(WorldObject* summoner, uint32 duration)
{
TempSummon::InitStats(duration);
TempSummon::InitStats(summoner, duration);
SetReactState(REACT_PASSIVE);
@@ -456,9 +452,9 @@ Guardian::Guardian(SummonPropertiesEntry const* properties, Unit* owner, bool is
}
}
void Guardian::InitStats(uint32 duration)
void Guardian::InitStats(WorldObject* summoner, uint32 duration)
{
Minion::InitStats(duration);
Minion::InitStats(summoner, duration);
InitStatsForLevel(GetOwner()->GetLevel());
@@ -468,9 +464,9 @@ void Guardian::InitStats(uint32 duration)
SetReactState(REACT_AGGRESSIVE);
}
void Guardian::InitSummon()
void Guardian::InitSummon(WorldObject* summoner)
{
TempSummon::InitSummon();
TempSummon::InitSummon(summoner);
if (GetOwner()->GetTypeId() == TYPEID_PLAYER
&& GetOwner()->GetMinionGUID() == GetGUID()
@@ -494,15 +490,15 @@ Puppet::Puppet(SummonPropertiesEntry const* properties, Unit* owner)
m_unitTypeMask |= UNIT_MASK_PUPPET;
}
void Puppet::InitStats(uint32 duration)
void Puppet::InitStats(WorldObject* summoner, uint32 duration)
{
Minion::InitStats(duration);
Minion::InitStats(summoner, duration);
SetReactState(REACT_PASSIVE);
}
void Puppet::InitSummon()
void Puppet::InitSummon(WorldObject* summoner)
{
Minion::InitSummon();
Minion::InitSummon(summoner);
if (!SetCharmedBy(GetOwner(), CHARM_TYPE_POSSESS))
ABORT();
}

View File

@@ -47,8 +47,8 @@ class TC_GAME_API TempSummon : public Creature
explicit TempSummon(SummonPropertiesEntry const* properties, WorldObject* owner, bool isWorldObject);
virtual ~TempSummon() { }
void Update(uint32 time) override;
virtual void InitStats(uint32 lifetime);
virtual void InitSummon();
virtual void InitStats(WorldObject* summoner, uint32 lifetime);
virtual void InitSummon(WorldObject* summoner);
void UpdateObjectVisibilityOnCreate() override;
void UpdateObjectVisibilityOnDestroy() override;
virtual void UnSummon(uint32 msTime = 0);
@@ -84,7 +84,7 @@ class TC_GAME_API Minion : public TempSummon
{
public:
Minion(SummonPropertiesEntry const* properties, Unit* owner, bool isWorldObject);
void InitStats(uint32 duration) override;
void InitStats(WorldObject* summoner, uint32 duration) override;
void RemoveFromWorld() override;
void setDeathState(DeathState s) override;
Unit* GetOwner() const { return m_owner; }
@@ -119,9 +119,9 @@ class TC_GAME_API Guardian : public Minion
{
public:
Guardian(SummonPropertiesEntry const* properties, Unit* owner, bool isWorldObject);
void InitStats(uint32 duration) override;
void InitStats(WorldObject* summoner, uint32 duration) override;
bool InitStatsForLevel(uint8 level);
void InitSummon() override;
void InitSummon(WorldObject* summoner) override;
bool UpdateStats(Stats stat) override;
bool UpdateAllStats() override;
@@ -145,8 +145,8 @@ class TC_GAME_API Puppet : public Minion
{
public:
Puppet(SummonPropertiesEntry const* properties, Unit* owner);
void InitStats(uint32 duration) override;
void InitSummon() override;
void InitStats(WorldObject* summoner, uint32 duration) override;
void InitSummon(WorldObject* summoner) override;
void Update(uint32 time) override;
};

View File

@@ -1920,7 +1920,7 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert
summon->SetHomePosition(pos);
summon->InitStats(duration);
summon->InitStats(summoner, duration);
summon->SetPrivateObjectOwner(privateObjectOwner);
@@ -1951,7 +1951,7 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert
return nullptr;
}
summon->InitSummon();
summon->InitSummon(summoner);
// call MoveInLineOfSight for nearby creatures
Trinity::AIRelocationNotifier notifier(*summon);

View File

@@ -52,7 +52,7 @@ void Totem::Update(uint32 time)
Creature::Update(time);
}
void Totem::InitStats(uint32 duration)
void Totem::InitStats(WorldObject* summoner, uint32 duration)
{
// client requires SMSG_TOTEM_CREATED to be sent before adding to world and before removing old totem
if (Player* owner = GetOwner()->ToPlayer())
@@ -75,7 +75,7 @@ void Totem::InitStats(uint32 duration)
GetEntry(), owner->GetGUID().ToString(), *m_unitData->CreatedBySpell, EnumUtils::ToTitle(Races(owner->GetRace())));
}
Minion::InitStats(duration);
Minion::InitStats(summoner, duration);
// Get spell cast by totem
if (SpellInfo const* totemSpell = sSpellMgr->GetSpellInfo(GetSpell(), GetMap()->GetDifficultyID()))
@@ -85,7 +85,7 @@ void Totem::InitStats(uint32 duration)
m_duration = duration;
}
void Totem::InitSummon()
void Totem::InitSummon(WorldObject* /*summoner*/)
{
if (m_type == TOTEM_PASSIVE && GetSpell())
CastSpell(this, GetSpell(), true);

View File

@@ -33,8 +33,8 @@ class TC_GAME_API Totem : public Minion
Totem(SummonPropertiesEntry const* properties, Unit* owner);
virtual ~Totem() { }
void Update(uint32 time) override;
void InitStats(uint32 duration) override;
void InitSummon() override;
void InitStats(WorldObject* summoner, uint32 duration) override;
void InitSummon(WorldObject* summoner) override;
void UnSummon(uint32 msTime = 0) override;
uint32 GetSpell(uint8 slot = 0) const { return m_spells[slot]; }
uint32 GetTotemDuration() const { return m_duration; }

View File

@@ -510,7 +510,7 @@ TempSummon* Transport::SummonPassenger(uint32 entry, Position const& pos, TempSu
/// because the current GameObjectModel cannot be moved without recreating
summon->AddUnitState(UNIT_STATE_IGNORE_PATHFINDING);
summon->InitStats(duration);
summon->InitStats(summoner, duration);
if (!map->AddToMap<Creature>(summon))
{
@@ -520,7 +520,7 @@ TempSummon* Transport::SummonPassenger(uint32 entry, Position const& pos, TempSu
_staticPassengers.insert(summon);
summon->InitSummon();
summon->InitSummon(summoner);
summon->SetTempSummonType(summonType);
return summon;