diff options
| -rw-r--r-- | src/server/game/Combat/ThreatManager.cpp | 20 | ||||
| -rw-r--r-- | src/server/game/DataStores/DBCEnums.h | 2 | ||||
| -rw-r--r-- | src/server/game/Entities/Creature/TemporarySummon.cpp | 2 | ||||
| -rw-r--r-- | src/server/game/Entities/Creature/TemporarySummon.h | 4 | ||||
| -rw-r--r-- | src/server/game/Entities/GameObject/GameObject.cpp | 4 | ||||
| -rw-r--r-- | src/server/game/Entities/Object/Object.cpp | 20 | ||||
| -rw-r--r-- | src/server/game/Entities/Object/Object.h | 4 | ||||
| -rw-r--r-- | src/server/game/Maps/Map.h | 2 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 10 |
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 |
