This commit is contained in:
parent
10a21d850d
commit
110bd99e56
3 changed files with 336 additions and 89 deletions
|
|
@ -46,6 +46,7 @@ namespace Server.Multis
|
|||
|
||||
private Direction m_Moving;
|
||||
private int m_Speed;
|
||||
private int m_ClientSpeed;
|
||||
|
||||
private bool m_Anchored;
|
||||
private string m_ShipName;
|
||||
|
|
@ -416,14 +417,36 @@ namespace Server.Multis
|
|||
return false;
|
||||
}
|
||||
|
||||
private static TimeSpan SlowInterval = TimeSpan.FromSeconds( 0.75 );
|
||||
private static TimeSpan FastInterval = TimeSpan.FromSeconds( 0.75 );
|
||||
/*
|
||||
* Intervals:
|
||||
* drift forward
|
||||
* fast | 0.25| 0.25
|
||||
* slow | 0.50| 0.50
|
||||
*
|
||||
* Speed:
|
||||
* drift forward
|
||||
* fast | 0x4| 0x4
|
||||
* slow | 0x3| 0x3
|
||||
*
|
||||
* Tiles (per interval):
|
||||
* drift forward
|
||||
* fast | 1| 1
|
||||
* slow | 1| 1
|
||||
*
|
||||
* 'walking' in piloting mode has a 1s interval, speed 0x2
|
||||
*/
|
||||
|
||||
// Legacy clients will continue to see the old-style movement, but speeds are adjusted
|
||||
private static bool NewBoatMovement = true;
|
||||
|
||||
private static TimeSpan SlowInterval = TimeSpan.FromSeconds( NewBoatMovement ? 0.50 : 0.75 );
|
||||
private static TimeSpan FastInterval = TimeSpan.FromSeconds( NewBoatMovement ? 0.25 : 0.75 );
|
||||
|
||||
private static int SlowSpeed = 1;
|
||||
private static int FastSpeed = 3;
|
||||
private static int FastSpeed = NewBoatMovement ? 1 : 3;
|
||||
|
||||
private static TimeSpan SlowDriftInterval = TimeSpan.FromSeconds( 1.50 );
|
||||
private static TimeSpan FastDriftInterval = TimeSpan.FromSeconds( 0.75 );
|
||||
private static TimeSpan SlowDriftInterval = TimeSpan.FromSeconds( NewBoatMovement ? 0.50 : 1.50 );
|
||||
private static TimeSpan FastDriftInterval = TimeSpan.FromSeconds( NewBoatMovement ? 0.25 : 0.75 );
|
||||
|
||||
private static int SlowDriftSpeed = 1;
|
||||
private static int FastDriftSpeed = 1;
|
||||
|
|
@ -549,8 +572,9 @@ namespace Server.Multis
|
|||
bool drift = ( dir != Forward && dir != ForwardLeft && dir != ForwardRight );
|
||||
TimeSpan interval = (fast ? (drift ? FastDriftInterval : FastInterval) : (drift ? SlowDriftInterval : SlowInterval));
|
||||
int speed = (fast ? (drift ? FastDriftSpeed : FastSpeed) : (drift ? SlowDriftSpeed : SlowSpeed));
|
||||
int clientSpeed = fast ? 0x4 : 0x3;
|
||||
|
||||
if ( StartMove( dir, speed, interval, false, true ) )
|
||||
if ( StartMove( dir, speed, clientSpeed, interval, false, true ) )
|
||||
{
|
||||
if ( m_TillerMan != null )
|
||||
m_TillerMan.Say( 501429 ); // Aye aye sir.
|
||||
|
|
@ -570,7 +594,7 @@ namespace Server.Multis
|
|||
TimeSpan interval = drift ? FastDriftInterval : FastInterval;
|
||||
int speed = drift ? FastDriftSpeed : FastSpeed;
|
||||
|
||||
if ( StartMove( dir, speed, interval, true, true ) )
|
||||
if ( StartMove( dir, speed, 0x1, interval, true, true ) )
|
||||
{
|
||||
if ( m_TillerMan != null )
|
||||
m_TillerMan.Say( 501429 ); // Aye aye sir.
|
||||
|
|
@ -653,28 +677,11 @@ namespace Server.Multis
|
|||
if ( map == null || map == Map.Internal )
|
||||
return DryDockResult.Items;
|
||||
|
||||
MultiComponentList mcl = Components;
|
||||
List<IEntity> ents = GetMovingEntities();
|
||||
|
||||
IPooledEnumerable eable = map.GetObjectsInBounds( new Rectangle2D( X + mcl.Min.X, Y + mcl.Min.Y, mcl.Width, mcl.Height ) );
|
||||
if ( ents.Count >= 1 )
|
||||
return ( ents[0] is Mobile ) ? DryDockResult.Mobiles : DryDockResult.Items;
|
||||
|
||||
foreach ( object o in eable )
|
||||
{
|
||||
if ( o == this || o == m_Hold || o == m_SPlank || o == m_PPlank || o == m_TillerMan )
|
||||
continue;
|
||||
|
||||
if ( o is Item && Contains( (Item)o ) )
|
||||
{
|
||||
eable.Free();
|
||||
return DryDockResult.Items;
|
||||
}
|
||||
else if ( o is Mobile && Contains( (Mobile)o ) )
|
||||
{
|
||||
eable.Free();
|
||||
return DryDockResult.Mobiles;
|
||||
}
|
||||
}
|
||||
|
||||
eable.Free();
|
||||
return DryDockResult.Valid;
|
||||
}
|
||||
|
||||
|
|
@ -1117,7 +1124,7 @@ namespace Server.Multis
|
|||
}
|
||||
}
|
||||
|
||||
public bool StartMove( Direction dir, int speed, TimeSpan interval, bool single, bool message )
|
||||
public bool StartMove( Direction dir, int speed, int clientSpeed, TimeSpan interval, bool single, bool message )
|
||||
{
|
||||
if ( CheckDecay() )
|
||||
return false;
|
||||
|
|
@ -1132,6 +1139,7 @@ namespace Server.Multis
|
|||
|
||||
m_Moving = dir;
|
||||
m_Speed = speed;
|
||||
m_ClientSpeed = clientSpeed;
|
||||
m_Order = BoatOrder.Move;
|
||||
|
||||
if ( m_MoveTimer != null )
|
||||
|
|
@ -1158,6 +1166,7 @@ namespace Server.Multis
|
|||
|
||||
m_Moving = Direction.North;
|
||||
m_Speed = 0;
|
||||
m_ClientSpeed = 0;
|
||||
m_MoveTimer.Stop();
|
||||
m_MoveTimer = null;
|
||||
|
||||
|
|
@ -1322,12 +1331,13 @@ namespace Server.Multis
|
|||
public bool DoMovement( bool message )
|
||||
{
|
||||
Direction dir;
|
||||
int speed;
|
||||
int speed, clientSpeed;
|
||||
|
||||
if ( this.Order == BoatOrder.Move )
|
||||
{
|
||||
dir = this.Moving;
|
||||
speed = this.Speed;
|
||||
dir = m_Moving;
|
||||
speed = m_Speed;
|
||||
clientSpeed = m_ClientSpeed;
|
||||
}
|
||||
else if ( MapItem == null || MapItem.Deleted )
|
||||
{
|
||||
|
|
@ -1396,12 +1406,13 @@ namespace Server.Multis
|
|||
return Turn( 2, true );
|
||||
|
||||
speed = Math.Min( this.Speed, maxSpeed );
|
||||
clientSpeed = 0x4;
|
||||
}
|
||||
|
||||
return Move( dir, speed, true );
|
||||
return Move( dir, speed, clientSpeed, true );
|
||||
}
|
||||
|
||||
public bool Move( Direction dir, int speed, bool message )
|
||||
public bool Move( Direction dir, int speed, int clientSpeed, bool message )
|
||||
{
|
||||
Map map = Map;
|
||||
|
||||
|
|
@ -1417,7 +1428,8 @@ namespace Server.Multis
|
|||
}
|
||||
|
||||
int rx = 0, ry = 0;
|
||||
Movement.Movement.Offset( (Direction)(((int)m_Facing + (int)dir) & 0x7), ref rx, ref ry );
|
||||
Direction d = (Direction)(((int)m_Facing + (int)dir) & 0x7);
|
||||
Movement.Movement.Offset( d, ref rx, ref ry );
|
||||
|
||||
for ( int i = 1; i <= speed; ++i )
|
||||
{
|
||||
|
|
@ -1476,48 +1488,129 @@ namespace Server.Multis
|
|||
}
|
||||
}
|
||||
|
||||
Teleport( xOffset, yOffset, 0 );
|
||||
if ( !NewBoatMovement || Math.Abs( xOffset ) > 1 || Math.Abs( yOffset ) > 1 )
|
||||
{
|
||||
Teleport( xOffset, yOffset, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
List<IEntity> toMove = GetMovingEntities();
|
||||
|
||||
SafeAdd( m_TillerMan, toMove );
|
||||
SafeAdd( m_Hold, toMove );
|
||||
SafeAdd( m_PPlank, toMove );
|
||||
SafeAdd( m_SPlank, toMove );
|
||||
|
||||
// Packet must be sent before actual locations are changed
|
||||
foreach ( NetState ns in Map.GetClientsInRange( Location, GetMaxUpdateRange() ) )
|
||||
{
|
||||
Mobile m = ns.Mobile;
|
||||
|
||||
if ( ns.HighSeas && m.CanSee( this ) && m.InRange( Location, GetUpdateRange( m ) ) )
|
||||
ns.Send( new MoveBoatHS( m, this, d, clientSpeed, toMove, xOffset, yOffset ) );
|
||||
}
|
||||
|
||||
foreach ( IEntity e in toMove )
|
||||
{
|
||||
if ( e is Item )
|
||||
{
|
||||
Item item = (Item)e;
|
||||
|
||||
item.NoMoveHS = true;
|
||||
|
||||
if ( !( item is TillerMan || item is Hold || item is Plank ) )
|
||||
item.Location = new Point3D( item.X + xOffset, item.Y + yOffset, item.Z );
|
||||
}
|
||||
else if ( e is Mobile )
|
||||
{
|
||||
Mobile m = (Mobile)e;
|
||||
|
||||
m.NoMoveHS = true;
|
||||
m.Location = new Point3D( m.X + xOffset, m.Y + yOffset, m.Z );
|
||||
}
|
||||
}
|
||||
|
||||
NoMoveHS = true;
|
||||
Location = new Point3D( X + xOffset, Y + yOffset, Z );
|
||||
|
||||
foreach ( IEntity e in toMove )
|
||||
{
|
||||
if ( e is Item )
|
||||
((Item)e).NoMoveHS = false;
|
||||
else if ( e is Mobile )
|
||||
((Mobile)e).NoMoveHS = false;
|
||||
}
|
||||
|
||||
NoMoveHS = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void SafeAdd( Item item, List<IEntity> toMove )
|
||||
{
|
||||
if ( item != null )
|
||||
toMove.Add( item );
|
||||
}
|
||||
|
||||
public void Teleport( int xOffset, int yOffset, int zOffset )
|
||||
{
|
||||
MultiComponentList mcl = Components;
|
||||
|
||||
ArrayList toMove = new ArrayList();
|
||||
|
||||
IPooledEnumerable eable = this.Map.GetObjectsInBounds( new Rectangle2D( X + mcl.Min.X, Y + mcl.Min.Y, mcl.Width, mcl.Height ) );
|
||||
|
||||
foreach ( object o in eable )
|
||||
{
|
||||
if ( o != this && !(o is TillerMan || o is Hold || o is Plank) )
|
||||
toMove.Add( o );
|
||||
}
|
||||
|
||||
eable.Free();
|
||||
List<IEntity> toMove = GetMovingEntities();
|
||||
|
||||
for ( int i = 0; i < toMove.Count; ++i )
|
||||
{
|
||||
object o = toMove[i];
|
||||
IEntity e = toMove[i];
|
||||
|
||||
if ( e is Item )
|
||||
{
|
||||
Item item = (Item)e;
|
||||
|
||||
item.Location = new Point3D( item.X + xOffset, item.Y + yOffset, item.Z + zOffset );
|
||||
}
|
||||
else if ( e is Mobile )
|
||||
{
|
||||
Mobile m = (Mobile)e;
|
||||
|
||||
m.Location = new Point3D( m.X + xOffset, m.Y + yOffset, m.Z + zOffset );
|
||||
}
|
||||
}
|
||||
|
||||
Location = new Point3D( X + xOffset, Y + yOffset, Z + zOffset );
|
||||
}
|
||||
|
||||
public List<IEntity> GetMovingEntities()
|
||||
{
|
||||
List<IEntity> list = new List<IEntity>();
|
||||
|
||||
Map map = Map;
|
||||
|
||||
if ( map == null || map == Map.Internal )
|
||||
return list;
|
||||
|
||||
MultiComponentList mcl = Components;
|
||||
|
||||
foreach ( object o in map.GetObjectsInBounds( new Rectangle2D( X + mcl.Min.X, Y + mcl.Min.Y, mcl.Width, mcl.Height ) ) )
|
||||
{
|
||||
if ( o == this || o is TillerMan || o is Hold || o is Plank )
|
||||
continue;
|
||||
|
||||
if ( o is Item )
|
||||
{
|
||||
Item item = (Item)o;
|
||||
|
||||
if ( Contains( item ) && item.Visible && item.Z >= Z )
|
||||
item.Location = new Point3D( item.X + xOffset, item.Y + yOffset, item.Z + zOffset );
|
||||
list.Add( item );
|
||||
}
|
||||
else if ( o is Mobile )
|
||||
{
|
||||
Mobile m = (Mobile)o;
|
||||
|
||||
if ( Contains( m ) )
|
||||
m.Location = new Point3D( m.X + xOffset, m.Y + yOffset, m.Z + zOffset );
|
||||
list.Add( m );
|
||||
}
|
||||
}
|
||||
|
||||
Location = new Point3D( X + xOffset, Y + yOffset, Z + zOffset );
|
||||
return list;
|
||||
}
|
||||
|
||||
public bool SetFacing( Direction facing )
|
||||
|
|
@ -1539,8 +1632,6 @@ namespace Server.Multis
|
|||
}
|
||||
}
|
||||
|
||||
this.Map.OnLeave( this );
|
||||
|
||||
Direction old = m_Facing;
|
||||
|
||||
m_Facing = facing;
|
||||
|
|
@ -1557,34 +1648,11 @@ namespace Server.Multis
|
|||
if ( m_SPlank != null )
|
||||
m_SPlank.SetFacing( facing );
|
||||
|
||||
MultiComponentList mcl = Components;
|
||||
|
||||
ArrayList toMove = new ArrayList();
|
||||
List<IEntity> toMove = GetMovingEntities();
|
||||
|
||||
toMove.Add( m_PPlank );
|
||||
toMove.Add( m_SPlank );
|
||||
|
||||
IPooledEnumerable eable = Map.GetObjectsInBounds( new Rectangle2D( X + mcl.Min.X, Y + mcl.Min.Y, mcl.Width, mcl.Height ) );
|
||||
|
||||
foreach ( object o in eable )
|
||||
{
|
||||
if ( o is Item )
|
||||
{
|
||||
Item item = (Item)o;
|
||||
|
||||
if ( item != this && Contains( item ) && item.Visible && item.Z >= Z && !(item is TillerMan || item is Hold || item is Plank) )
|
||||
toMove.Add( item );
|
||||
}
|
||||
else if ( o is Mobile && Contains( (Mobile)o ) )
|
||||
{
|
||||
toMove.Add( o );
|
||||
|
||||
((Mobile)o).Direction = (Direction)((int)((Mobile)o).Direction - (int)old + (int)facing);
|
||||
}
|
||||
}
|
||||
|
||||
eable.Free();
|
||||
|
||||
int xOffset = 0, yOffset = 0;
|
||||
Movement.Movement.Offset( facing, ref xOffset, ref yOffset );
|
||||
|
||||
|
|
@ -1599,12 +1667,21 @@ namespace Server.Multis
|
|||
|
||||
for ( int i = 0; i < toMove.Count; ++i )
|
||||
{
|
||||
object o = toMove[i];
|
||||
IEntity e = toMove[i];
|
||||
|
||||
if ( o is Item )
|
||||
((Item)o).Location = Rotate( ((Item)o).Location, count );
|
||||
else if ( o is Mobile )
|
||||
((Mobile)o).Location = Rotate( ((Mobile)o).Location, count );
|
||||
if ( e is Item )
|
||||
{
|
||||
Item item = (Item)e;
|
||||
|
||||
item.Location = Rotate( item.Location, count );
|
||||
}
|
||||
else if ( e is Mobile )
|
||||
{
|
||||
Mobile m = (Mobile)e;
|
||||
|
||||
m.Direction = ( m.Direction - old + facing ) & Direction.Mask;
|
||||
m.Location = Rotate( m.Location, count );
|
||||
}
|
||||
}
|
||||
|
||||
switch ( facing )
|
||||
|
|
@ -1615,8 +1692,6 @@ namespace Server.Multis
|
|||
case Direction.West: ItemID = WestID; break;
|
||||
}
|
||||
|
||||
this.Map.OnEnter( this );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1665,5 +1740,160 @@ namespace Server.Multis
|
|||
UpdateAllComponents();
|
||||
}
|
||||
}
|
||||
|
||||
#region High Seas
|
||||
|
||||
/*
|
||||
* OSI sends the 0xF7 packet instead, holding 0xF3 packets
|
||||
* for every entity on the boat. Though, the regular 0xF3
|
||||
* packets are still being sent as well as entities come
|
||||
* into sight. Do we really need it?
|
||||
*/
|
||||
/*
|
||||
protected override Packet GetWorldPacketFor( NetState state )
|
||||
{
|
||||
if ( NewBoatMovement && state.HighSeas )
|
||||
return new DisplayBoatHS( state.Mobile, this );
|
||||
else
|
||||
return base.GetWorldPacketFor( state );
|
||||
}
|
||||
*/
|
||||
|
||||
public sealed class MoveBoatHS : Packet
|
||||
{
|
||||
public MoveBoatHS( Mobile beholder, BaseBoat boat, Direction d, int speed, List<IEntity> ents, int xOffset, int yOffset )
|
||||
: base( 0xF6 )
|
||||
{
|
||||
EnsureCapacity( 3 + 15 + ents.Count * 10 );
|
||||
|
||||
m_Stream.Write( (int) boat.Serial );
|
||||
m_Stream.Write( (byte) speed );
|
||||
m_Stream.Write( (byte) d );
|
||||
m_Stream.Write( (byte) boat.Facing );
|
||||
m_Stream.Write( (short) ( boat.X + xOffset ) );
|
||||
m_Stream.Write( (short) ( boat.Y + yOffset ) );
|
||||
m_Stream.Write( (short) boat.Z );
|
||||
m_Stream.Write( (short) 0 ); // count placeholder
|
||||
|
||||
int count = 0;
|
||||
|
||||
foreach ( IEntity ent in ents )
|
||||
{
|
||||
if ( !beholder.CanSee( ent ) )
|
||||
continue;
|
||||
|
||||
m_Stream.Write( (int) ent.Serial );
|
||||
m_Stream.Write( (short) ( ent.X + xOffset ) );
|
||||
m_Stream.Write( (short) ( ent.Y + yOffset ) );
|
||||
m_Stream.Write( (short) ent.Z );
|
||||
++count;
|
||||
}
|
||||
|
||||
m_Stream.Seek( 16, System.IO.SeekOrigin.Begin );
|
||||
m_Stream.Write( (short) count );
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class DisplayBoatHS : Packet
|
||||
{
|
||||
public DisplayBoatHS( Mobile beholder, BaseBoat boat )
|
||||
: base( 0xF7 )
|
||||
{
|
||||
List<IEntity> ents = boat.GetMovingEntities();
|
||||
|
||||
SafeAdd( boat.TillerMan, ents );
|
||||
SafeAdd( boat.Hold, ents );
|
||||
SafeAdd( boat.PPlank, ents );
|
||||
SafeAdd( boat.SPlank, ents );
|
||||
|
||||
ents.Add( boat );
|
||||
|
||||
EnsureCapacity( 3 + 2 + ents.Count * 26 );
|
||||
|
||||
m_Stream.Write( (short) 0 ); // count placeholder
|
||||
|
||||
int count = 0;
|
||||
|
||||
foreach ( IEntity ent in ents )
|
||||
{
|
||||
if ( !beholder.CanSee( ent ) )
|
||||
continue;
|
||||
|
||||
// Embedded WorldItemHS packets
|
||||
m_Stream.Write( (byte) 0xF3 );
|
||||
m_Stream.Write( (short) 0x1 );
|
||||
|
||||
if ( ent is BaseMulti )
|
||||
{
|
||||
BaseMulti bm = (BaseMulti)ent;
|
||||
|
||||
m_Stream.Write( (byte) 0x02 );
|
||||
m_Stream.Write( (int) bm.Serial );
|
||||
// TODO: Mask no longer needed, merge with Item case?
|
||||
m_Stream.Write( (ushort) ( bm.ItemID & 0x3FFF ) );
|
||||
m_Stream.Write( (byte) 0 );
|
||||
|
||||
m_Stream.Write( (short) bm.Amount );
|
||||
m_Stream.Write( (short) bm.Amount );
|
||||
|
||||
m_Stream.Write( (short) ( bm.X & 0x7FFF ) );
|
||||
m_Stream.Write( (short) ( bm.Y & 0x3FFF ) );
|
||||
m_Stream.Write( (sbyte) bm.Z );
|
||||
|
||||
m_Stream.Write( (byte) bm.Light );
|
||||
m_Stream.Write( (short) bm.Hue );
|
||||
m_Stream.Write( (byte) bm.GetPacketFlags() );
|
||||
}
|
||||
else if ( ent is Mobile )
|
||||
{
|
||||
Mobile m = (Mobile)ent;
|
||||
|
||||
m_Stream.Write( (byte) 0x01 );
|
||||
m_Stream.Write( (int) m.Serial );
|
||||
m_Stream.Write( (short) m.Body );
|
||||
m_Stream.Write( (byte) 0 );
|
||||
|
||||
m_Stream.Write( (short) 1 );
|
||||
m_Stream.Write( (short) 1 );
|
||||
|
||||
m_Stream.Write( (short) ( m.X & 0x7FFF ) );
|
||||
m_Stream.Write( (short) ( m.Y & 0x3FFF ) );
|
||||
m_Stream.Write( (sbyte) m.Z );
|
||||
|
||||
m_Stream.Write( (byte) m.Direction );
|
||||
m_Stream.Write( (short) m.Hue );
|
||||
m_Stream.Write( (byte) m.GetPacketFlags() );
|
||||
}
|
||||
else if ( ent is Item )
|
||||
{
|
||||
Item item = (Item)ent;
|
||||
|
||||
m_Stream.Write( (byte) 0x00 );
|
||||
m_Stream.Write( (int) item.Serial );
|
||||
m_Stream.Write( (ushort) ( item.ItemID & 0xFFFF ) );
|
||||
m_Stream.Write( (byte) 0 );
|
||||
|
||||
m_Stream.Write( (short) item.Amount );
|
||||
m_Stream.Write( (short) item.Amount );
|
||||
|
||||
m_Stream.Write( (short) ( item.X & 0x7FFF ) );
|
||||
m_Stream.Write( (short) ( item.Y & 0x3FFF ) );
|
||||
m_Stream.Write( (sbyte) item.Z );
|
||||
|
||||
m_Stream.Write( (byte) item.Light );
|
||||
m_Stream.Write( (short) item.Hue );
|
||||
m_Stream.Write( (byte) item.GetPacketFlags() );
|
||||
}
|
||||
|
||||
m_Stream.Write( (short) 0x00 );
|
||||
++count;
|
||||
}
|
||||
|
||||
m_Stream.Seek( 3, System.IO.SeekOrigin.Begin );
|
||||
m_Stream.Write( (short) count );
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue