aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Combat/ThreatManager.cpp18
-rw-r--r--src/server/game/Entities/Creature/TemporarySummon.cpp2
-rw-r--r--src/server/game/Entities/Creature/TemporarySummon.h3
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp4
-rw-r--r--src/server/game/Entities/Object/Object.cpp20
-rw-r--r--src/server/game/Entities/Object/Object.h4
-rw-r--r--src/server/game/Maps/Map.h2
-rw-r--r--src/server/game/Spells/SpellEffects.cpp10
-rw-r--r--src/server/shared/DataStores/DBCEnums.h2
9 files changed, 49 insertions, 16 deletions
diff --git a/src/server/game/Combat/ThreatManager.cpp b/src/server/game/Combat/ThreatManager.cpp
index df954a71ff4..ac099abe940 100644
--- a/src/server/game/Combat/ThreatManager.cpp
+++ b/src/server/game/Combat/ThreatManager.cpp
@@ -31,6 +31,7 @@
#include "ObjectAccessor.h"
#include "WorldPacket.h"
#include <algorithm>
+#include "TemporarySummon.h"
#include "Hacks/boost_1_74_fibonacci_heap.h"
BOOST_1_74_FIBONACCI_HEAP_MSVC_COMPILE_FIX(ThreatManager::threat_list_heap::value_type)
@@ -319,6 +320,23 @@ void ThreatManager::AddThreat(Unit* target, float amount, SpellInfo const* spell
return;
amount = 0.0f;
}
+ else if (TempSummon* tempSummonVictim = target->ToTempSummon())
+ {
+ if (tempSummonVictim->IsVisibleBySummonerOnly())
+ {
+ if (Unit* tempSummonSummoner = tempSummonVictim->GetSummonerUnit())
+ {
+ // Personnal Spawns from same summoner can aggro each other
+ if (!_owner->ToTempSummon() ||
+ !_owner->ToTempSummon()->IsVisibleBySummonerOnly() ||
+ tempSummonVictim->GetSummonerGUID() != GetOwner()->ToTempSummon()->GetSummonerGUID())
+ {
+ AddThreat(tempSummonSummoner, amount, spell, ignoreModifiers, ignoreRedirects);
+ amount = 0.0f;
+ }
+ }
+ }
+ }
// if we cannot actually have a threat list, we instead just set combat state and avoid creating threat refs altogether
if (!CanHaveThreatList())
diff --git a/src/server/game/Entities/Creature/TemporarySummon.cpp b/src/server/game/Entities/Creature/TemporarySummon.cpp
index 5f692e6d404..183f2eb76a5 100644
--- a/src/server/game/Entities/Creature/TemporarySummon.cpp
+++ b/src/server/game/Entities/Creature/TemporarySummon.cpp
@@ -28,7 +28,7 @@
TempSummon::TempSummon(SummonPropertiesEntry const* properties, WorldObject* owner, bool isWorldObject) :
Creature(isWorldObject), m_Properties(properties), m_type(TEMPSUMMON_MANUAL_DESPAWN),
-m_timer(0), m_lifetime(0), m_canFollowOwner(true)
+m_timer(0), m_lifetime(0), m_canFollowOwner(true), m_visibleBySummonerOnly(false)
{
if (owner)
m_summonerGUID = owner->GetGUID();
diff --git a/src/server/game/Entities/Creature/TemporarySummon.h b/src/server/game/Entities/Creature/TemporarySummon.h
index 9b85be6ff4b..24aff599f97 100644
--- a/src/server/game/Entities/Creature/TemporarySummon.h
+++ b/src/server/game/Entities/Creature/TemporarySummon.h
@@ -54,6 +54,8 @@ class TC_GAME_API TempSummon : public Creature
uint32 GetTimer() const { return m_timer; }
bool CanFollowOwner() const { return m_canFollowOwner; }
void SetCanFollowOwner(bool can) { m_canFollowOwner = can; }
+ void SetVisibleBySummonerOnly(bool visibleBySummonerOnly) { m_visibleBySummonerOnly = visibleBySummonerOnly; }
+ bool IsVisibleBySummonerOnly() const { return m_visibleBySummonerOnly; }
SummonPropertiesEntry const* const m_Properties;
@@ -64,6 +66,7 @@ class TC_GAME_API TempSummon : public Creature
uint32 m_lifetime;
ObjectGuid m_summonerGUID;
bool m_canFollowOwner;
+ bool m_visibleBySummonerOnly;
};
class TC_GAME_API Minion : public TempSummon
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index a9bed61c0b7..53ebcef7d12 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -2660,7 +2660,7 @@ void GameObject::UpdateModelPosition()
class GameObjectModelOwnerImpl : public GameObjectModelOwnerBase
{
public:
- explicit GameObjectModelOwnerImpl(GameObject const* owner) : _owner(owner) { }
+ explicit GameObjectModelOwnerImpl(GameObject* owner) : _owner(owner) { }
bool IsSpawned() const override { return _owner->isSpawned(); }
uint32 GetDisplayId() const override { return _owner->GetDisplayId(); }
@@ -2671,7 +2671,7 @@ public:
void DebugVisualizeCorner(G3D::Vector3 const& corner) const override { const_cast<GameObject*>(_owner)->SummonCreature(1, corner.x, corner.y, corner.z, 0, TEMPSUMMON_MANUAL_DESPAWN); }
private:
- GameObject const* _owner;
+ GameObject* _owner;
};
GameObjectModel* GameObject::CreateModel()
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index a1bdca52d97..590b351d762 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -1586,8 +1586,15 @@ bool WorldObject::CanSeeOrDetect(WorldObject const* obj, bool ignoreStealth, boo
WorldObject const* viewpoint = this;
if (Player const* player = ToPlayer())
+ {
viewpoint = player->GetViewpoint();
+ if (Creature const* creature = obj->ToCreature())
+ if (TempSummon const* tempSummon = creature->ToTempSummon())
+ if (tempSummon->IsVisibleBySummonerOnly() && GetGUID() != tempSummon->GetSummonerGUID())
+ return false;
+ }
+
if (!viewpoint)
viewpoint = this;
@@ -1847,7 +1854,7 @@ void WorldObject::AddObjectToRemoveList()
map->AddObjectToRemoveList(this);
}
-TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropertiesEntry const* properties /*= nullptr*/, uint32 duration /*= 0*/, WorldObject* summoner /*= nullptr*/, uint32 spellId /*= 0*/, uint32 vehId /*= 0*/)
+TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropertiesEntry const* properties /*= nullptr*/, uint32 duration /*= 0*/, WorldObject* summoner /*= nullptr*/, uint32 spellId /*= 0*/, uint32 vehId /*= 0*/, bool visibleBySummonerOnly /*= false*/)
{
uint32 mask = UNIT_MASK_SUMMON;
if (properties)
@@ -1934,6 +1941,9 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert
summon->SetHomePosition(pos);
summon->InitStats(duration);
+
+ summon->SetVisibleBySummonerOnly(visibleBySummonerOnly);
+
AddToMap(summon->ToCreature());
summon->InitSummon();
@@ -1984,11 +1994,11 @@ void WorldObject::ClearZoneScript()
m_zoneScript = nullptr;
}
-TempSummon* WorldObject::SummonCreature(uint32 entry, Position const& pos, TempSummonType despawnType /*= TEMPSUMMON_MANUAL_DESPAWN*/, Milliseconds despawnTime /*= 0s*/, uint32 /*vehId = 0*/, uint32 spellId /*= 0*/)
+TempSummon* WorldObject::SummonCreature(uint32 entry, Position const& pos, TempSummonType despawnType /*= TEMPSUMMON_MANUAL_DESPAWN*/, Milliseconds despawnTime /*= 0s*/, uint32 /*vehId = 0*/, uint32 spellId /*= 0*/, bool visibleBySummonerOnly /*= false*/)
{
if (Map* map = FindMap())
{
- if (TempSummon* summon = map->SummonCreature(entry, pos, nullptr, despawnTime.count(), this, spellId))
+ if (TempSummon* summon = map->SummonCreature(entry, pos, nullptr, despawnTime.count(), this, spellId, 0, visibleBySummonerOnly))
{
summon->SetTempSummonType(despawnType);
return summon;
@@ -1998,13 +2008,13 @@ TempSummon* WorldObject::SummonCreature(uint32 entry, Position const& pos, TempS
return nullptr;
}
-TempSummon* WorldObject::SummonCreature(uint32 id, float x, float y, float z, float o /*= 0*/, TempSummonType despawnType /*= TEMPSUMMON_MANUAL_DESPAWN*/, Milliseconds despawnTime /*= 0s*/)
+TempSummon* WorldObject::SummonCreature(uint32 id, float x, float y, float z, float o /*= 0*/, TempSummonType despawnType /*= TEMPSUMMON_MANUAL_DESPAWN*/, Milliseconds despawnTime /*= 0s*/, bool visibleBySummonerOnly /*= false*/)
{
if (!x && !y && !z)
GetClosePoint(x, y, z, GetCombatReach());
if (!o)
o = GetOrientation();
- return SummonCreature(id, { x,y,z,o }, despawnType, despawnTime);
+ return SummonCreature(id, { x,y,z,o }, despawnType, despawnTime, 0, 0, visibleBySummonerOnly);
}
GameObject* WorldObject::SummonGameObject(uint32 entry, Position const& pos, QuaternionData const& rot, Seconds respawnTime, GOSummonType summonType)
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index 1fb239a1031..c30eadecb9a 100644
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -404,8 +404,8 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation
void ClearZoneScript();
ZoneScript* GetZoneScript() const { return m_zoneScript; }
- TempSummon* SummonCreature(uint32 entry, Position const& pos, TempSummonType despawnType = TEMPSUMMON_MANUAL_DESPAWN, Milliseconds despawnTime = 0s, uint32 vehId = 0, uint32 spellId = 0);
- TempSummon* SummonCreature(uint32 entry, float x, float y, float z, float o = 0, TempSummonType despawnType = TEMPSUMMON_MANUAL_DESPAWN, Milliseconds despawnTime = 0s);
+ TempSummon* SummonCreature(uint32 entry, Position const& pos, TempSummonType despawnType = TEMPSUMMON_MANUAL_DESPAWN, Milliseconds despawnTime = 0s, uint32 vehId = 0, uint32 spellId = 0, bool visibleBySummonerOnly = false);
+ TempSummon* SummonCreature(uint32 entry, float x, float y, float z, float o = 0, TempSummonType despawnType = TEMPSUMMON_MANUAL_DESPAWN, Milliseconds despawnTime = 0s, bool visibleBySummonerOnly = false);
GameObject* SummonGameObject(uint32 entry, Position const& pos, QuaternionData const& rot, Seconds respawnTime, GOSummonType summonType = GO_SUMMON_TIMED_OR_CORPSE_DESPAWN);
GameObject* SummonGameObject(uint32 entry, float x, float y, float z, float ang, QuaternionData const& rot, Seconds respawnTime, GOSummonType summonType = GO_SUMMON_TIMED_OR_CORPSE_DESPAWN);
Creature* SummonTrigger(float x, float y, float z, float ang, Milliseconds despawnTime, CreatureAI* (*GetAI)(Creature*) = nullptr);
diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h
index 032ed6cf40d..601d0db2bc4 100644
--- a/src/server/game/Maps/Map.h
+++ b/src/server/game/Maps/Map.h
@@ -499,7 +499,7 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
void UpdateIteratorBack(Player* player);
- TempSummon* SummonCreature(uint32 entry, Position const& pos, SummonPropertiesEntry const* properties = nullptr, uint32 duration = 0, WorldObject* summoner = nullptr, uint32 spellId = 0, uint32 vehId = 0);
+ TempSummon* SummonCreature(uint32 entry, Position const& pos, SummonPropertiesEntry const* properties = nullptr, uint32 duration = 0, WorldObject* summoner = nullptr, uint32 spellId = 0, uint32 vehId = 0, bool visibleOnlyBySummoner = false);
void SummonCreatureGroup(uint8 group, std::list<TempSummon*>* list = nullptr);
Player* GetPlayer(ObjectGuid const& guid);
Corpse* GetCorpse(ObjectGuid const& guid);
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 68025cffc10..3cb8ee239dd 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -2043,6 +2043,8 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)
if (m_originalCaster)
caster = m_originalCaster;
+
+ bool personalSpawn = (properties->Flags & SUMMON_PROP_FLAG_PERSONAL_SPAWN) != 0;
int32 duration = m_spellInfo->GetDuration();
if (Player* modOwner = caster->GetSpellModOwner())
modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
@@ -2118,7 +2120,7 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)
if (!unitCaster)
return;
- summon = unitCaster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, unitCaster, m_spellInfo->Id);
+ summon = unitCaster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, unitCaster, m_spellInfo->Id, 0, personalSpawn);
if (!summon || !summon->IsTotem())
return;
@@ -2138,7 +2140,7 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)
if (!unitCaster)
return;
- summon = unitCaster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, unitCaster, m_spellInfo->Id);
+ summon = unitCaster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, unitCaster, m_spellInfo->Id, 0, personalSpawn);
if (!summon || !summon->HasUnitTypeMask(UNIT_MASK_MINION))
return;
@@ -2162,7 +2164,7 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)
// randomize position for multiple summons
pos = caster->GetRandomPoint(*destTarget, radius);
- summon = caster->SummonCreature(entry, pos, summonType, Milliseconds(duration), 0, m_spellInfo->Id);
+ summon = caster->SummonCreature(entry, pos, summonType, Milliseconds(duration), 0, m_spellInfo->Id, personalSpawn);
if (!summon)
continue;
@@ -2187,7 +2189,7 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)
if (!unitCaster)
return;
- summon = unitCaster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, unitCaster, m_spellInfo->Id);
+ summon = unitCaster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, unitCaster, m_spellInfo->Id, 0, personalSpawn);
break;
}
case SUMMON_CATEGORY_VEHICLE:
diff --git a/src/server/shared/DataStores/DBCEnums.h b/src/server/shared/DataStores/DBCEnums.h
index dd8592ee071..b87252b6e1d 100644
--- a/src/server/shared/DataStores/DBCEnums.h
+++ b/src/server/shared/DataStores/DBCEnums.h
@@ -415,7 +415,7 @@ enum SummonPropFlags
SUMMON_PROP_FLAG_UNK2 = 0x00000002, // 616 spells in 3.0.3, something friendly
SUMMON_PROP_FLAG_UNK3 = 0x00000004, // 22 spells in 3.0.3, no idea...
SUMMON_PROP_FLAG_UNK4 = 0x00000008, // 49 spells in 3.0.3, some mounts
- SUMMON_PROP_FLAG_UNK5 = 0x00000010, // 25 spells in 3.0.3, quest related?
+ SUMMON_PROP_FLAG_PERSONAL_SPAWN = 0x00000010, // Personal Spawn (creature visible only by summoner)
SUMMON_PROP_FLAG_UNK6 = 0x00000020, // 0 spells in 3.3.5, unused
SUMMON_PROP_FLAG_UNK7 = 0x00000040, // 12 spells in 3.0.3, no idea
SUMMON_PROP_FLAG_UNK8 = 0x00000080, // 4 spells in 3.0.3, no idea