Skip to content

Commit ec1ab2a

Browse files
committed
Core/Creatures: move level and faction initialization into SummonInfo API
1 parent dd58d5e commit ec1ab2a

File tree

9 files changed

+141
-94
lines changed

9 files changed

+141
-94
lines changed

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

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -596,7 +596,10 @@ bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/,
596596
if (!GetCreatureAddon())
597597
SetSheath(SHEATH_STATE_MELEE);
598598

599-
SetFaction(cInfo->faction);
599+
if (SummonInfo const* summonInfo = GetSummonInfo())
600+
SetFaction(summonInfo->GetFactionId().value_or(cInfo->faction));
601+
else
602+
SetFaction(cInfo->faction);
600603

601604
uint32 npcflags = 0, unitFlags = 0, unitFlags2 = 0;
602605
ObjectMgr::ChooseCreatureFlags(cInfo, &npcflags, &unitFlags, &unitFlags2, _staticFlags, data);
@@ -1414,12 +1417,22 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask)
14141417

14151418
void Creature::SelectLevel()
14161419
{
1417-
CreatureTemplate const* cInfo = GetCreatureTemplate();
1420+
uint8 level = [&]() -> uint8
1421+
{
1422+
// Some summons override their default level selection
1423+
if (SummonInfo const* summonInfo = GetSummonInfo())
1424+
if (summonInfo->GetCreatureLevel().has_value())
1425+
return *summonInfo->GetCreatureLevel();
1426+
1427+
CreatureTemplate const* cInfo = GetCreatureTemplate();
1428+
1429+
// level
1430+
uint8 minlevel = std::min(cInfo->maxlevel, cInfo->minlevel);
1431+
uint8 maxlevel = std::max(cInfo->maxlevel, cInfo->minlevel);
1432+
1433+
return minlevel == maxlevel ? minlevel : urand(minlevel, maxlevel);
1434+
}();
14181435

1419-
// level
1420-
uint8 minlevel = std::min(cInfo->maxlevel, cInfo->minlevel);
1421-
uint8 maxlevel = std::max(cInfo->maxlevel, cInfo->minlevel);
1422-
uint8 level = minlevel == maxlevel ? minlevel : urand(minlevel, maxlevel);
14231436
SetLevel(level);
14241437
}
14251438

@@ -1430,10 +1443,17 @@ void Creature::UpdateLevelDependantStats()
14301443
CreatureBaseStats const* stats = sObjectMgr->GetCreatureBaseStats(getLevel(), cInfo->unit_class);
14311444

14321445
// health
1433-
float healthmod = _GetHealthMod(rank);
1446+
uint32 health = [&]() -> uint32
1447+
{
1448+
// Some summons have their maximum health overridden by their summon spell effect values (e.g. player Shaman totems)
1449+
if (SummonInfo const* summonInfo = GetSummonInfo())
1450+
if (summonInfo->GetMaxHealth().has_value())
1451+
return *_summonInfo->GetMaxHealth();
14341452

1435-
uint32 basehp = stats->GenerateHealth(cInfo);
1436-
uint32 health = uint32(basehp * healthmod);
1453+
float healthmod = _GetHealthMod(rank);
1454+
uint32 basehp = stats->GenerateHealth(cInfo);
1455+
return uint32(basehp * healthmod);
1456+
}();
14371457

14381458
SetCreateHealth(health);
14391459
SetMaxHealth(health);

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

Lines changed: 64 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,21 @@
1919

2020
#include "Creature.h"
2121
#include "DBCStores.h"
22+
#include "DBCEnums.h"
2223
#include "Log.h"
2324
#include "ObjectAccessor.h"
2425
#include "SummonInfoArgs.h"
2526

2627
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)
28+
_summonedCreature(ASSERT_NOTNULL(summonedCreature)), _summonerGUID(args.Summoner ? args.Summoner->GetGUID() : ObjectGuid::Empty),
29+
_remainingDuration(args.Duration), _maxHealth(args.MaxHealth), _creatureLevel(args.CreatureLevel),
30+
_flags(SummonPropertiesFlags::None), _control(SummonPropertiesControl::None), _summonSlot(SummonPropertiesSlot::None)
3031
{
3132
if (args.SummonPropertiesId.has_value())
32-
InitializeSummonProperties(*args.SummonPropertiesId);
33+
InitializeSummonProperties(*args.SummonPropertiesId, Object::ToUnit(args.Summoner));
3334
}
3435

35-
void SummonInfo::InitializeSummonProperties(uint32 summonPropertiesId)
36+
void SummonInfo::InitializeSummonProperties(uint32 summonPropertiesId, Unit const* summoner)
3637
{
3738
SummonPropertiesEntry const* summonProperties = sSummonPropertiesStore.LookupEntry(summonPropertiesId);
3839
if (!summonProperties)
@@ -44,12 +45,27 @@ void SummonInfo::InitializeSummonProperties(uint32 summonPropertiesId)
4445
if (summonProperties->Faction)
4546
_factionId = summonProperties->Faction;
4647

47-
_despawnOnSummonerLogout = summonProperties->GetFlags().HasFlag(SummonPropertiesFlags::DespawnOnSummonerLogout);
48-
_despawnOnSummonerDeath = summonProperties->GetFlags().HasFlag(SummonPropertiesFlags::DespawnOnSummonerDeath);
49-
_despawnWhenExpired = summonProperties->GetFlags().HasFlag(SummonPropertiesFlags::DespawnWhenExpired);
48+
_flags = summonProperties->GetFlags();
49+
_summonSlot = static_cast<SummonPropertiesSlot>(summonProperties->Slot);
50+
_control = static_cast<SummonPropertiesControl>(summonProperties->Control);
5051

51-
//if (_despawnOnSummonerDeath && summonProperties->GetFlags().HasFlag(SummonPropertiesFlags::DontDespawnOnSummonerDeath))
52-
// _despawnOnSummonerDeath = false;
52+
if (summoner)
53+
{
54+
if (_flags.HasFlag(SummonPropertiesFlags::UseSummonerFaction))
55+
_factionId = summoner->GetFaction();
56+
57+
if (_control != SummonPropertiesControl::None)
58+
{
59+
// Controlled summons inherit the level of their summoner unless explicitly stated otherwise.
60+
// Level can be overridden either by SummonPropertiesFlags::UseCreatureLevel or by a spell effect value
61+
if (!_flags.HasFlag(SummonPropertiesFlags::UseCreatureLevel) && !_creatureLevel.has_value())
62+
_creatureLevel = summoner->getLevel();
63+
64+
// Controlled summons inherit their summoner's faction if not overridden by DBC data
65+
if (!_factionId.has_value())
66+
_factionId = summoner->GetFaction();
67+
}
68+
}
5369
}
5470

5571
Creature* SummonInfo::GetSummonedCreature() const
@@ -59,18 +75,12 @@ Creature* SummonInfo::GetSummonedCreature() const
5975

6076
Unit* SummonInfo::GetUnitSummoner() const
6177
{
62-
if (!_summonerGUID.has_value())
63-
return nullptr;
64-
65-
return ObjectAccessor::GetUnit(*_summonedCreature, *_summonerGUID);
78+
return ObjectAccessor::GetUnit(*_summonedCreature, _summonerGUID);
6679
}
6780

6881
GameObject* SummonInfo::GetGameObjectSummoner() const
6982
{
70-
if (!_summonerGUID.has_value())
71-
return nullptr;
72-
73-
return ObjectAccessor::GetGameObject(*_summonedCreature, *_summonerGUID);
83+
return ObjectAccessor::GetGameObject(*_summonedCreature, _summonerGUID);
7484
}
7585

7686
Optional<Milliseconds> SummonInfo::GetRemainingDuration() const
@@ -83,42 +93,68 @@ Optional<uint64> SummonInfo::GetMaxHealth() const
8393
return _maxHealth;
8494
}
8595

86-
Optional<uint32> SummonInfo::GetSummonSpellId() const
96+
Optional<uint32> SummonInfo::GetFactionId() const
8797
{
88-
return _summonSpellId;
98+
return _factionId;
8999
}
90100

91-
Optional<uint32> SummonInfo::GetFactionId() const
101+
Optional<uint8> SummonInfo::GetCreatureLevel() const
92102
{
93-
return _factionId;
103+
return _creatureLevel;
94104
}
95105

96106
bool SummonInfo::DespawnsOnSummonerLogout() const
97107
{
98-
return _despawnOnSummonerLogout;
108+
return _flags.HasFlag(SummonPropertiesFlags::DespawnOnSummonerLogout);
99109
}
100110

101111
void SummonInfo::SetDespawnOnSummonerLogout(bool set)
102112
{
103-
_despawnOnSummonerLogout = set;
113+
if (set)
114+
_flags |= SummonPropertiesFlags::DespawnOnSummonerLogout;
115+
else
116+
_flags.RemoveFlag(SummonPropertiesFlags::DespawnOnSummonerLogout);
104117
}
105118

106119
bool SummonInfo::DespawnsOnSummonerDeath() const
107120
{
108-
return _despawnOnSummonerDeath;
121+
return _flags.HasFlag(SummonPropertiesFlags::DespawnOnSummonerDeath);
109122
}
110123

111124
void SummonInfo::SetDespawnOnSummonerDeath(bool set)
112125
{
113-
_despawnOnSummonerDeath = set;
126+
if (set)
127+
_flags |= SummonPropertiesFlags::DespawnOnSummonerDeath;
128+
else
129+
_flags.RemoveFlag(SummonPropertiesFlags::DespawnOnSummonerDeath);
114130
}
115131

116132
bool SummonInfo::DespawnsWhenExpired() const
117133
{
118-
return _despawnWhenExpired;
134+
return _flags.HasFlag(SummonPropertiesFlags::DespawnWhenExpired);
119135
}
120136

121137
void SummonInfo::SetDespawnWhenExpired(bool set)
122138
{
123-
_despawnWhenExpired = set;
139+
if (set)
140+
_flags |= SummonPropertiesFlags::DespawnWhenExpired;
141+
else
142+
_flags.RemoveFlag(SummonPropertiesFlags::DespawnWhenExpired);
143+
}
144+
145+
bool SummonInfo::UsesSummonerFaction() const
146+
{
147+
return _flags.HasFlag(SummonPropertiesFlags::UseSummonerFaction);
148+
}
149+
150+
void SummonInfo::SetUseSummonerFaction(bool set)
151+
{
152+
if (set)
153+
_flags |= SummonPropertiesFlags::UseSummonerFaction;
154+
else
155+
_flags.RemoveFlag(SummonPropertiesFlags::UseSummonerFaction);
156+
}
157+
bool SummonInfo::IsControlledBySummoner() const
158+
{
159+
return _control > SummonPropertiesControl::None;
124160
}

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

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@
1818
#ifndef _SummonInfo_h__
1919
#define _SummonInfo_h__
2020

21+
#include "DBCEnums.h"
2122
#include "Define.h"
2223
#include "Duration.h"
24+
#include "EnumFlag.h"
2325
#include "ObjectGuid.h"
2426
#include "Optional.h"
2527

@@ -40,10 +42,10 @@ class TC_GAME_API SummonInfo
4042
explicit SummonInfo(Creature* summonedCreature, SummonInfoArgs const& args);
4143

4244
// Initializes additional settings based on the provided SummonProperties ID.
43-
void InitializeSummonProperties(uint32 summonPropertiesId);
45+
void InitializeSummonProperties(uint32 summonPropertiesId, Unit const* summoner);
4446
// Returns the creature that is tied to this SummonInfo instance.
4547
Creature* GetSummonedCreature() const;
46-
// Returns the Unit summoner, or nullptr if no summoner has been provided or if the summoner is not a Unit.
48+
// Returns the Unit summoner, or nullptr if no summoner has been provided or if the summoner is not an Unit.
4749
Unit* GetUnitSummoner() const;
4850
// Returns the GameObject summoner, or nullptr if no summoner has been provided or if the summoner is not a GameObject.
4951
GameObject* GetGameObjectSummoner() const;
@@ -52,10 +54,10 @@ class TC_GAME_API SummonInfo
5254
Optional<Milliseconds> GetRemainingDuration() const;
5355
// Returns the health amount that will override the default max health calculation. Nullopt when no amount is provided.
5456
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;
5757
// Returns the FactionTemplate ID of the summon that is overriding the default ID of the creature. Nullopt when the faction has not been overriden.
5858
Optional<uint32> GetFactionId() const;
59+
// Returns the level of the creature that will override the default level calculation. Nullopt when the creature uses its default values.
60+
Optional<uint8> GetCreatureLevel() const;
5961

6062
// Returns true when the summon will despawn when the summoner logs out. This also includes despawning and teleporting between map instances.
6163
bool DespawnsOnSummonerLogout() const;
@@ -69,17 +71,23 @@ class TC_GAME_API SummonInfo
6971
bool DespawnsWhenExpired() const;
7072
// Marks the summon to despawn after its duration has expired. If disabled, the summon will just die.
7173
void SetDespawnWhenExpired(bool set);
74+
// Returns true when the summon will inherit its summoner's faction.
75+
bool UsesSummonerFaction() const;
76+
// Marks the summon to inherit its summoner's faction.
77+
void SetUseSummonerFaction(bool set);
78+
// Returns true when the summon is either a Guardian, Pet, Vehicle or Possessed summon
79+
bool IsControlledBySummoner() const;
7280

7381
private:
7482
Creature* _summonedCreature;
75-
Optional<ObjectGuid> _summonerGUID;
83+
ObjectGuid _summonerGUID;
7684
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
85+
Optional<uint64> _maxHealth; // Implemented in Creature::UpdateLevelDependantStats
86+
Optional<uint32> _factionId; // Implemented in Creature::UpdateEntry
87+
Optional<uint8> _creatureLevel; // Implemented in Creature::SelectLevel
88+
EnumFlag<SummonPropertiesFlags> _flags;
89+
SummonPropertiesControl _control;
90+
SummonPropertiesSlot _summonSlot;
8391
};
8492

8593
#endif // _SummonInfo_h__

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,17 @@
2121
#include "Define.h"
2222
#include "Duration.h"
2323
#include "Optional.h"
24-
#include "ObjectGuid.h"
24+
25+
class WorldObject;
2526

2627
// 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.
2728
struct SummonInfoArgs
2829
{
29-
Optional<ObjectGuid> SummonerGUID;
30+
WorldObject const* Summoner = nullptr;
3031
Optional<uint64> MaxHealth;
3132
Optional<Milliseconds> Duration;
3233
Optional<uint32> SummonPropertiesId;
33-
Optional<uint32> SummonSpellId;
34+
Optional<uint8> CreatureLevel;
3435
};
3536

3637
#endif // _SummonInfoArgs_h__

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

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,6 @@ void TempSummon::InitStats(uint32 duration)
172172

173173
if (owner && IsTrigger() && m_spells[0])
174174
{
175-
SetFaction(owner->GetFaction());
176-
SetLevel(owner->getLevel());
177175
if (owner->GetTypeId() == TYPEID_PLAYER)
178176
m_ControlledByPlayer = true;
179177
}
@@ -197,9 +195,6 @@ void TempSummon::InitStats(uint32 duration)
197195

198196
if (m_Properties->Control != SUMMON_CATEGORY_WILD)
199197
{
200-
if (!m_Properties->Faction)
201-
SetFaction(owner->GetFaction());
202-
203198
// Creator guid is always set for allied summons
204199
SetCreatorGUID(owner->GetGUID());
205200

@@ -218,10 +213,6 @@ void TempSummon::InitStats(uint32 duration)
218213
if (owner->IsTotem())
219214
owner->m_Controlled.insert(this);
220215
}
221-
222-
// If property has a faction defined, use it.
223-
if (m_Properties->Faction)
224-
SetFaction(m_Properties->Faction);
225216
}
226217

227218
void TempSummon::InitSummon()
@@ -393,7 +384,7 @@ void Guardian::InitStats(uint32 duration)
393384
{
394385
Minion::InitStats(duration);
395386

396-
InitStatsForLevel(GetOwner()->getLevel());
387+
InitStatsForLevel(getLevel());
397388

398389
if (GetOwner()->GetTypeId() == TYPEID_PLAYER && HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN))
399390
m_charmInfo->InitCharmCreateSpells();
@@ -423,7 +414,6 @@ Puppet::Puppet(SummonPropertiesEntry const* properties, Unit* owner)
423414
void Puppet::InitStats(uint32 duration)
424415
{
425416
Minion::InitStats(duration);
426-
SetLevel(GetOwner()->getLevel());
427417
SetReactState(REACT_PASSIVE);
428418
}
429419

0 commit comments

Comments
 (0)