RunUO Community

This is a sample guest message. Register a free account today to become a member! Once signed in, you'll be able to participate on this site by adding your own topics and posts, as well as connect with other members through your own private inbox!

Boats with Regions and SmoothMovement mods [RUNUO 2.0 SVN 889]

fwiffo

Sorceror
*ATTENTION!*
this mod, to work, requires a CORE edit, I have made a patch against runuo svn 889 (or something like so, don't remember and I'm lazy to check), the edits are really easy to do, so you won't have much hassle in doing them....please, understand that those edits are required, or items will be scattered in the sea.
*/ATTENTION!*

What can be done with the regions inside a boat?
Basically you can restrict cast, restrict items or skill used, just like what can be done in "Regions in a Box" made by Asayre.

I have made some effort for the smooth movement packet for High Seas, if you don't support it and/or you don't want it, just comment out the lines.

Any request or bugfix, please post them here, I will fix them ASAP.
 

Attachments

  • BoatRegion_plus_Smoothmove(pre-release).7z
    16.1 KB · Views: 216

Pakko

Traveler
Ok, i am havin an issue with this on compile!

here is my mobile.cs

Code:
int oldAmount = item.Amount;
                            //item.Amount = amount; //Set in LiftItemDupe
                            Region reg = Region.Find( item.Location, item.Map );
 
                            if( amount < oldAmount )
                                LiftItemDupe( item, amount );
                                {
                                Item newItem = LiftItemDupe( item, amount );
                                reg.OnLiftItem( item, newItem );
                            }
                            else
                                reg.OnItemRemoved( item );
                            //item.Dupe( oldAmount - amount );
       
                            Map map = from.Map;


Here is the error!


Code:
C:\Users\lk\Desktop\Wisdom Beta Server 2012>cd Server
 
C:\Users\lk\Desktop\Wisdom Beta Server 2012\Server>SET DOTNET=C:\WINDOWS\Microso
ft.NET\Framework\v2.0.50727
 
C:\Users\lk\Desktop\Wisdom Beta Server 2012\Server>SET PATH=C:\WINDOWS\Microsoft
.NET\Framework\v2.0.50727
 
C:\Users\lk\Desktop\Wisdom Beta Server 2012\Server>csc.exe /win32icon:orb.ico /r
:Ultima.dll /debug /nowarn:0618 /nologo /out:..\Orb_Server.exe /unsafe /recurse:
*.cs
Mobile.cs(4443,8): error CS1525: Invalid expression term 'else'
Mobile.cs(4443,12): error CS1002: ; expected
 
C:\Users\lk\Desktop\Wisdom Beta Server 2012\Server>PAUSE
Press any key to continue . . .
 

fwiffo

Sorceror
uhm....you made the patch the wrong way:

Code:
if( amount < oldAmount )
{
    Item newItem = LiftItemDupe( item, amount );
    reg.OnLiftItem( item, newItem );
}
else
    reg.OnItemRemoved( item );
 

Pakko

Traveler
It compiled but i got this error now :),

Code:
 + Multis/Boats/BaseBoat.cs:
    CS1502: Line 1599: The best overloaded method match for 'System.Collections.
Generic.List<Server.ISpawnable>.AddRange(System.Collections.Generic.IEnumerable<
Server.ISpawnable>)' has some invalid arguments
    CS1503: Line 1599: Argument '1': cannot convert from 'System.Collections.Gen
eric.List<Server.Item>' to 'System.Collections.Generic.IEnumerable<Server.ISpawn
able>'
    CS1502: Line 1600: The best overloaded method match for 'System.Collections.
Generic.List<Server.ISpawnable>.AddRange(System.Collections.Generic.IEnumerable<
Server.ISpawnable>)' has some invalid arguments
    CS1503: Line 1600: Argument '1': cannot convert from 'System.Collections.Gen
eric.List<Server.Mobile>' to 'System.Collections.Generic.IEnumerable<Server.ISpa
wnable>'

I commented these out can you just clarify this is fine, because its compiled fine now and i havnt slept for a while. Im off to bed i hope i havnt bothered you too much, with silly questions.


public void Teleport( int xOffset, int yOffset, int zOffset )
{
byte direction=(byte)Utility.GetDirection( this, new Point2D(this.Location.X + xOffset, this.Location.Y + yOffset) );

List<ISpawnable> toMove = new List<ISpawnable>();
//toMove.AddRange(m_ItemsOnBoard);
//toMove.AddRange(m_MobilesOnBoard);

this.Location = new Point3D( X + xOffset, Y + yOffset, Z + zOffset );
 

fwiffo

Sorceror
Yes, I just forgot that all the common distributions out there uses by default the crappy .net 2.0

Compile the core this way, inside the directory where your SERVER CORE IS, using a command prompt:
Code:
C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\csc /out:Server.exe /recurse:.\*.cs /unsafe /o /r:C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.dll;C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Core.dll;C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Data.dll;C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Xml.dll

for orbsydia this is the compile batch:
Code:
cd Server
SET DOTNET=C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319
SET PATH=%DOTNET%
csc.exe /win32icon:orb.ico /r:Ultima.dll /debug /nowarn:0618 /nologo /out:..\Orb_Server.exe /unsafe /recurse:*.cs
PAUSE
cd ..
title Orbsydia Server - Based on UO 2.2 SVN R25 - by Team Orbsydia
echo off
cls
Orb_Server.exe

It won't use all the fancy .net4 server specific stuff, but you can save a lot of time and at least you can begin using the better framework and throw away the old one in the meantime.

When you use the core compiled that way, it will work just fine.

PS: No, I won't downgrade my script just to support "legacy" code, sorry for that
PPS: add all the other needed dll in the commandline, or just modify the compile batch, if you have one, to use the new framework, it's a good thing you will do, and you won't regret it.
 

Friendly_Bob

Sorceror
i've debugged it and im down to where the code is messing up not allowing traveling
Code:
     public bool CanFit( Point3D p, Map map, int itemID )
        {
            if ( map == null || map == Map.Internal || CheckDecay() )
                return false;

            MultiComponentList newComponents = MultiData.GetComponents( itemID );

            for ( int x = 0; x < newComponents.Width; ++x )
            {
                for ( int y = 0; y < newComponents.Height; ++y )
                {
                    int tx = p.X + newComponents.Min.X + x;
                    int ty = p.Y + newComponents.Min.Y + y;

                    if ( newComponents.Tiles[x][y].Length == 0 || Contains( tx, ty ) )
                        continue;

                    LandTile landTile = map.Tiles.GetLandTile( tx, ty );
                    StaticTile[] tiles = map.Tiles.GetStaticTiles( tx, ty, true );

                    bool hasWater = false;

                    if ( landTile.Z == p.Z && ((landTile.ID >= 168 && landTile.ID <= 171) || (landTile.ID >= 310 && landTile.ID <= 311)) )
                        hasWater = true;

                    int z = p.Z;

                    //int landZ = 0, landAvg = 0, landTop = 0;

                    //map.GetAverageZ( tx, ty, ref landZ, ref landAvg, ref landTop );

                    //if ( !landTile.Ignored && top > landZ && landTop > z )
                    //    return false;

                    for ( int i = 0; i < tiles.Length; ++i )
                    {
                        StaticTile tile = tiles[i];
                        bool isWater = ( tile.ID >= 0x1796 && tile.ID <= 0x17B2 );

                        if ( tile.Z == p.Z && isWater )
                            hasWater = true;
                        else if ( tile.Z >= p.Z && !isWater )
                            return false;
                    }

                    if ( !hasWater )
                        return false;
                }
            }

            IPooledEnumerable eable = map.GetItemsInBounds( new Rectangle2D( p.X + newComponents.Min.X, p.Y + newComponents.Min.Y, newComponents.Width, newComponents.Height ) );

            foreach ( Item item in eable )
            {
                if ( item is BaseMulti || item.ItemID > TileData.MaxItemValue || item.Z < p.Z || !item.Visible )
                    continue;

                int x = item.X - p.X + newComponents.Min.X;
                int y = item.Y - p.Y + newComponents.Min.Y;

                if ( x >= 0 && x < newComponents.Width && y >= 0 && y < newComponents.Height && newComponents.Tiles[x][y].Length == 0 )
                    continue;
                else if ( Contains( item ) )
                    continue;

                eable.Free();
                return false;
            }

            eable.Free();

            return true;
        }
i dont know why its doing but its saying all the water tiles are not there im about to debug farther and if anyone else has the issue that im having ill post the answer here :D
 

Vorspire

Knight
Your smooth move packet contains a gigantic memory leak by the way.

This packet differs slightly because the length must be converted to little-endian format, otherwise every time the packet is sent with a standard length it will be read by the client the wrong way and will create an internal memory buffer that is insanely large.
If you travel with the boat at high speed, you move about 10 tiles before your client locks up.

I've done a lot of work with these boats and the solution is here;
Code:
short length = (short)(18 + (list.Length * 10));
EnsureCapacity(length);

length = (short)(((length & 0xff) << 8) | ((length >> 8) & 0xff));
m_Stream.Seek(1, SeekOrigin.Begin);
m_Stream.Write(length);

Here's a complete write-up of the packets I use;
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

using Server;
using Server.Network;
using Server.Mobiles;
using Server.Items;

namespace Server.Vehicles
{
	public sealed class VehicleMovement : Packet
	{
		public VehicleMovement(BaseVehicle vehicle, Point3D newLocation)
			: base(0xF6)
		{
			IEntity[] list = vehicle.GetDynamicEntities(false, true, true, false);

			short length = (short)(18 + (list.Length * 10));
			EnsureCapacity(length);

			length = (short)(((length & 0xff) << 8) | ((length >> 8) & 0xff));
			m_Stream.Seek(1, SeekOrigin.Begin);
			m_Stream.Write(length);

			m_Stream.Write((int)vehicle.Serial);
			m_Stream.Write((byte)vehicle.Speed);
			m_Stream.Write((byte)vehicle.Moving);
			m_Stream.Write((byte)vehicle.Direction);

			m_Stream.Write((short)newLocation.X);
			m_Stream.Write((short)newLocation.Y);
			m_Stream.Write((byte)0xFF);
			m_Stream.Write((sbyte)newLocation.Z);

			m_Stream.Write((byte)0x0);
			m_Stream.Write((byte)list.Length);

			for (int i = 0; i < list.Length; i++)
			{
				IEntity entity = list[i];

				m_Stream.Write((int)entity.Serial);
				m_Stream.Write((short)entity.X);
				m_Stream.Write((short)entity.Y);
				m_Stream.Write((byte)0xFF);
				m_Stream.Write((sbyte)entity.Z);
			}
		}
	}

	public sealed class VehicleDriverLock : Packet
	{
		public VehicleDriverLock(Mobile m)
			: base(0xBF)
		{
			short length = 19;
			EnsureCapacity(length);

			length = (short)(((length & 0xff) << 8) | ((length >> 8) & 0xff));
			m_Stream.Seek(1, SeekOrigin.Begin);
			m_Stream.Write(length);

			m_Stream.Write((short)0x19);
			m_Stream.Write((byte)0x05);
			m_Stream.Write((int)m.Serial);
			m_Stream.Write((byte)0x00);

			m_Stream.Write((byte)0xFF);
			m_Stream.Write((byte)0x00);
			m_Stream.Write((short)0x04);
			m_Stream.Write((short)0x00);
			m_Stream.Write((byte)0x00);
			m_Stream.Write((byte)0x00);
		}
	}

	public sealed class EntityListUpdate : Packet
	{
		public EntityListUpdate(params IEntity[] list)
			: base(0xF7)
		{
			EnsureCapacity(2 + (list.Length * 26));

			m_Stream.Write((byte)0x0);
			m_Stream.Write((byte)list.Length);

			for (int i = 0; i < list.Length; i++)
			{
				IEntity entity = list[i];
				int itemID = 0;
				short amount = 0x01, hue = 0x00;
				byte cmd = 0x0, light = 0x0, flags = 0x0;

				if (entity is BaseMulti)
				{
					BaseMulti multi = entity as BaseMulti;

					cmd = 0x2;
					itemID = multi.ItemID;
					itemID &= 0x3FFF;
				}
				else if (entity is Item)
				{
					Item item = entity as Item;

					cmd = 0x0;
					itemID = item.ItemID;
					itemID &= 0xFFFF;
					amount = (short)item.Amount;
					light = (byte)item.Light;
					flags = (byte)item.GetPacketFlags();
				}
				else if (entity is Mobile)
				{
					Mobile mobile = entity as Mobile;

					cmd = 0x1;
					itemID = mobile.BodyValue;
					flags = (byte)mobile.GetPacketFlags();
				}

				m_Stream.Write((byte)0xF3);
				m_Stream.Write((short)0x01);
				m_Stream.Write(cmd);
				m_Stream.Write((int)entity.Serial);
				m_Stream.Write((ushort)itemID);
				m_Stream.Write((byte)0x0); //direction?

				m_Stream.Write(amount);
				m_Stream.Write(amount);

				m_Stream.Write((short)entity.X);
				m_Stream.Write((short)entity.Y);
				m_Stream.Write((sbyte)entity.Z);

				m_Stream.Write(light);
				m_Stream.Write(hue);
				m_Stream.Write(flags);

				m_Stream.Write((short)0x00); // ??
			}
		}
	}
}
 

fwiffo

Sorceror
Thank you :p

If I can use your packet I'll adopt it and fix the boat script too, only if you want to, anyway :)
 

Vorspire

Knight
I post it public so the community may use my code as they see fit, credited or not :)

These packets are tailored more towards supporting ANY Multi as a vehicle (BaseVehicle in my system) so it doesn't explicitly accept boats, you can literally use smooth movement with any multi, including house foundations.

Happy to see you got around to releasing this fwiffo, good work :)
 

Juzzver

Sorceror
If use commands: "Turn left or Turn right", server is going crushed.

Exception:
System.InvalidOperationException: Collection was modified; impossible to perform the operation are presented.
в System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
в System.Collections.Generic.List`1.Enumerator.MoveNextRare()
в System.Collections.Generic.List`1.Enumerator.MoveNext()
в Server.Multis.BaseBoat.SetFacing(Direction facing)
в Server.Multis.BaseBoat.Turn(Int32 offset, Boolean message)
в Server.Multis.BaseBoat.TurnTimer.OnTick()
в Server.Timer.Slice() в d:\games\Sphere\Last SVN\Server\Timer.cs:строка 386
в Server.Core.Main(String[] args) в d:\games\Sphere\Last SVN\Server\Main.cs:строка 517
 

_Epila_

Sorceror
I've applied your patch and vorpire's fix but i'm getting some glitches, as you can see
 

fwiffo

Sorceror
this is the large boat?

Have you tried with small and medium?
Beside those two, the large has the center of the boat not in the mast, but in a paver below of one tile, check moving in the tile where there is the piece missing and do [where if it says that it is boatregion or not, maybe put the thing here for others to see, I'll fix asap if it's a bug.
 

Vorspire

Knight
I've applied your patch and vorpire's fix but i'm getting some glitches, as you can see

This happens when the update packets are sent at the wrong time, I can't remember exactly, but they should be sent either directly before the boat's location changes, or directly after.

IIRC, my vehicles system pre-calculates the point to where the boat will move, then sends the update packet before the boat location is actually changed.
The update packet contains the pre-calculated point.

The smooth movement packet is simply the same as a Moving Effect packet, except it moves multiID's instead of a given itemID.
 

fwiffo

Sorceror
Anyway, those pieces are added manually before moving the boat (so you have to add the plank right & left, plus back and container in the moving packet + add it in the moving cycle), but it should be already like so, they are used as IEntity, anyway for simplicity you can use ISpawnable, so you can use the same list for moving && packet sending.

Damn, I've to edit it, but my time is really so damn short :(
 

_Epila_

Sorceror
i've tested boat movement on OSI, it seems that the server only sends the Smooth Effect packet (0xF6) for every entity inside the boat region. The server did not sent the world item packet used to update the item location (same for mobiles)
 

Corrado

Sorceror
I know this is a bit of an older post, but has anyone gotten smooth boat movement working successfully ?

I'd love to add it to my shard, but don't even know where to begin when it comes to packets and all that....
 

peepeetree

Sorceror
I know this is a bit of an older post, but has anyone gotten smooth boat movement working successfully ?

I'd love to add it to my shard, but don't even know where to begin when it comes to packets and all that....

I second this, before I go messing around with core edits I would prefer to know others are getting it to work without any issues.
 
Top