Core/GameObjects: Transport (type 11) improvements

Port From (https://github.com/TrinityCore/TrinityCore/commit/630b60eb0dcd3d9ce41582664ab822b049365431)
This commit is contained in:
hondacrx
2022-06-03 16:20:41 -04:00
parent e65ce31742
commit 40444525b2
30 changed files with 807 additions and 377 deletions
+102 -77
View File
@@ -27,37 +27,102 @@ namespace Game.Entities
{
public interface ITransport
{
ObjectGuid GetTransportGUID();
// This method transforms supplied transport offsets into global coordinates
void CalculatePassengerPosition(ref float x, ref float y, ref float z, ref float o);
// This method transforms supplied global coordinates into local offsets
void CalculatePassengerOffset(ref float x, ref float y, ref float z, ref float o);
}
public class TransportPosHelper
{
public static void CalculatePassengerPosition(ref float x, ref float y, ref float z, ref float o, float transX, float transY, float transZ, float transO)
float GetTransportOrientation();
void AddPassenger(WorldObject passenger);
ITransport RemovePassenger(WorldObject passenger);
public static void UpdatePassengerPosition(ITransport transport, Map map, WorldObject passenger, float x, float y, float z, float o, bool setHomePosition)
{
// transport teleported but passenger not yet (can happen for players)
if (passenger.GetMap() != map)
return;
// if passenger is on vehicle we have to assume the vehicle is also on transport
// and its the vehicle that will be updating its passengers
Unit unit = passenger.ToUnit();
if (unit != null)
if (unit.GetVehicle())
return;
// Do not use Unit::UpdatePosition here, we don't want to remove auras
// as if regular movement occurred
switch (passenger.GetTypeId())
{
case TypeId.Unit:
{
Creature creature = passenger.ToCreature();
map.CreatureRelocation(creature, x, y, z, o, false);
if (setHomePosition)
{
creature.GetTransportHomePosition(out x, out y, out z, out o);
transport.CalculatePassengerPosition(ref x, ref y, ref z, ref o);
creature.SetHomePosition(x, y, z, o);
}
break;
}
case TypeId.Player:
//relocate only passengers in world and skip any player that might be still logging in/teleporting
if (passenger.IsInWorld && !passenger.ToPlayer().IsBeingTeleported())
{
map.PlayerRelocation(passenger.ToPlayer(), x, y, z, o);
passenger.ToPlayer().SetFallInformation(0, passenger.GetPositionZ());
}
break;
case TypeId.GameObject:
map.GameObjectRelocation(passenger.ToGameObject(), x, y, z, o, false);
passenger.ToGameObject().RelocateStationaryPosition(x, y, z, o);
break;
case TypeId.DynamicObject:
map.DynamicObjectRelocation(passenger.ToDynamicObject(), x, y, z, o);
break;
case TypeId.AreaTrigger:
map.AreaTriggerRelocation(passenger.ToAreaTrigger(), x, y, z, o);
break;
default:
break;
}
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;
o = Position.NormalizeOrientation(transO + o);
x = transX + inx * (float)Math.Cos(transO) - iny * (float)Math.Sin(transO);
y = transY + iny * (float)Math.Cos(transO) + inx * (float)Math.Sin(transO);
x = transX + inx * MathF.Cos(transO) - iny * MathF.Sin(transO);
y = transY + iny * MathF.Cos(transO) + inx * MathF.Sin(transO);
z = transZ + inz;
}
public static void CalculatePassengerOffset(ref float x, ref float y, ref float z, ref float o, float transX, float transY, float transZ, float transO)
static void CalculatePassengerOffset(ref float x, ref float y, ref float z, ref float o, float transX, float transY, float transZ, float transO)
{
o = Position.NormalizeOrientation(o - transO);
z -= transZ;
y -= transY;
x -= transX;
y -= transY; // y = searchedY * std::cos(o) + searchedX * std::sin(o)
x -= transX; // x = searchedX * std::cos(o) + searchedY * std::sin(o + pi)
float inx = x, iny = y;
y = (iny - inx * (float)Math.Tan(transO)) / ((float)Math.Cos(transO) + (float)Math.Sin(transO) * (float)Math.Tan(transO));
x = (inx + iny * (float)Math.Tan(transO)) / ((float)Math.Cos(transO) + (float)Math.Sin(transO) * (float)Math.Tan(transO));
y = (iny - inx * MathF.Tan(transO)) / (MathF.Cos(transO) + MathF.Sin(transO) * MathF.Tan(transO));
x = (inx + iny * MathF.Tan(transO)) / (MathF.Cos(transO) + MathF.Sin(transO) * MathF.Tan(transO));
}
int GetMapIdForSpawning();
}
public class Transport : GameObject, ITransport
@@ -122,7 +187,6 @@ namespace Game.Entities
ReplaceAllFlags(goOverride.Flags);
}
m_goValue.Transport.PathProgress = 0;
SetObjectScale(goinfo.size);
SetPeriod(tInfo.pathTime);
SetEntry(goinfo.entry);
@@ -163,9 +227,9 @@ namespace Game.Entities
return;
if (IsMoving() || !_pendingStop)
m_goValue.Transport.PathProgress += diff;
_pathProgress += diff;
uint timer = m_goValue.Transport.PathProgress % GetTransportPeriod();
uint timer = _pathProgress % GetTransportPeriod();
bool justStopped = false;
// Set current waypoint
@@ -189,9 +253,9 @@ namespace Game.Entities
if (_pendingStop && GetGoState() != GameObjectState.Ready)
{
SetGoState(GameObjectState.Ready);
m_goValue.Transport.PathProgress /= GetTransportPeriod();
m_goValue.Transport.PathProgress *= GetTransportPeriod();
m_goValue.Transport.PathProgress += _currentFrame.ArriveTime;
_pathProgress /= GetTransportPeriod();
_pathProgress *= GetTransportPeriod();
_pathProgress += _currentFrame.ArriveTime;
}
break; // its a stop frame and we are waiting
}
@@ -296,7 +360,7 @@ namespace Game.Entities
}
}
public void RemovePassenger(WorldObject passenger)
public ITransport RemovePassenger(WorldObject passenger)
{
bool erased = _passengers.Remove(passenger);
@@ -313,6 +377,8 @@ namespace Game.Entities
plr.SetFallInformation(0, plr.GetPositionZ());
}
}
return this;
}
public Creature CreateNPCPassenger(ulong guid, CreatureData data)
@@ -511,14 +577,19 @@ namespace Game.Entities
public void CalculatePassengerPosition(ref float x, ref float y, ref float z, ref float o)
{
TransportPosHelper.CalculatePassengerPosition(ref x, ref y, ref z, ref o, GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation());
ITransport.CalculatePassengerPosition(ref x, ref y, ref z, ref o, GetPositionX(), GetPositionY(), GetPositionZ(), GetTransportOrientation());
}
public void CalculatePassengerOffset(ref float x, ref float y, ref float z, ref float o)
{
TransportPosHelper.CalculatePassengerOffset(ref x, ref y, ref z, ref o, GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation());
ITransport.CalculatePassengerOffset(ref x, ref y, ref z, ref o, GetPositionX(), GetPositionY(), GetPositionZ(), GetTransportOrientation());
}
public int GetMapIdForSpawning()
{
return GetGoInfo().MoTransport.SpawnMap;
}
public void UpdatePosition(float x, float y, float z, float o)
{
bool newActive = GetMap().IsGridLoaded(x, y);
@@ -652,7 +723,7 @@ namespace Game.Entities
float destX, destY, destZ, destO;
obj.m_movementInfo.transport.pos.GetPosition(out destX, out destY, out destZ, out destO);
TransportPosHelper.CalculatePassengerPosition(ref destX, ref destY, ref destZ, ref destO, x, y, z, o);
ITransport.CalculatePassengerPosition(ref destX, ref destY, ref destZ, ref destO, x, y, z, o);
obj.ToUnit().NearTeleportTo(destX, destY, destZ, destO);
}
@@ -683,7 +754,7 @@ namespace Game.Entities
{
float destX, destY, destZ, destO;
obj.m_movementInfo.transport.pos.GetPosition(out destX, out destY, out destZ, out destO);
TransportPosHelper.CalculatePassengerPosition(ref destX, ref destY, ref destZ, ref destO, x, y, z, o);
ITransport.CalculatePassengerPosition(ref destX, ref destY, ref destZ, ref destO, x, y, z, o);
switch (obj.GetTypeId())
{
@@ -707,62 +778,12 @@ namespace Game.Entities
void UpdatePassengerPositions(HashSet<WorldObject> passengers)
{
foreach (var passenger in passengers)
foreach (WorldObject passenger in passengers)
{
// transport teleported but passenger not yet (can happen for players)
if (passenger.GetMap() != GetMap())
continue;
// if passenger is on vehicle we have to assume the vehicle is also on transport
// and its the vehicle that will be updating its passengers
Unit unit = passenger.ToUnit();
if (unit)
if (unit.GetVehicle() != null)
continue;
// Do not use Unit.UpdatePosition here, we don't want to remove auras
// as if regular movement occurred
float x, y, z, o;
passenger.m_movementInfo.transport.pos.GetPosition(out x, out y, out z, out o);
CalculatePassengerPosition(ref x, ref y, ref z, ref o);
switch (passenger.GetTypeId())
{
case TypeId.Unit:
{
Creature creature = passenger.ToCreature();
GetMap().CreatureRelocation(creature, x, y, z, o, false);
creature.GetTransportHomePosition(out x, out y, out z, out o);
CalculatePassengerPosition(ref x, ref y, ref z, ref o);
creature.SetHomePosition(x, y, z, o);
break;
}
case TypeId.Player:
if (passenger.IsInWorld && !passenger.ToPlayer().IsBeingTeleported())
{
GetMap().PlayerRelocation(passenger.ToPlayer(), x, y, z, o);
passenger.ToPlayer().SetFallInformation(0, passenger.GetPositionZ());
}
break;
case TypeId.GameObject:
GetMap().GameObjectRelocation(passenger.ToGameObject(), x, y, z, o, false);
passenger.ToGameObject().RelocateStationaryPosition(x, y, z, o);
break;
case TypeId.DynamicObject:
GetMap().DynamicObjectRelocation(passenger.ToDynamicObject(), x, y, z, o);
break;
case TypeId.AreaTrigger:
GetMap().AreaTriggerRelocation(passenger.ToAreaTrigger(), x, y, z, o);
break;
default:
break;
}
if (unit != null)
{
Vehicle vehicle = unit.GetVehicleKit();
if (vehicle != null)
vehicle.RelocatePassengers();
}
ITransport.UpdatePassengerPosition(this, GetMap(), passenger, x, y, z, o, true);
}
}
@@ -790,9 +811,12 @@ namespace Game.Entities
public HashSet<WorldObject> GetPassengers() { return _passengers; }
public override uint GetTransportPeriod() { return m_gameObjectData.Level; }
public ObjectGuid GetTransportGUID() { return GetGUID(); }
public float GetTransportOrientation() { return GetOrientation(); }
public uint GetTransportPeriod() { return m_gameObjectData.Level; }
public void SetPeriod(uint period) { SetLevel(period); }
uint GetTimer() { return m_goValue.Transport.PathProgress; }
public uint GetTimer() { return _pathProgress; }
public List<KeyFrame> GetKeyFrames() { return _transportInfo.keyFrames; }
public TransportTemplate GetTransportTemplate() { return _transportInfo; }
@@ -805,6 +829,7 @@ namespace Game.Entities
KeyFrame _currentFrame;
int _nextFrame;
uint _pathProgress;
TimeTracker _positionChangeTimer = new();
bool _isMoving;
bool _pendingStop;