aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp2
-rw-r--r--src/server/game/Entities/GameObject/GameObject.h5
-rw-r--r--src/server/game/Entities/Object/Object.cpp4
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h2
-rw-r--r--src/server/game/Spells/Spell.h1
-rw-r--r--src/server/game/Spells/SpellEffects.cpp51
-rw-r--r--src/server/game/Spells/SpellInfo.cpp2
7 files changed, 63 insertions, 4 deletions
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index 4f2a19a2d72..ca4ff39e14e 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -107,7 +107,7 @@ QuaternionData QuaternionData::fromEulerAnglesZYX(float Z, float Y, float X)
}
GameObject::GameObject() : WorldObject(false), MapObject(),
- m_model(nullptr), m_goValue(), m_AI(nullptr), m_respawnCompatibilityMode(false), _animKitId(0), _worldEffectID(0)
+ m_model(nullptr), m_goValue(), m_AI(nullptr), m_respawnCompatibilityMode(false), _animKitId(0), _worldEffectID(0), m_visibleByUnitOnly()
{
m_objectType |= TYPEMASK_GAMEOBJECT;
m_objectTypeId = TYPEID_GAMEOBJECT;
diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h
index d49a8363e51..faf4b8dec72 100644
--- a/src/server/game/Entities/GameObject/GameObject.h
+++ b/src/server/game/Entities/GameObject/GameObject.h
@@ -317,6 +317,10 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject>
void AIM_Destroy();
bool AIM_Initialize();
+ void SetVisibleByUnitOnly(ObjectGuid unit) { m_visibleByUnitOnly = unit; }
+ bool IsVisibleByUnitOnly() const { return !m_visibleByUnitOnly.IsEmpty(); }
+ ObjectGuid GetVisibleByUnitOnly() const { return m_visibleByUnitOnly; }
+
UF::UpdateField<UF::GameObjectData, 0, TYPEID_GAMEOBJECT> m_gameObjectData;
protected:
@@ -374,5 +378,6 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject>
bool m_respawnCompatibilityMode;
uint16 _animKitId;
uint32 _worldEffectID;
+ ObjectGuid m_visibleByUnitOnly;
};
#endif
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index 96992a698a5..7e9ce1fff40 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -1453,6 +1453,10 @@ bool WorldObject::CanSeeOrDetect(WorldObject const* obj, bool ignoreStealth, boo
return false;
}
+ if (GameObject const* go = obj->ToGameObject())
+ if (go->IsVisibleByUnitOnly() && GetGUID() != go->GetVisibleByUnitOnly())
+ return false;
+
if (!viewpoint)
viewpoint = this;
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index 83b6372cc4b..e6243536357 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -1219,7 +1219,7 @@ enum SpellEffectName
SPELL_EFFECT_ALLOW_CONTROL_PET = 168, // NYI
SPELL_EFFECT_DESTROY_ITEM = 169,
SPELL_EFFECT_UPDATE_ZONE_AURAS_AND_PHASES = 170, // NYI
- SPELL_EFFECT_171 = 171, // Summons gamebject
+ SPELL_EFFECT_SUMMON_PERSONAL_GAMEOBJECT = 171, // Summons gamebject
SPELL_EFFECT_RESURRECT_WITH_AURA = 172,
SPELL_EFFECT_UNLOCK_GUILD_VAULT_TAB = 173, // Guild tab unlocked (guild perk)
SPELL_EFFECT_APPLY_AURA_ON_PET = 174, // NYI
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index 11a196d2ed4..e9f609639cb 100644
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -462,6 +462,7 @@ class TC_GAME_API Spell
void EffectCastButtons(SpellEffIndex effIndex);
void EffectRechargeItem(SpellEffIndex effIndex);
void EffectGiveCurrency(SpellEffIndex effIndex);
+ void EffectSummonPersonalGameObject(SpellEffIndex effIndex);
void EffectResurrectWithAura(SpellEffIndex effIndex);
void EffectCreateAreaTrigger(SpellEffIndex effIndex);
void EffectRemoveTalent(SpellEffIndex effIndex);
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 7db4fc958d5..e373411b120 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -249,7 +249,7 @@ NonDefaultConstructible<pEffect> SpellEffects[TOTAL_SPELL_EFFECTS] =
&Spell::EffectNULL, //168 SPELL_EFFECT_ALLOW_CONTROL_PET
&Spell::EffectDestroyItem, //169 SPELL_EFFECT_DESTROY_ITEM
&Spell::EffectUpdateZoneAurasAndPhases, //170 SPELL_EFFECT_UPDATE_ZONE_AURAS_AND_PHASES
- &Spell::EffectNULL, //171 SPELL_EFFECT_171
+ &Spell::EffectSummonPersonalGameObject, //171 SPELL_EFFECT_SUMMON_PERSONAL_GAMEOBJECT
&Spell::EffectResurrectWithAura, //172 SPELL_EFFECT_RESURRECT_WITH_AURA
&Spell::EffectUnlockGuildVaultTab, //173 SPELL_EFFECT_UNLOCK_GUILD_VAULT_TAB
&Spell::EffectApplyAura, //174 SPELL_EFFECT_APPLY_AURA_ON_PET
@@ -5427,6 +5427,55 @@ void Spell::EffectUnlockGuildVaultTab(SpellEffIndex /*effIndex*/)
guild->HandleBuyBankTab(caster->GetSession(), damage - 1); // Bank tabs start at zero internally
}
+void Spell::EffectSummonPersonalGameObject(SpellEffIndex effIndex)
+{
+ if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
+ return;
+
+ uint32 goId = effectInfo->MiscValue;
+ if (!goId)
+ return;
+
+ float x, y, z;
+ if (m_targets.HasDst())
+ destTarget->GetPosition(x, y, z);
+ else
+ m_caster->GetClosePoint(x, y, z, DEFAULT_PLAYER_BOUNDING_RADIUS);
+
+ Map* map = m_caster->GetMap();
+ Position pos = Position(x, y, z, m_caster->GetOrientation());
+ QuaternionData rot = QuaternionData::fromEulerAnglesZYX(m_caster->GetOrientation(), 0.f, 0.f);
+ GameObject* go = GameObject::CreateGameObject(goId, map, pos, rot, 255, GO_STATE_READY);
+
+ if (!go)
+ {
+ TC_LOG_WARN("spells", "SpellEffect Failed to summon personal gameobject. SpellId %u, effect %u", m_spellInfo->Id, effIndex);
+ return;
+ }
+
+ PhasingHandler::InheritPhaseShift(go, m_caster);
+
+ int32 duration = m_spellInfo->CalcDuration(m_caster);
+
+ go->SetRespawnTime(duration > 0 ? duration / IN_MILLISECONDS : 0);
+ go->SetSpellId(m_spellInfo->Id);
+ go->SetVisibleByUnitOnly(m_caster->GetGUID());
+
+ ExecuteLogEffectSummonObject(effIndex, go);
+
+ map->AddToMap(go);
+
+ if (GameObject* linkedTrap = go->GetLinkedTrap())
+ {
+ PhasingHandler::InheritPhaseShift(linkedTrap, m_caster);
+
+ linkedTrap->SetRespawnTime(duration > 0 ? duration / IN_MILLISECONDS : 0);
+ linkedTrap->SetSpellId(m_spellInfo->Id);
+
+ ExecuteLogEffectSummonObject(effIndex, linkedTrap);
+ }
+}
+
void Spell::EffectResurrectWithAura(SpellEffIndex effIndex)
{
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index 4f98c6573c7..81a71a8df8c 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -962,7 +962,7 @@ SpellEffectInfo::StaticData SpellEffectInfo::_data[TOTAL_SPELL_EFFECTS] =
{EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 168 SPELL_EFFECT_168
{EFFECT_IMPLICIT_TARGET_CASTER, TARGET_OBJECT_TYPE_UNIT}, // 169 SPELL_EFFECT_DESTROY_ITEM
{EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 170 SPELL_EFFECT_170
- {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_DEST}, // 171 SPELL_EFFECT_171
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_DEST}, // 171 SPELL_EFFECT_SUMMON_PERSONAL_GAMEOBJECT
{EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 172 SPELL_EFFECT_172
{EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 173 SPELL_EFFECT_UNLOCK_GUILD_VAULT_TAB
{EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 174 SPELL_EFFECT_174