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
|
Max = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum GameObjectDynamicLowFlags
|
public enum GameObjectDynamicLowFlags : ushort
|
||||||
{
|
{
|
||||||
HideModel = 0x02,
|
HideModel = 0x02,
|
||||||
Activate = 0x04,
|
Activate = 0x04,
|
||||||
|
|||||||
@@ -1360,7 +1360,7 @@ namespace Game.AI
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
if (e.GetTargetType() == SmartTargets.Self)
|
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)
|
else if (e.GetTargetType() == SmartTargets.Position)
|
||||||
_me.SetFacingTo(e.Target.o);
|
_me.SetFacingTo(e.Target.o);
|
||||||
else if (!targets.Empty())
|
else if (!targets.Empty())
|
||||||
|
|||||||
@@ -1079,7 +1079,7 @@ namespace Game.Chat
|
|||||||
[Command("transport", RBACPermissions.CommandDebugTransport)]
|
[Command("transport", RBACPermissions.CommandDebugTransport)]
|
||||||
static bool HandleDebugTransportCommand(CommandHandler handler, string operation)
|
static bool HandleDebugTransportCommand(CommandHandler handler, string operation)
|
||||||
{
|
{
|
||||||
Transport transport = handler.GetSession().GetPlayer().GetTransport();
|
Transport transport = handler.GetSession().GetPlayer().GetTransport<Transport>();
|
||||||
if (!transport)
|
if (!transport)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|||||||
@@ -959,7 +959,7 @@ namespace Game.Chat
|
|||||||
areaId, (areaEntry != null ? areaEntry.AreaName[handler.GetSessionDbcLocale()] : unknown),
|
areaId, (areaEntry != null ? areaEntry.AreaName[handler.GetSessionDbcLocale()] : unknown),
|
||||||
obj.GetPositionX(), obj.GetPositionY(), obj.GetPositionZ(), obj.GetOrientation());
|
obj.GetPositionX(), obj.GetPositionY(), obj.GetPositionZ(), obj.GetOrientation());
|
||||||
|
|
||||||
Transport transport = obj.GetTransport();
|
Transport transport = obj.GetTransport<Transport>();
|
||||||
if (transport)
|
if (transport)
|
||||||
{
|
{
|
||||||
handler.SendSysMessage(CypherStrings.TransportPosition, transport.GetGoInfo().MoTransport.SpawnMap, obj.GetTransOffsetX(), obj.GetTransOffsetY(), obj.GetTransOffsetZ(), obj.GetTransOffsetO(),
|
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();
|
Player chr = handler.GetSession().GetPlayer();
|
||||||
Map map = chr.GetMap();
|
Map map = chr.GetMap();
|
||||||
|
|
||||||
Transport trans = chr.GetTransport();
|
Transport trans = chr.GetTransport<Transport>();
|
||||||
if (trans)
|
if (trans)
|
||||||
{
|
{
|
||||||
ulong guid = Global.ObjectMgr.GenerateCreatureSpawnId();
|
ulong guid = Global.ObjectMgr.GenerateCreatureSpawnId();
|
||||||
|
|||||||
@@ -191,8 +191,8 @@ namespace Game.Entities
|
|||||||
}
|
}
|
||||||
|
|
||||||
// movement on transport of areatriggers on unit is handled by themself
|
// movement on transport of areatriggers on unit is handled by themself
|
||||||
Transport transport = m_movementInfo.transport.guid.IsEmpty() ? caster.GetTransport() : null;
|
ITransport transport = m_movementInfo.transport.guid.IsEmpty() ? caster.GetTransport() : null;
|
||||||
if (transport)
|
if (transport != null)
|
||||||
{
|
{
|
||||||
float x, y, z, o;
|
float x, y, z, o;
|
||||||
pos.GetPosition(out x, out y, out z, out o);
|
pos.GetPosition(out x, out y, out z, out o);
|
||||||
@@ -211,7 +211,7 @@ namespace Game.Entities
|
|||||||
|
|
||||||
if (!GetMap().AddToMap(this))
|
if (!GetMap().AddToMap(this))
|
||||||
{ // Returning false will cause the object to be deleted - remove from transport
|
{ // Returning false will cause the object to be deleted - remove from transport
|
||||||
if (transport)
|
if (transport != null)
|
||||||
transport.RemovePassenger(this);
|
transport.RemovePassenger(this);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -286,6 +286,7 @@ namespace Game.Entities
|
|||||||
}
|
}
|
||||||
|
|
||||||
public CorpseDynFlags GetCorpseDynamicFlags() { return (CorpseDynFlags)(uint)m_corpseData.DynamicFlags; }
|
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 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 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); }
|
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;
|
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);
|
SaveToDB(mapId, data.SpawnDifficulties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -111,8 +111,8 @@ namespace Game.Entities
|
|||||||
if (IsWorldObject())
|
if (IsWorldObject())
|
||||||
SetActive(true); //must before add to map to be put in world container
|
SetActive(true); //must before add to map to be put in world container
|
||||||
|
|
||||||
Transport transport = caster.GetTransport();
|
ITransport transport = caster.GetTransport();
|
||||||
if (transport)
|
if (transport != null)
|
||||||
{
|
{
|
||||||
float x, y, z, o;
|
float x, y, z, o;
|
||||||
pos.GetPosition(out x, out y, out z, out o);
|
pos.GetPosition(out x, out y, out z, out o);
|
||||||
@@ -126,7 +126,7 @@ namespace Game.Entities
|
|||||||
if (!GetMap().AddToMap(this))
|
if (!GetMap().AddToMap(this))
|
||||||
{
|
{
|
||||||
// Returning false will cause the object to be deleted - remove from transport
|
// Returning false will cause the object to be deleted - remove from transport
|
||||||
if (transport)
|
if (transport != null)
|
||||||
transport.RemovePassenger(this);
|
transport.RemovePassenger(this);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,8 +60,6 @@ namespace Game.Entities
|
|||||||
{
|
{
|
||||||
m_AI = null;
|
m_AI = null;
|
||||||
m_model = null;
|
m_model = null;
|
||||||
if (m_goInfo != null && m_goInfo.type == GameObjectTypes.Transport)
|
|
||||||
m_goValue.Transport.StopFrames.Clear();
|
|
||||||
|
|
||||||
base.Dispose();
|
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));
|
SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.ParentRotation), new Quaternion(goInfo.DestructibleBuilding.DestructibleModelRec, 0f, 0f, 0f));
|
||||||
break;
|
break;
|
||||||
case GameObjectTypes.Transport:
|
case GameObjectTypes.Transport:
|
||||||
m_goValue.Transport.AnimationInfo = Global.TransportMgr.GetTransportAnimInfo(goInfo.entry);
|
m_goTypeImpl = new GameObjectType.Transport(this);
|
||||||
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);
|
|
||||||
|
|
||||||
if (goInfo.Transport.startOpen != 0)
|
if (goInfo.Transport.startOpen != 0)
|
||||||
SetTransportState(GameObjectState.TransportStopped, goInfo.Transport.startOpen - 1);
|
SetGoState(GameObjectState.TransportStopped);
|
||||||
else
|
else
|
||||||
SetTransportState(GameObjectState.TransportActive);
|
SetGoState(GameObjectState.TransportActive);
|
||||||
|
|
||||||
SetGoAnimProgress(animProgress);
|
SetGoAnimProgress(animProgress);
|
||||||
|
SetActive(true);
|
||||||
break;
|
break;
|
||||||
case GameObjectTypes.FishingNode:
|
case GameObjectTypes.FishingNode:
|
||||||
SetLevel(1);
|
SetLevel(1);
|
||||||
@@ -452,6 +427,9 @@ namespace Game.Entities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_goTypeImpl != null)
|
||||||
|
m_goTypeImpl.Update(diff);
|
||||||
|
|
||||||
switch (m_lootState)
|
switch (m_lootState)
|
||||||
{
|
{
|
||||||
case LootState.NotReady:
|
case LootState.NotReady:
|
||||||
@@ -475,50 +453,6 @@ namespace Game.Entities
|
|||||||
m_lootState = LootState.Ready;
|
m_lootState = LootState.Ready;
|
||||||
break;
|
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:
|
case GameObjectTypes.FishingNode:
|
||||||
{
|
{
|
||||||
// fishing code (bobber ready)
|
// fishing code (bobber ready)
|
||||||
@@ -1072,7 +1006,13 @@ namespace Game.Entities
|
|||||||
return;
|
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)
|
public void SaveToDB(uint mapid, List<Difficulty> spawnDifficulties)
|
||||||
@@ -1293,7 +1233,7 @@ namespace Game.Entities
|
|||||||
if (gInfo == null)
|
if (gInfo == null)
|
||||||
return false;
|
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()
|
public bool IsDestructibleBuilding()
|
||||||
@@ -1581,7 +1521,7 @@ namespace Game.Entities
|
|||||||
case GameObjectActions.GoTo9thFloor:
|
case GameObjectActions.GoTo9thFloor:
|
||||||
case GameObjectActions.GoTo10thFloor:
|
case GameObjectActions.GoTo10thFloor:
|
||||||
if (GetGoType() == GameObjectTypes.Transport)
|
if (GetGoType() == GameObjectTypes.Transport)
|
||||||
SetTransportState(GameObjectState.TransportStopped, (uint)(action - GameObjectActions.GoTo1stFloor));
|
SetGoState((GameObjectState)action);
|
||||||
else
|
else
|
||||||
Log.outError(LogFilter.Spells, $"Spell {spellId} targeted non-transport gameobject for transport only action \"Go to Floor\" {action} in effect {effectIndex}");
|
Log.outError(LogFilter.Spells, $"Spell {spellId} targeted non-transport gameobject for transport only action \"Go to Floor\" {action} in effect {effectIndex}");
|
||||||
break;
|
break;
|
||||||
@@ -2453,7 +2393,7 @@ namespace Game.Entities
|
|||||||
{
|
{
|
||||||
Quaternion localRotation = GetLocalRotation();
|
Quaternion localRotation = GetLocalRotation();
|
||||||
|
|
||||||
Transport transport = GetTransport();
|
Transport transport = GetTransport<Transport>();
|
||||||
if (transport != null)
|
if (transport != null)
|
||||||
{
|
{
|
||||||
Quaternion worldRotation = transport.GetWorldRotation();
|
Quaternion worldRotation = transport.GetWorldRotation();
|
||||||
@@ -2473,7 +2413,7 @@ namespace Game.Entities
|
|||||||
{
|
{
|
||||||
return $"{base.GetDebugInfo()}\nSpawnId: {GetSpawnId()} GoState: {GetGoState()} ScriptId: {GetScriptId()} AIName: {GetAIName()}";
|
return $"{base.GetDebugInfo()}\nSpawnId: {GetSpawnId()} GoState: {GetGoState()} ScriptId: {GetScriptId()} AIName: {GetAIName()}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsAtInteractDistance(Player player, SpellInfo spell = null)
|
public bool IsAtInteractDistance(Player player, SpellInfo spell = null)
|
||||||
{
|
{
|
||||||
if (spell != null || (spell = GetSpellForLock(player)) != null)
|
if (spell != null || (spell = GetSpellForLock(player)) != null)
|
||||||
@@ -2518,7 +2458,7 @@ namespace Game.Entities
|
|||||||
{
|
{
|
||||||
return IsInMap(player) && IsInPhase(player) && IsAtInteractDistance(player);
|
return IsInMap(player) && IsInPhase(player) && IsAtInteractDistance(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SpellInfo GetSpellForLock(Player player)
|
public SpellInfo GetSpellForLock(Player player)
|
||||||
{
|
{
|
||||||
if (!player)
|
if (!player)
|
||||||
@@ -2563,7 +2503,6 @@ namespace Game.Entities
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void ModifyHealth(int change, WorldObject attackerOrHealer = null, uint spellId = 0)
|
public void ModifyHealth(int change, WorldObject attackerOrHealer = null, uint spellId = 0)
|
||||||
{
|
{
|
||||||
if (m_goValue.Building.MaxHealth == 0 || change == 0)
|
if (m_goValue.Building.MaxHealth == 0 || change == 0)
|
||||||
@@ -2742,9 +2681,14 @@ namespace Game.Entities
|
|||||||
|
|
||||||
public void SetGoState(GameObjectState state)
|
public void SetGoState(GameObjectState state)
|
||||||
{
|
{
|
||||||
|
GameObjectState oldState = GetGoState();
|
||||||
SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.State), (sbyte)state);
|
SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.State), (sbyte)state);
|
||||||
if (GetAI() != null)
|
if (GetAI() != null)
|
||||||
GetAI().OnStateChanged(state);
|
GetAI().OnStateChanged(state);
|
||||||
|
|
||||||
|
if (m_goTypeImpl != null)
|
||||||
|
m_goTypeImpl.OnStateChanged(oldState, state);
|
||||||
|
|
||||||
if (m_model != null && !IsTransport())
|
if (m_model != null && !IsTransport())
|
||||||
{
|
{
|
||||||
if (!IsInWorld)
|
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)
|
public void SetDisplayId(uint displayid)
|
||||||
{
|
{
|
||||||
SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.DisplayID), displayid);
|
SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.DisplayID), displayid);
|
||||||
@@ -2985,6 +2897,33 @@ namespace Game.Entities
|
|||||||
base.ClearUpdateMask(remove);
|
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)
|
public void GetRespawnPosition(out float x, out float y, out float z, out float ori)
|
||||||
{
|
{
|
||||||
if (m_goData != null)
|
if (m_goData != null)
|
||||||
@@ -2993,6 +2932,31 @@ namespace Game.Entities
|
|||||||
GetPosition(out x, out y, out z, out ori);
|
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()
|
public float GetInteractionDistance()
|
||||||
{
|
{
|
||||||
switch (GetGoType())
|
switch (GetGoType())
|
||||||
@@ -3239,7 +3203,7 @@ namespace Game.Entities
|
|||||||
return m_goValue.CapturePoint.State == BattlegroundCapturePointState.ContestedHorde
|
return m_goValue.CapturePoint.State == BattlegroundCapturePointState.ContestedHorde
|
||||||
|| m_goValue.CapturePoint.State == BattlegroundCapturePointState.HordeCaptured;
|
|| m_goValue.CapturePoint.State == BattlegroundCapturePointState.HordeCaptured;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override ushort GetAIAnimKitId() { return _animKitId; }
|
public override ushort GetAIAnimKitId() { return _animKitId; }
|
||||||
|
|
||||||
public uint GetWorldEffectID() { return _worldEffectID; }
|
public uint GetWorldEffectID() { return _worldEffectID; }
|
||||||
@@ -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 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 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 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 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; }
|
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 GetStationaryY() { return StationaryPosition.GetPositionY(); }
|
||||||
public override float GetStationaryZ() { return StationaryPosition.GetPositionZ(); }
|
public override float GetStationaryZ() { return StationaryPosition.GetPositionZ(); }
|
||||||
public override float GetStationaryO() { return StationaryPosition.GetOrientation(); }
|
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); }
|
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());
|
Cell.VisitWorldObjects(this, deliverer, GetVisibilityRange());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HandleCustomTypeCommand(GameObjectTypeBase.CustomCommand command)
|
||||||
|
{
|
||||||
|
if (m_goTypeImpl != null)
|
||||||
|
command.Execute(m_goTypeImpl);
|
||||||
|
}
|
||||||
|
|
||||||
public void CreateModel()
|
public void CreateModel()
|
||||||
{
|
{
|
||||||
m_model = GameObjectModel.Create(new GameObjectModelOwnerImpl(this));
|
m_model = GameObjectModel.Create(new GameObjectModelOwnerImpl(this));
|
||||||
@@ -3419,8 +3396,9 @@ namespace Game.Entities
|
|||||||
public bool GetRespawnCompatibilityMode() { return m_respawnCompatibilityMode; }
|
public bool GetRespawnCompatibilityMode() { return m_respawnCompatibilityMode; }
|
||||||
|
|
||||||
#region Fields
|
#region Fields
|
||||||
protected GameObjectFieldData m_gameObjectData;
|
public GameObjectFieldData m_gameObjectData;
|
||||||
protected GameObjectValue m_goValue;
|
GameObjectTypeBase m_goTypeImpl;
|
||||||
|
protected GameObjectValue m_goValue; // TODO: replace with m_goTypeImpl
|
||||||
protected GameObjectTemplate m_goInfo;
|
protected GameObjectTemplate m_goInfo;
|
||||||
protected GameObjectTemplateAddon m_goTemplateAddon;
|
protected GameObjectTemplateAddon m_goTemplateAddon;
|
||||||
GameObjectData m_goData;
|
GameObjectData m_goData;
|
||||||
@@ -3509,6 +3487,26 @@ namespace Game.Entities
|
|||||||
GameObject _owner;
|
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 struct GameObjectValue
|
||||||
{
|
{
|
||||||
public transport Transport;
|
public transport Transport;
|
||||||
@@ -3549,4 +3547,387 @@ namespace Game.Entities
|
|||||||
public uint AssaultTimer;
|
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;
|
return SpellFocus.GiganticAOI != 0;
|
||||||
case GameObjectTypes.Goober:
|
case GameObjectTypes.Goober:
|
||||||
return Goober.GiganticAOI != 0;
|
return Goober.GiganticAOI != 0;
|
||||||
|
case GameObjectTypes.Transport:
|
||||||
|
return true;
|
||||||
case GameObjectTypes.SpellCaster:
|
case GameObjectTypes.SpellCaster:
|
||||||
return SpellCaster.GiganticAOI != 0;
|
return SpellCaster.GiganticAOI != 0;
|
||||||
case GameObjectTypes.FlagStand:
|
case GameObjectTypes.FlagStand:
|
||||||
|
|||||||
@@ -79,27 +79,27 @@ namespace Game.Entities
|
|||||||
|
|
||||||
uint GetViewerDependentDynamicFlags(ObjectFieldData objectData, WorldObject obj, Player receiver)
|
uint GetViewerDependentDynamicFlags(ObjectFieldData objectData, WorldObject obj, Player receiver)
|
||||||
{
|
{
|
||||||
UnitDynFlags unitDynFlags = (UnitDynFlags)(uint)objectData.DynamicFlags;
|
uint unitDynFlags = objectData.DynamicFlags;
|
||||||
|
|
||||||
Unit unit = obj.ToUnit();
|
Unit unit = obj.ToUnit();
|
||||||
if (unit != null)
|
if (unit != null)
|
||||||
{
|
{
|
||||||
unitDynFlags &= ~UnitDynFlags.Tapped;
|
unitDynFlags &= ~(uint)UnitDynFlags.Tapped;
|
||||||
|
|
||||||
Creature creature = obj.ToCreature();
|
Creature creature = obj.ToCreature();
|
||||||
if (creature != null)
|
if (creature != null)
|
||||||
{
|
{
|
||||||
if (creature.HasLootRecipient() && !creature.IsTappedBy(receiver))
|
if (creature.HasLootRecipient() && !creature.IsTappedBy(receiver))
|
||||||
unitDynFlags |= UnitDynFlags.Tapped;
|
unitDynFlags |= (uint)UnitDynFlags.Tapped;
|
||||||
|
|
||||||
if (!receiver.IsAllowedToLoot(creature))
|
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
|
// 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()))
|
if (!unit.HasAuraTypeWithCaster(AuraType.ModStalked, receiver.GetGUID()))
|
||||||
unitDynFlags &= ~UnitDynFlags.TrackUnit;
|
unitDynFlags &= ~(uint)UnitDynFlags.TrackUnit;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -126,12 +126,18 @@ namespace Game.Entities
|
|||||||
dynFlags |= GameObjectDynamicLowFlags.Sparkle | GameObjectDynamicLowFlags.Highlight;
|
dynFlags |= GameObjectDynamicLowFlags.Sparkle | GameObjectDynamicLowFlags.Highlight;
|
||||||
break;
|
break;
|
||||||
case GameObjectTypes.Transport:
|
case GameObjectTypes.Transport:
|
||||||
|
{
|
||||||
|
dynFlags = (GameObjectDynamicLowFlags)((int)unitDynFlags & 0xFFFF);
|
||||||
|
pathProgress = (ushort)((int)unitDynFlags >> 16);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case GameObjectTypes.MapObjTransport:
|
case GameObjectTypes.MapObjTransport:
|
||||||
{
|
{
|
||||||
uint transportPeriod = gameObject.GetTransportPeriod();
|
Transport transport = gameObject.ToTransport();
|
||||||
|
uint transportPeriod = transport.GetTransportPeriod();
|
||||||
if (transportPeriod != 0)
|
if (transportPeriod != 0)
|
||||||
{
|
{
|
||||||
float timer = (float)(gameObject.GetGoValue().Transport.PathProgress % transportPeriod);
|
float timer = (float)(transport.GetTimer() % transportPeriod);
|
||||||
pathProgress = (ushort)(timer / (float)transportPeriod * 65535.0f);
|
pathProgress = (ushort)(timer / (float)transportPeriod * 65535.0f);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -146,11 +152,11 @@ namespace Game.Entities
|
|||||||
break;
|
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.Z);
|
||||||
data.WriteFloat(rotation.W);
|
data.WriteFloat(rotation.W);
|
||||||
data.WriteUInt32(FactionTemplate);
|
data.WriteUInt32(FactionTemplate);
|
||||||
data.WriteInt8(GetViewerGameObjectState(this, owner, receiver));
|
data.WriteInt8(State);
|
||||||
data.WriteInt8(TypeID);
|
data.WriteInt8(TypeID);
|
||||||
data.WriteUInt8(PercentHealth);
|
data.WriteUInt8(PercentHealth);
|
||||||
data.WriteUInt32(ArtKit);
|
data.WriteUInt32(ArtKit);
|
||||||
data.WriteInt32(EnableDoodadSets.Size());
|
data.WriteInt32(EnableDoodadSets.Size());
|
||||||
data.WriteUInt32(CustomParam);
|
data.WriteUInt32(CustomParam);
|
||||||
data.WriteUInt32(GetViewerGameObjectLevel(this, owner, receiver));
|
data.WriteUInt32(Level);
|
||||||
data.WriteUInt32(AnimGroupInstance);
|
data.WriteUInt32(AnimGroupInstance);
|
||||||
for (int i = 0; i < EnableDoodadSets.Size(); ++i)
|
for (int i = 0; i < EnableDoodadSets.Size(); ++i)
|
||||||
{
|
{
|
||||||
@@ -5053,7 +5059,7 @@ namespace Game.Entities
|
|||||||
}
|
}
|
||||||
if (changesMask[14])
|
if (changesMask[14])
|
||||||
{
|
{
|
||||||
data.WriteInt8(GetViewerGameObjectState(this, owner, receiver));
|
data.WriteInt8(State);
|
||||||
}
|
}
|
||||||
if (changesMask[15])
|
if (changesMask[15])
|
||||||
{
|
{
|
||||||
@@ -5073,7 +5079,7 @@ namespace Game.Entities
|
|||||||
}
|
}
|
||||||
if (changesMask[19])
|
if (changesMask[19])
|
||||||
{
|
{
|
||||||
data.WriteUInt32(GetViewerGameObjectLevel(this, owner, receiver));
|
data.WriteUInt32(Level);
|
||||||
}
|
}
|
||||||
if (changesMask[20])
|
if (changesMask[20])
|
||||||
{
|
{
|
||||||
@@ -5116,24 +5122,6 @@ namespace Game.Entities
|
|||||||
|
|
||||||
return flags;
|
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>
|
public class DynamicObjectData : BaseUpdateData<DynamicObject>
|
||||||
|
|||||||
@@ -246,14 +246,10 @@ namespace Game.Entities
|
|||||||
|
|
||||||
public void BuildMovementUpdate(WorldPacket data, CreateObjectBits flags, Player target)
|
public void BuildMovementUpdate(WorldPacket data, CreateObjectBits flags, Player target)
|
||||||
{
|
{
|
||||||
int PauseTimesCount = 0;
|
List<uint> PauseTimes = null;
|
||||||
|
|
||||||
GameObject go = ToGameObject();
|
GameObject go = ToGameObject();
|
||||||
if (go)
|
if (go)
|
||||||
{
|
PauseTimes = go.GetPauseTimes();
|
||||||
if (go.GetGoType() == GameObjectTypes.Transport)
|
|
||||||
PauseTimesCount = go.GetGoValue().Transport.StopFrames.Count;
|
|
||||||
}
|
|
||||||
|
|
||||||
data.WriteBit(flags.NoBirthAnim);
|
data.WriteBit(flags.NoBirthAnim);
|
||||||
data.WriteBit(flags.EnablePortals);
|
data.WriteBit(flags.EnablePortals);
|
||||||
@@ -368,7 +364,7 @@ namespace Game.Entities
|
|||||||
MovementExtensions.WriteCreateObjectSplineDataBlock(unit.MoveSpline, data);
|
MovementExtensions.WriteCreateObjectSplineDataBlock(unit.MoveSpline, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
data.WriteInt32(PauseTimesCount);
|
data.WriteInt32(PauseTimes != null ? PauseTimes.Count : 0);
|
||||||
|
|
||||||
if (flags.Stationary)
|
if (flags.Stationary)
|
||||||
{
|
{
|
||||||
@@ -381,20 +377,9 @@ namespace Game.Entities
|
|||||||
|
|
||||||
if (flags.CombatVictim)
|
if (flags.CombatVictim)
|
||||||
data.WritePackedGuid(ToUnit().GetVictim().GetGUID()); // CombatVictim
|
data.WritePackedGuid(ToUnit().GetVictim().GetGUID()); // CombatVictim
|
||||||
|
|
||||||
if (flags.ServerTime)
|
if (flags.ServerTime)
|
||||||
{
|
data.WriteUInt32(GameTime.GetGameTimeMS());
|
||||||
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)
|
if (flags.Vehicle)
|
||||||
{
|
{
|
||||||
@@ -413,11 +398,9 @@ namespace Game.Entities
|
|||||||
if (flags.Rotation)
|
if (flags.Rotation)
|
||||||
data.WriteInt64(ToGameObject().GetPackedLocalRotation()); // Rotation
|
data.WriteInt64(ToGameObject().GetPackedLocalRotation()); // Rotation
|
||||||
|
|
||||||
if (go)
|
if (PauseTimes != null && !PauseTimes.Empty())
|
||||||
{
|
foreach (var stopFrame in PauseTimes)
|
||||||
for (int i = 0; i < PauseTimesCount; ++i)
|
data.WriteUInt32(stopFrame);
|
||||||
data.WriteUInt32(go.GetGoValue().Transport.StopFrames[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags.MovementTransport)
|
if (flags.MovementTransport)
|
||||||
{
|
{
|
||||||
@@ -969,19 +952,9 @@ namespace Game.Entities
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (on)
|
if (on)
|
||||||
{
|
map.AddToActive(this);
|
||||||
if (IsTypeId(TypeId.Unit))
|
|
||||||
map.AddToActive(ToCreature());
|
|
||||||
else if (IsTypeId(TypeId.DynamicObject))
|
|
||||||
map.AddToActive(ToDynamicObject());
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
map.RemoveFromActive(this);
|
||||||
if (IsTypeId(TypeId.Unit))
|
|
||||||
map.RemoveFromActive(ToCreature());
|
|
||||||
else if (IsTypeId(TypeId.DynamicObject))
|
|
||||||
map.RemoveFromActive(ToDynamicObject());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsFarVisible() { return m_isFarVisible; }
|
bool IsFarVisible() { return m_isFarVisible; }
|
||||||
@@ -1010,8 +983,8 @@ namespace Game.Entities
|
|||||||
if (IsInWorld)
|
if (IsInWorld)
|
||||||
RemoveFromWorld();
|
RemoveFromWorld();
|
||||||
|
|
||||||
Transport transport = GetTransport();
|
ITransport transport = GetTransport();
|
||||||
if (transport)
|
if (transport != null)
|
||||||
transport.RemovePassenger(this);
|
transport.RemovePassenger(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2957,12 +2930,6 @@ namespace Game.Entities
|
|||||||
public float GetObjectScale() { return m_objectData.Scale; }
|
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 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 TypeId GetTypeId() { return ObjectTypeId; }
|
||||||
public bool IsTypeId(TypeId typeId) { return GetTypeId() == typeId; }
|
public bool IsTypeId(TypeId typeId) { return GetTypeId() == typeId; }
|
||||||
public bool IsTypeMask(TypeMask mask) { return Convert.ToBoolean(mask & ObjectTypeMask); }
|
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 IsActiveObject() { return m_isActive; }
|
||||||
public bool IsPermanentWorldObject() { return m_isWorldObject; }
|
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 GetTransOffsetX() { return m_movementInfo.transport.pos.GetPositionX(); }
|
||||||
public float GetTransOffsetY() { return m_movementInfo.transport.pos.GetPositionY(); }
|
public float GetTransOffsetY() { return m_movementInfo.transport.pos.GetPositionY(); }
|
||||||
public float GetTransOffsetZ() { return m_movementInfo.transport.pos.GetPositionZ(); }
|
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 sbyte GetTransSeat() { return m_movementInfo.transport.seat; }
|
||||||
public virtual ObjectGuid GetTransGUID()
|
public virtual ObjectGuid GetTransGUID()
|
||||||
{
|
{
|
||||||
if (GetTransport())
|
if (GetTransport() != null)
|
||||||
return GetTransport().GetGUID();
|
return GetTransport().GetTransportGUID();
|
||||||
|
|
||||||
return ObjectGuid.Empty;
|
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 GetStationaryX() { return GetPositionX(); }
|
||||||
public virtual float GetStationaryY() { return GetPositionY(); }
|
public virtual float GetStationaryY() { return GetPositionY(); }
|
||||||
@@ -3065,7 +3036,7 @@ namespace Game.Entities
|
|||||||
Position thisOrTransport = this;
|
Position thisOrTransport = this;
|
||||||
Position objOrObjTransport = obj;
|
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;
|
thisOrTransport = m_movementInfo.transport.pos;
|
||||||
objOrObjTransport = obj.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)
|
public void UpdateAllowedPositionZ(float x, float y, ref float z, ref float groundZ)
|
||||||
{
|
{
|
||||||
// TODO: Allow transports to be part of dynamic vmap tree
|
// TODO: Allow transports to be part of dynamic vmap tree
|
||||||
if (GetTransport())
|
if (GetTransport() != null)
|
||||||
{
|
{
|
||||||
groundZ = z;
|
groundZ = z;
|
||||||
return;
|
return;
|
||||||
@@ -3690,7 +3661,7 @@ namespace Game.Entities
|
|||||||
bool m_isWorldObject;
|
bool m_isWorldObject;
|
||||||
public ZoneScript m_zoneScript;
|
public ZoneScript m_zoneScript;
|
||||||
|
|
||||||
Transport m_transport;
|
ITransport m_transport;
|
||||||
Map _currMap;
|
Map _currMap;
|
||||||
uint instanceId;
|
uint instanceId;
|
||||||
PhaseShift _phaseShift = new();
|
PhaseShift _phaseShift = new();
|
||||||
|
|||||||
@@ -3429,8 +3429,9 @@ namespace Game.Entities
|
|||||||
stmt.AddValue(index++, finiteAlways(GetTransOffsetZ()));
|
stmt.AddValue(index++, finiteAlways(GetTransOffsetZ()));
|
||||||
stmt.AddValue(index++, finiteAlways(GetTransOffsetO()));
|
stmt.AddValue(index++, finiteAlways(GetTransOffsetO()));
|
||||||
ulong transLowGUID = 0;
|
ulong transLowGUID = 0;
|
||||||
if (GetTransport())
|
Transport transport = GetTransport<Transport>();
|
||||||
transLowGUID = GetTransport().GetGUID().GetCounter();
|
if (transport != null)
|
||||||
|
transLowGUID = transport.GetGUID().GetCounter();
|
||||||
stmt.AddValue(index++, transLowGUID);
|
stmt.AddValue(index++, transLowGUID);
|
||||||
|
|
||||||
StringBuilder ss = new();
|
StringBuilder ss = new();
|
||||||
@@ -3570,8 +3571,9 @@ namespace Game.Entities
|
|||||||
stmt.AddValue(index++, finiteAlways(GetTransOffsetZ()));
|
stmt.AddValue(index++, finiteAlways(GetTransOffsetZ()));
|
||||||
stmt.AddValue(index++, finiteAlways(GetTransOffsetO()));
|
stmt.AddValue(index++, finiteAlways(GetTransOffsetO()));
|
||||||
ulong transLowGUID = 0;
|
ulong transLowGUID = 0;
|
||||||
if (GetTransport())
|
Transport transport = GetTransport<Transport>();
|
||||||
transLowGUID = GetTransport().GetGUID().GetCounter();
|
if (transport != null)
|
||||||
|
transLowGUID = transport.GetGUID().GetCounter();
|
||||||
stmt.AddValue(index++, transLowGUID);
|
stmt.AddValue(index++, transLowGUID);
|
||||||
|
|
||||||
StringBuilder ss = new();
|
StringBuilder ss = new();
|
||||||
|
|||||||
@@ -803,7 +803,7 @@ namespace Game.Entities
|
|||||||
m_MirrorTimerFlags |= PlayerUnderwaterState.InWater;
|
m_MirrorTimerFlags |= PlayerUnderwaterState.InWater;
|
||||||
|
|
||||||
// Fatigue bar state (if not on flight path or transport)
|
// 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;
|
m_MirrorTimerFlags |= PlayerUnderwaterState.InDarkWater;
|
||||||
|
|
||||||
// Lava state (any contact)
|
// 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);
|
Log.outDebug(LogFilter.Maps, "Player {0} using client without required expansion tried teleport to non accessible map {1}", GetName(), mapid);
|
||||||
|
|
||||||
Transport _transport = GetTransport();
|
ITransport _transport = GetTransport();
|
||||||
if (_transport)
|
if (_transport != null)
|
||||||
{
|
{
|
||||||
_transport.RemovePassenger(this);
|
_transport.RemovePassenger(this);
|
||||||
RepopAtGraveyard(); // teleport to near graveyard if on transport, looks blizz like :)
|
RepopAtGraveyard(); // teleport to near graveyard if on transport, looks blizz like :)
|
||||||
@@ -1708,8 +1708,8 @@ namespace Game.Entities
|
|||||||
DisableSpline();
|
DisableSpline();
|
||||||
GetMotionMaster().Remove(MovementGeneratorType.Effect);
|
GetMotionMaster().Remove(MovementGeneratorType.Effect);
|
||||||
|
|
||||||
Transport transport = GetTransport();
|
ITransport transport = GetTransport();
|
||||||
if (transport)
|
if (transport != null)
|
||||||
{
|
{
|
||||||
if (!options.HasAnyFlag(TeleportToOptions.NotLeaveTransport))
|
if (!options.HasAnyFlag(TeleportToOptions.NotLeaveTransport))
|
||||||
transport.RemovePassenger(this);
|
transport.RemovePassenger(this);
|
||||||
@@ -1849,11 +1849,11 @@ namespace Game.Entities
|
|||||||
transferPending.MapID = (int)mapid;
|
transferPending.MapID = (int)mapid;
|
||||||
transferPending.OldMapPosition = GetPosition();
|
transferPending.OldMapPosition = GetPosition();
|
||||||
|
|
||||||
transport = GetTransport();
|
Transport transport1 = (Transport)GetTransport();
|
||||||
if (transport)
|
if (transport1 != null)
|
||||||
{
|
{
|
||||||
TransferPending.ShipTransferPending shipTransferPending = new();
|
TransferPending.ShipTransferPending shipTransferPending = new();
|
||||||
shipTransferPending.Id = transport.GetEntry();
|
shipTransferPending.Id = transport1.GetEntry();
|
||||||
shipTransferPending.OriginMapID = (int)GetMapId();
|
shipTransferPending.OriginMapID = (int)GetMapId();
|
||||||
transferPending.Ship = shipTransferPending;
|
transferPending.Ship = shipTransferPending;
|
||||||
}
|
}
|
||||||
@@ -6242,14 +6242,6 @@ namespace Game.Entities
|
|||||||
{
|
{
|
||||||
switch (target.GetTypeId())
|
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:
|
case TypeId.Unit:
|
||||||
s64.Add(target.GetGUID());
|
s64.Add(target.GetGUID());
|
||||||
v.Add(target.ToCreature());
|
v.Add(target.ToCreature());
|
||||||
|
|||||||
@@ -27,37 +27,102 @@ namespace Game.Entities
|
|||||||
{
|
{
|
||||||
public interface ITransport
|
public interface ITransport
|
||||||
{
|
{
|
||||||
|
ObjectGuid GetTransportGUID();
|
||||||
|
|
||||||
// This method transforms supplied transport offsets into global coordinates
|
// This method transforms supplied transport offsets into global coordinates
|
||||||
void CalculatePassengerPosition(ref float x, ref float y, ref float z, ref float o);
|
void CalculatePassengerPosition(ref float x, ref float y, ref float z, ref float o);
|
||||||
|
|
||||||
// This method transforms supplied global coordinates into local offsets
|
// This method transforms supplied global coordinates into local offsets
|
||||||
void CalculatePassengerOffset(ref float x, ref float y, ref float z, ref float o);
|
void CalculatePassengerOffset(ref float x, ref float y, ref float z, ref float o);
|
||||||
}
|
|
||||||
|
|
||||||
public class TransportPosHelper
|
float GetTransportOrientation();
|
||||||
{
|
|
||||||
public static void CalculatePassengerPosition(ref float x, ref float y, ref float z, ref float o, float transX, float transY, float transZ, float transO)
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unit != null)
|
||||||
|
{
|
||||||
|
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;
|
float inx = x, iny = y, inz = z;
|
||||||
o = Position.NormalizeOrientation(transO + o);
|
o = Position.NormalizeOrientation(transO + o);
|
||||||
|
|
||||||
x = transX + inx * (float)Math.Cos(transO) - iny * (float)Math.Sin(transO);
|
x = transX + inx * MathF.Cos(transO) - iny * MathF.Sin(transO);
|
||||||
y = transY + iny * (float)Math.Cos(transO) + inx * (float)Math.Sin(transO);
|
y = transY + iny * MathF.Cos(transO) + inx * MathF.Sin(transO);
|
||||||
z = transZ + inz;
|
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);
|
o = Position.NormalizeOrientation(o - transO);
|
||||||
|
|
||||||
z -= transZ;
|
z -= transZ;
|
||||||
y -= transY;
|
y -= transY; // y = searchedY * std::cos(o) + searchedX * std::sin(o)
|
||||||
x -= transX;
|
x -= transX; // x = searchedX * std::cos(o) + searchedY * std::sin(o + pi)
|
||||||
|
|
||||||
float inx = x, iny = y;
|
float inx = x, iny = y;
|
||||||
y = (iny - inx * (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 * (float)Math.Tan(transO)) / ((float)Math.Cos(transO) + (float)Math.Sin(transO) * (float)Math.Tan(transO));
|
x = (inx + iny * MathF.Tan(transO)) / (MathF.Cos(transO) + MathF.Sin(transO) * MathF.Tan(transO));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GetMapIdForSpawning();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Transport : GameObject, ITransport
|
public class Transport : GameObject, ITransport
|
||||||
@@ -122,7 +187,6 @@ namespace Game.Entities
|
|||||||
ReplaceAllFlags(goOverride.Flags);
|
ReplaceAllFlags(goOverride.Flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_goValue.Transport.PathProgress = 0;
|
|
||||||
SetObjectScale(goinfo.size);
|
SetObjectScale(goinfo.size);
|
||||||
SetPeriod(tInfo.pathTime);
|
SetPeriod(tInfo.pathTime);
|
||||||
SetEntry(goinfo.entry);
|
SetEntry(goinfo.entry);
|
||||||
@@ -163,9 +227,9 @@ namespace Game.Entities
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (IsMoving() || !_pendingStop)
|
if (IsMoving() || !_pendingStop)
|
||||||
m_goValue.Transport.PathProgress += diff;
|
_pathProgress += diff;
|
||||||
|
|
||||||
uint timer = m_goValue.Transport.PathProgress % GetTransportPeriod();
|
uint timer = _pathProgress % GetTransportPeriod();
|
||||||
bool justStopped = false;
|
bool justStopped = false;
|
||||||
|
|
||||||
// Set current waypoint
|
// Set current waypoint
|
||||||
@@ -189,9 +253,9 @@ namespace Game.Entities
|
|||||||
if (_pendingStop && GetGoState() != GameObjectState.Ready)
|
if (_pendingStop && GetGoState() != GameObjectState.Ready)
|
||||||
{
|
{
|
||||||
SetGoState(GameObjectState.Ready);
|
SetGoState(GameObjectState.Ready);
|
||||||
m_goValue.Transport.PathProgress /= GetTransportPeriod();
|
_pathProgress /= GetTransportPeriod();
|
||||||
m_goValue.Transport.PathProgress *= GetTransportPeriod();
|
_pathProgress *= GetTransportPeriod();
|
||||||
m_goValue.Transport.PathProgress += _currentFrame.ArriveTime;
|
_pathProgress += _currentFrame.ArriveTime;
|
||||||
}
|
}
|
||||||
break; // its a stop frame and we are waiting
|
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);
|
bool erased = _passengers.Remove(passenger);
|
||||||
|
|
||||||
@@ -313,6 +377,8 @@ namespace Game.Entities
|
|||||||
plr.SetFallInformation(0, plr.GetPositionZ());
|
plr.SetFallInformation(0, plr.GetPositionZ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Creature CreateNPCPassenger(ulong guid, CreatureData data)
|
public Creature CreateNPCPassenger(ulong guid, CreatureData data)
|
||||||
@@ -511,14 +577,19 @@ namespace Game.Entities
|
|||||||
|
|
||||||
public void CalculatePassengerPosition(ref float x, ref float y, ref float z, ref float o)
|
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)
|
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)
|
public void UpdatePosition(float x, float y, float z, float o)
|
||||||
{
|
{
|
||||||
bool newActive = GetMap().IsGridLoaded(x, y);
|
bool newActive = GetMap().IsGridLoaded(x, y);
|
||||||
@@ -652,7 +723,7 @@ namespace Game.Entities
|
|||||||
|
|
||||||
float destX, destY, destZ, destO;
|
float destX, destY, destZ, destO;
|
||||||
obj.m_movementInfo.transport.pos.GetPosition(out destX, out destY, out destZ, out 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);
|
obj.ToUnit().NearTeleportTo(destX, destY, destZ, destO);
|
||||||
}
|
}
|
||||||
@@ -683,7 +754,7 @@ namespace Game.Entities
|
|||||||
{
|
{
|
||||||
float destX, destY, destZ, destO;
|
float destX, destY, destZ, destO;
|
||||||
obj.m_movementInfo.transport.pos.GetPosition(out destX, out destY, out destZ, out 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())
|
switch (obj.GetTypeId())
|
||||||
{
|
{
|
||||||
@@ -707,62 +778,12 @@ namespace Game.Entities
|
|||||||
|
|
||||||
void UpdatePassengerPositions(HashSet<WorldObject> passengers)
|
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;
|
float x, y, z, o;
|
||||||
passenger.m_movementInfo.transport.pos.GetPosition(out x, out y, out z, out o);
|
passenger.m_movementInfo.transport.pos.GetPosition(out x, out y, out z, out o);
|
||||||
CalculatePassengerPosition(ref x, ref y, ref z, ref o);
|
CalculatePassengerPosition(ref x, ref y, ref z, ref o);
|
||||||
switch (passenger.GetTypeId())
|
ITransport.UpdatePassengerPosition(this, GetMap(), passenger, x, y, z, o, true);
|
||||||
{
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -790,9 +811,12 @@ namespace Game.Entities
|
|||||||
|
|
||||||
public HashSet<WorldObject> GetPassengers() { return _passengers; }
|
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); }
|
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 List<KeyFrame> GetKeyFrames() { return _transportInfo.keyFrames; }
|
||||||
public TransportTemplate GetTransportTemplate() { return _transportInfo; }
|
public TransportTemplate GetTransportTemplate() { return _transportInfo; }
|
||||||
@@ -805,6 +829,7 @@ namespace Game.Entities
|
|||||||
|
|
||||||
KeyFrame _currentFrame;
|
KeyFrame _currentFrame;
|
||||||
int _nextFrame;
|
int _nextFrame;
|
||||||
|
uint _pathProgress;
|
||||||
TimeTracker _positionChangeTimer = new();
|
TimeTracker _positionChangeTimer = new();
|
||||||
bool _isMoving;
|
bool _isMoving;
|
||||||
bool _pendingStop;
|
bool _pendingStop;
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ namespace Game.Entities
|
|||||||
|
|
||||||
MoveSplineInit init = new(this);
|
MoveSplineInit init = new(this);
|
||||||
init.MoveTo(GetPositionX(), GetPositionY(), GetPositionZ(), false);
|
init.MoveTo(GetPositionX(), GetPositionY(), GetPositionZ(), false);
|
||||||
if (GetTransport())
|
if (GetTransport() != null)
|
||||||
init.DisableTransportPathTransformations(); // It makes no sense to target global orientation
|
init.DisableTransportPathTransformations(); // It makes no sense to target global orientation
|
||||||
init.SetFacing(ori);
|
init.SetFacing(ori);
|
||||||
|
|
||||||
@@ -1834,7 +1834,7 @@ namespace Game.Entities
|
|||||||
if (GetVehicle() != null)
|
if (GetVehicle() != null)
|
||||||
return GetVehicleBase().GetGUID();
|
return GetVehicleBase().GetGUID();
|
||||||
if (GetTransport() != null)
|
if (GetTransport() != null)
|
||||||
return GetTransport().GetGUID();
|
return GetTransport().GetTransportGUID();
|
||||||
|
|
||||||
return ObjectGuid.Empty;
|
return ObjectGuid.Empty;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -295,7 +295,7 @@ namespace Game.Entities
|
|||||||
return false;
|
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());
|
Log.outFatal(LogFilter.Unit, "Unit:SetCharmedBy: Player on transport is trying to charm {0} (GUID {1})", GetEntry(), GetGUID().ToString());
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -1003,7 +1003,7 @@ namespace Game.Entities
|
|||||||
}
|
}
|
||||||
|
|
||||||
Cypher.Assert(!m_vehicle);
|
Cypher.Assert(!m_vehicle);
|
||||||
vehicle.AddPassenger(this, seatId);
|
vehicle.AddVehiclePassenger(this, seatId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ChangeSeat(sbyte seatId, bool next = true)
|
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
|
// This should be done before dismiss, because there may be some aura removal
|
||||||
VehicleSeatAddon seatAddon = m_vehicle.GetSeatAddonForSeatOfPassenger(this);
|
VehicleSeatAddon seatAddon = m_vehicle.GetSeatAddonForSeatOfPassenger(this);
|
||||||
Vehicle vehicle = m_vehicle.RemovePassenger(this);
|
Vehicle vehicle = (Vehicle)m_vehicle.RemovePassenger(this);
|
||||||
|
|
||||||
if (vehicle == null)
|
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 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 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 void SetCreatedBySpell(uint spellId) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.CreatedBySpell), spellId); }
|
||||||
|
|
||||||
public Emote GetEmoteState() { return (Emote)(int)m_unitData.EmoteState; }
|
public Emote GetEmoteState() { return (Emote)(int)m_unitData.EmoteState; }
|
||||||
|
|||||||
@@ -291,7 +291,7 @@ namespace Game.Entities
|
|||||||
// @VehicleJoinEvent.Abort
|
// @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.)
|
// @Prevent adding passengers when vehicle is uninstalling. (Bad script in OnUninstall/OnRemovePassenger/PassengerBoarded hook.)
|
||||||
if (_status == Status.UnInstalling)
|
if (_status == Status.UnInstalling)
|
||||||
@@ -355,8 +355,12 @@ namespace Game.Entities
|
|||||||
return true;
|
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)
|
if (unit.GetVehicle() != this)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@@ -421,8 +425,8 @@ namespace Game.Entities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var pair in seatRelocation)
|
foreach (var (passenger, position) in seatRelocation)
|
||||||
pair.Item1.UpdatePosition(pair.Item2);
|
ITransport.UpdatePassengerPosition(this, _me.GetMap(), passenger, position.GetPositionX(), position.GetPositionY(), position.GetPositionZ(), position.GetOrientation(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsVehicleInUse()
|
public bool IsVehicleInUse()
|
||||||
@@ -487,20 +491,28 @@ namespace Game.Entities
|
|||||||
return ret;
|
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)
|
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().GetPositionX(), GetBase().GetPositionY(),
|
||||||
GetBase().GetPositionZ(), GetBase().GetOrientation());
|
GetBase().GetPositionZ(), GetBase().GetOrientation());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CalculatePassengerOffset(ref float x, ref float y, ref float z, ref float o)
|
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().GetPositionX(), GetBase().GetPositionY(),
|
||||||
GetBase().GetPositionZ(), GetBase().GetOrientation());
|
GetBase().GetPositionZ(), GetBase().GetOrientation());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int GetMapIdForSpawning() { return (int)GetBase().GetMapId(); }
|
||||||
|
|
||||||
public void RemovePendingEvent(VehicleJoinEvent e)
|
public void RemovePendingEvent(VehicleJoinEvent e)
|
||||||
{
|
{
|
||||||
foreach (var Event in _pendingJoinEvents)
|
foreach (var Event in _pendingJoinEvents)
|
||||||
|
|||||||
@@ -839,7 +839,7 @@ namespace Game.Garrisons
|
|||||||
float y = spawn.GetPositionY();
|
float y = spawn.GetPositionY();
|
||||||
float z = spawn.GetPositionZ();
|
float z = spawn.GetPositionZ();
|
||||||
float o = spawn.GetOrientation();
|
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);
|
spawn.Relocate(x, y, z, o);
|
||||||
switch (spawn.GetTypeId())
|
switch (spawn.GetTypeId())
|
||||||
|
|||||||
@@ -110,31 +110,37 @@ namespace Game
|
|||||||
|
|
||||||
if (plrMover)
|
if (plrMover)
|
||||||
{
|
{
|
||||||
if (!plrMover.GetTransport())
|
if (plrMover.GetTransport() == null)
|
||||||
{
|
{
|
||||||
Transport transport = plrMover.GetMap().GetTransport(movementInfo.transport.guid);
|
GameObject go = plrMover.GetMap().GetGameObject(movementInfo.transport.guid);
|
||||||
if (transport)
|
if (go != null)
|
||||||
transport.AddPassenger(plrMover);
|
{
|
||||||
|
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);
|
plrMover.GetTransport().RemovePassenger(plrMover);
|
||||||
Transport transport = plrMover.GetMap().GetTransport(movementInfo.transport.guid);
|
GameObject go = plrMover.GetMap().GetGameObject(movementInfo.transport.guid);
|
||||||
if (transport)
|
if (go != null)
|
||||||
transport.AddPassenger(plrMover);
|
{
|
||||||
|
ITransport transport = go.ToTransportBase();
|
||||||
|
if (transport != null)
|
||||||
|
transport.AddPassenger(plrMover);
|
||||||
|
else
|
||||||
|
movementInfo.ResetTransport();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
movementInfo.ResetTransport();
|
movementInfo.ResetTransport();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mover.GetTransport() && !mover.GetVehicle())
|
if (mover.GetTransport() == null && !mover.GetVehicle())
|
||||||
{
|
movementInfo.transport.Reset();
|
||||||
GameObject go = mover.GetMap().GetGameObject(movementInfo.transport.guid);
|
|
||||||
if (!go || go.GetGoType() != GameObjectTypes.Transport)
|
|
||||||
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);
|
plrMover.GetTransport().RemovePassenger(plrMover);
|
||||||
|
|
||||||
// fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
|
// 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;
|
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
|
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
|
// 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
|
// 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)
|
if (transport)
|
||||||
{
|
{
|
||||||
foreach (var obj in transport.GetPassengers())
|
foreach (var obj in transport.GetPassengers())
|
||||||
@@ -128,6 +128,9 @@ namespace Game.Maps
|
|||||||
case TypeId.DynamicObject:
|
case TypeId.DynamicObject:
|
||||||
i_player.UpdateVisibilityOf(obj.ToDynamicObject(), i_data, i_visibleNow);
|
i_player.UpdateVisibilityOf(obj.ToDynamicObject(), i_data, i_visibleNow);
|
||||||
break;
|
break;
|
||||||
|
case TypeId.AreaTrigger:
|
||||||
|
i_player.UpdateVisibilityOf(obj.ToAreaTrigger(), i_data, i_visibleNow);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-10
@@ -1131,9 +1131,7 @@ namespace Game.Maps
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
go.Relocate(x, y, z, orientation);
|
go.Relocate(x, y, z, orientation);
|
||||||
go.UpdateModelPosition();
|
go.AfterRelocation();
|
||||||
go.UpdatePositionData();
|
|
||||||
go.UpdateObjectVisibility(false);
|
|
||||||
RemoveGameObjectFromMoveList(go);
|
RemoveGameObjectFromMoveList(go);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1354,9 +1352,7 @@ namespace Game.Maps
|
|||||||
{
|
{
|
||||||
// update pos
|
// update pos
|
||||||
go.Relocate(go._newPosition);
|
go.Relocate(go._newPosition);
|
||||||
go.UpdateModelPosition();
|
go.AfterRelocation();
|
||||||
go.UpdatePositionData();
|
|
||||||
go.UpdateObjectVisibility(false);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -2247,7 +2243,7 @@ namespace Game.Maps
|
|||||||
var data = new UpdateData(player.GetMapId());
|
var data = new UpdateData(player.GetMapId());
|
||||||
|
|
||||||
// attach to player data current transport data
|
// attach to player data current transport data
|
||||||
Transport transport = player.GetTransport();
|
Transport transport = player.GetTransport<Transport>();
|
||||||
if (transport != null)
|
if (transport != null)
|
||||||
{
|
{
|
||||||
transport.BuildCreateUpdateBlockForPlayer(data, player);
|
transport.BuildCreateUpdateBlockForPlayer(data, player);
|
||||||
@@ -4168,8 +4164,8 @@ namespace Game.Maps
|
|||||||
if (!summon.Create(GenerateLowGuid(HighGuid.Creature), this, entry, pos, null, vehId, true))
|
if (!summon.Create(GenerateLowGuid(HighGuid.Creature), this, entry, pos, null, vehId, true))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
Transport transport = summoner != null ? summoner.GetTransport() : null;
|
ITransport transport = summoner != null ? summoner.GetTransport() : null;
|
||||||
if (transport)
|
if (transport != null)
|
||||||
{
|
{
|
||||||
pos.GetPosition(out float x, out float y, out float z, out float o);
|
pos.GetPosition(out float x, out float y, out float z, out float o);
|
||||||
transport.CalculatePassengerOffset(ref x, ref y, ref z, ref o);
|
transport.CalculatePassengerOffset(ref x, ref y, ref z, ref o);
|
||||||
@@ -4209,7 +4205,7 @@ namespace Game.Maps
|
|||||||
if (!AddToMap(summon.ToCreature()))
|
if (!AddToMap(summon.ToCreature()))
|
||||||
{
|
{
|
||||||
// Returning false will cause the object to be deleted - remove from transport
|
// Returning false will cause the object to be deleted - remove from transport
|
||||||
if (transport)
|
if (transport != null)
|
||||||
transport.RemovePassenger(summon);
|
transport.RemovePassenger(summon);
|
||||||
|
|
||||||
summon.Dispose();
|
summon.Dispose();
|
||||||
|
|||||||
@@ -425,6 +425,18 @@ namespace Game.Maps
|
|||||||
_transportAnimations[transportEntry] = animNode;
|
_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)
|
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
|
// instance case, execute GetGameObjectEntry hook
|
||||||
@@ -530,14 +542,6 @@ namespace Game.Maps
|
|||||||
{
|
{
|
||||||
return _transportSpawns.LookupByKey(spawnId);
|
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();
|
Dictionary<uint, TransportTemplate> _transportTemplates = new();
|
||||||
MultiMap<uint, uint> _instanceTransports = new();
|
MultiMap<uint, uint> _instanceTransports = new();
|
||||||
@@ -557,8 +561,8 @@ namespace Game.Maps
|
|||||||
mode = Spline.EvaluationMode.Catmullrom;
|
mode = Spline.EvaluationMode.Catmullrom;
|
||||||
cyclic = false;
|
cyclic = false;
|
||||||
points = new Vector3[_points.Count];
|
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];
|
points[i] = _points[i];
|
||||||
|
|
||||||
lo = 1;
|
lo = 1;
|
||||||
@@ -627,26 +631,59 @@ namespace Game.Maps
|
|||||||
|
|
||||||
public class TransportAnimation
|
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())
|
if (Path.Empty())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
foreach (var pair in Path)
|
List<uint> lKeys = Path.Keys.ToList();
|
||||||
if (time >= pair.Key)
|
int reqIndex = lKeys.IndexOf(time) - 1;
|
||||||
return pair.Value;
|
|
||||||
|
|
||||||
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 TransportAnimationRecord GetNextAnimNode(uint time)
|
||||||
public Dictionary<uint, TransportRotationRecord> Rotations = new();
|
{
|
||||||
public uint TotalTime;
|
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
|
public class TransportSpawn
|
||||||
|
|||||||
@@ -303,10 +303,10 @@ namespace Game.Movement
|
|||||||
owner.SetHomePosition(x, y, z, o);
|
owner.SetHomePosition(x, y, z, o);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Transport trans = owner.GetTransport();
|
ITransport trans = owner.GetTransport();
|
||||||
if (trans)
|
if (trans != null)
|
||||||
{
|
{
|
||||||
o -= trans.GetOrientation();
|
o -= trans.GetTransportOrientation();
|
||||||
owner.SetTransportHomePosition(x, y, z, o);
|
owner.SetTransportHomePosition(x, y, z, o);
|
||||||
trans.CalculatePassengerPosition(ref x, ref y, ref z, ref o);
|
trans.CalculatePassengerPosition(ref x, ref y, ref z, ref o);
|
||||||
owner.SetHomePosition(x, y, z, o);
|
owner.SetHomePosition(x, y, z, o);
|
||||||
|
|||||||
@@ -222,11 +222,14 @@ namespace Game.Movement
|
|||||||
if (args.TransformForTransport)
|
if (args.TransformForTransport)
|
||||||
{
|
{
|
||||||
Unit vehicle = unit.GetVehicleBase();
|
Unit vehicle = unit.GetVehicleBase();
|
||||||
Transport transport = unit.GetTransport();
|
|
||||||
if (vehicle != null)
|
if (vehicle != null)
|
||||||
angle -= vehicle.Orientation;
|
angle -= vehicle.GetOrientation();
|
||||||
else if (transport != null)
|
else
|
||||||
angle -= transport.Orientation;
|
{
|
||||||
|
ITransport transport = unit.GetTransport();
|
||||||
|
if (transport != null)
|
||||||
|
angle -= transport.GetTransportOrientation();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
args.facing.angle = MathFunctions.wrap(angle, 0.0f, MathFunctions.TwoPi);
|
args.facing.angle = MathFunctions.wrap(angle, 0.0f, MathFunctions.TwoPi);
|
||||||
|
|||||||
@@ -7077,8 +7077,8 @@ namespace Game.Spells
|
|||||||
|
|
||||||
if (target.GetGUID() != corpse.GetOwnerGUID())
|
if (target.GetGUID() != corpse.GetOwnerGUID())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!corpse.HasDynamicFlag(UnitDynFlags.Lootable))
|
if (!corpse.HasCorpseDynamicFlag(CorpseDynFlags.Lootable))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!corpse.IsWithinLOSInMap(m_caster, LineOfSightChecks.All, ModelIgnoreFlags.M2))
|
if (!corpse.IsWithinLOSInMap(m_caster, LineOfSightChecks.All, ModelIgnoreFlags.M2))
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ namespace Scripts.World.ItemScripts
|
|||||||
if (player.GetZoneId() != Misc.ZoneIdHowling)
|
if (player.GetZoneId() != Misc.ZoneIdHowling)
|
||||||
return false;
|
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);
|
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(SpellIds.PetrovBomb, Difficulty.None);
|
||||||
if (spellInfo != null)
|
if (spellInfo != null)
|
||||||
|
|||||||
Reference in New Issue
Block a user