Core/GameObjects: Transport (type 11) improvements
Port From (https://github.com/TrinityCore/TrinityCore/commit/630b60eb0dcd3d9ce41582664ab822b049365431)
This commit is contained in:
@@ -93,7 +93,7 @@ namespace Framework.Constants
|
||||
Max = 3
|
||||
}
|
||||
|
||||
public enum GameObjectDynamicLowFlags
|
||||
public enum GameObjectDynamicLowFlags : ushort
|
||||
{
|
||||
HideModel = 0x02,
|
||||
Activate = 0x04,
|
||||
|
||||
@@ -1360,7 +1360,7 @@ namespace Game.AI
|
||||
break;
|
||||
|
||||
if (e.GetTargetType() == SmartTargets.Self)
|
||||
_me.SetFacingTo((_me.GetTransport() ? _me.GetTransportHomePosition() : _me.GetHomePosition()).GetOrientation());
|
||||
_me.SetFacingTo((_me.GetTransport() != null ? _me.GetTransportHomePosition() : _me.GetHomePosition()).GetOrientation());
|
||||
else if (e.GetTargetType() == SmartTargets.Position)
|
||||
_me.SetFacingTo(e.Target.o);
|
||||
else if (!targets.Empty())
|
||||
|
||||
@@ -1079,7 +1079,7 @@ namespace Game.Chat
|
||||
[Command("transport", RBACPermissions.CommandDebugTransport)]
|
||||
static bool HandleDebugTransportCommand(CommandHandler handler, string operation)
|
||||
{
|
||||
Transport transport = handler.GetSession().GetPlayer().GetTransport();
|
||||
Transport transport = handler.GetSession().GetPlayer().GetTransport<Transport>();
|
||||
if (!transport)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -959,7 +959,7 @@ namespace Game.Chat
|
||||
areaId, (areaEntry != null ? areaEntry.AreaName[handler.GetSessionDbcLocale()] : unknown),
|
||||
obj.GetPositionX(), obj.GetPositionY(), obj.GetPositionZ(), obj.GetOrientation());
|
||||
|
||||
Transport transport = obj.GetTransport();
|
||||
Transport transport = obj.GetTransport<Transport>();
|
||||
if (transport)
|
||||
{
|
||||
handler.SendSysMessage(CypherStrings.TransportPosition, transport.GetGoInfo().MoTransport.SpawnMap, obj.GetTransOffsetX(), obj.GetTransOffsetY(), obj.GetTransOffsetZ(), obj.GetTransOffsetO(),
|
||||
|
||||
@@ -654,7 +654,7 @@ namespace Game.Chat
|
||||
Player chr = handler.GetSession().GetPlayer();
|
||||
Map map = chr.GetMap();
|
||||
|
||||
Transport trans = chr.GetTransport();
|
||||
Transport trans = chr.GetTransport<Transport>();
|
||||
if (trans)
|
||||
{
|
||||
ulong guid = Global.ObjectMgr.GenerateCreatureSpawnId();
|
||||
|
||||
@@ -191,8 +191,8 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
// movement on transport of areatriggers on unit is handled by themself
|
||||
Transport transport = m_movementInfo.transport.guid.IsEmpty() ? caster.GetTransport() : null;
|
||||
if (transport)
|
||||
ITransport transport = m_movementInfo.transport.guid.IsEmpty() ? caster.GetTransport() : null;
|
||||
if (transport != null)
|
||||
{
|
||||
float x, y, z, o;
|
||||
pos.GetPosition(out x, out y, out z, out o);
|
||||
@@ -211,7 +211,7 @@ namespace Game.Entities
|
||||
|
||||
if (!GetMap().AddToMap(this))
|
||||
{ // Returning false will cause the object to be deleted - remove from transport
|
||||
if (transport)
|
||||
if (transport != null)
|
||||
transport.RemovePassenger(this);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -286,6 +286,7 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
public CorpseDynFlags GetCorpseDynamicFlags() { return (CorpseDynFlags)(uint)m_corpseData.DynamicFlags; }
|
||||
public bool HasCorpseDynamicFlag(CorpseDynFlags flag) { return (m_corpseData.DynamicFlags & (uint)flag) != 0; }
|
||||
public void SetCorpseDynamicFlag(CorpseDynFlags dynamicFlags) { SetUpdateFieldFlagValue(m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.DynamicFlags), (uint)dynamicFlags); }
|
||||
public void RemoveCorpseDynamicFlag(CorpseDynFlags dynamicFlags) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.DynamicFlags), (uint)dynamicFlags); }
|
||||
public void ReplaceAllCorpseDynamicFlags(CorpseDynFlags dynamicFlags) { SetUpdateFieldValue(m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.DynamicFlags), (uint)dynamicFlags); }
|
||||
|
||||
@@ -1254,7 +1254,12 @@ namespace Game.Entities
|
||||
return;
|
||||
}
|
||||
|
||||
uint mapId = GetTransport() ? (uint)GetTransport().GetGoInfo().MoTransport.SpawnMap : GetMapId();
|
||||
uint mapId = GetMapId();
|
||||
ITransport transport = GetTransport();
|
||||
if (transport != null)
|
||||
if (transport.GetMapIdForSpawning() >= 0)
|
||||
mapId = (uint)transport.GetMapIdForSpawning();
|
||||
|
||||
SaveToDB(mapId, data.SpawnDifficulties);
|
||||
}
|
||||
|
||||
|
||||
@@ -111,8 +111,8 @@ namespace Game.Entities
|
||||
if (IsWorldObject())
|
||||
SetActive(true); //must before add to map to be put in world container
|
||||
|
||||
Transport transport = caster.GetTransport();
|
||||
if (transport)
|
||||
ITransport transport = caster.GetTransport();
|
||||
if (transport != null)
|
||||
{
|
||||
float x, y, z, o;
|
||||
pos.GetPosition(out x, out y, out z, out o);
|
||||
@@ -126,7 +126,7 @@ namespace Game.Entities
|
||||
if (!GetMap().AddToMap(this))
|
||||
{
|
||||
// Returning false will cause the object to be deleted - remove from transport
|
||||
if (transport)
|
||||
if (transport != null)
|
||||
transport.RemovePassenger(this);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -60,8 +60,6 @@ namespace Game.Entities
|
||||
{
|
||||
m_AI = null;
|
||||
m_model = null;
|
||||
if (m_goInfo != null && m_goInfo.type == GameObjectTypes.Transport)
|
||||
m_goValue.Transport.StopFrames.Clear();
|
||||
|
||||
base.Dispose();
|
||||
}
|
||||
@@ -311,38 +309,15 @@ namespace Game.Entities
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.ParentRotation), new Quaternion(goInfo.DestructibleBuilding.DestructibleModelRec, 0f, 0f, 0f));
|
||||
break;
|
||||
case GameObjectTypes.Transport:
|
||||
m_goValue.Transport.AnimationInfo = Global.TransportMgr.GetTransportAnimInfo(goInfo.entry);
|
||||
m_goValue.Transport.PathProgress = Time.GetMSTime();
|
||||
if (!m_goValue.Transport.AnimationInfo.Path.Empty())
|
||||
m_goValue.Transport.PathProgress -= m_goValue.Transport.PathProgress % GetTransportPeriod(); // align to period
|
||||
m_goValue.Transport.CurrentSeg = 0;
|
||||
m_goValue.Transport.StateUpdateTimer = 0;
|
||||
m_goValue.Transport.StopFrames = new List<uint>();
|
||||
if (goInfo.Transport.Timeto2ndfloor > 0)
|
||||
m_goValue.Transport.StopFrames.Add(goInfo.Transport.Timeto2ndfloor);
|
||||
if (goInfo.Transport.Timeto3rdfloor > 0)
|
||||
m_goValue.Transport.StopFrames.Add(goInfo.Transport.Timeto3rdfloor);
|
||||
if (goInfo.Transport.Timeto4thfloor > 0)
|
||||
m_goValue.Transport.StopFrames.Add(goInfo.Transport.Timeto4thfloor);
|
||||
if (goInfo.Transport.Timeto5thfloor > 0)
|
||||
m_goValue.Transport.StopFrames.Add(goInfo.Transport.Timeto5thfloor);
|
||||
if (goInfo.Transport.Timeto6thfloor > 0)
|
||||
m_goValue.Transport.StopFrames.Add(goInfo.Transport.Timeto6thfloor);
|
||||
if (goInfo.Transport.Timeto7thfloor > 0)
|
||||
m_goValue.Transport.StopFrames.Add(goInfo.Transport.Timeto7thfloor);
|
||||
if (goInfo.Transport.Timeto8thfloor > 0)
|
||||
m_goValue.Transport.StopFrames.Add(goInfo.Transport.Timeto8thfloor);
|
||||
if (goInfo.Transport.Timeto9thfloor > 0)
|
||||
m_goValue.Transport.StopFrames.Add(goInfo.Transport.Timeto9thfloor);
|
||||
if (goInfo.Transport.Timeto10thfloor > 0)
|
||||
m_goValue.Transport.StopFrames.Add(goInfo.Transport.Timeto10thfloor);
|
||||
m_goTypeImpl = new GameObjectType.Transport(this);
|
||||
|
||||
if (goInfo.Transport.startOpen != 0)
|
||||
SetTransportState(GameObjectState.TransportStopped, goInfo.Transport.startOpen - 1);
|
||||
SetGoState(GameObjectState.TransportStopped);
|
||||
else
|
||||
SetTransportState(GameObjectState.TransportActive);
|
||||
SetGoState(GameObjectState.TransportActive);
|
||||
|
||||
SetGoAnimProgress(animProgress);
|
||||
SetActive(true);
|
||||
break;
|
||||
case GameObjectTypes.FishingNode:
|
||||
SetLevel(1);
|
||||
@@ -452,6 +427,9 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
if (m_goTypeImpl != null)
|
||||
m_goTypeImpl.Update(diff);
|
||||
|
||||
switch (m_lootState)
|
||||
{
|
||||
case LootState.NotReady:
|
||||
@@ -475,50 +453,6 @@ namespace Game.Entities
|
||||
m_lootState = LootState.Ready;
|
||||
break;
|
||||
}
|
||||
case GameObjectTypes.Transport:
|
||||
if (m_goValue.Transport.AnimationInfo.Path.Empty())
|
||||
break;
|
||||
|
||||
m_goValue.Transport.PathProgress += diff;
|
||||
|
||||
if (GetGoState() == GameObjectState.TransportActive)
|
||||
{
|
||||
m_goValue.Transport.PathProgress += diff;
|
||||
/* TODO: Fix movement in unloaded grid - currently GO will just disappear
|
||||
public uint timer = m_goValue.Transport.PathProgress % GetTransportPeriod();
|
||||
TransportAnimationEntry const* node = m_goValue.Transport.AnimationInfo.GetAnimNode(timer);
|
||||
if (node && m_goValue.Transport.CurrentSeg != node.TimeSeg)
|
||||
{
|
||||
m_goValue.Transport.CurrentSeg = node.TimeSeg;
|
||||
|
||||
G3D.Quat rotation = m_goValue.Transport.AnimationInfo.GetAnimRotation(timer);
|
||||
G3D.Vector3 pos = rotation.toRotationMatrix()
|
||||
G3D.Matrix3.fromEulerAnglesZYX(GetOrientation(), 0.0f, 0.0f)
|
||||
G3D.Vector3(node.X, node.Y, node.Z);
|
||||
|
||||
pos += G3D.Vector3(GetStationaryX(), GetStationaryY(), GetStationaryZ());
|
||||
|
||||
G3D.Vector3 src(GetPositionX(), GetPositionY(), GetPositionZ());
|
||||
|
||||
TC_LOG_DEBUG("misc", "Src: {0} Dest: {1}", src.toString().c_str(), pos.toString().c_str());
|
||||
|
||||
GetMap().GameObjectRelocation(this, pos.x, pos.y, pos.z, GetOrientation());
|
||||
}
|
||||
*/
|
||||
if (!m_goValue.Transport.StopFrames.Empty())
|
||||
{
|
||||
uint visualStateBefore = (m_goValue.Transport.StateUpdateTimer / 20000) & 1;
|
||||
m_goValue.Transport.StateUpdateTimer += diff;
|
||||
uint visualStateAfter = (m_goValue.Transport.StateUpdateTimer / 20000) & 1;
|
||||
if (visualStateBefore != visualStateAfter)
|
||||
{
|
||||
m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.Level);
|
||||
m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.State);
|
||||
ForceUpdateFieldChange();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GameObjectTypes.FishingNode:
|
||||
{
|
||||
// fishing code (bobber ready)
|
||||
@@ -1072,7 +1006,13 @@ namespace Game.Entities
|
||||
return;
|
||||
}
|
||||
|
||||
SaveToDB(GetMapId(), data.SpawnDifficulties);
|
||||
uint mapId = GetMapId();
|
||||
ITransport transport = GetTransport();
|
||||
if (transport != null)
|
||||
if (transport.GetMapIdForSpawning() >= 0)
|
||||
mapId = (uint)transport.GetMapIdForSpawning();
|
||||
|
||||
SaveToDB(mapId, data.SpawnDifficulties);
|
||||
}
|
||||
|
||||
public void SaveToDB(uint mapid, List<Difficulty> spawnDifficulties)
|
||||
@@ -1293,7 +1233,7 @@ namespace Game.Entities
|
||||
if (gInfo == null)
|
||||
return false;
|
||||
|
||||
return gInfo.type == GameObjectTypes.MapObjTransport || (gInfo.type == GameObjectTypes.Transport && m_goValue.Transport.StopFrames.Empty());
|
||||
return gInfo.type == GameObjectTypes.MapObjTransport || gInfo.type == GameObjectTypes.Transport;
|
||||
}
|
||||
|
||||
public bool IsDestructibleBuilding()
|
||||
@@ -1581,7 +1521,7 @@ namespace Game.Entities
|
||||
case GameObjectActions.GoTo9thFloor:
|
||||
case GameObjectActions.GoTo10thFloor:
|
||||
if (GetGoType() == GameObjectTypes.Transport)
|
||||
SetTransportState(GameObjectState.TransportStopped, (uint)(action - GameObjectActions.GoTo1stFloor));
|
||||
SetGoState((GameObjectState)action);
|
||||
else
|
||||
Log.outError(LogFilter.Spells, $"Spell {spellId} targeted non-transport gameobject for transport only action \"Go to Floor\" {action} in effect {effectIndex}");
|
||||
break;
|
||||
@@ -2453,7 +2393,7 @@ namespace Game.Entities
|
||||
{
|
||||
Quaternion localRotation = GetLocalRotation();
|
||||
|
||||
Transport transport = GetTransport();
|
||||
Transport transport = GetTransport<Transport>();
|
||||
if (transport != null)
|
||||
{
|
||||
Quaternion worldRotation = transport.GetWorldRotation();
|
||||
@@ -2563,7 +2503,6 @@ namespace Game.Entities
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public void ModifyHealth(int change, WorldObject attackerOrHealer = null, uint spellId = 0)
|
||||
{
|
||||
if (m_goValue.Building.MaxHealth == 0 || change == 0)
|
||||
@@ -2742,9 +2681,14 @@ namespace Game.Entities
|
||||
|
||||
public void SetGoState(GameObjectState state)
|
||||
{
|
||||
GameObjectState oldState = GetGoState();
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.State), (sbyte)state);
|
||||
if (GetAI() != null)
|
||||
GetAI().OnStateChanged(state);
|
||||
|
||||
if (m_goTypeImpl != null)
|
||||
m_goTypeImpl.OnStateChanged(oldState, state);
|
||||
|
||||
if (m_model != null && !IsTransport())
|
||||
{
|
||||
if (!IsInWorld)
|
||||
@@ -2759,38 +2703,6 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
public virtual uint GetTransportPeriod()
|
||||
{
|
||||
Cypher.Assert(GetGoInfo().type == GameObjectTypes.Transport);
|
||||
if (!m_goValue.Transport.AnimationInfo.Path.Empty())
|
||||
return m_goValue.Transport.AnimationInfo.TotalTime;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void SetTransportState(GameObjectState state, uint stopFrame = 0)
|
||||
{
|
||||
if (GetGoState() == state)
|
||||
return;
|
||||
|
||||
Cypher.Assert(GetGoInfo().type == GameObjectTypes.Transport);
|
||||
Cypher.Assert(state >= GameObjectState.TransportActive);
|
||||
if (state == GameObjectState.TransportActive)
|
||||
{
|
||||
m_goValue.Transport.StateUpdateTimer = 0;
|
||||
m_goValue.Transport.PathProgress = Time.GetMSTime();
|
||||
if (GetGoState() >= GameObjectState.TransportStopped)
|
||||
m_goValue.Transport.PathProgress += m_goValue.Transport.StopFrames.LookupByIndex(GetGoState() - GameObjectState.TransportStopped);
|
||||
SetGoState(GameObjectState.TransportActive);
|
||||
}
|
||||
else
|
||||
{
|
||||
Cypher.Assert(stopFrame < m_goValue.Transport.StopFrames.Count);
|
||||
m_goValue.Transport.PathProgress = Time.GetMSTime() + m_goValue.Transport.StopFrames[(int)stopFrame];
|
||||
SetGoState((GameObjectState)((int)GameObjectState.TransportStopped + stopFrame));
|
||||
}
|
||||
}
|
||||
|
||||
public void SetDisplayId(uint displayid)
|
||||
{
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.DisplayID), displayid);
|
||||
@@ -2985,6 +2897,33 @@ namespace Game.Entities
|
||||
base.ClearUpdateMask(remove);
|
||||
}
|
||||
|
||||
public List<uint> GetPauseTimes()
|
||||
{
|
||||
GameObjectType.Transport transport = m_goTypeImpl as GameObjectType.Transport;
|
||||
if (transport != null)
|
||||
return transport.GetPauseTimes();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void SetPathProgressForClient(float progress)
|
||||
{
|
||||
DoWithSuppressingObjectUpdates(() =>
|
||||
{
|
||||
ObjectFieldData dynflagMask = new();
|
||||
dynflagMask.MarkChanged(m_objectData.DynamicFlags);
|
||||
bool marked = (m_objectData.GetUpdateMask() & dynflagMask.GetUpdateMask()).IsAnySet();
|
||||
|
||||
uint dynamicFlags = (uint)GetDynamicFlags();
|
||||
dynamicFlags &= 0xFFFF; // remove high bits
|
||||
dynamicFlags |= (uint)(progress * 65535.0f) << 16;
|
||||
ReplaceAllDynamicFlags((GameObjectDynamicLowFlags)dynamicFlags);
|
||||
|
||||
if (!marked)
|
||||
m_objectData.ClearChanged(m_objectData.DynamicFlags);
|
||||
});
|
||||
}
|
||||
|
||||
public void GetRespawnPosition(out float x, out float y, out float z, out float ori)
|
||||
{
|
||||
if (m_goData != null)
|
||||
@@ -2993,6 +2932,31 @@ namespace Game.Entities
|
||||
GetPosition(out x, out y, out z, out ori);
|
||||
}
|
||||
|
||||
public ITransport ToTransportBase()
|
||||
{
|
||||
switch (GetGoType())
|
||||
{
|
||||
case GameObjectTypes.Transport:
|
||||
return (GameObjectType.Transport)m_goTypeImpl;
|
||||
case GameObjectTypes.MapObjTransport:
|
||||
return (Transport)this;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void AfterRelocation()
|
||||
{
|
||||
UpdateModelPosition();
|
||||
UpdatePositionData();
|
||||
if (m_goTypeImpl != null)
|
||||
m_goTypeImpl.OnRelocated();
|
||||
|
||||
UpdateObjectVisibility(false);
|
||||
}
|
||||
|
||||
public float GetInteractionDistance()
|
||||
{
|
||||
switch (GetGoType())
|
||||
@@ -3308,6 +3272,12 @@ namespace Game.Entities
|
||||
public void ReplaceAllFlags(GameObjectFlags flags) { SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.Flags), (uint)flags); }
|
||||
public void SetLevel(uint level) { SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.Level), level); }
|
||||
|
||||
public GameObjectDynamicLowFlags GetDynamicFlags() { return (GameObjectDynamicLowFlags)(uint)m_objectData.DynamicFlags; }
|
||||
public bool HasDynamicFlag(GameObjectDynamicLowFlags flag) { return (m_objectData.DynamicFlags & (uint)flag) != 0; }
|
||||
public void SetDynamicFlag(GameObjectDynamicLowFlags flag) { SetUpdateFieldFlagValue(m_values.ModifyValue(m_objectData).ModifyValue(m_objectData.DynamicFlags), (uint)flag); }
|
||||
public void RemoveDynamicFlag(GameObjectDynamicLowFlags flag) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(m_objectData).ModifyValue(m_objectData.DynamicFlags), (uint)flag); }
|
||||
public void ReplaceAllDynamicFlags(GameObjectDynamicLowFlags flag) { SetUpdateFieldValue(m_values.ModifyValue(m_objectData).ModifyValue(m_objectData.DynamicFlags), (uint)flag); }
|
||||
|
||||
public GameObjectTypes GetGoType() { return (GameObjectTypes)(sbyte)m_gameObjectData.TypeID; }
|
||||
public void SetGoType(GameObjectTypes type) { SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.TypeID), (sbyte)type); }
|
||||
public GameObjectState GetGoState() { return (GameObjectState)(sbyte)m_gameObjectData.State; }
|
||||
@@ -3389,6 +3359,7 @@ namespace Game.Entities
|
||||
public override float GetStationaryY() { return StationaryPosition.GetPositionY(); }
|
||||
public override float GetStationaryZ() { return StationaryPosition.GetPositionZ(); }
|
||||
public override float GetStationaryO() { return StationaryPosition.GetOrientation(); }
|
||||
public Position GetStationaryPosition() { return StationaryPosition; }
|
||||
|
||||
public void RelocateStationaryPosition(float x, float y, float z, float o) { StationaryPosition.Relocate(x, y, z, o); }
|
||||
|
||||
@@ -3407,6 +3378,12 @@ namespace Game.Entities
|
||||
Cell.VisitWorldObjects(this, deliverer, GetVisibilityRange());
|
||||
}
|
||||
|
||||
void HandleCustomTypeCommand(GameObjectTypeBase.CustomCommand command)
|
||||
{
|
||||
if (m_goTypeImpl != null)
|
||||
command.Execute(m_goTypeImpl);
|
||||
}
|
||||
|
||||
public void CreateModel()
|
||||
{
|
||||
m_model = GameObjectModel.Create(new GameObjectModelOwnerImpl(this));
|
||||
@@ -3419,8 +3396,9 @@ namespace Game.Entities
|
||||
public bool GetRespawnCompatibilityMode() { return m_respawnCompatibilityMode; }
|
||||
|
||||
#region Fields
|
||||
protected GameObjectFieldData m_gameObjectData;
|
||||
protected GameObjectValue m_goValue;
|
||||
public GameObjectFieldData m_gameObjectData;
|
||||
GameObjectTypeBase m_goTypeImpl;
|
||||
protected GameObjectValue m_goValue; // TODO: replace with m_goTypeImpl
|
||||
protected GameObjectTemplate m_goInfo;
|
||||
protected GameObjectTemplateAddon m_goTemplateAddon;
|
||||
GameObjectData m_goData;
|
||||
@@ -3509,6 +3487,26 @@ namespace Game.Entities
|
||||
GameObject _owner;
|
||||
}
|
||||
|
||||
// Base class for GameObject type specific implementations
|
||||
class GameObjectTypeBase
|
||||
{
|
||||
protected GameObject _owner;
|
||||
|
||||
public GameObjectTypeBase(GameObject owner)
|
||||
{
|
||||
_owner = owner;
|
||||
}
|
||||
|
||||
public virtual void Update(uint diff) { }
|
||||
public virtual void OnStateChanged(GameObjectState oldState, GameObjectState newState) { }
|
||||
public virtual void OnRelocated() { }
|
||||
|
||||
public class CustomCommand
|
||||
{
|
||||
public virtual void Execute(GameObjectTypeBase type) { }
|
||||
}
|
||||
}
|
||||
|
||||
public struct GameObjectValue
|
||||
{
|
||||
public transport Transport;
|
||||
@@ -3549,4 +3547,387 @@ namespace Game.Entities
|
||||
public uint AssaultTimer;
|
||||
}
|
||||
}
|
||||
|
||||
namespace GameObjectType
|
||||
{
|
||||
//11 GAMEOBJECT_TYPE_TRANSPORT
|
||||
class Transport : GameObjectTypeBase, ITransport
|
||||
{
|
||||
TransportAnimation _animationInfo;
|
||||
uint _pathProgress;
|
||||
uint _stateChangeTime;
|
||||
uint _stateChangeProgress;
|
||||
List<uint> _stopFrames = new();
|
||||
bool _autoCycleBetweenStopFrames;
|
||||
TimeTracker _positionUpdateTimer;
|
||||
List<WorldObject> _passengers = new();
|
||||
|
||||
static TimeSpan PositionUpdateInterval = TimeSpan.FromMilliseconds(50);
|
||||
|
||||
public Transport(GameObject owner) : base(owner)
|
||||
{
|
||||
_animationInfo = Global.TransportMgr.GetTransportAnimInfo(owner.GetGoInfo().entry);
|
||||
_pathProgress = GameTime.GetGameTimeMS() % GetTransportPeriod();
|
||||
_stateChangeTime = GameTime.GetGameTimeMS();
|
||||
_stateChangeProgress = _pathProgress;
|
||||
|
||||
GameObjectTemplate goInfo = _owner.GetGoInfo();
|
||||
if (goInfo.Transport.Timeto2ndfloor > 0)
|
||||
{
|
||||
_stopFrames.Add(goInfo.Transport.Timeto2ndfloor);
|
||||
if (goInfo.Transport.Timeto3rdfloor > 0)
|
||||
{
|
||||
_stopFrames.Add(goInfo.Transport.Timeto3rdfloor);
|
||||
if (goInfo.Transport.Timeto4thfloor > 0)
|
||||
{
|
||||
_stopFrames.Add(goInfo.Transport.Timeto4thfloor);
|
||||
if (goInfo.Transport.Timeto5thfloor > 0)
|
||||
{
|
||||
_stopFrames.Add(goInfo.Transport.Timeto5thfloor);
|
||||
if (goInfo.Transport.Timeto6thfloor > 0)
|
||||
{
|
||||
_stopFrames.Add(goInfo.Transport.Timeto6thfloor);
|
||||
if (goInfo.Transport.Timeto7thfloor > 0)
|
||||
{
|
||||
_stopFrames.Add(goInfo.Transport.Timeto7thfloor);
|
||||
if (goInfo.Transport.Timeto8thfloor > 0)
|
||||
{
|
||||
_stopFrames.Add(goInfo.Transport.Timeto8thfloor);
|
||||
if (goInfo.Transport.Timeto9thfloor > 0)
|
||||
{
|
||||
_stopFrames.Add(goInfo.Transport.Timeto9thfloor);
|
||||
if (goInfo.Transport.Timeto10thfloor > 0)
|
||||
_stopFrames.Add(goInfo.Transport.Timeto10thfloor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_positionUpdateTimer.Reset(PositionUpdateInterval);
|
||||
}
|
||||
|
||||
public override void Update(uint diff)
|
||||
{
|
||||
if (_animationInfo == null)
|
||||
return;
|
||||
|
||||
_positionUpdateTimer.Update(diff);
|
||||
if (!_positionUpdateTimer.Passed())
|
||||
return;
|
||||
|
||||
_positionUpdateTimer.Reset(PositionUpdateInterval);
|
||||
|
||||
uint now = GameTime.GetGameTimeMS();
|
||||
uint period = GetTransportPeriod();
|
||||
uint newProgress = 0;
|
||||
if (_stopFrames.Empty())
|
||||
newProgress = now % period;
|
||||
else
|
||||
{
|
||||
int stopTargetTime = 0;
|
||||
if (_owner.GetGoState() == GameObjectState.TransportActive)
|
||||
stopTargetTime = 0;
|
||||
else
|
||||
stopTargetTime = (int)(_stopFrames[_owner.GetGoState() - GameObjectState.TransportStopped]);
|
||||
|
||||
if (now < _owner.m_gameObjectData.Level)
|
||||
{
|
||||
int timeToStop = (int)(_owner.m_gameObjectData.Level - _stateChangeTime);
|
||||
float stopSourcePathPct = (float)_stateChangeProgress / (float)period;
|
||||
float stopTargetPathPct = (float)stopTargetTime / (float)period;
|
||||
float timeSinceStopProgressPct = (float)(now - _stateChangeTime) / (float)timeToStop;
|
||||
|
||||
float progressPct;
|
||||
if (!_owner.HasDynamicFlag(GameObjectDynamicLowFlags.InvertedMovement))
|
||||
{
|
||||
if (_owner.GetGoState() == GameObjectState.TransportActive)
|
||||
stopTargetPathPct = 1.0f;
|
||||
|
||||
float pathPctBetweenStops = stopTargetPathPct - stopSourcePathPct;
|
||||
if (pathPctBetweenStops < 0.0f)
|
||||
pathPctBetweenStops += 1.0f;
|
||||
|
||||
progressPct = pathPctBetweenStops * timeSinceStopProgressPct + stopSourcePathPct;
|
||||
if (progressPct > 1.0f)
|
||||
progressPct = progressPct - 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
float pathPctBetweenStops = stopSourcePathPct - stopTargetPathPct;
|
||||
if (pathPctBetweenStops < 0.0f)
|
||||
pathPctBetweenStops += 1.0f;
|
||||
|
||||
progressPct = stopSourcePathPct - pathPctBetweenStops * timeSinceStopProgressPct;
|
||||
if (progressPct < 0.0f)
|
||||
progressPct += 1.0f;
|
||||
}
|
||||
|
||||
newProgress = (uint)((float)period * progressPct) % period;
|
||||
}
|
||||
else
|
||||
newProgress = (uint)stopTargetTime;
|
||||
|
||||
if (newProgress == stopTargetTime && newProgress != _pathProgress)
|
||||
{
|
||||
uint eventId;
|
||||
switch (_owner.GetGoState() - GameObjectState.TransportActive)
|
||||
{
|
||||
case 0:
|
||||
eventId = _owner.GetGoInfo().Transport.Reached1stfloor;
|
||||
break;
|
||||
case 1:
|
||||
eventId = _owner.GetGoInfo().Transport.Reached2ndfloor;
|
||||
break;
|
||||
case 2:
|
||||
eventId = _owner.GetGoInfo().Transport.Reached3rdfloor;
|
||||
break;
|
||||
case 3:
|
||||
eventId = _owner.GetGoInfo().Transport.Reached4thfloor;
|
||||
break;
|
||||
case 4:
|
||||
eventId = _owner.GetGoInfo().Transport.Reached5thfloor;
|
||||
break;
|
||||
case 5:
|
||||
eventId = _owner.GetGoInfo().Transport.Reached6thfloor;
|
||||
break;
|
||||
case 6:
|
||||
eventId = _owner.GetGoInfo().Transport.Reached7thfloor;
|
||||
break;
|
||||
case 7:
|
||||
eventId = _owner.GetGoInfo().Transport.Reached8thfloor;
|
||||
break;
|
||||
case 8:
|
||||
eventId = _owner.GetGoInfo().Transport.Reached9thfloor;
|
||||
break;
|
||||
case 9:
|
||||
eventId = _owner.GetGoInfo().Transport.Reached10thfloor;
|
||||
break;
|
||||
default:
|
||||
eventId = 0u;
|
||||
break;
|
||||
}
|
||||
|
||||
if (eventId != 0)
|
||||
GameEvents.Trigger(eventId, _owner, null);
|
||||
|
||||
if (_autoCycleBetweenStopFrames)
|
||||
{
|
||||
GameObjectState currentState = _owner.GetGoState();
|
||||
GameObjectState newState;
|
||||
if (currentState == GameObjectState.TransportActive)
|
||||
newState = GameObjectState.TransportStopped;
|
||||
else if (currentState - GameObjectState.TransportActive == _stopFrames.Count)
|
||||
newState = currentState - 1;
|
||||
else if (_owner.HasDynamicFlag(GameObjectDynamicLowFlags.InvertedMovement))
|
||||
newState = currentState - 1;
|
||||
else
|
||||
newState = currentState + 1;
|
||||
|
||||
_owner.SetGoState(newState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_pathProgress == newProgress)
|
||||
return;
|
||||
|
||||
_pathProgress = newProgress;
|
||||
|
||||
TransportAnimationRecord oldAnimation = _animationInfo.GetPrevAnimNode(newProgress);
|
||||
TransportAnimationRecord newAnimation = _animationInfo.GetNextAnimNode(newProgress);
|
||||
if (oldAnimation != null && newAnimation != null)
|
||||
{
|
||||
Matrix4x4 pathRotation = Matrix4x4.CreateFromQuaternion(new Quaternion(_owner.m_gameObjectData.ParentRotation.GetValue().X, _owner.m_gameObjectData.ParentRotation.GetValue().Y,
|
||||
_owner.m_gameObjectData.ParentRotation.GetValue().Z, _owner.m_gameObjectData.ParentRotation.GetValue().W));
|
||||
|
||||
Vector3 prev = new(oldAnimation.Pos.X, oldAnimation.Pos.Y, oldAnimation.Pos.Z);
|
||||
Vector3 next = new(newAnimation.Pos.X, newAnimation.Pos.Y, newAnimation.Pos.Z);
|
||||
|
||||
float animProgress = (float)(newProgress - oldAnimation.TimeIndex) / (float)(newAnimation.TimeIndex - oldAnimation.TimeIndex);
|
||||
|
||||
Vector3 dst = Vector3.Transform(Vector3.Lerp(prev, next, animProgress), pathRotation);//todo check this
|
||||
|
||||
dst += _owner.GetStationaryPosition();
|
||||
|
||||
_owner.GetMap().GameObjectRelocation(_owner, dst.X, dst.Y, dst.Z, _owner.GetOrientation());
|
||||
}
|
||||
|
||||
TransportRotationRecord oldRotation = _animationInfo.GetPrevAnimRotation(newProgress);
|
||||
TransportRotationRecord newRotation = _animationInfo.GetNextAnimRotation(newProgress);
|
||||
if (oldRotation != null && newRotation != null)
|
||||
{
|
||||
Quaternion prev = new(oldRotation.Rot[0], oldRotation.Rot[1], oldRotation.Rot[2], oldRotation.Rot[3]);
|
||||
Quaternion next = new(newRotation.Rot[0], newRotation.Rot[1], newRotation.Rot[2], newRotation.Rot[3]);
|
||||
|
||||
float animProgress = (float)(newProgress - oldRotation.TimeIndex) / (float)(newRotation.TimeIndex - oldRotation.TimeIndex);
|
||||
|
||||
Quaternion rotation = Quaternion.Lerp(prev, next, animProgress);
|
||||
|
||||
_owner.SetLocalRotation(rotation.X, rotation.Y, rotation.Z, rotation.W);
|
||||
_owner.UpdateModelPosition();
|
||||
}
|
||||
|
||||
// update progress marker for client
|
||||
_owner.SetPathProgressForClient((float)_pathProgress / (float)period);
|
||||
}
|
||||
|
||||
public override void OnStateChanged(GameObjectState oldState, GameObjectState newState)
|
||||
{
|
||||
Cypher.Assert(newState >= GameObjectState.TransportActive);
|
||||
|
||||
// transports without stop frames just keep animating in state 24
|
||||
if (_stopFrames.Empty())
|
||||
{
|
||||
if (newState != GameObjectState.TransportActive)
|
||||
_owner.SetGoState(GameObjectState.TransportActive);
|
||||
return;
|
||||
}
|
||||
|
||||
uint stopPathProgress = 0;
|
||||
|
||||
if (newState != GameObjectState.TransportActive)
|
||||
{
|
||||
Cypher.Assert(newState < (GameObjectState)(GameObjectState.TransportStopped + 9));
|
||||
int stopFrame = (int)(newState - GameObjectState.TransportStopped);
|
||||
Cypher.Assert(stopFrame < _stopFrames.Count);
|
||||
stopPathProgress = _stopFrames[stopFrame];
|
||||
}
|
||||
|
||||
_stateChangeTime = GameTime.GetGameTimeMS();
|
||||
_stateChangeProgress = _pathProgress;
|
||||
uint timeToStop = (uint)Math.Abs(_pathProgress - stopPathProgress);
|
||||
_owner.SetLevel(GameTime.GetGameTimeMS() + timeToStop);
|
||||
_owner.SetPathProgressForClient((float)_pathProgress / (float)GetTransportPeriod());
|
||||
|
||||
if (oldState == GameObjectState.Active || oldState == newState)
|
||||
{
|
||||
// initialization
|
||||
if (_pathProgress > stopPathProgress)
|
||||
_owner.SetDynamicFlag(GameObjectDynamicLowFlags.InvertedMovement);
|
||||
else
|
||||
_owner.RemoveDynamicFlag(GameObjectDynamicLowFlags.InvertedMovement);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int pauseTimesCount = _stopFrames.Count;
|
||||
int newToOldStateDelta = newState - oldState;
|
||||
if (newToOldStateDelta < 0)
|
||||
newToOldStateDelta += pauseTimesCount + 1;
|
||||
|
||||
int oldToNewStateDelta = oldState - newState;
|
||||
if (oldToNewStateDelta < 0)
|
||||
oldToNewStateDelta += pauseTimesCount + 1;
|
||||
|
||||
if (oldToNewStateDelta < newToOldStateDelta)
|
||||
_owner.SetDynamicFlag(GameObjectDynamicLowFlags.InvertedMovement);
|
||||
else
|
||||
_owner.RemoveDynamicFlag(GameObjectDynamicLowFlags.InvertedMovement);
|
||||
}
|
||||
|
||||
public override void OnRelocated()
|
||||
{
|
||||
UpdatePassengerPositions();
|
||||
}
|
||||
|
||||
public void UpdatePassengerPositions()
|
||||
{
|
||||
foreach (WorldObject passenger in _passengers)
|
||||
{
|
||||
float x, y, z, o;
|
||||
passenger.m_movementInfo.transport.pos.GetPosition(out x, out y, out z, out o);
|
||||
CalculatePassengerPosition(ref x, ref y, ref z, ref o);
|
||||
ITransport.UpdatePassengerPosition(this, _owner.GetMap(), passenger, x, y, z, o, true);
|
||||
}
|
||||
}
|
||||
|
||||
public uint GetTransportPeriod()
|
||||
{
|
||||
if (_animationInfo != null)
|
||||
return _animationInfo.TotalTime;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
public List<uint> GetPauseTimes()
|
||||
{
|
||||
return _stopFrames;
|
||||
}
|
||||
|
||||
public ObjectGuid GetTransportGUID() { return _owner.GetGUID(); }
|
||||
|
||||
public float GetTransportOrientation() { return _owner.GetOrientation(); }
|
||||
|
||||
public void AddPassenger(WorldObject passenger)
|
||||
{
|
||||
if (!_owner.IsInWorld)
|
||||
return;
|
||||
|
||||
if (!_passengers.Contains(passenger))
|
||||
{
|
||||
_passengers.Add(passenger);
|
||||
passenger.SetTransport(this);
|
||||
passenger.m_movementInfo.transport.guid = GetTransportGUID();
|
||||
Log.outDebug(LogFilter.Transport, $"Object {passenger.GetName()} boarded transport {_owner.GetName()}.");
|
||||
}
|
||||
}
|
||||
|
||||
public ITransport RemovePassenger(WorldObject passenger)
|
||||
{
|
||||
if (_passengers.Remove(passenger))
|
||||
{
|
||||
passenger.SetTransport(null);
|
||||
passenger.m_movementInfo.transport.Reset();
|
||||
Log.outDebug(LogFilter.Transport, $"Object {passenger.GetName()} removed from transport {_owner.GetName()}.");
|
||||
|
||||
Player plr = passenger.ToPlayer();
|
||||
if (plr != null)
|
||||
plr.SetFallInformation(0, plr.GetPositionZ());
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public void CalculatePassengerPosition(ref float x, ref float y, ref float z, ref float o)
|
||||
{
|
||||
ITransport.CalculatePassengerPosition(ref x, ref y, ref z, ref o, _owner.GetPositionX(), _owner.GetPositionY(), _owner.GetPositionZ(), _owner.GetOrientation());
|
||||
}
|
||||
|
||||
public void CalculatePassengerOffset(ref float x, ref float y, ref float z, ref float o)
|
||||
{
|
||||
ITransport.CalculatePassengerOffset(ref x, ref y, ref z, ref o, _owner.GetPositionX(), _owner.GetPositionY(), _owner.GetPositionZ(), _owner.GetOrientation());
|
||||
}
|
||||
|
||||
public int GetMapIdForSpawning()
|
||||
{
|
||||
return _owner.GetGoInfo().Transport.SpawnMap;
|
||||
}
|
||||
|
||||
public void SetAutoCycleBetweenStopFrames(bool on)
|
||||
{
|
||||
_autoCycleBetweenStopFrames = on;
|
||||
}
|
||||
}
|
||||
|
||||
class SetTransportAutoCycleBetweenStopFrames : GameObjectTypeBase.CustomCommand
|
||||
{
|
||||
bool _on;
|
||||
|
||||
public SetTransportAutoCycleBetweenStopFrames(bool on)
|
||||
{
|
||||
_on = on;
|
||||
}
|
||||
|
||||
public override void Execute(GameObjectTypeBase type)
|
||||
{
|
||||
Transport transport = (Transport)type;
|
||||
if (transport != null)
|
||||
transport.SetAutoCycleBetweenStopFrames(_on);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -544,6 +544,8 @@ namespace Game.Entities
|
||||
return SpellFocus.GiganticAOI != 0;
|
||||
case GameObjectTypes.Goober:
|
||||
return Goober.GiganticAOI != 0;
|
||||
case GameObjectTypes.Transport:
|
||||
return true;
|
||||
case GameObjectTypes.SpellCaster:
|
||||
return SpellCaster.GiganticAOI != 0;
|
||||
case GameObjectTypes.FlagStand:
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
@@ -383,18 +379,7 @@ namespace Game.Entities
|
||||
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());
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
@@ -3429,8 +3429,9 @@ namespace Game.Entities
|
||||
stmt.AddValue(index++, finiteAlways(GetTransOffsetZ()));
|
||||
stmt.AddValue(index++, finiteAlways(GetTransOffsetO()));
|
||||
ulong transLowGUID = 0;
|
||||
if (GetTransport())
|
||||
transLowGUID = GetTransport().GetGUID().GetCounter();
|
||||
Transport transport = GetTransport<Transport>();
|
||||
if (transport != null)
|
||||
transLowGUID = transport.GetGUID().GetCounter();
|
||||
stmt.AddValue(index++, transLowGUID);
|
||||
|
||||
StringBuilder ss = new();
|
||||
@@ -3570,8 +3571,9 @@ namespace Game.Entities
|
||||
stmt.AddValue(index++, finiteAlways(GetTransOffsetZ()));
|
||||
stmt.AddValue(index++, finiteAlways(GetTransOffsetO()));
|
||||
ulong transLowGUID = 0;
|
||||
if (GetTransport())
|
||||
transLowGUID = GetTransport().GetGUID().GetCounter();
|
||||
Transport transport = GetTransport<Transport>();
|
||||
if (transport != null)
|
||||
transLowGUID = transport.GetGUID().GetCounter();
|
||||
stmt.AddValue(index++, transLowGUID);
|
||||
|
||||
StringBuilder ss = new();
|
||||
|
||||
@@ -803,7 +803,7 @@ namespace Game.Entities
|
||||
m_MirrorTimerFlags |= PlayerUnderwaterState.InWater;
|
||||
|
||||
// Fatigue bar state (if not on flight path or transport)
|
||||
if (newLiquidData.type_flags.HasAnyFlag(LiquidHeaderTypeFlags.DarkWater) && !IsInFlight() && !GetTransport())
|
||||
if (newLiquidData.type_flags.HasAnyFlag(LiquidHeaderTypeFlags.DarkWater) && !IsInFlight() && GetTransport() == null)
|
||||
m_MirrorTimerFlags |= PlayerUnderwaterState.InDarkWater;
|
||||
|
||||
// Lava state (any contact)
|
||||
|
||||
@@ -1686,8 +1686,8 @@ namespace Game.Entities
|
||||
{
|
||||
Log.outDebug(LogFilter.Maps, "Player {0} using client without required expansion tried teleport to non accessible map {1}", GetName(), mapid);
|
||||
|
||||
Transport _transport = GetTransport();
|
||||
if (_transport)
|
||||
ITransport _transport = GetTransport();
|
||||
if (_transport != null)
|
||||
{
|
||||
_transport.RemovePassenger(this);
|
||||
RepopAtGraveyard(); // teleport to near graveyard if on transport, looks blizz like :)
|
||||
@@ -1708,8 +1708,8 @@ namespace Game.Entities
|
||||
DisableSpline();
|
||||
GetMotionMaster().Remove(MovementGeneratorType.Effect);
|
||||
|
||||
Transport transport = GetTransport();
|
||||
if (transport)
|
||||
ITransport transport = GetTransport();
|
||||
if (transport != null)
|
||||
{
|
||||
if (!options.HasAnyFlag(TeleportToOptions.NotLeaveTransport))
|
||||
transport.RemovePassenger(this);
|
||||
@@ -1849,11 +1849,11 @@ namespace Game.Entities
|
||||
transferPending.MapID = (int)mapid;
|
||||
transferPending.OldMapPosition = GetPosition();
|
||||
|
||||
transport = GetTransport();
|
||||
if (transport)
|
||||
Transport transport1 = (Transport)GetTransport();
|
||||
if (transport1 != null)
|
||||
{
|
||||
TransferPending.ShipTransferPending shipTransferPending = new();
|
||||
shipTransferPending.Id = transport.GetEntry();
|
||||
shipTransferPending.Id = transport1.GetEntry();
|
||||
shipTransferPending.OriginMapID = (int)GetMapId();
|
||||
transferPending.Ship = shipTransferPending;
|
||||
}
|
||||
@@ -6242,14 +6242,6 @@ namespace Game.Entities
|
||||
{
|
||||
switch (target.GetTypeId())
|
||||
{
|
||||
case TypeId.GameObject:
|
||||
// @HACK: This is to prevent objects like deeprun tram from disappearing when player moves far from its spawn point while riding it
|
||||
// But exclude stoppable elevators from this hack - they would be teleporting from one end to another
|
||||
// if affected transports move so far horizontally that it causes them to run out of visibility range then you are out of luck
|
||||
// fix visibility instead of adding hacks here
|
||||
if (!target.ToGameObject().IsDynTransport())
|
||||
s64.Add(target.GetGUID());
|
||||
break;
|
||||
case TypeId.Unit:
|
||||
s64.Add(target.GetGUID());
|
||||
v.Add(target.ToCreature());
|
||||
|
||||
@@ -27,37 +27,102 @@ namespace Game.Entities
|
||||
{
|
||||
public interface ITransport
|
||||
{
|
||||
ObjectGuid GetTransportGUID();
|
||||
|
||||
// This method transforms supplied transport offsets into global coordinates
|
||||
void CalculatePassengerPosition(ref float x, ref float y, ref float z, ref float o);
|
||||
|
||||
// This method transforms supplied global coordinates into local offsets
|
||||
void CalculatePassengerOffset(ref float x, ref float y, ref float z, ref float o);
|
||||
|
||||
float GetTransportOrientation();
|
||||
|
||||
void AddPassenger(WorldObject passenger);
|
||||
|
||||
ITransport RemovePassenger(WorldObject passenger);
|
||||
|
||||
public static void UpdatePassengerPosition(ITransport transport, Map map, WorldObject passenger, float x, float y, float z, float o, bool setHomePosition)
|
||||
{
|
||||
// transport teleported but passenger not yet (can happen for players)
|
||||
if (passenger.GetMap() != map)
|
||||
return;
|
||||
|
||||
// if passenger is on vehicle we have to assume the vehicle is also on transport
|
||||
// and its the vehicle that will be updating its passengers
|
||||
Unit unit = passenger.ToUnit();
|
||||
if (unit != null)
|
||||
if (unit.GetVehicle())
|
||||
return;
|
||||
|
||||
// Do not use Unit::UpdatePosition here, we don't want to remove auras
|
||||
// as if regular movement occurred
|
||||
switch (passenger.GetTypeId())
|
||||
{
|
||||
case TypeId.Unit:
|
||||
{
|
||||
Creature creature = passenger.ToCreature();
|
||||
map.CreatureRelocation(creature, x, y, z, o, false);
|
||||
if (setHomePosition)
|
||||
{
|
||||
creature.GetTransportHomePosition(out x, out y, out z, out o);
|
||||
transport.CalculatePassengerPosition(ref x, ref y, ref z, ref o);
|
||||
creature.SetHomePosition(x, y, z, o);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TypeId.Player:
|
||||
//relocate only passengers in world and skip any player that might be still logging in/teleporting
|
||||
if (passenger.IsInWorld && !passenger.ToPlayer().IsBeingTeleported())
|
||||
{
|
||||
map.PlayerRelocation(passenger.ToPlayer(), x, y, z, o);
|
||||
passenger.ToPlayer().SetFallInformation(0, passenger.GetPositionZ());
|
||||
}
|
||||
break;
|
||||
case TypeId.GameObject:
|
||||
map.GameObjectRelocation(passenger.ToGameObject(), x, y, z, o, false);
|
||||
passenger.ToGameObject().RelocateStationaryPosition(x, y, z, o);
|
||||
break;
|
||||
case TypeId.DynamicObject:
|
||||
map.DynamicObjectRelocation(passenger.ToDynamicObject(), x, y, z, o);
|
||||
break;
|
||||
case TypeId.AreaTrigger:
|
||||
map.AreaTriggerRelocation(passenger.ToAreaTrigger(), x, y, z, o);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
public class TransportPosHelper
|
||||
if (unit != null)
|
||||
{
|
||||
public static void CalculatePassengerPosition(ref float x, ref float y, ref float z, ref float o, float transX, float transY, float transZ, float transO)
|
||||
Vehicle vehicle = unit.GetVehicleKit();
|
||||
if (vehicle != null)
|
||||
vehicle.RelocatePassengers();
|
||||
}
|
||||
}
|
||||
|
||||
static void CalculatePassengerPosition(ref float x, ref float y, ref float z, ref float o, float transX, float transY, float transZ, float transO)
|
||||
{
|
||||
float inx = x, iny = y, inz = z;
|
||||
o = Position.NormalizeOrientation(transO + o);
|
||||
|
||||
x = transX + inx * (float)Math.Cos(transO) - iny * (float)Math.Sin(transO);
|
||||
y = transY + iny * (float)Math.Cos(transO) + inx * (float)Math.Sin(transO);
|
||||
x = transX + inx * MathF.Cos(transO) - iny * MathF.Sin(transO);
|
||||
y = transY + iny * MathF.Cos(transO) + inx * MathF.Sin(transO);
|
||||
z = transZ + inz;
|
||||
}
|
||||
|
||||
public static void CalculatePassengerOffset(ref float x, ref float y, ref float z, ref float o, float transX, float transY, float transZ, float transO)
|
||||
static void CalculatePassengerOffset(ref float x, ref float y, ref float z, ref float o, float transX, float transY, float transZ, float transO)
|
||||
{
|
||||
o = Position.NormalizeOrientation(o - transO);
|
||||
|
||||
z -= transZ;
|
||||
y -= transY;
|
||||
x -= transX;
|
||||
|
||||
y -= transY; // y = searchedY * std::cos(o) + searchedX * std::sin(o)
|
||||
x -= transX; // x = searchedX * std::cos(o) + searchedY * std::sin(o + pi)
|
||||
float inx = x, iny = y;
|
||||
y = (iny - inx * (float)Math.Tan(transO)) / ((float)Math.Cos(transO) + (float)Math.Sin(transO) * (float)Math.Tan(transO));
|
||||
x = (inx + iny * (float)Math.Tan(transO)) / ((float)Math.Cos(transO) + (float)Math.Sin(transO) * (float)Math.Tan(transO));
|
||||
y = (iny - inx * MathF.Tan(transO)) / (MathF.Cos(transO) + MathF.Sin(transO) * MathF.Tan(transO));
|
||||
x = (inx + iny * MathF.Tan(transO)) / (MathF.Cos(transO) + MathF.Sin(transO) * MathF.Tan(transO));
|
||||
}
|
||||
|
||||
int GetMapIdForSpawning();
|
||||
}
|
||||
|
||||
public class Transport : GameObject, ITransport
|
||||
@@ -122,7 +187,6 @@ namespace Game.Entities
|
||||
ReplaceAllFlags(goOverride.Flags);
|
||||
}
|
||||
|
||||
m_goValue.Transport.PathProgress = 0;
|
||||
SetObjectScale(goinfo.size);
|
||||
SetPeriod(tInfo.pathTime);
|
||||
SetEntry(goinfo.entry);
|
||||
@@ -163,9 +227,9 @@ namespace Game.Entities
|
||||
return;
|
||||
|
||||
if (IsMoving() || !_pendingStop)
|
||||
m_goValue.Transport.PathProgress += diff;
|
||||
_pathProgress += diff;
|
||||
|
||||
uint timer = m_goValue.Transport.PathProgress % GetTransportPeriod();
|
||||
uint timer = _pathProgress % GetTransportPeriod();
|
||||
bool justStopped = false;
|
||||
|
||||
// Set current waypoint
|
||||
@@ -189,9 +253,9 @@ namespace Game.Entities
|
||||
if (_pendingStop && GetGoState() != GameObjectState.Ready)
|
||||
{
|
||||
SetGoState(GameObjectState.Ready);
|
||||
m_goValue.Transport.PathProgress /= GetTransportPeriod();
|
||||
m_goValue.Transport.PathProgress *= GetTransportPeriod();
|
||||
m_goValue.Transport.PathProgress += _currentFrame.ArriveTime;
|
||||
_pathProgress /= GetTransportPeriod();
|
||||
_pathProgress *= GetTransportPeriod();
|
||||
_pathProgress += _currentFrame.ArriveTime;
|
||||
}
|
||||
break; // its a stop frame and we are waiting
|
||||
}
|
||||
@@ -296,7 +360,7 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
public void RemovePassenger(WorldObject passenger)
|
||||
public ITransport RemovePassenger(WorldObject passenger)
|
||||
{
|
||||
bool erased = _passengers.Remove(passenger);
|
||||
|
||||
@@ -313,6 +377,8 @@ namespace Game.Entities
|
||||
plr.SetFallInformation(0, plr.GetPositionZ());
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Creature CreateNPCPassenger(ulong guid, CreatureData data)
|
||||
@@ -511,12 +577,17 @@ namespace Game.Entities
|
||||
|
||||
public void CalculatePassengerPosition(ref float x, ref float y, ref float z, ref float o)
|
||||
{
|
||||
TransportPosHelper.CalculatePassengerPosition(ref x, ref y, ref z, ref o, GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation());
|
||||
ITransport.CalculatePassengerPosition(ref x, ref y, ref z, ref o, GetPositionX(), GetPositionY(), GetPositionZ(), GetTransportOrientation());
|
||||
}
|
||||
|
||||
public void CalculatePassengerOffset(ref float x, ref float y, ref float z, ref float o)
|
||||
{
|
||||
TransportPosHelper.CalculatePassengerOffset(ref x, ref y, ref z, ref o, GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation());
|
||||
ITransport.CalculatePassengerOffset(ref x, ref y, ref z, ref o, GetPositionX(), GetPositionY(), GetPositionZ(), GetTransportOrientation());
|
||||
}
|
||||
|
||||
public int GetMapIdForSpawning()
|
||||
{
|
||||
return GetGoInfo().MoTransport.SpawnMap;
|
||||
}
|
||||
|
||||
public void UpdatePosition(float x, float y, float z, float o)
|
||||
@@ -652,7 +723,7 @@ namespace Game.Entities
|
||||
|
||||
float destX, destY, destZ, destO;
|
||||
obj.m_movementInfo.transport.pos.GetPosition(out destX, out destY, out destZ, out destO);
|
||||
TransportPosHelper.CalculatePassengerPosition(ref destX, ref destY, ref destZ, ref destO, x, y, z, o);
|
||||
ITransport.CalculatePassengerPosition(ref destX, ref destY, ref destZ, ref destO, x, y, z, o);
|
||||
|
||||
obj.ToUnit().NearTeleportTo(destX, destY, destZ, destO);
|
||||
}
|
||||
@@ -683,7 +754,7 @@ namespace Game.Entities
|
||||
{
|
||||
float destX, destY, destZ, destO;
|
||||
obj.m_movementInfo.transport.pos.GetPosition(out destX, out destY, out destZ, out destO);
|
||||
TransportPosHelper.CalculatePassengerPosition(ref destX, ref destY, ref destZ, ref destO, x, y, z, o);
|
||||
ITransport.CalculatePassengerPosition(ref destX, ref destY, ref destZ, ref destO, x, y, z, o);
|
||||
|
||||
switch (obj.GetTypeId())
|
||||
{
|
||||
@@ -707,62 +778,12 @@ namespace Game.Entities
|
||||
|
||||
void UpdatePassengerPositions(HashSet<WorldObject> passengers)
|
||||
{
|
||||
foreach (var passenger in passengers)
|
||||
foreach (WorldObject passenger in passengers)
|
||||
{
|
||||
// transport teleported but passenger not yet (can happen for players)
|
||||
if (passenger.GetMap() != GetMap())
|
||||
continue;
|
||||
|
||||
// if passenger is on vehicle we have to assume the vehicle is also on transport
|
||||
// and its the vehicle that will be updating its passengers
|
||||
Unit unit = passenger.ToUnit();
|
||||
if (unit)
|
||||
if (unit.GetVehicle() != null)
|
||||
continue;
|
||||
|
||||
// Do not use Unit.UpdatePosition here, we don't want to remove auras
|
||||
// as if regular movement occurred
|
||||
float x, y, z, o;
|
||||
passenger.m_movementInfo.transport.pos.GetPosition(out x, out y, out z, out o);
|
||||
CalculatePassengerPosition(ref x, ref y, ref z, ref o);
|
||||
switch (passenger.GetTypeId())
|
||||
{
|
||||
case TypeId.Unit:
|
||||
{
|
||||
Creature creature = passenger.ToCreature();
|
||||
GetMap().CreatureRelocation(creature, x, y, z, o, false);
|
||||
creature.GetTransportHomePosition(out x, out y, out z, out o);
|
||||
CalculatePassengerPosition(ref x, ref y, ref z, ref o);
|
||||
creature.SetHomePosition(x, y, z, o);
|
||||
break;
|
||||
}
|
||||
case TypeId.Player:
|
||||
if (passenger.IsInWorld && !passenger.ToPlayer().IsBeingTeleported())
|
||||
{
|
||||
GetMap().PlayerRelocation(passenger.ToPlayer(), x, y, z, o);
|
||||
passenger.ToPlayer().SetFallInformation(0, passenger.GetPositionZ());
|
||||
}
|
||||
break;
|
||||
case TypeId.GameObject:
|
||||
GetMap().GameObjectRelocation(passenger.ToGameObject(), x, y, z, o, false);
|
||||
passenger.ToGameObject().RelocateStationaryPosition(x, y, z, o);
|
||||
break;
|
||||
case TypeId.DynamicObject:
|
||||
GetMap().DynamicObjectRelocation(passenger.ToDynamicObject(), x, y, z, o);
|
||||
break;
|
||||
case TypeId.AreaTrigger:
|
||||
GetMap().AreaTriggerRelocation(passenger.ToAreaTrigger(), x, y, z, o);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (unit != null)
|
||||
{
|
||||
Vehicle vehicle = unit.GetVehicleKit();
|
||||
if (vehicle != null)
|
||||
vehicle.RelocatePassengers();
|
||||
}
|
||||
ITransport.UpdatePassengerPosition(this, GetMap(), passenger, x, y, z, o, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -790,9 +811,12 @@ namespace Game.Entities
|
||||
|
||||
public HashSet<WorldObject> GetPassengers() { return _passengers; }
|
||||
|
||||
public override uint GetTransportPeriod() { return m_gameObjectData.Level; }
|
||||
public ObjectGuid GetTransportGUID() { return GetGUID(); }
|
||||
public float GetTransportOrientation() { return GetOrientation(); }
|
||||
|
||||
public uint GetTransportPeriod() { return m_gameObjectData.Level; }
|
||||
public void SetPeriod(uint period) { SetLevel(period); }
|
||||
uint GetTimer() { return m_goValue.Transport.PathProgress; }
|
||||
public uint GetTimer() { return _pathProgress; }
|
||||
|
||||
public List<KeyFrame> GetKeyFrames() { return _transportInfo.keyFrames; }
|
||||
public TransportTemplate GetTransportTemplate() { return _transportInfo; }
|
||||
@@ -805,6 +829,7 @@ namespace Game.Entities
|
||||
|
||||
KeyFrame _currentFrame;
|
||||
int _nextFrame;
|
||||
uint _pathProgress;
|
||||
TimeTracker _positionChangeTimer = new();
|
||||
bool _isMoving;
|
||||
bool _pendingStop;
|
||||
|
||||
@@ -209,7 +209,7 @@ namespace Game.Entities
|
||||
|
||||
MoveSplineInit init = new(this);
|
||||
init.MoveTo(GetPositionX(), GetPositionY(), GetPositionZ(), false);
|
||||
if (GetTransport())
|
||||
if (GetTransport() != null)
|
||||
init.DisableTransportPathTransformations(); // It makes no sense to target global orientation
|
||||
init.SetFacing(ori);
|
||||
|
||||
@@ -1834,7 +1834,7 @@ namespace Game.Entities
|
||||
if (GetVehicle() != null)
|
||||
return GetVehicleBase().GetGUID();
|
||||
if (GetTransport() != null)
|
||||
return GetTransport().GetGUID();
|
||||
return GetTransport().GetTransportGUID();
|
||||
|
||||
return ObjectGuid.Empty;
|
||||
}
|
||||
|
||||
@@ -295,7 +295,7 @@ namespace Game.Entities
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsTypeId(TypeId.Player) && ToPlayer().GetTransport())
|
||||
if (IsPlayer() && ToPlayer().GetTransport() != null)
|
||||
{
|
||||
Log.outFatal(LogFilter.Unit, "Unit:SetCharmedBy: Player on transport is trying to charm {0} (GUID {1})", GetEntry(), GetGUID().ToString());
|
||||
return false;
|
||||
|
||||
@@ -1003,7 +1003,7 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
Cypher.Assert(!m_vehicle);
|
||||
vehicle.AddPassenger(this, seatId);
|
||||
vehicle.AddVehiclePassenger(this, seatId);
|
||||
}
|
||||
|
||||
public void ChangeSeat(sbyte seatId, bool next = true)
|
||||
@@ -1067,7 +1067,7 @@ namespace Game.Entities
|
||||
|
||||
// This should be done before dismiss, because there may be some aura removal
|
||||
VehicleSeatAddon seatAddon = m_vehicle.GetSeatAddonForSeatOfPassenger(this);
|
||||
Vehicle vehicle = m_vehicle.RemovePassenger(this);
|
||||
Vehicle vehicle = (Vehicle)m_vehicle.RemovePassenger(this);
|
||||
|
||||
if (vehicle == null)
|
||||
{
|
||||
@@ -1998,6 +1998,12 @@ namespace Game.Entities
|
||||
public void RemoveUnitFlag3(UnitFlags3 flags) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Flags3), (uint)flags); }
|
||||
public void ReplaceAllUnitFlags3(UnitFlags3 flags) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Flags3), (uint)flags); }
|
||||
|
||||
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 void SetCreatedBySpell(uint spellId) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.CreatedBySpell), spellId); }
|
||||
|
||||
public Emote GetEmoteState() { return (Emote)(int)m_unitData.EmoteState; }
|
||||
|
||||
@@ -291,7 +291,7 @@ namespace Game.Entities
|
||||
// @VehicleJoinEvent.Abort
|
||||
}
|
||||
|
||||
public bool AddPassenger(Unit unit, sbyte seatId)
|
||||
public bool AddVehiclePassenger(Unit unit, sbyte seatId)
|
||||
{
|
||||
// @Prevent adding passengers when vehicle is uninstalling. (Bad script in OnUninstall/OnRemovePassenger/PassengerBoarded hook.)
|
||||
if (_status == Status.UnInstalling)
|
||||
@@ -355,8 +355,12 @@ namespace Game.Entities
|
||||
return true;
|
||||
}
|
||||
|
||||
public Vehicle RemovePassenger(Unit unit)
|
||||
public ITransport RemovePassenger(WorldObject passenger)
|
||||
{
|
||||
Unit unit = passenger.ToUnit();
|
||||
if (unit == null)
|
||||
return null;
|
||||
|
||||
if (unit.GetVehicle() != this)
|
||||
return null;
|
||||
|
||||
@@ -421,8 +425,8 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var pair in seatRelocation)
|
||||
pair.Item1.UpdatePosition(pair.Item2);
|
||||
foreach (var (passenger, position) in seatRelocation)
|
||||
ITransport.UpdatePassengerPosition(this, _me.GetMap(), passenger, position.GetPositionX(), position.GetPositionY(), position.GetPositionZ(), position.GetOrientation(), false);
|
||||
}
|
||||
|
||||
public bool IsVehicleInUse()
|
||||
@@ -487,20 +491,28 @@ namespace Game.Entities
|
||||
return ret;
|
||||
}
|
||||
|
||||
public ObjectGuid GetTransportGUID() { return GetBase().GetGUID(); }
|
||||
|
||||
public float GetTransportOrientation() { return GetBase().GetOrientation(); }
|
||||
|
||||
public void AddPassenger(WorldObject passenger) { Log.outFatal(LogFilter.Vehicle, "Vehicle cannot directly gain passengers without auras"); }
|
||||
|
||||
public void CalculatePassengerPosition(ref float x, ref float y, ref float z, ref float o)
|
||||
{
|
||||
TransportPosHelper.CalculatePassengerPosition(ref x, ref y, ref z, ref o,
|
||||
ITransport.CalculatePassengerPosition(ref x, ref y, ref z, ref o,
|
||||
GetBase().GetPositionX(), GetBase().GetPositionY(),
|
||||
GetBase().GetPositionZ(), GetBase().GetOrientation());
|
||||
}
|
||||
|
||||
public void CalculatePassengerOffset(ref float x, ref float y, ref float z, ref float o)
|
||||
{
|
||||
TransportPosHelper.CalculatePassengerOffset(ref x, ref y, ref z, ref o,
|
||||
ITransport.CalculatePassengerOffset(ref x, ref y, ref z, ref o,
|
||||
GetBase().GetPositionX(), GetBase().GetPositionY(),
|
||||
GetBase().GetPositionZ(), GetBase().GetOrientation());
|
||||
}
|
||||
|
||||
public int GetMapIdForSpawning() { return (int)GetBase().GetMapId(); }
|
||||
|
||||
public void RemovePendingEvent(VehicleJoinEvent e)
|
||||
{
|
||||
foreach (var Event in _pendingJoinEvents)
|
||||
|
||||
@@ -839,7 +839,7 @@ namespace Game.Garrisons
|
||||
float y = spawn.GetPositionY();
|
||||
float z = spawn.GetPositionZ();
|
||||
float o = spawn.GetOrientation();
|
||||
TransportPosHelper.CalculatePassengerPosition(ref x, ref y, ref z, ref o, building.GetPositionX(), building.GetPositionY(), building.GetPositionZ(), building.GetOrientation());
|
||||
ITransport.CalculatePassengerPosition(ref x, ref y, ref z, ref o, building.GetPositionX(), building.GetPositionY(), building.GetPositionZ(), building.GetOrientation());
|
||||
|
||||
spawn.Relocate(x, y, z, o);
|
||||
switch (spawn.GetTypeId())
|
||||
|
||||
@@ -110,31 +110,37 @@ namespace Game
|
||||
|
||||
if (plrMover)
|
||||
{
|
||||
if (!plrMover.GetTransport())
|
||||
if (plrMover.GetTransport() == null)
|
||||
{
|
||||
Transport transport = plrMover.GetMap().GetTransport(movementInfo.transport.guid);
|
||||
if (transport)
|
||||
GameObject go = plrMover.GetMap().GetGameObject(movementInfo.transport.guid);
|
||||
if (go != null)
|
||||
{
|
||||
ITransport transport = go.ToTransportBase();
|
||||
if (transport != null)
|
||||
transport.AddPassenger(plrMover);
|
||||
}
|
||||
else if (plrMover.GetTransport().GetGUID() != movementInfo.transport.guid)
|
||||
}
|
||||
else if (plrMover.GetTransport().GetTransportGUID() != movementInfo.transport.guid)
|
||||
{
|
||||
plrMover.GetTransport().RemovePassenger(plrMover);
|
||||
Transport transport = plrMover.GetMap().GetTransport(movementInfo.transport.guid);
|
||||
if (transport)
|
||||
GameObject go = plrMover.GetMap().GetGameObject(movementInfo.transport.guid);
|
||||
if (go != null)
|
||||
{
|
||||
ITransport transport = go.ToTransportBase();
|
||||
if (transport != null)
|
||||
transport.AddPassenger(plrMover);
|
||||
else
|
||||
movementInfo.ResetTransport();
|
||||
}
|
||||
else
|
||||
movementInfo.ResetTransport();
|
||||
}
|
||||
}
|
||||
|
||||
if (!mover.GetTransport() && !mover.GetVehicle())
|
||||
{
|
||||
GameObject go = mover.GetMap().GetGameObject(movementInfo.transport.guid);
|
||||
if (!go || go.GetGoType() != GameObjectTypes.Transport)
|
||||
if (mover.GetTransport() == null && !mover.GetVehicle())
|
||||
movementInfo.transport.Reset();
|
||||
}
|
||||
}
|
||||
else if (plrMover && plrMover.GetTransport()) // if we were on a transport, leave
|
||||
else if (plrMover && plrMover.GetTransport() != null) // if we were on a transport, leave
|
||||
plrMover.GetTransport().RemovePassenger(plrMover);
|
||||
|
||||
// fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
|
||||
@@ -531,7 +537,7 @@ namespace Game
|
||||
return;
|
||||
}
|
||||
|
||||
if (!GetPlayer().GetTransport() && Math.Abs(GetPlayer().GetSpeed(move_type) - packet.Speed) > 0.01f)
|
||||
if (GetPlayer().GetTransport() == null && Math.Abs(GetPlayer().GetSpeed(move_type) - packet.Speed) > 0.01f)
|
||||
{
|
||||
if (GetPlayer().GetSpeed(move_type) > packet.Speed) // must be greater - just correct
|
||||
{
|
||||
|
||||
@@ -103,7 +103,7 @@ namespace Game.Maps
|
||||
{
|
||||
// at this moment i_clientGUIDs have guids that not iterate at grid level checks
|
||||
// but exist one case when this possible and object not out of range: transports
|
||||
Transport transport = i_player.GetTransport();
|
||||
Transport transport = i_player.GetTransport<Transport>();
|
||||
if (transport)
|
||||
{
|
||||
foreach (var obj in transport.GetPassengers())
|
||||
@@ -128,6 +128,9 @@ namespace Game.Maps
|
||||
case TypeId.DynamicObject:
|
||||
i_player.UpdateVisibilityOf(obj.ToDynamicObject(), i_data, i_visibleNow);
|
||||
break;
|
||||
case TypeId.AreaTrigger:
|
||||
i_player.UpdateVisibilityOf(obj.ToAreaTrigger(), i_data, i_visibleNow);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
+6
-10
@@ -1131,9 +1131,7 @@ namespace Game.Maps
|
||||
else
|
||||
{
|
||||
go.Relocate(x, y, z, orientation);
|
||||
go.UpdateModelPosition();
|
||||
go.UpdatePositionData();
|
||||
go.UpdateObjectVisibility(false);
|
||||
go.AfterRelocation();
|
||||
RemoveGameObjectFromMoveList(go);
|
||||
}
|
||||
|
||||
@@ -1354,9 +1352,7 @@ namespace Game.Maps
|
||||
{
|
||||
// update pos
|
||||
go.Relocate(go._newPosition);
|
||||
go.UpdateModelPosition();
|
||||
go.UpdatePositionData();
|
||||
go.UpdateObjectVisibility(false);
|
||||
go.AfterRelocation();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2247,7 +2243,7 @@ namespace Game.Maps
|
||||
var data = new UpdateData(player.GetMapId());
|
||||
|
||||
// attach to player data current transport data
|
||||
Transport transport = player.GetTransport();
|
||||
Transport transport = player.GetTransport<Transport>();
|
||||
if (transport != null)
|
||||
{
|
||||
transport.BuildCreateUpdateBlockForPlayer(data, player);
|
||||
@@ -4168,8 +4164,8 @@ namespace Game.Maps
|
||||
if (!summon.Create(GenerateLowGuid(HighGuid.Creature), this, entry, pos, null, vehId, true))
|
||||
return null;
|
||||
|
||||
Transport transport = summoner != null ? summoner.GetTransport() : null;
|
||||
if (transport)
|
||||
ITransport transport = summoner != null ? summoner.GetTransport() : null;
|
||||
if (transport != null)
|
||||
{
|
||||
pos.GetPosition(out float x, out float y, out float z, out float o);
|
||||
transport.CalculatePassengerOffset(ref x, ref y, ref z, ref o);
|
||||
@@ -4209,7 +4205,7 @@ namespace Game.Maps
|
||||
if (!AddToMap(summon.ToCreature()))
|
||||
{
|
||||
// Returning false will cause the object to be deleted - remove from transport
|
||||
if (transport)
|
||||
if (transport != null)
|
||||
transport.RemovePassenger(summon);
|
||||
|
||||
summon.Dispose();
|
||||
|
||||
@@ -425,6 +425,18 @@ namespace Game.Maps
|
||||
_transportAnimations[transportEntry] = animNode;
|
||||
}
|
||||
|
||||
public void AddPathRotationToTransport(uint transportEntry, uint timeSeg, TransportRotationRecord node)
|
||||
{
|
||||
if (!_transportAnimations.ContainsKey(transportEntry))
|
||||
_transportAnimations[transportEntry] = new();
|
||||
|
||||
TransportAnimation animNode = _transportAnimations[transportEntry];
|
||||
animNode.Rotations[timeSeg] = node;
|
||||
|
||||
if (animNode.Path.Empty() && animNode.TotalTime < timeSeg)
|
||||
animNode.TotalTime = timeSeg;
|
||||
}
|
||||
|
||||
public Transport CreateTransport(uint entry, ulong guid = 0, Map map = null, PhaseUseFlagsValues phaseUseFlags = 0, uint phaseId = 0, uint phaseGroupId = 0)
|
||||
{
|
||||
// instance case, execute GetGameObjectEntry hook
|
||||
@@ -531,14 +543,6 @@ namespace Game.Maps
|
||||
return _transportSpawns.LookupByKey(spawnId);
|
||||
}
|
||||
|
||||
public void AddPathRotationToTransport(uint transportEntry, uint timeSeg, TransportRotationRecord node)
|
||||
{
|
||||
if (!_transportAnimations.ContainsKey(transportEntry))
|
||||
_transportAnimations[transportEntry] = new TransportAnimation();
|
||||
|
||||
_transportAnimations[transportEntry].Rotations[timeSeg] = node;
|
||||
}
|
||||
|
||||
Dictionary<uint, TransportTemplate> _transportTemplates = new();
|
||||
MultiMap<uint, uint> _instanceTransports = new();
|
||||
Dictionary<uint, TransportAnimation> _transportAnimations = new();
|
||||
@@ -558,7 +562,7 @@ namespace Game.Maps
|
||||
cyclic = false;
|
||||
points = new Vector3[_points.Count];
|
||||
|
||||
for(var i = 0; i < _points.Count; ++i)
|
||||
for (var i = 0; i < _points.Count; ++i)
|
||||
points[i] = _points[i];
|
||||
|
||||
lo = 1;
|
||||
@@ -627,26 +631,59 @@ namespace Game.Maps
|
||||
|
||||
public class TransportAnimation
|
||||
{
|
||||
TransportAnimationRecord GetAnimNode(uint time)
|
||||
public Dictionary<uint, TransportAnimationRecord> Path = new();
|
||||
public Dictionary<uint, TransportRotationRecord> Rotations = new();
|
||||
public uint TotalTime;
|
||||
|
||||
public TransportAnimationRecord GetPrevAnimNode(uint time)
|
||||
{
|
||||
if (Path.Empty())
|
||||
return null;
|
||||
|
||||
foreach (var pair in Path)
|
||||
if (time >= pair.Key)
|
||||
return pair.Value;
|
||||
List<uint> lKeys = Path.Keys.ToList();
|
||||
int reqIndex = lKeys.IndexOf(time) - 1;
|
||||
|
||||
return Path.First().Value;
|
||||
if (reqIndex != -1)
|
||||
return Path[lKeys[reqIndex]];
|
||||
|
||||
return Path.LastOrDefault().Value;
|
||||
}
|
||||
|
||||
TransportRotationRecord GetAnimRotation(uint time)
|
||||
public TransportRotationRecord GetPrevAnimRotation(uint time)
|
||||
{
|
||||
return Rotations.LookupByKey(time);
|
||||
if (Rotations.Empty())
|
||||
return null;
|
||||
|
||||
List<uint> lKeys = Rotations.Keys.ToList();
|
||||
int reqIndex = lKeys.IndexOf(time) - 1;
|
||||
|
||||
if (reqIndex != -1)
|
||||
return Rotations[lKeys[reqIndex]];
|
||||
|
||||
return Rotations.LastOrDefault().Value;
|
||||
}
|
||||
|
||||
public Dictionary<uint, TransportAnimationRecord> Path = new();
|
||||
public Dictionary<uint, TransportRotationRecord> Rotations = new();
|
||||
public uint TotalTime;
|
||||
public TransportAnimationRecord GetNextAnimNode(uint time)
|
||||
{
|
||||
if (Path.Empty())
|
||||
return null;
|
||||
|
||||
if (Path.TryGetValue(time, out TransportAnimationRecord record))
|
||||
return record;
|
||||
|
||||
return Path.FirstOrDefault().Value;
|
||||
}
|
||||
|
||||
public TransportRotationRecord GetNextAnimRotation(uint time)
|
||||
{
|
||||
if (Rotations.Empty())
|
||||
return null;
|
||||
|
||||
if (Rotations.TryGetValue(time, out TransportRotationRecord record))
|
||||
return record;
|
||||
|
||||
return Rotations.FirstOrDefault().Value;
|
||||
}
|
||||
}
|
||||
|
||||
public class TransportSpawn
|
||||
|
||||
@@ -303,10 +303,10 @@ namespace Game.Movement
|
||||
owner.SetHomePosition(x, y, z, o);
|
||||
else
|
||||
{
|
||||
Transport trans = owner.GetTransport();
|
||||
if (trans)
|
||||
ITransport trans = owner.GetTransport();
|
||||
if (trans != null)
|
||||
{
|
||||
o -= trans.GetOrientation();
|
||||
o -= trans.GetTransportOrientation();
|
||||
owner.SetTransportHomePosition(x, y, z, o);
|
||||
trans.CalculatePassengerPosition(ref x, ref y, ref z, ref o);
|
||||
owner.SetHomePosition(x, y, z, o);
|
||||
|
||||
@@ -222,11 +222,14 @@ namespace Game.Movement
|
||||
if (args.TransformForTransport)
|
||||
{
|
||||
Unit vehicle = unit.GetVehicleBase();
|
||||
Transport transport = unit.GetTransport();
|
||||
if (vehicle != null)
|
||||
angle -= vehicle.Orientation;
|
||||
else if (transport != null)
|
||||
angle -= transport.Orientation;
|
||||
angle -= vehicle.GetOrientation();
|
||||
else
|
||||
{
|
||||
ITransport transport = unit.GetTransport();
|
||||
if (transport != null)
|
||||
angle -= transport.GetTransportOrientation();
|
||||
}
|
||||
}
|
||||
|
||||
args.facing.angle = MathFunctions.wrap(angle, 0.0f, MathFunctions.TwoPi);
|
||||
|
||||
@@ -7078,7 +7078,7 @@ namespace Game.Spells
|
||||
if (target.GetGUID() != corpse.GetOwnerGUID())
|
||||
return false;
|
||||
|
||||
if (!corpse.HasDynamicFlag(UnitDynFlags.Lootable))
|
||||
if (!corpse.HasCorpseDynamicFlag(CorpseDynFlags.Lootable))
|
||||
return false;
|
||||
|
||||
if (!corpse.IsWithinLOSInMap(m_caster, LineOfSightChecks.All, ModelIgnoreFlags.M2))
|
||||
|
||||
@@ -186,7 +186,7 @@ namespace Scripts.World.ItemScripts
|
||||
if (player.GetZoneId() != Misc.ZoneIdHowling)
|
||||
return false;
|
||||
|
||||
if (!player.GetTransport() || player.GetAreaId() != Misc.AreaIdShatteredStraits)
|
||||
if (player.GetTransport() == null || player.GetAreaId() != Misc.AreaIdShatteredStraits)
|
||||
{
|
||||
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(SpellIds.PetrovBomb, Difficulty.None);
|
||||
if (spellInfo != null)
|
||||
|
||||
Reference in New Issue
Block a user