diff options
author | Giacomo Pozzoni <giacomopoz@gmail.com> | 2020-12-26 22:32:01 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-26 22:32:01 +0100 |
commit | 3b2c878dd067f49ee48ddfc27c62eb4e1fe619d9 (patch) | |
tree | ee44efef2fba97af61bed899c0ad29c5e35a017d /src | |
parent | e8b78acbee35b63f4f19fdcfdf4915cf9d784b27 (diff) |
Core/Spells: Implemented personal summons (#19231) (#25765)
* Core/Spells: Implemented personal summons (#19231)
* By default determined by summon property flag SUMMON_PROP_FLAG_PERSONAL_SPAWN
Closes #18254
(cherry picked from commit b7bb5e6a98119512702519adecf559ecedc20743)
# Conflicts:
# src/server/game/Combat/ThreatManager.cpp
# src/server/game/DataStores/DBCEnums.h
# src/server/game/Entities/Creature/TemporarySummon.cpp
# src/server/game/Entities/Creature/TemporarySummon.h
# src/server/game/Entities/GameObject/GameObject.cpp
# src/server/game/Entities/Object/Object.cpp
# src/server/game/Entities/Object/Object.h
# src/server/game/Maps/Map.h
# src/server/game/Spells/SpellEffects.cpp
* Build fix
* Implement feedback
* Fix parameters passed in wrong order
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Combat/ThreatManager.cpp | 18 | ||||
-rw-r--r-- | src/server/game/Entities/Creature/TemporarySummon.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Creature/TemporarySummon.h | 3 | ||||
-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 | ||||
-rw-r--r-- | src/server/shared/DataStores/DBCEnums.h | 2 |
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 |