Skip to content

Commit 5848eed

Browse files
committed
Core/Creature: implement initial SummonInfo API for handling summons in the future
1 parent 0f41e34 commit 5848eed

File tree

10 files changed

+427
-1
lines changed

10 files changed

+427
-1
lines changed

src/common/Utilities/advstd.h

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,91 @@
1818
#ifndef TRINITY_ADVSTD_H
1919
#define TRINITY_ADVSTD_H
2020

21+
#include <version>
22+
23+
#ifdef __cpp_lib_bit_cast
24+
#include <bit>
25+
#else
26+
#include <cstring> // for memcpy
27+
#endif
28+
#include <compare>
29+
2130
// this namespace holds implementations of upcoming stdlib features that our c++ version doesn't have yet
2231
namespace advstd
2332
{
33+
// libc++ is missing these two
34+
[[nodiscard]] constexpr bool is_eq(std::partial_ordering cmp) noexcept { return cmp == 0; }
35+
[[nodiscard]] constexpr bool is_neq(std::partial_ordering cmp) noexcept { return cmp != 0; }
36+
37+
#ifdef __cpp_lib_bit_cast
38+
using std::bit_cast;
39+
#else
40+
// libstdc++ v10 is missing this
41+
template <typename To, typename From,
42+
std::enable_if_t<std::conjunction_v<
43+
std::bool_constant<sizeof(To) == sizeof(From)>,
44+
std::is_trivially_copyable<To>,
45+
std::is_trivially_copyable<From>>, int> = 0>
46+
[[nodiscard]] constexpr To bit_cast(From const& from) noexcept
47+
{
48+
To to;
49+
std::memcpy(&to, &from, sizeof(To));
50+
return to;
51+
}
52+
#endif
53+
}
54+
55+
// std::forward_like
56+
#ifdef __cpp_lib_forward_like
57+
#include <utility>
58+
namespace advstd
59+
{
60+
using std::forward_like;
61+
}
62+
#else
63+
namespace advstd
64+
{
65+
template <class T, class U>
66+
[[nodiscard]] constexpr decltype(auto) forward_like(U&& value) noexcept
67+
{
68+
using ValueU = std::remove_reference_t<U>;
69+
using ValueConstU = std::conditional_t<std::is_const_v<std::remove_reference_t<T>>, ValueU const, ValueU>;
70+
return static_cast<std::conditional_t<std::is_rvalue_reference_v<T&&>, ValueConstU&&, ValueConstU&>>(value);
71+
}
72+
}
73+
#endif
74+
75+
// std::ranges::contains
76+
#include <algorithm>
77+
#ifndef __cpp_lib_ranges_contains
78+
#include <functional> // for std::ranges::equal_to, std::identity
79+
#include <iterator> // for std::input_iterator, std::sentinel_for, std::projected
80+
#endif
81+
82+
namespace advstd::ranges
83+
{
84+
#ifndef __cpp_lib_ranges_contains
85+
struct Contains
86+
{
87+
template<std::input_iterator I, std::sentinel_for<I> S, class T, class Proj = std::identity>
88+
requires std::indirect_binary_predicate<std::ranges::equal_to, std::projected<I, Proj>, T const*>
89+
[[nodiscard]] inline constexpr bool operator()(I first, S last, T const& value, Proj proj = {}) const
90+
{
91+
return std::ranges::find(std::move(first), last, value, proj) != last;
92+
}
93+
94+
template<std::ranges::input_range R, class T, class Proj = std::identity>
95+
requires std::indirect_binary_predicate<std::ranges::equal_to, std::projected<std::ranges::iterator_t<R>, Proj>, T const*>
96+
[[nodiscard]] inline constexpr bool operator()(R&& r, T const& value, Proj proj = {}) const
97+
{
98+
auto first = std::ranges::begin(r);
99+
auto last = std::ranges::end(r);
100+
return std::ranges::find(std::move(first), last, value, proj) != last;
101+
}
102+
} inline constexpr contains;
103+
#else
104+
using std::ranges::contains;
105+
#endif
24106
}
25107

26108
#endif

src/server/game/Entities/Creature/Creature.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#include "ScriptedGossip.h"
5252
#include "SpellAuraEffects.h"
5353
#include "SpellMgr.h"
54+
#include "SummonInfo.h"
5455
#include "TemporarySummon.h"
5556
#include "Transport.h"
5657
#include "Util.h"
@@ -316,6 +317,11 @@ void Creature::AddToWorld()
316317
if (IsVehicle())
317318
GetVehicleKit()->Install();
318319

320+
// If the creature has been summoned, register it for the summoner
321+
if (IsSummon())
322+
if (Unit* summoner = GetSummonInfo()->GetUnitSummoner())
323+
summoner->RegisterSummon(GetSummonInfo());
324+
319325
if (GetZoneScript())
320326
GetZoneScript()->OnCreatureCreate(this);
321327
}
@@ -325,6 +331,11 @@ void Creature::RemoveFromWorld()
325331
{
326332
if (IsInWorld())
327333
{
334+
// If the creature about to despawn, unregister it for the summoner
335+
if (IsSummon())
336+
if (Unit* summoner = GetSummonInfo()->GetUnitSummoner())
337+
summoner->UnregisterSummon(GetSummonInfo());
338+
328339
if (GetZoneScript())
329340
GetZoneScript()->OnCreatureRemove(this);
330341

@@ -2761,6 +2772,22 @@ void Creature::InitializeMovementSpeeds()
27612772
SetSpeed(MOVE_WALK, _creatureMovementInfo.WalkSpeed);
27622773
}
27632774

2775+
void Creature::InitializeSummonInfo(SummonInfoArgs const& args)
2776+
{
2777+
ASSERT(_summonInfo == nullptr, "SummonInfo has already been initialized and must not be allocated again!");
2778+
_summonInfo = std::make_unique<SummonInfo>(this, args);
2779+
}
2780+
2781+
SummonInfo* Creature::GetSummonInfo() const
2782+
{
2783+
return _summonInfo.get();
2784+
}
2785+
2786+
bool Creature::IsSummon() const
2787+
{
2788+
return _summonInfo != nullptr;
2789+
}
2790+
27642791
void Creature::AllLootRemovedFromCorpse()
27652792
{
27662793
if (loot.loot_type != LOOT_SKINNING && !IsPet() && GetCreatureTemplate()->SkinLootId && hasLootRecipient())

src/server/game/Entities/Creature/Creature.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,11 @@ class Group;
3434
class Quest;
3535
class Player;
3636
class SpellInfo;
37+
class SummonInfo;
3738
class WorldSession;
3839

40+
struct SummonInfoArgs;
41+
3942
enum MovementGeneratorType : uint8;
4043

4144
struct VendorItemCount
@@ -420,6 +423,13 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
420423
void ResetNoNpcDamageBelowPctHealthValue() { _noNpcDamageBelowPctHealth = 0.f; }
421424
float GetNoNpcDamageBelowPctHealthValue() const { return _noNpcDamageBelowPctHealth; }
422425

426+
// Initializes the summon API for this creature which marks it as summon and will be treated accordingly
427+
void InitializeSummonInfo(SummonInfoArgs const& args);
428+
// Returns a pointer to the SummonInfo API, nullptr if the creature is not a summon
429+
SummonInfo* GetSummonInfo() const;
430+
431+
bool IsSummon() const override;
432+
423433
protected:
424434
bool CreateFromProto(ObjectGuid::LowType guidlow, uint32 entry, CreatureData const* data = nullptr, uint32 vehId = 0);
425435
bool InitEntry(uint32 entry, CreatureData const* data = nullptr);
@@ -510,6 +520,9 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
510520

511521
Optional<uint32> _defaultMountDisplayIdOverride;
512522
float _noNpcDamageBelowPctHealth;
523+
524+
// The Summon API which controls the behavior of summons
525+
std::unique_ptr<SummonInfo> _summonInfo;
513526
};
514527

515528
class TC_GAME_API AssistDelayEvent : public BasicEvent
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/*
2+
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3+
*
4+
* This program is free software; you can redistribute it and/or modify it
5+
* under the terms of the GNU General Public License as published by the
6+
* Free Software Foundation; either version 2 of the License, or (at your
7+
* option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12+
* more details.
13+
*
14+
* You should have received a copy of the GNU General Public License along
15+
* with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
#include "SummonInfo.h"
19+
20+
#include "Creature.h"
21+
#include "DBCStores.h"
22+
#include "Log.h"
23+
#include "ObjectAccessor.h"
24+
#include "SummonInfoArgs.h"
25+
26+
SummonInfo::SummonInfo(Creature* summonedCreature, SummonInfoArgs const& args) :
27+
_summonedCreature(ASSERT_NOTNULL(summonedCreature)), _summonerGUID(args.SummonerGUID), _remainingDuration(args.Duration),
28+
_maxHealth(args.MaxHealth), _summonSpellId(args.SummonSpellId),_despawnOnSummonerLogout(false),
29+
_despawnOnSummonerDeath(false), _despawnWhenExpired(false)
30+
{
31+
if (args.SummonPropertiesId.has_value())
32+
InitializeSummonProperties(*args.SummonPropertiesId);
33+
}
34+
35+
void SummonInfo::InitializeSummonProperties(uint32 summonPropertiesId)
36+
{
37+
SummonPropertiesEntry const* summonProperties = sSummonPropertiesStore.LookupEntry(summonPropertiesId);
38+
if (!summonProperties)
39+
{
40+
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);
41+
return;
42+
}
43+
44+
if (summonProperties->Faction)
45+
_factionId = summonProperties->Faction;
46+
47+
_despawnOnSummonerLogout = summonProperties->GetFlags().HasFlag(SummonPropertiesFlags::DespawnOnSummonerLogout);
48+
_despawnOnSummonerDeath = summonProperties->GetFlags().HasFlag(SummonPropertiesFlags::DespawnOnSummonerDeath);
49+
_despawnWhenExpired = summonProperties->GetFlags().HasFlag(SummonPropertiesFlags::DespawnWhenExpired);
50+
51+
//if (_despawnOnSummonerDeath && summonProperties->GetFlags().HasFlag(SummonPropertiesFlags::DontDespawnOnSummonerDeath))
52+
// _despawnOnSummonerDeath = false;
53+
}
54+
55+
Creature* SummonInfo::GetSummonedCreature() const
56+
{
57+
return _summonedCreature;
58+
}
59+
60+
Unit* SummonInfo::GetUnitSummoner() const
61+
{
62+
if (!_summonerGUID.has_value())
63+
return nullptr;
64+
65+
return ObjectAccessor::GetUnit(*_summonedCreature, *_summonerGUID);
66+
}
67+
68+
GameObject* SummonInfo::GetGameObjectSummoner() const
69+
{
70+
if (!_summonerGUID.has_value())
71+
return nullptr;
72+
73+
return ObjectAccessor::GetGameObject(*_summonedCreature, *_summonerGUID);
74+
}
75+
76+
Optional<Milliseconds> SummonInfo::GetRemainingDuration() const
77+
{
78+
return _remainingDuration;
79+
}
80+
81+
Optional<uint64> SummonInfo::GetMaxHealth() const
82+
{
83+
return _maxHealth;
84+
}
85+
86+
Optional<uint32> SummonInfo::GetSummonSpellId() const
87+
{
88+
return _summonSpellId;
89+
}
90+
91+
Optional<uint32> SummonInfo::GetFactionId() const
92+
{
93+
return _factionId;
94+
}
95+
96+
bool SummonInfo::DespawnsOnSummonerLogout() const
97+
{
98+
return _despawnOnSummonerLogout;
99+
}
100+
101+
void SummonInfo::SetDespawnOnSummonerLogout(bool set)
102+
{
103+
_despawnOnSummonerLogout = set;
104+
}
105+
106+
bool SummonInfo::DespawnsOnSummonerDeath() const
107+
{
108+
return _despawnOnSummonerDeath;
109+
}
110+
111+
void SummonInfo::SetDespawnOnSummonerDeath(bool set)
112+
{
113+
_despawnOnSummonerDeath = set;
114+
}
115+
116+
bool SummonInfo::DespawnsWhenExpired() const
117+
{
118+
return _despawnWhenExpired;
119+
}
120+
121+
void SummonInfo::SetDespawnWhenExpired(bool set)
122+
{
123+
_despawnWhenExpired = set;
124+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3+
*
4+
* This program is free software; you can redistribute it and/or modify it
5+
* under the terms of the GNU General Public License as published by the
6+
* Free Software Foundation; either version 2 of the License, or (at your
7+
* option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12+
* more details.
13+
*
14+
* You should have received a copy of the GNU General Public License along
15+
* with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
#ifndef _SummonInfo_h__
19+
#define _SummonInfo_h__
20+
21+
#include "Define.h"
22+
#include "Duration.h"
23+
#include "ObjectGuid.h"
24+
#include "Optional.h"
25+
26+
class Creature;
27+
class GameObject;
28+
class Unit;
29+
30+
struct SummonInfoArgs;
31+
32+
class TC_GAME_API SummonInfo
33+
{
34+
public:
35+
SummonInfo(SummonInfo const& right) = delete;
36+
SummonInfo(SummonInfo&& right) = delete;
37+
SummonInfo& operator=(SummonInfo const& right) = delete;
38+
SummonInfo& operator=(SummonInfo&& right) = delete;
39+
40+
explicit SummonInfo(Creature* summonedCreature, SummonInfoArgs const& args);
41+
42+
// Initializes additional settings based on the provided SummonProperties ID.
43+
void InitializeSummonProperties(uint32 summonPropertiesId);
44+
// Returns the creature that is tied to this SummonInfo instance.
45+
Creature* GetSummonedCreature() const;
46+
// Returns the Unit summoner, or nullptr if no summoner has been provided or if the summoner is not a Unit.
47+
Unit* GetUnitSummoner() const;
48+
// Returns the GameObject summoner, or nullptr if no summoner has been provided or if the summoner is not a GameObject.
49+
GameObject* GetGameObjectSummoner() const;
50+
51+
// Returns the remaining time until the summon expires. Nullopt when no duration was set which implies that the summon is permanent.
52+
Optional<Milliseconds> GetRemainingDuration() const;
53+
// Returns the health amount that will override the default max health calculation. Nullopt when no amount is provided.
54+
Optional<uint64> GetMaxHealth() const;
55+
// 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).
56+
Optional<uint32> GetSummonSpellId() const;
57+
// Returns the FactionTemplate ID of the summon that is overriding the default ID of the creature. Nullopt when the faction has not been overriden.
58+
Optional<uint32> GetFactionId() const;
59+
60+
// Returns true when the summon will despawn when the summoner logs out. This also includes despawning and teleporting between map instances.
61+
bool DespawnsOnSummonerLogout() const;
62+
// Marks the summon to despawn when the summoner logs out. This also includes despawning and teleporting between map instaces.
63+
void SetDespawnOnSummonerLogout(bool set);
64+
// Returns true when the summon will despawn when its summoner has died.
65+
bool DespawnsOnSummonerDeath() const;
66+
// Marks the summon to despawn when the summoner has died.
67+
void SetDespawnOnSummonerDeath(bool set);
68+
// Returns true when the summon will despawn after its duration has expired. If not set, the summon will just die.
69+
bool DespawnsWhenExpired() const;
70+
// Marks the summon to despawn after its duration has expired. If disabled, the summon will just die.
71+
void SetDespawnWhenExpired(bool set);
72+
73+
private:
74+
Creature* _summonedCreature;
75+
Optional<ObjectGuid> _summonerGUID;
76+
Optional<Milliseconds> _remainingDuration; // NYI
77+
Optional<uint64> _maxHealth; // NYI
78+
Optional<uint32> _summonSpellId; // NYI
79+
Optional<uint32> _factionId; // NYI
80+
bool _despawnOnSummonerLogout; // NYI
81+
bool _despawnOnSummonerDeath; // NYI
82+
bool _despawnWhenExpired; // NYI
83+
};
84+
85+
#endif // _SummonInfo_h__

0 commit comments

Comments
 (0)