Core/Scenes: Implemented spell created SceneObjects

Port From (https://github.com/TrinityCore/TrinityCore/commit/d7302ffd1499433fef2cc4e824ae9443c3d2c79f)
This commit is contained in:
hondacrx
2021-10-11 17:21:33 -04:00
parent b0528d1ad3
commit d2bcc321f5
11 changed files with 374 additions and 17 deletions
+6 -4
View File
@@ -107,11 +107,13 @@ namespace Framework.Constants
GameObject = 0x08,
Player = 0x10,
AreaTrigger = 0x20,
Conversation = 0x40,
All = 0x7F,
SceneObject = 0x40,
Conversation = 0x80,
//GameObjects, Creatures(except pets), DynamicObject, Corpse(Bones), AreaTrigger
AllGrid = GameObject | Creature | DynamicObject | Corpse | AreaTrigger | Conversation,
All = 0xFF,
//GameObjects, Creatures(except pets), DynamicObject, Corpse(Bones), AreaTrigger, SceneObject
AllGrid = GameObject | Creature | DynamicObject | Corpse | AreaTrigger | SceneObject | Conversation,
//Player, Pets, Corpse(resurrectable), DynamicObject(farsight)
AllWorld = Player | Creature | Corpse | DynamicObject
+1 -1
View File
@@ -50,7 +50,7 @@ namespace Framework.Constants
DynamicObject = 0x200,
Corpse = 0x400,
AreaTrigger = 0x800,
Sceneobject = 0x1000,
SceneObject = 0x1000,
Conversation = 0x2000,
Seer = Player | Unit | DynamicObject
}
@@ -2839,4 +2839,10 @@ namespace Framework.Constants
FanfareNeeded = 0x80,
DisplayOverridden = 0x100
}
public enum SceneType
{
Normal = 0,
PetBattle = 1
}
}
@@ -5566,7 +5566,7 @@ namespace Game.Entities
WriteUpdate(data, _changesMask, false, owner, receiver);
}
void WriteUpdate(WorldPacket data, UpdateMask changesMask, bool ignoreNestedChangesMask, WorldObject owner, Player receiver)
public void WriteUpdate(WorldPacket data, UpdateMask changesMask, bool ignoreNestedChangesMask, WorldObject owner, Player receiver)
{
data.WriteBits(_changesMask.GetBlock(0), 5);
+9 -8
View File
@@ -20,14 +20,14 @@ using Framework.Dynamic;
using Framework.GameMath;
using Game.AI;
using Game.BattleFields;
using Game.DataStorage;
using Game.Maps;
using Game.Networking;
using Game.Networking.Packets;
using Game.Scenarios;
using Game.Spells;
using System;
using System.Collections.Generic;
using Game.DataStorage;
using Game.Spells;
namespace Game.Entities
{
@@ -155,6 +155,7 @@ namespace Game.Entities
case HighGuid.Corpse:
case HighGuid.DynamicObject:
case HighGuid.AreaTrigger:
case HighGuid.SceneObject:
case HighGuid.Conversation:
updateType = UpdateType.CreateObject2;
break;
@@ -606,11 +607,11 @@ namespace Game.Entities
// *data << ObjectGuid(ReplaceObject);
//}
//if (flags.SceneObject)
//{
// data.WriteBit(HasLocalScriptData);
// data.WriteBit(HasPetBattleFullUpdate);
// data.FlushBits();
if (flags.SceneObject)
{
data.WriteBit(false); // HasLocalScriptData
data.WriteBit(false); // HasPetBattleFullUpdate
data.FlushBits();
// if (HasLocalScriptData)
// {
@@ -714,7 +715,7 @@ namespace Game.Entities
// data.WriteBit(CanAwardXP);
// data.FlushBits();
// }
//}
}
if (flags.ActivePlayer)
{
+208
View File
@@ -0,0 +1,208 @@
/*
* Copyright (C) 2012-2020 CypherCore <http://github.com/CypherCore>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using Framework.Constants;
using Game.Maps;
using Game.Networking;
using Game.Spells;
namespace Game.Entities
{
public class SceneObject : WorldObject
{
SceneObjectData m_sceneObjectData;
Position _stationaryPosition;
ObjectGuid _createdBySpellCast;
public SceneObject() : base(false)
{
ObjectTypeMask |= TypeMask.SceneObject;
ObjectTypeId = TypeId.SceneObject;
m_updateFlag.Stationary = true;
m_updateFlag.SceneObject = true;
}
public override void AddToWorld()
{
if (!IsInWorld)
{
GetMap().GetObjectsStore().Add(GetGUID(), this);
base.AddToWorld();
}
}
public override void RemoveFromWorld()
{
if (IsInWorld)
{
base.RemoveFromWorld();
GetMap().GetObjectsStore().Remove(GetGUID());
}
}
public override void Update(uint diff)
{
base.Update(diff);
if (ShouldBeRemoved())
Remove();
}
void Remove()
{
if (IsInWorld)
AddObjectToRemoveList();
}
bool ShouldBeRemoved()
{
Unit creator = Global.ObjAccessor.GetUnit(this, GetOwnerGUID());
if (creator == null)
return true;
if (!_createdBySpellCast.IsEmpty())
{
// search for a dummy aura on creator
Aura linkedAura = creator.GetAura(_createdBySpellCast.GetEntry(), aura => aura.GetCastId() == _createdBySpellCast);
if (linkedAura == null)
return true;
}
return false;
}
public static SceneObject CreateSceneObject(uint sceneId, Unit creator, Position pos, ObjectGuid privateObjectOwner)
{
SceneTemplate sceneTemplate = Global.ObjectMgr.GetSceneTemplate(sceneId);
if (sceneTemplate == null)
return null;
ulong lowGuid = creator.GetMap().GenerateLowGuid(HighGuid.SceneObject);
SceneObject sceneObject = new SceneObject();
if (!sceneObject.Create(lowGuid, SceneType.Normal, sceneId, sceneTemplate != null ? sceneTemplate.ScenePackageId : 0, creator.GetMap(), creator, pos, privateObjectOwner))
{
sceneObject.Dispose();
return null;
}
return sceneObject;
}
bool Create(ulong lowGuid, SceneType type, uint sceneId, uint scriptPackageId, Map map, Unit creator, Position pos, ObjectGuid privateObjectOwner)
{
SetMap(map);
Relocate(pos);
RelocateStationaryPosition(pos);
SetPrivateObjectOwner(privateObjectOwner);
_Create(ObjectGuid.Create(HighGuid.SceneObject, GetMapId(), sceneId, lowGuid));
PhasingHandler.InheritPhaseShift(this, creator);
SetEntry(scriptPackageId);
SetObjectScale(1.0f);
SetUpdateFieldValue(m_values.ModifyValue(m_sceneObjectData).ModifyValue(m_sceneObjectData.ScriptPackageID), (int)scriptPackageId);
SetUpdateFieldValue(m_values.ModifyValue(m_sceneObjectData).ModifyValue(m_sceneObjectData.RndSeedVal), GameTime.GetGameTimeMS());
SetUpdateFieldValue(m_values.ModifyValue(m_sceneObjectData).ModifyValue(m_sceneObjectData.CreatedBy), creator.GetGUID());
SetUpdateFieldValue(m_values.ModifyValue(m_sceneObjectData).ModifyValue(m_sceneObjectData.SceneType), (uint)type);
if (!GetMap().AddToMap(this))
return false;
return true;
}
public override void BuildValuesCreate(WorldPacket data, Player target)
{
UpdateFieldFlag flags = GetUpdateFieldFlagsFor(target);
WorldPacket buffer = new();
m_objectData.WriteCreate(buffer, flags, this, target);
m_sceneObjectData.WriteCreate(buffer, flags, this, target);
data.WriteUInt32(buffer.GetSize());
data.WriteUInt8((byte)flags);
data.WriteBytes(buffer);
}
public override void BuildValuesUpdate(WorldPacket data, Player target)
{
UpdateFieldFlag flags = GetUpdateFieldFlagsFor(target);
WorldPacket buffer = new();
buffer.WriteUInt32(m_values.GetChangedObjectTypeMask());
if (m_values.HasChanged(TypeId.Object))
m_objectData.WriteUpdate(buffer, flags, this, target);
if (m_values.HasChanged(TypeId.SceneObject))
m_sceneObjectData.WriteUpdate(buffer, flags, this, target);
data.WriteUInt32(buffer.GetSize());
data.WriteBytes(buffer);
}
void BuildValuesUpdateForPlayerWithMask(UpdateData data, UpdateMask requestedObjectMask, UpdateMask requestedSceneObjectMask, Player target)
{
UpdateMask valuesMask = new((int)TypeId.Max);
if (requestedObjectMask.IsAnySet())
valuesMask.Set((int)TypeId.Object);
if (requestedSceneObjectMask.IsAnySet())
valuesMask.Set((int)TypeId.SceneObject);
WorldPacket buffer = new();
buffer.WriteUInt32(valuesMask.GetBlock(0));
if (valuesMask[(int)TypeId.Object])
m_objectData.WriteUpdate(buffer, requestedObjectMask, true, this, target);
if (valuesMask[(int)TypeId.SceneObject])
m_sceneObjectData.WriteUpdate(buffer, requestedSceneObjectMask, true, this, target);
WorldPacket buffer1 = new();
buffer1.WriteUInt8((byte)UpdateType.Values);
buffer1.WritePackedGuid(GetGUID());
buffer1.WriteUInt32(buffer.GetSize());
buffer1.WriteBytes(buffer.GetData());
data.AddUpdateBlock(buffer1);
}
public override void ClearUpdateMask(bool remove)
{
m_values.ClearChangesMask(m_sceneObjectData);
base.ClearUpdateMask(remove);
}
public override ObjectGuid GetOwnerGUID() { return m_sceneObjectData.CreatedBy; }
public override uint GetFaction() { return 0; }
public override float GetStationaryX() { return _stationaryPosition.GetPositionX(); }
public override float GetStationaryY() { return _stationaryPosition.GetPositionY(); }
public override float GetStationaryZ() { return _stationaryPosition.GetPositionZ(); }
public override float GetStationaryO() { return _stationaryPosition.GetOrientation(); }
void RelocateStationaryPosition(Position pos) { _stationaryPosition.Relocate(pos); }
public void SetCreatedBySpellCast(ObjectGuid castId) { _createdBySpellCast = castId; }
}
}
+11
View File
@@ -51,6 +51,8 @@ public class ObjectAccessor : Singleton<ObjectAccessor>
return GetAreaTrigger(p, guid);
case HighGuid.Corpse:
return GetCorpse(p, guid);
case HighGuid.SceneObject:
return GetSceneObject(p, guid);
case HighGuid.Conversation:
return GetConversation(p, guid);
default:
@@ -92,6 +94,10 @@ public class ObjectAccessor : Singleton<ObjectAccessor>
if (typemask.HasAnyFlag(TypeMask.AreaTrigger))
return GetAreaTrigger(p, guid);
break;
case HighGuid.SceneObject:
if (typemask.HasAnyFlag(TypeMask.SceneObject))
return GetSceneObject(p, guid);
break;
case HighGuid.Conversation:
if (typemask.HasAnyFlag(TypeMask.Conversation))
return GetConversation(p, guid);
@@ -133,6 +139,11 @@ public class ObjectAccessor : Singleton<ObjectAccessor>
return u.GetMap().GetAreaTrigger(guid);
}
static SceneObject GetSceneObject(WorldObject u, ObjectGuid guid)
{
return u.GetMap().GetSceneObject(guid);
}
static Conversation GetConversation(WorldObject u, ObjectGuid guid)
{
return u.GetMap().GetConversation(guid);
+9 -1
View File
@@ -292,6 +292,7 @@ namespace Game.Maps
visitor.Visit(_container.dynamicObjects);
visitor.Visit(_container.corpses);
visitor.Visit(_container.areaTriggers);
visitor.Visit(_container.sceneObjects);
visitor.Visit(_container.conversations);
visitor.Visit(_container.worldObjects);
break;
@@ -349,7 +350,7 @@ namespace Game.Maps
MultiTypeContainer _objects;
/// <summary>
/// Holds all Grid objects - GameObjects, Creatures(except pets), DynamicObject, Corpse(Bones), AreaTrigger, Conversation
/// Holds all Grid objects - GameObjects, Creatures(except pets), DynamicObject, Corpse(Bones), AreaTrigger, Conversation, SceneObject
/// </summary>
MultiTypeContainer _container;
}
@@ -379,6 +380,9 @@ namespace Game.Maps
case TypeId.AreaTrigger:
areaTriggers.Add((AreaTrigger)obj);
break;
case TypeId.SceneObject:
sceneObjects.Add((SceneObject)obj);
break;
case TypeId.Conversation:
conversations.Add((Conversation)obj);
break;
@@ -408,6 +412,9 @@ namespace Game.Maps
case TypeId.AreaTrigger:
areaTriggers.Remove((AreaTrigger)obj);
break;
case TypeId.SceneObject:
sceneObjects.Remove((SceneObject)obj);
break;
case TypeId.Conversation:
conversations.Remove((Conversation)obj);
break;
@@ -447,6 +454,7 @@ namespace Game.Maps
public List<Corpse> corpses = new();
public List<DynamicObject> dynamicObjects = new();
public List<AreaTrigger> areaTriggers = new();
public List<SceneObject> sceneObjects = new();
public List<Conversation> conversations = new();
public List<GameObject> gameObjects = new();
public List<WorldObject> worldObjects = new();
+67
View File
@@ -31,6 +31,7 @@ namespace Game.Maps
public virtual void Visit(IList<WorldObject> objs) { }
public virtual void Visit(IList<Creature> objs) { }
public virtual void Visit(IList<AreaTrigger> objs) { }
public virtual void Visit(IList<SceneObject> objs) { }
public virtual void Visit(IList<Conversation> objs) { }
public virtual void Visit(IList<GameObject> objs) { }
public virtual void Visit(IList<DynamicObject> objs) { }
@@ -66,6 +67,7 @@ namespace Game.Maps
public void Visit(IList<WorldObject> collection) { _notifier.Visit(collection); }
public void Visit(IList<Creature> creatures) { _notifier.Visit(creatures); }
public void Visit(IList<AreaTrigger> areatriggers) { _notifier.Visit(areatriggers); }
public void Visit(IList<SceneObject> sceneObjects) { _notifier.Visit(sceneObjects); }
public void Visit(IList<Conversation> conversations) { _notifier.Visit(conversations); }
public void Visit(IList<GameObject> gameobjects) { _notifier.Visit(gameobjects); }
public void Visit(IList<DynamicObject> dynamicobjects) { _notifier.Visit(dynamicobjects); }
@@ -767,6 +769,19 @@ namespace Game.Maps
}
}
public override void Visit(IList<SceneObject> objs)
{
if (!i_mapTypeMask.HasAnyFlag(GridMapTypeMask.SceneObject))
return;
for (var i = 0; i < objs.Count; ++i)
{
SceneObject sceneObject = objs[i];
if (sceneObject.IsInPhase(_searcher))
i_do.Invoke(sceneObject);
}
}
public override void Visit(IList<Conversation> objs)
{
if (!i_mapTypeMask.HasAnyFlag(GridMapTypeMask.Conversation))
@@ -1129,6 +1144,29 @@ namespace Game.Maps
}
}
public override void Visit(IList<SceneObject> objs)
{
if (!i_mapTypeMask.HasAnyFlag(GridMapTypeMask.SceneObject))
return;
// already found
if (i_object)
return;
for (var i = 0; i < objs.Count; ++i)
{
SceneObject sceneObject = objs[i];
if (!sceneObject.IsInPhase(_searcher))
continue;
if (i_check.Invoke(sceneObject))
{
i_object = sceneObject;
return;
}
}
}
public override void Visit(IList<Conversation> objs)
{
if (!i_mapTypeMask.HasAnyFlag(GridMapTypeMask.Conversation))
@@ -1264,6 +1302,22 @@ namespace Game.Maps
}
}
public override void Visit(IList<SceneObject> objs)
{
if (!i_mapTypeMask.HasAnyFlag(GridMapTypeMask.SceneObject))
return;
for (var i = 0; i < objs.Count; ++i)
{
SceneObject sceneObject = objs[i];
if (!sceneObject.IsInPhase(_searcher))
continue;
if (i_check.Invoke(sceneObject))
i_object = sceneObject;
}
}
public override void Visit(IList<Conversation> objs)
{
if (!i_mapTypeMask.HasAnyFlag(GridMapTypeMask.Conversation))
@@ -1375,6 +1429,19 @@ namespace Game.Maps
}
}
public override void Visit(IList<SceneObject> objs)
{
if (!i_mapTypeMask.HasAnyFlag(GridMapTypeMask.Conversation))
return;
for (var i = 0; i < objs.Count; ++i)
{
SceneObject sceneObject = objs[i];
if (i_check.Invoke(sceneObject))
i_objects.Add(sceneObject);
}
}
public override void Visit(IList<Conversation> objs)
{
if (!i_mapTypeMask.HasAnyFlag(GridMapTypeMask.Conversation))
+7 -1
View File
@@ -21,7 +21,6 @@ using Framework.Dynamic;
using Framework.GameMath;
using Game.BattleGrounds;
using Game.Collision;
using Game.Combat;
using Game.DataStorage;
using Game.Entities;
using Game.Groups;
@@ -3824,14 +3823,21 @@ namespace Game.Maps
return (AreaTrigger)_objectsStore.LookupByKey(guid);
}
public SceneObject GetSceneObject(ObjectGuid guid)
{
return _objectsStore.LookupByKey(guid) as SceneObject;
}
public Conversation GetConversation(ObjectGuid guid)
{
return (Conversation)_objectsStore.LookupByKey(guid);
}
public Player GetPlayer(ObjectGuid guid)
{
return Global.ObjAccessor.GetPlayer(this, guid);
}
public Corpse GetCorpse(ObjectGuid guid)
{
if (!guid.IsCorpse())
+49 -1
View File
@@ -16,7 +16,6 @@
*/
using Framework.Constants;
using Framework.Dynamic;
using Framework.GameMath;
using Game.BattleGrounds;
using Game.BattlePets;
@@ -32,6 +31,7 @@ using Game.Movement;
using Game.Networking.Packets;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Game.Spells
{
@@ -5589,6 +5589,54 @@ namespace Game.Spells
m_caster.ToPlayer().GetSceneMgr().PlaySceneByPackageId((uint)effectInfo.MiscValue, SceneFlags.PlayerNonInteractablePhased, destTarget);
}
bool IsUnitTargetSceneObjectAura(Spell spell, TargetInfo target)
{
if (target.TargetGUID != spell.GetCaster().GetGUID())
return false;
foreach (SpellEffectInfo spellEffectInfo in spell.GetSpellInfo().GetEffects())
if ((target.EffectMask & (1 << (int)spellEffectInfo.EffectIndex)) != 0 && spellEffectInfo.IsUnitOwnedAuraEffect())
return true;
return false;
}
[SpellEffectHandler(SpellEffectName.CreateSceneObject)]
void EffectCreateSceneObject()
{
if (effectHandleMode != SpellEffectHandleMode.Hit)
return;
if (!unitCaster || !m_targets.HasDst())
return;
SceneObject sceneObject = SceneObject.CreateSceneObject((uint)effectInfo.MiscValue, unitCaster, destTarget.GetPosition(), ObjectGuid.Empty);
if (sceneObject != null)
{
bool hasAuraTargetingCaster = m_UniqueTargetInfo.Any(target => IsUnitTargetSceneObjectAura(this, target));
if (hasAuraTargetingCaster)
sceneObject.SetCreatedBySpellCast(m_castId);
}
}
[SpellEffectHandler(SpellEffectName.CreatePersonalSceneObject)]
void EffectCreatePrivateSceneObject()
{
if (effectHandleMode != SpellEffectHandleMode.Hit)
return;
if (!unitCaster || !m_targets.HasDst())
return;
SceneObject sceneObject = SceneObject.CreateSceneObject((uint)effectInfo.MiscValue, unitCaster, destTarget.GetPosition(), unitCaster.GetGUID());
if (sceneObject != null)
{
bool hasAuraTargetingCaster = m_UniqueTargetInfo.Any(target => IsUnitTargetSceneObjectAura(this, target));
if (hasAuraTargetingCaster)
sceneObject.SetCreatedBySpellCast(m_castId);
}
}
[SpellEffectHandler(SpellEffectName.PlayScene)]
void EffectPlayScene()
{