Core/Creature: implement initial SummonInfo API for handling summons in the future

This commit is contained in:
Ovahlord committed 2025-08-09 15:01:55 +02:00
1 parent 0f41e34aa1
commit 5848eedb24
10 files changed
+427 -1

No files matched your search

+82
View File
@@ -18,9 +18,91 @@
#ifndef TRINITY_ADVSTD_H #ifndef TRINITY_ADVSTD_H
#define TRINITY_ADVSTD_H #define TRINITY_ADVSTD_H
#include <version>
#ifdef __cpp_lib_bit_cast
#include <bit>
#else
#include <cstring> // for memcpy
#endif
#include <compare>
// this namespace holds implementations of upcoming stdlib features that our c++ version doesn't have yet // this namespace holds implementations of upcoming stdlib features that our c++ version doesn't have yet
namespace advstd namespace advstd
{ {
// libc++ is missing these two
[[nodiscard]] constexpr bool is_eq(std::partial_ordering cmp) noexcept { return cmp == 0; }
[[nodiscard]] constexpr bool is_neq(std::partial_ordering cmp) noexcept { return cmp != 0; }
#ifdef __cpp_lib_bit_cast
using std::bit_cast;
#else
// libstdc++ v10 is missing this
template <typename To, typename From,
std::enable_if_t<std::conjunction_v<
std::bool_constant<sizeof(To) == sizeof(From)>,
std::is_trivially_copyable<To>,
std::is_trivially_copyable<From>>, int> = 0>
[[nodiscard]] constexpr To bit_cast(From const& from) noexcept
{
To to;
std::memcpy(&to, &from, sizeof(To));
return to;
}
#endif
}
// std::forward_like
#ifdef __cpp_lib_forward_like
#include <utility>
namespace advstd
{
using std::forward_like;
}
#else
namespace advstd
{
template <class T, class U>
[[nodiscard]] constexpr decltype(auto) forward_like(U&& value) noexcept
{
using ValueU = std::remove_reference_t<U>;
using ValueConstU = std::conditional_t<std::is_const_v<std::remove_reference_t<T>>, ValueU const, ValueU>;
return static_cast<std::conditional_t<std::is_rvalue_reference_v<T&&>, ValueConstU&&, ValueConstU&>>(value);
}
}
#endif
// std::ranges::contains
#include <algorithm>
#ifndef __cpp_lib_ranges_contains
#include <functional> // for std::ranges::equal_to, std::identity
#include <iterator> // for std::input_iterator, std::sentinel_for, std::projected
#endif
namespace advstd::ranges
{
#ifndef __cpp_lib_ranges_contains
struct Contains
{
template<std::input_iterator I, std::sentinel_for<I> S, class T, class Proj = std::identity>
requires std::indirect_binary_predicate<std::ranges::equal_to, std::projected<I, Proj>, T const*>
[[nodiscard]] inline constexpr bool operator()(I first, S last, T const& value, Proj proj = {}) const
{
return std::ranges::find(std::move(first), last, value, proj) != last;
}
template<std::ranges::input_range R, class T, class Proj = std::identity>
requires std::indirect_binary_predicate<std::ranges::equal_to, std::projected<std::ranges::iterator_t<R>, Proj>, T const*>
[[nodiscard]] inline constexpr bool operator()(R&& r, T const& value, Proj proj = {}) const
{
auto first = std::ranges::begin(r);
auto last = std::ranges::end(r);
return std::ranges::find(std::move(first), last, value, proj) != last;
}
} inline constexpr contains;
#else
using std::ranges::contains;
#endif
} }
#endif #endif
@@ -51,6 +51,7 @@
#include "ScriptedGossip.h" #include "ScriptedGossip.h"
#include "SpellAuraEffects.h" #include "SpellAuraEffects.h"
#include "SpellMgr.h" #include "SpellMgr.h"
#include "SummonInfo.h"
#include "TemporarySummon.h" #include "TemporarySummon.h"
#include "Transport.h" #include "Transport.h"
#include "Util.h" #include "Util.h"
@@ -316,6 +317,11 @@ void Creature::AddToWorld()
if (IsVehicle()) if (IsVehicle())
GetVehicleKit()->Install(); GetVehicleKit()->Install();
// If the creature has been summoned, register it for the summoner
if (IsSummon())
if (Unit* summoner = GetSummonInfo()->GetUnitSummoner())
summoner->RegisterSummon(GetSummonInfo());
if (GetZoneScript()) if (GetZoneScript())
GetZoneScript()->OnCreatureCreate(this); GetZoneScript()->OnCreatureCreate(this);
} }
@@ -325,6 +331,11 @@ void Creature::RemoveFromWorld()
{ {
if (IsInWorld()) if (IsInWorld())
{ {
// If the creature about to despawn, unregister it for the summoner
if (IsSummon())
if (Unit* summoner = GetSummonInfo()->GetUnitSummoner())
summoner->UnregisterSummon(GetSummonInfo());
if (GetZoneScript()) if (GetZoneScript())
GetZoneScript()->OnCreatureRemove(this); GetZoneScript()->OnCreatureRemove(this);
@@ -2761,6 +2772,22 @@ void Creature::InitializeMovementSpeeds()
SetSpeed(MOVE_WALK, _creatureMovementInfo.WalkSpeed); SetSpeed(MOVE_WALK, _creatureMovementInfo.WalkSpeed);
} }
void Creature::InitializeSummonInfo(SummonInfoArgs const& args)
{
ASSERT(_summonInfo == nullptr, "SummonInfo has already been initialized and must not be allocated again!");
_summonInfo = std::make_unique<SummonInfo>(this, args);
}
SummonInfo* Creature::GetSummonInfo() const
{
return _summonInfo.get();
}
bool Creature::IsSummon() const
{
return _summonInfo != nullptr;
}
void Creature::AllLootRemovedFromCorpse() void Creature::AllLootRemovedFromCorpse()
{ {
if (loot.loot_type != LOOT_SKINNING && !IsPet() && GetCreatureTemplate()->SkinLootId && hasLootRecipient()) if (loot.loot_type != LOOT_SKINNING && !IsPet() && GetCreatureTemplate()->SkinLootId && hasLootRecipient())
@@ -34,8 +34,11 @@ class Group;
class Quest; class Quest;
class Player; class Player;
class SpellInfo; class SpellInfo;
class SummonInfo;
class WorldSession; class WorldSession;
struct SummonInfoArgs;
enum MovementGeneratorType : uint8; enum MovementGeneratorType : uint8;
struct VendorItemCount struct VendorItemCount
@@ -420,6 +423,13 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
void ResetNoNpcDamageBelowPctHealthValue() { _noNpcDamageBelowPctHealth = 0.f; } void ResetNoNpcDamageBelowPctHealthValue() { _noNpcDamageBelowPctHealth = 0.f; }
float GetNoNpcDamageBelowPctHealthValue() const { return _noNpcDamageBelowPctHealth; } float GetNoNpcDamageBelowPctHealthValue() const { return _noNpcDamageBelowPctHealth; }
// Initializes the summon API for this creature which marks it as summon and will be treated accordingly
void InitializeSummonInfo(SummonInfoArgs const& args);
// Returns a pointer to the SummonInfo API, nullptr if the creature is not a summon
SummonInfo* GetSummonInfo() const;
bool IsSummon() const override;
protected: protected:
bool CreateFromProto(ObjectGuid::LowType guidlow, uint32 entry, CreatureData const* data = nullptr, uint32 vehId = 0); bool CreateFromProto(ObjectGuid::LowType guidlow, uint32 entry, CreatureData const* data = nullptr, uint32 vehId = 0);
bool InitEntry(uint32 entry, CreatureData const* data = nullptr); bool InitEntry(uint32 entry, CreatureData const* data = nullptr);
@@ -510,6 +520,9 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
Optional<uint32> _defaultMountDisplayIdOverride; Optional<uint32> _defaultMountDisplayIdOverride;
float _noNpcDamageBelowPctHealth; float _noNpcDamageBelowPctHealth;
// The Summon API which controls the behavior of summons
std::unique_ptr<SummonInfo> _summonInfo;
}; };
class TC_GAME_API AssistDelayEvent : public BasicEvent class TC_GAME_API AssistDelayEvent : public BasicEvent
@@ -0,0 +1,124 @@
/*
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "SummonInfo.h"
#include "Creature.h"
#include "DBCStores.h"
#include "Log.h"
#include "ObjectAccessor.h"
#include "SummonInfoArgs.h"
SummonInfo::SummonInfo(Creature* summonedCreature, SummonInfoArgs const& args) :
_summonedCreature(ASSERT_NOTNULL(summonedCreature)), _summonerGUID(args.SummonerGUID), _remainingDuration(args.Duration),
_maxHealth(args.MaxHealth), _summonSpellId(args.SummonSpellId),_despawnOnSummonerLogout(false),
_despawnOnSummonerDeath(false), _despawnWhenExpired(false)
{
if (args.SummonPropertiesId.has_value())
InitializeSummonProperties(*args.SummonPropertiesId);
}
void SummonInfo::InitializeSummonProperties(uint32 summonPropertiesId)
{
SummonPropertiesEntry const* summonProperties = sSummonPropertiesStore.LookupEntry(summonPropertiesId);
if (!summonProperties)
{
TC_LOG_ERROR("entities.unit", "Creature %s has been summoned with a non-existing SummonProperties.dbc entry (RecId: %u).", _summonedCreature->GetGUID().ToString().c_str(), summonPropertiesId);
return;
}
if (summonProperties->Faction)
_factionId = summonProperties->Faction;
_despawnOnSummonerLogout = summonProperties->GetFlags().HasFlag(SummonPropertiesFlags::DespawnOnSummonerLogout);
_despawnOnSummonerDeath = summonProperties->GetFlags().HasFlag(SummonPropertiesFlags::DespawnOnSummonerDeath);
_despawnWhenExpired = summonProperties->GetFlags().HasFlag(SummonPropertiesFlags::DespawnWhenExpired);
//if (_despawnOnSummonerDeath && summonProperties->GetFlags().HasFlag(SummonPropertiesFlags::DontDespawnOnSummonerDeath))
// _despawnOnSummonerDeath = false;
}
Creature* SummonInfo::GetSummonedCreature() const
{
return _summonedCreature;
}
Unit* SummonInfo::GetUnitSummoner() const
{
if (!_summonerGUID.has_value())
return nullptr;
return ObjectAccessor::GetUnit(*_summonedCreature, *_summonerGUID);
}
GameObject* SummonInfo::GetGameObjectSummoner() const
{
if (!_summonerGUID.has_value())
return nullptr;
return ObjectAccessor::GetGameObject(*_summonedCreature, *_summonerGUID);
}
Optional<Milliseconds> SummonInfo::GetRemainingDuration() const
{
return _remainingDuration;
}
Optional<uint64> SummonInfo::GetMaxHealth() const
{
return _maxHealth;
}
Optional<uint32> SummonInfo::GetSummonSpellId() const
{
return _summonSpellId;
}
Optional<uint32> SummonInfo::GetFactionId() const
{
return _factionId;
}
bool SummonInfo::DespawnsOnSummonerLogout() const
{
return _despawnOnSummonerLogout;
}
void SummonInfo::SetDespawnOnSummonerLogout(bool set)
{
_despawnOnSummonerLogout = set;
}
bool SummonInfo::DespawnsOnSummonerDeath() const
{
return _despawnOnSummonerDeath;
}
void SummonInfo::SetDespawnOnSummonerDeath(bool set)
{
_despawnOnSummonerDeath = set;
}
bool SummonInfo::DespawnsWhenExpired() const
{
return _despawnWhenExpired;
}
void SummonInfo::SetDespawnWhenExpired(bool set)
{
_despawnWhenExpired = set;
}
@@ -0,0 +1,85 @@
/*
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _SummonInfo_h__
#define _SummonInfo_h__
#include "Define.h"
#include "Duration.h"
#include "ObjectGuid.h"
#include "Optional.h"
class Creature;
class GameObject;
class Unit;
struct SummonInfoArgs;
class TC_GAME_API SummonInfo
{
public:
SummonInfo(SummonInfo const& right) = delete;
SummonInfo(SummonInfo&& right) = delete;
SummonInfo& operator=(SummonInfo const& right) = delete;
SummonInfo& operator=(SummonInfo&& right) = delete;
explicit SummonInfo(Creature* summonedCreature, SummonInfoArgs const& args);
// Initializes additional settings based on the provided SummonProperties ID.
void InitializeSummonProperties(uint32 summonPropertiesId);
// Returns the creature that is tied to this SummonInfo instance.
Creature* GetSummonedCreature() const;
// Returns the Unit summoner, or nullptr if no summoner has been provided or if the summoner is not a Unit.
Unit* GetUnitSummoner() const;
// Returns the GameObject summoner, or nullptr if no summoner has been provided or if the summoner is not a GameObject.
GameObject* GetGameObjectSummoner() const;
// Returns the remaining time until the summon expires. Nullopt when no duration was set which implies that the summon is permanent.
Optional<Milliseconds> GetRemainingDuration() const;
// Returns the health amount that will override the default max health calculation. Nullopt when no amount is provided.
Optional<uint64> GetMaxHealth() const;
// Returns the ID of the spell that has been used to summon the creature. Nullopt when the creature has not been summoned by a spell (scripted summons/ other APIs).
Optional<uint32> GetSummonSpellId() const;
// Returns the FactionTemplate ID of the summon that is overriding the default ID of the creature. Nullopt when the faction has not been overriden.
Optional<uint32> GetFactionId() const;
// Returns true when the summon will despawn when the summoner logs out. This also includes despawning and teleporting between map instances.
bool DespawnsOnSummonerLogout() const;
// Marks the summon to despawn when the summoner logs out. This also includes despawning and teleporting between map instaces.
void SetDespawnOnSummonerLogout(bool set);
// Returns true when the summon will despawn when its summoner has died.
bool DespawnsOnSummonerDeath() const;
// Marks the summon to despawn when the summoner has died.
void SetDespawnOnSummonerDeath(bool set);
// Returns true when the summon will despawn after its duration has expired. If not set, the summon will just die.
bool DespawnsWhenExpired() const;
// Marks the summon to despawn after its duration has expired. If disabled, the summon will just die.
void SetDespawnWhenExpired(bool set);
private:
Creature* _summonedCreature;
Optional<ObjectGuid> _summonerGUID;
Optional<Milliseconds> _remainingDuration; // NYI
Optional<uint64> _maxHealth; // NYI
Optional<uint32> _summonSpellId; // NYI
Optional<uint32> _factionId; // NYI
bool _despawnOnSummonerLogout; // NYI
bool _despawnOnSummonerDeath; // NYI
bool _despawnWhenExpired; // NYI
};
#endif // _SummonInfo_h__
@@ -0,0 +1,36 @@
/*
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _SummonInfoArgs_h__
#define _SummonInfoArgs_h__
#include "Define.h"
#include "Duration.h"
#include "Optional.h"
#include "ObjectGuid.h"
// Controls the behavior of a summoned creature and must be set with extreme care. If you want a blank summon that just exists as a permanent spawn, leave all fields untouched.
struct SummonInfoArgs
{
Optional<ObjectGuid> SummonerGUID;
Optional<uint64> MaxHealth;
Optional<Milliseconds> Duration;
Optional<uint32> SummonPropertiesId;
Optional<uint32> SummonSpellId;
};
#endif // _SummonInfoArgs_h__
@@ -46,6 +46,7 @@
#include "SpellDefines.h" #include "SpellDefines.h"
#include "SpellMgr.h" #include "SpellMgr.h"
#include "StringConvert.h" #include "StringConvert.h"
#include "SummonInfoArgs.h"
#include "TemporarySummon.h" #include "TemporarySummon.h"
#include "Totem.h" #include "Totem.h"
#include "Transport.h" #include "Transport.h"
@@ -2086,6 +2087,22 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonCreatur
if (summonArgs.Summoner) if (summonArgs.Summoner)
PhasingHandler::InheritPhaseShift(summon, summonArgs.Summoner); PhasingHandler::InheritPhaseShift(summon, summonArgs.Summoner);
// Store special settings which have been extracted from spell effects/scripts
SummonInfoArgs args;
if (summonArgs.Summoner)
args.SummonerGUID = summonArgs.Summoner->GetGUID();
if (summonArgs.SummonProperties)
args.SummonPropertiesId = summonArgs.SummonProperties->ID;
if (summonArgs.SummonDuration)
args.Duration = Milliseconds(summonArgs.SummonDuration);
if (summonArgs.SummonSpellId)
args.SummonSpellId = summonArgs.SummonSpellId;
if (summonArgs.SummonHealth)
args.MaxHealth = summonArgs.SummonHealth;
// Initialize the SummonInfo API which marks the creature as Summon
summon->InitializeSummonInfo(args);
TransportBase* transport = summonArgs.Summoner ? summonArgs.Summoner->GetTransport() : nullptr; TransportBase* transport = summonArgs.Summoner ? summonArgs.Summoner->GetTransport() : nullptr;
if (transport) if (transport)
{ {
+13
View File
@@ -28,6 +28,8 @@
#include "SpellHistory.h" #include "SpellHistory.h"
#include "SpellAuras.h" #include "SpellAuras.h"
#include "SpellAuraEffects.h" #include "SpellAuraEffects.h"
#include "SummonInfo.h"
#include "SummonInfoArgs.h"
#include "Unit.h" #include "Unit.h"
#include "Util.h" #include "Util.h"
#include "Group.h" #include "Group.h"
@@ -43,6 +45,8 @@ Pet::Pet(Player* owner, PetType type) :
{ {
ASSERT(GetOwner()); ASSERT(GetOwner());
InitializeSummonInfo({ .SummonerGUID = GetOwner()->GetGUID()});
m_unitTypeMask |= UNIT_MASK_PET; m_unitTypeMask |= UNIT_MASK_PET;
if (type == HUNTER_PET) if (type == HUNTER_PET)
m_unitTypeMask |= UNIT_MASK_HUNTER_PET; m_unitTypeMask |= UNIT_MASK_HUNTER_PET;
@@ -69,6 +73,11 @@ void Pet::AddToWorld()
///- Register the pet for guid lookup ///- Register the pet for guid lookup
GetMap()->GetObjectsStore().Insert<Pet>(GetGUID(), this); GetMap()->GetObjectsStore().Insert<Pet>(GetGUID(), this);
Unit::AddToWorld(); Unit::AddToWorld();
// SummonInfo should always be initialized for pets. Make sure that we will not go any further if this is no longer the case.
if (Unit* summoner = ASSERT_NOTNULL(GetSummonInfo())->GetUnitSummoner())
summoner->RegisterSummon(GetSummonInfo());
AIM_Initialize(); AIM_Initialize();
} }
@@ -89,6 +98,10 @@ void Pet::RemoveFromWorld()
///- Remove the pet from the accessor ///- Remove the pet from the accessor
if (IsInWorld()) if (IsInWorld())
{ {
// SummonInfo should always be initialized for pets. Make sure that we will not go any further if this is no longer the case.
if (Unit* summoner = ASSERT_NOTNULL(GetSummonInfo())->GetUnitSummoner())
summoner->UnregisterSummon(GetSummonInfo());
///- Don't call the function for Creature, normal mobs + totems go in a different storage ///- Don't call the function for Creature, normal mobs + totems go in a different storage
Unit::RemoveFromWorld(); Unit::RemoveFromWorld();
GetMap()->GetObjectsStore().Remove<Pet>(GetGUID()); GetMap()->GetObjectsStore().Remove<Pet>(GetGUID());
+21
View File
@@ -79,6 +79,7 @@
#include "SpellInfo.h" #include "SpellInfo.h"
#include "SpellMgr.h" #include "SpellMgr.h"
#include "SpellPackets.h" #include "SpellPackets.h"
#include "SummonInfo.h"
#include "TemporarySummon.h" #include "TemporarySummon.h"
#include "Totem.h" #include "Totem.h"
#include "Transport.h" #include "Transport.h"
@@ -8818,6 +8819,23 @@ uint32 Unit::GetCreatureTypeMask() const
return (creatureType >= 1) ? (1 << (creatureType - 1)) : 0; return (creatureType >= 1) ? (1 << (creatureType - 1)) : 0;
} }
void Unit::RegisterSummon(SummonInfo* summon)
{
if (!summon)
return;
if (!advstd::ranges::contains(_activeSummons, summon))
_activeSummons.push_back(summon);
}
void Unit::UnregisterSummon(SummonInfo* summon)
{
if (!summon)
return;
std::erase(_activeSummons, summon);
}
void Unit::SetShapeshiftForm(ShapeshiftForm form) void Unit::SetShapeshiftForm(ShapeshiftForm form)
{ {
SetByteValue(UNIT_FIELD_BYTES_2, UNIT_BYTES_2_OFFSET_SHAPESHIFT_FORM, form); SetByteValue(UNIT_FIELD_BYTES_2, UNIT_BYTES_2_OFFSET_SHAPESHIFT_FORM, form);
@@ -9607,6 +9625,9 @@ void Unit::RemoveFromWorld()
} }
} }
// Clear all active summon references. If we are about to switch map instances, we want to make sure that we leave all summons behind so we won't do threadunsafe operations
_activeSummons.clear();
WorldObject::RemoveFromWorld(); WorldObject::RemoveFromWorld();
m_duringRemoveFromWorld = false; m_duringRemoveFromWorld = false;
} }
+9 -1
View File
@@ -87,6 +87,7 @@ class Spell;
class SpellCastTargets; class SpellCastTargets;
class SpellHistory; class SpellHistory;
class SpellInfo; class SpellInfo;
class SummonInfo;
class Totem; class Totem;
class Transport; class Transport;
class TransportBase; class TransportBase;
@@ -756,7 +757,7 @@ class TC_GAME_API Unit : public WorldObject
uint32 HasUnitTypeMask(uint32 mask) const { return mask & m_unitTypeMask; } uint32 HasUnitTypeMask(uint32 mask) const { return mask & m_unitTypeMask; }
void AddUnitTypeMask(uint32 mask) { m_unitTypeMask |= mask; } void AddUnitTypeMask(uint32 mask) { m_unitTypeMask |= mask; }
bool IsSummon() const { return (m_unitTypeMask & UNIT_MASK_SUMMON) != 0; } virtual bool IsSummon() const { return false; }
bool IsMinion() const { return (m_unitTypeMask & UNIT_MASK_MINION) != 0; } bool IsMinion() const { return (m_unitTypeMask & UNIT_MASK_MINION) != 0; }
bool IsGuardian() const { return (m_unitTypeMask & UNIT_MASK_GUARDIAN) != 0; } bool IsGuardian() const { return (m_unitTypeMask & UNIT_MASK_GUARDIAN) != 0; }
bool IsPet() const { return (m_unitTypeMask & UNIT_MASK_PET) != 0; } bool IsPet() const { return (m_unitTypeMask & UNIT_MASK_PET) != 0; }
@@ -1323,6 +1324,11 @@ class TC_GAME_API Unit : public WorldObject
std::array<ObjectGuid, MAX_SUMMON_SLOT> m_SummonSlot; std::array<ObjectGuid, MAX_SUMMON_SLOT> m_SummonSlot;
std::array<ObjectGuid, MAX_GAMEOBJECT_SLOT> m_ObjectSlot; std::array<ObjectGuid, MAX_GAMEOBJECT_SLOT> m_ObjectSlot;
// Registers the SummonInfo API of a summoned creature to allow safely accessing it
void RegisterSummon(SummonInfo* summon);
// Unregisters the SummonInfo API of a summoned creature so it can no longer be accessed
void UnregisterSummon(SummonInfo* summon);
ShapeshiftForm GetShapeshiftForm() const { return ShapeshiftForm(GetByteValue(UNIT_FIELD_BYTES_2, UNIT_BYTES_2_OFFSET_SHAPESHIFT_FORM)); } ShapeshiftForm GetShapeshiftForm() const { return ShapeshiftForm(GetByteValue(UNIT_FIELD_BYTES_2, UNIT_BYTES_2_OFFSET_SHAPESHIFT_FORM)); }
void SetShapeshiftForm(ShapeshiftForm form); void SetShapeshiftForm(ShapeshiftForm form);
@@ -1819,6 +1825,8 @@ class TC_GAME_API Unit : public WorldObject
std::unordered_map<MovementChangeType, PlayerMovementPendingChange> m_pendingMovementChanges; std::unordered_map<MovementChangeType, PlayerMovementPendingChange> m_pendingMovementChanges;
/* Player Movement fields END*/ /* Player Movement fields END*/
std::vector<SummonInfo*> _activeSummons;
}; };
namespace Trinity namespace Trinity