aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Combat/ThreatManager.cpp20
-rw-r--r--src/server/game/DataStores/DBCEnums.h2
-rw-r--r--src/server/game/Entities/Creature/TemporarySummon.cpp2
-rw-r--r--src/server/game/Entities/Creature/TemporarySummon.h4
-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
9 files changed, 51 insertions, 17 deletions
diff --git a/src/server/game/Combat/ThreatManager.cpp b/src/server/game/Combat/ThreatManager.cpp
index d9d86aa24b3..e3a8cd7bcb3 100644
--- a/src/server/game/Combat/ThreatManager.cpp
+++ b/src/server/game/Combat/ThreatManager.cpp
@@ -25,6 +25,7 @@
#include "UnitEvents.h"
#include "SpellAuras.h"
#include "SpellMgr.h"
+#include "TemporarySummon.h"
//==============================================================
//================= ThreatCalcHelper ===========================
@@ -415,11 +416,28 @@ void ThreatManager::addThreat(Unit* victim, float threat, SpellSchoolMask school
void ThreatManager::doAddThreat(Unit* victim, float threat)
{
uint32 redirectThreadPct = victim->GetRedirectThreatPercent();
+ Unit* redirectTarget = victim->GetRedirectThreatTarget();
+
+ // If victim is personnal spawn, redirect all aggro to summoner
+ if (TempSummon* tempSummonVictim = victim->ToTempSummon())
+ {
+ if (tempSummonVictim->IsVisibleBySummonerOnly())
+ {
+ // Personnal Spawns from same summoner can aggro each other
+ if (!GetOwner()->ToTempSummon() ||
+ !GetOwner()->ToTempSummon()->IsVisibleBySummonerOnly() ||
+ tempSummonVictim->GetSummonerGUID() != GetOwner()->ToTempSummon()->GetSummonerGUID())
+ {
+ redirectThreadPct = 100;
+ redirectTarget = tempSummonVictim->GetSummoner();
+ }
+ }
+ }
// must check > 0.0f, otherwise dead loop
if (threat > 0.0f && redirectThreadPct)
{
- if (Unit* redirectTarget = victim->GetRedirectThreatTarget())
+ if (redirectTarget)
{
float redirectThreat = CalculatePct(threat, redirectThreadPct);
threat -= redirectThreat;
diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h
index 404c5de75a8..92b8d0128c4 100644
--- a/src/server/game/DataStores/DBCEnums.h
+++ b/src/server/game/DataStores/DBCEnums.h
@@ -957,7 +957,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
diff --git a/src/server/game/Entities/Creature/TemporarySummon.cpp b/src/server/game/Entities/Creature/TemporarySummon.cpp
index b13c85cf36c..7a609a2c83a 100644
--- a/src/server/game/Entities/Creature/TemporarySummon.cpp
+++ b/src/server/game/Entities/Creature/TemporarySummon.cpp
@@ -27,7 +27,7 @@
TempSummon::TempSummon(SummonPropertiesEntry const* properties, Unit* owner, bool isWorldObject) :
Creature(isWorldObject), m_Properties(properties), m_type(TEMPSUMMON_MANUAL_DESPAWN),
-m_timer(0), m_lifetime(0)
+m_timer(0), m_lifetime(0), 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 49662e1ac95..785b848529b 100644
--- a/src/server/game/Entities/Creature/TemporarySummon.h
+++ b/src/server/game/Entities/Creature/TemporarySummon.h
@@ -60,12 +60,16 @@ class TC_GAME_API TempSummon : public Creature
TempSummonType const& GetSummonType() { return m_type; }
uint32 GetTimer() const { return m_timer; }
+ void SetVisibleBySummonerOnly(bool visibleBySummonerOnly) { m_visibleBySummonerOnly = visibleBySummonerOnly; }
+ bool IsVisibleBySummonerOnly() const { return m_visibleBySummonerOnly; }
+
const SummonPropertiesEntry* const m_Properties;
private:
TempSummonType m_type;
uint32 m_timer;
uint32 m_lifetime;
ObjectGuid m_summonerGUID;
+ 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 185d2f1f781..2917f7d2b08 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -2645,7 +2645,7 @@ void GameObject::SetAnimKitId(uint16 animKitId, bool oneshot)
class GameObjectModelOwnerImpl : public GameObjectModelOwnerBase
{
public:
- explicit GameObjectModelOwnerImpl(GameObject const* owner) : _owner(owner) { }
+ explicit GameObjectModelOwnerImpl(GameObject* owner) : _owner(owner) { }
virtual ~GameObjectModelOwnerImpl() = default;
bool IsSpawned() const override { return _owner->isSpawned(); }
@@ -2658,7 +2658,7 @@ public:
void DebugVisualizeCorner(G3D::Vector3 const& corner) const override { _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 6175f8c7a02..17d767f04e9 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -2112,8 +2112,15 @@ bool WorldObject::CanSeeOrDetect(WorldObject const* obj, bool ignoreStealth, boo
WorldObject const* viewpoint = this;
if (Player const* player = this->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;
@@ -2346,7 +2353,7 @@ void WorldObject::AddObjectToRemoveList()
map->AddObjectToRemoveList(this);
}
-TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropertiesEntry const* properties /*= NULL*/, uint32 duration /*= 0*/, Unit* summoner /*= NULL*/, uint32 spellId /*= 0*/, uint32 vehId /*= 0*/)
+TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropertiesEntry const* properties /*= NULL*/, uint32 duration /*= 0*/, Unit* summoner /*= NULL*/, uint32 spellId /*= 0*/, uint32 vehId /*= 0*/, bool visibleBySummonerOnly /*= false*/)
{
uint32 mask = UNIT_MASK_SUMMON;
if (properties)
@@ -2431,6 +2438,9 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert
summon->SetHomePosition(pos);
summon->InitStats(duration);
+
+ summon->SetVisibleBySummonerOnly(visibleBySummonerOnly);
+
AddToMap(summon->ToCreature());
summon->InitSummon();
@@ -2485,11 +2495,11 @@ Scenario* WorldObject::GetScenario() const
return nullptr;
}
-TempSummon* WorldObject::SummonCreature(uint32 entry, Position const& pos, TempSummonType spwtype /*= TEMPSUMMON_MANUAL_DESPAWN*/, uint32 duration /*= 0*/, uint32 /*vehId = 0*/) const
+TempSummon* WorldObject::SummonCreature(uint32 entry, Position const& pos, TempSummonType spwtype /*= TEMPSUMMON_MANUAL_DESPAWN*/, uint32 duration /*= 0*/, uint32 vehId /*= 0*/, bool visibleBySummonerOnly /*= false*/)
{
if (Map* map = FindMap())
{
- if (TempSummon* summon = map->SummonCreature(entry, pos, NULL, duration, isType(TYPEMASK_UNIT) ? (Unit*)this : NULL))
+ if (TempSummon* summon = map->SummonCreature(entry, pos, nullptr, duration, ToUnit(), 0, vehId, visibleBySummonerOnly))
{
summon->SetTempSummonType(spwtype);
return summon;
@@ -2499,7 +2509,7 @@ TempSummon* WorldObject::SummonCreature(uint32 entry, Position const& pos, TempS
return nullptr;
}
-TempSummon* WorldObject::SummonCreature(uint32 id, float x, float y, float z, float ang /*= 0*/, TempSummonType spwtype /*= TEMPSUMMON_MANUAL_DESPAWN*/, uint32 despwtime /*= 0*/) const
+TempSummon* WorldObject::SummonCreature(uint32 id, float x, float y, float z, float ang /*= 0*/, TempSummonType spwtype /*= TEMPSUMMON_MANUAL_DESPAWN*/, uint32 despwtime /*= 0*/, bool visibleBySummonerOnly /*= false*/)
{
if (!x && !y && !z)
{
@@ -2509,7 +2519,7 @@ TempSummon* WorldObject::SummonCreature(uint32 id, float x, float y, float z, fl
Position pos;
pos.Relocate(x, y, z, ang);
- return SummonCreature(id, pos, spwtype, despwtime, 0);
+ return SummonCreature(id, pos, spwtype, despwtime, 0, visibleBySummonerOnly);
}
GameObject* WorldObject::SummonGameObject(uint32 entry, Position const& pos, QuaternionData const& rot, uint32 respawnTime)
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index 13b75f8bc89..539cf8fbccf 100644
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -502,8 +502,8 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation
Scenario* GetScenario() const;
- TempSummon* SummonCreature(uint32 id, Position const& pos, TempSummonType spwtype = TEMPSUMMON_MANUAL_DESPAWN, uint32 despwtime = 0, uint32 vehId = 0) const;
- TempSummon* SummonCreature(uint32 id, float x, float y, float z, float ang = 0, TempSummonType spwtype = TEMPSUMMON_MANUAL_DESPAWN, uint32 despwtime = 0) const;
+ TempSummon* SummonCreature(uint32 id, Position const& pos, TempSummonType spwtype = TEMPSUMMON_MANUAL_DESPAWN, uint32 despwtime = 0, uint32 vehId = 0, bool visibleBySummonerOnly = false);
+ TempSummon* SummonCreature(uint32 id, float x, float y, float z, float ang = 0, TempSummonType spwtype = TEMPSUMMON_MANUAL_DESPAWN, uint32 despwtime = 0, bool visibleBySummonerOnly = false);
GameObject* SummonGameObject(uint32 entry, Position const& pos, QuaternionData const& rot, uint32 respawnTime /* s */);
GameObject* SummonGameObject(uint32 entry, float x, float y, float z, float ang, QuaternionData const& rot, uint32 respawnTime /* s */);
Creature* SummonTrigger(float x, float y, float z, float ang, uint32 dur, CreatureAI* (*GetAI)(Creature*) = NULL);
diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h
index a459c653af7..5f7c391a794 100644
--- a/src/server/game/Maps/Map.h
+++ b/src/server/game/Maps/Map.h
@@ -447,7 +447,7 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
void UpdateIteratorBack(Player* player);
- TempSummon* SummonCreature(uint32 entry, Position const& pos, SummonPropertiesEntry const* properties = NULL, uint32 duration = 0, Unit* summoner = NULL, uint32 spellId = 0, uint32 vehId = 0);
+ TempSummon* SummonCreature(uint32 entry, Position const& pos, SummonPropertiesEntry const* properties = NULL, uint32 duration = 0, Unit* summoner = NULL, uint32 spellId = 0, uint32 vehId = 0, bool visibleOnlyBySummoner = false);
void SummonCreatureGroup(uint8 group, std::list<TempSummon*>* list = NULL);
AreaTrigger* GetAreaTrigger(ObjectGuid const& guid);
Conversation* GetConversation(ObjectGuid const& guid);
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index a03b124f4b4..0c2e55e7025 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -1974,6 +1974,8 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)
if (!m_originalCaster)
return;
+ bool personalSpawn = (properties->Flags & SUMMON_PROP_FLAG_PERSONAL_SPAWN) != 0;
+
int32 duration = m_spellInfo->CalcDuration(m_originalCaster);
TempSummon* summon = NULL;
@@ -2035,7 +2037,7 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)
case SUMMON_TYPE_LIGHTWELL:
case SUMMON_TYPE_TOTEM:
{
- summon = m_caster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, m_originalCaster, m_spellInfo->Id);
+ summon = m_caster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, m_originalCaster, m_spellInfo->Id, 0, personalSpawn);
if (!summon || !summon->IsTotem())
return;
@@ -2048,7 +2050,7 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)
}
case SUMMON_TYPE_MINIPET:
{
- summon = m_caster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, m_originalCaster, m_spellInfo->Id);
+ summon = m_caster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, m_originalCaster, m_spellInfo->Id, 0, personalSpawn);
if (!summon || !summon->HasUnitTypeMask(UNIT_MASK_MINION))
return;
@@ -2075,7 +2077,7 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)
// randomize position for multiple summons
pos = m_caster->GetRandomPoint(*destTarget, radius);
- summon = m_originalCaster->SummonCreature(entry, pos, summonType, duration);
+ summon = m_originalCaster->SummonCreature(entry, pos, summonType, duration, 0, personalSpawn);
if (!summon)
continue;
@@ -2096,7 +2098,7 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)
SummonGuardian(effIndex, entry, properties, numSummons);
break;
case SUMMON_CATEGORY_PUPPET:
- summon = m_caster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, m_originalCaster, m_spellInfo->Id);
+ summon = m_caster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, m_originalCaster, m_spellInfo->Id, 0, personalSpawn);
break;
case SUMMON_CATEGORY_VEHICLE:
// Summoning spells (usually triggered by npc_spellclick) that spawn a vehicle and that cause the clicker