Core/GameObjects: Transport (type 11) improvements

Port From (https://github.com/TrinityCore/TrinityCore/commit/630b60eb0dcd3d9ce41582664ab822b049365431)
This commit is contained in:
hondacrx
2022-06-03 16:20:41 -04:00
parent e65ce31742
commit 40444525b2
30 changed files with 807 additions and 377 deletions
@@ -79,27 +79,27 @@ namespace Game.Entities
uint GetViewerDependentDynamicFlags(ObjectFieldData objectData, WorldObject obj, Player receiver)
{
UnitDynFlags unitDynFlags = (UnitDynFlags)(uint)objectData.DynamicFlags;
uint unitDynFlags = objectData.DynamicFlags;
Unit unit = obj.ToUnit();
if (unit != null)
{
unitDynFlags &= ~UnitDynFlags.Tapped;
unitDynFlags &= ~(uint)UnitDynFlags.Tapped;
Creature creature = obj.ToCreature();
if (creature != null)
{
if (creature.HasLootRecipient() && !creature.IsTappedBy(receiver))
unitDynFlags |= UnitDynFlags.Tapped;
unitDynFlags |= (uint)UnitDynFlags.Tapped;
if (!receiver.IsAllowedToLoot(creature))
unitDynFlags &= ~UnitDynFlags.Lootable;
unitDynFlags &= ~(uint)UnitDynFlags.Lootable;
}
// unit UNIT_DYNFLAG_TRACK_UNIT should only be sent to caster of SPELL_AURA_MOD_STALKED auras
if (unitDynFlags.HasAnyFlag(UnitDynFlags.TrackUnit))
if (unitDynFlags.HasAnyFlag((uint)UnitDynFlags.TrackUnit))
if (!unit.HasAuraTypeWithCaster(AuraType.ModStalked, receiver.GetGUID()))
unitDynFlags &= ~UnitDynFlags.TrackUnit;
unitDynFlags &= ~(uint)UnitDynFlags.TrackUnit;
}
else
{
@@ -126,12 +126,18 @@ namespace Game.Entities
dynFlags |= GameObjectDynamicLowFlags.Sparkle | GameObjectDynamicLowFlags.Highlight;
break;
case GameObjectTypes.Transport:
{
dynFlags = (GameObjectDynamicLowFlags)((int)unitDynFlags & 0xFFFF);
pathProgress = (ushort)((int)unitDynFlags >> 16);
break;
}
case GameObjectTypes.MapObjTransport:
{
uint transportPeriod = gameObject.GetTransportPeriod();
Transport transport = gameObject.ToTransport();
uint transportPeriod = transport.GetTransportPeriod();
if (transportPeriod != 0)
{
float timer = (float)(gameObject.GetGoValue().Transport.PathProgress % transportPeriod);
float timer = (float)(transport.GetTimer() % transportPeriod);
pathProgress = (ushort)(timer / (float)transportPeriod * 65535.0f);
}
break;
@@ -146,11 +152,11 @@ namespace Game.Entities
break;
}
unitDynFlags = (UnitDynFlags)((pathProgress << 16) | (ushort)dynFlags);
unitDynFlags = (uint)((pathProgress << 16) | (ushort)dynFlags);
}
}
return (uint)unitDynFlags;
return unitDynFlags;
}
}
@@ -4946,13 +4952,13 @@ namespace Game.Entities
data.WriteFloat(rotation.Z);
data.WriteFloat(rotation.W);
data.WriteUInt32(FactionTemplate);
data.WriteInt8(GetViewerGameObjectState(this, owner, receiver));
data.WriteInt8(State);
data.WriteInt8(TypeID);
data.WriteUInt8(PercentHealth);
data.WriteUInt32(ArtKit);
data.WriteInt32(EnableDoodadSets.Size());
data.WriteUInt32(CustomParam);
data.WriteUInt32(GetViewerGameObjectLevel(this, owner, receiver));
data.WriteUInt32(Level);
data.WriteUInt32(AnimGroupInstance);
for (int i = 0; i < EnableDoodadSets.Size(); ++i)
{
@@ -5053,7 +5059,7 @@ namespace Game.Entities
}
if (changesMask[14])
{
data.WriteInt8(GetViewerGameObjectState(this, owner, receiver));
data.WriteInt8(State);
}
if (changesMask[15])
{
@@ -5073,7 +5079,7 @@ namespace Game.Entities
}
if (changesMask[19])
{
data.WriteUInt32(GetViewerGameObjectLevel(this, owner, receiver));
data.WriteUInt32(Level);
}
if (changesMask[20])
{
@@ -5116,24 +5122,6 @@ namespace Game.Entities
return flags;
}
uint GetViewerGameObjectLevel(GameObjectFieldData gameObjectData, GameObject gameObject, Player receiver)
{
uint level = gameObjectData.Level;
bool isStoppableTransport = gameObject.GetGoType() == GameObjectTypes.Transport && !gameObject.GetGoValue().Transport.StopFrames.Empty();
return isStoppableTransport ? gameObject.GetGoValue().Transport.PathProgress : level;
}
sbyte GetViewerGameObjectState(GameObjectFieldData gameObjectData, GameObject gameObject, Player receiver)
{
sbyte state = gameObjectData.State;
bool isStoppableTransport = gameObject.GetGoType() == GameObjectTypes.Transport && !gameObject.GetGoValue().Transport.StopFrames.Empty();
if (isStoppableTransport && gameObject.GetGoState() == GameObjectState.TransportActive)
if (((gameObject.GetGoValue().Transport.StateUpdateTimer / 20000) & 1) != 0)
state = (sbyte)GameObjectState.TransportStopped;
return state;
}
}
public class DynamicObjectData : BaseUpdateData<DynamicObject>
+23 -52
View File
@@ -246,14 +246,10 @@ namespace Game.Entities
public void BuildMovementUpdate(WorldPacket data, CreateObjectBits flags, Player target)
{
int PauseTimesCount = 0;
List<uint> PauseTimes = null;
GameObject go = ToGameObject();
if (go)
{
if (go.GetGoType() == GameObjectTypes.Transport)
PauseTimesCount = go.GetGoValue().Transport.StopFrames.Count;
}
PauseTimes = go.GetPauseTimes();
data.WriteBit(flags.NoBirthAnim);
data.WriteBit(flags.EnablePortals);
@@ -368,7 +364,7 @@ namespace Game.Entities
MovementExtensions.WriteCreateObjectSplineDataBlock(unit.MoveSpline, data);
}
data.WriteInt32(PauseTimesCount);
data.WriteInt32(PauseTimes != null ? PauseTimes.Count : 0);
if (flags.Stationary)
{
@@ -381,20 +377,9 @@ namespace Game.Entities
if (flags.CombatVictim)
data.WritePackedGuid(ToUnit().GetVictim().GetGUID()); // CombatVictim
if (flags.ServerTime)
{
GameObject go1 = ToGameObject();
/** @TODO Use IsTransport() to also handle type 11 (TRANSPORT)
Currently grid objects are not updated if there are no nearby players,
this causes clients to receive different PathProgress
resulting in players seeing the object in a different position
*/
if (go1 && go1.ToTransport()) // ServerTime
data.WriteUInt32(go1.GetGoValue().Transport.PathProgress);
else
data.WriteUInt32(GameTime.GetGameTimeMS());
}
data.WriteUInt32(GameTime.GetGameTimeMS());
if (flags.Vehicle)
{
@@ -413,11 +398,9 @@ namespace Game.Entities
if (flags.Rotation)
data.WriteInt64(ToGameObject().GetPackedLocalRotation()); // Rotation
if (go)
{
for (int i = 0; i < PauseTimesCount; ++i)
data.WriteUInt32(go.GetGoValue().Transport.StopFrames[i]);
}
if (PauseTimes != null && !PauseTimes.Empty())
foreach (var stopFrame in PauseTimes)
data.WriteUInt32(stopFrame);
if (flags.MovementTransport)
{
@@ -969,19 +952,9 @@ namespace Game.Entities
return;
if (on)
{
if (IsTypeId(TypeId.Unit))
map.AddToActive(ToCreature());
else if (IsTypeId(TypeId.DynamicObject))
map.AddToActive(ToDynamicObject());
}
map.AddToActive(this);
else
{
if (IsTypeId(TypeId.Unit))
map.RemoveFromActive(ToCreature());
else if (IsTypeId(TypeId.DynamicObject))
map.RemoveFromActive(ToDynamicObject());
}
map.RemoveFromActive(this);
}
bool IsFarVisible() { return m_isFarVisible; }
@@ -1010,8 +983,8 @@ namespace Game.Entities
if (IsInWorld)
RemoveFromWorld();
Transport transport = GetTransport();
if (transport)
ITransport transport = GetTransport();
if (transport != null)
transport.RemovePassenger(this);
}
@@ -2957,12 +2930,6 @@ namespace Game.Entities
public float GetObjectScale() { return m_objectData.Scale; }
public virtual void SetObjectScale(float scale) { SetUpdateFieldValue(m_values.ModifyValue(m_objectData).ModifyValue(m_objectData.Scale), scale); }
public UnitDynFlags GetDynamicFlags() { return (UnitDynFlags)(uint)m_objectData.DynamicFlags; }
public bool HasDynamicFlag(UnitDynFlags flag) { return (m_objectData.DynamicFlags & (uint)flag) != 0; }
public void SetDynamicFlag(UnitDynFlags flag) { SetUpdateFieldFlagValue(m_values.ModifyValue(m_objectData).ModifyValue(m_objectData.DynamicFlags), (uint)flag); }
public void RemoveDynamicFlag(UnitDynFlags flag) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(m_objectData).ModifyValue(m_objectData.DynamicFlags), (uint)flag); }
public void ReplaceAllDynamicFlags(UnitDynFlags flag) { SetUpdateFieldValue(m_values.ModifyValue(m_objectData).ModifyValue(m_objectData.DynamicFlags), (uint)flag); }
public TypeId GetTypeId() { return ObjectTypeId; }
public bool IsTypeId(TypeId typeId) { return GetTypeId() == typeId; }
public bool IsTypeMask(TypeMask mask) { return Convert.ToBoolean(mask & ObjectTypeMask); }
@@ -3007,7 +2974,11 @@ namespace Game.Entities
public bool IsActiveObject() { return m_isActive; }
public bool IsPermanentWorldObject() { return m_isWorldObject; }
public Transport GetTransport() { return m_transport; }
public ITransport GetTransport() { return m_transport; }
public T GetTransport<T>() where T : ITransport
{
return (T)m_transport;
}
public float GetTransOffsetX() { return m_movementInfo.transport.pos.GetPositionX(); }
public float GetTransOffsetY() { return m_movementInfo.transport.pos.GetPositionY(); }
public float GetTransOffsetZ() { return m_movementInfo.transport.pos.GetPositionZ(); }
@@ -3017,12 +2988,12 @@ namespace Game.Entities
public sbyte GetTransSeat() { return m_movementInfo.transport.seat; }
public virtual ObjectGuid GetTransGUID()
{
if (GetTransport())
return GetTransport().GetGUID();
if (GetTransport() != null)
return GetTransport().GetTransportGUID();
return ObjectGuid.Empty;
}
public void SetTransport(Transport t) { m_transport = t; }
public void SetTransport(ITransport t) { m_transport = t; }
public virtual float GetStationaryX() { return GetPositionX(); }
public virtual float GetStationaryY() { return GetPositionY(); }
@@ -3065,7 +3036,7 @@ namespace Game.Entities
Position thisOrTransport = this;
Position objOrObjTransport = obj;
if (GetTransport() && obj.GetTransport() != null && obj.GetTransport().GetGUID() == GetTransport().GetGUID())
if (GetTransport() != null && obj.GetTransport() != null && obj.GetTransport().GetTransportGUID() == GetTransport().GetTransportGUID())
{
thisOrTransport = m_movementInfo.transport.pos;
objOrObjTransport = obj.m_movementInfo.transport.pos;
@@ -3340,7 +3311,7 @@ namespace Game.Entities
public void UpdateAllowedPositionZ(float x, float y, ref float z, ref float groundZ)
{
// TODO: Allow transports to be part of dynamic vmap tree
if (GetTransport())
if (GetTransport() != null)
{
groundZ = z;
return;
@@ -3690,7 +3661,7 @@ namespace Game.Entities
bool m_isWorldObject;
public ZoneScript m_zoneScript;
Transport m_transport;
ITransport m_transport;
Map _currMap;
uint instanceId;
PhaseShift _phaseShift = new();