Adds assemblies config, fixes crash bugs. (#134)

This commit is contained in:
Kamron Batman 2020-05-09 12:55:56 -07:00 • committed by GitHub
parent 0140eb73b4
commit 8ec166bcd0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3223 changed files with 191 additions and 191 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,172 @@
using Server.Engines.CannedEvil;
using Server.Network;
using Server.Regions;
using Server.Targeting;
namespace Server.Multis
{
public abstract class BaseBoatDeed : Item
{
public BaseBoatDeed(int id, Point3D offset) : base(0x14F2)
{
Weight = 1.0;
if (!Core.AOS)
LootType = LootType.Newbied;
MultiID = id;
Offset = offset;
}
public BaseBoatDeed(Serial serial) : base(serial)
{
}
[CommandProperty(AccessLevel.GameMaster)]
public int MultiID { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public Point3D Offset { get; set; }
public abstract BaseBoat Boat { get; }
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
writer.Write(MultiID);
writer.Write(Offset);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 0:
{
MultiID = reader.ReadInt();
Offset = reader.ReadPoint3D();
break;
}
}
if (Weight == 0.0)
Weight = 1.0;
}
public override void OnDoubleClick(Mobile from)
{
if (!IsChildOf(from.Backpack))
{
from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it.
}
else if (from.AccessLevel < AccessLevel.GameMaster && (from.Map == Map.Ilshenar || from.Map == Map.Malas))
{
from.SendLocalizedMessage(1010567, null, 0x25); // You may not place a boat from this location.
}
else
{
if (Core.SE)
from.SendLocalizedMessage(502482); // Where do you wish to place the ship?
else
from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 502482); // Where do you wish to place the ship?
from.Target = new InternalTarget(this);
}
}
public void OnPlacement(Mobile from, Point3D p)
{
if (Deleted) return;
if (!IsChildOf(from.Backpack))
{
from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it.
}
else
{
Map map = from.Map;
if (map == null)
return;
if (from.AccessLevel < AccessLevel.GameMaster && (map == Map.Ilshenar || map == Map.Malas))
{
from.SendLocalizedMessage(1043284); // A ship can not be created here.
return;
}
if (from.Region.IsPartOf<HouseRegion>() || BaseBoat.FindBoatAt(from, from.Map) != null)
{
from.SendLocalizedMessage(1010568, null,
0x25); // You may not place a ship while on another ship or inside a house.
return;
}
BaseBoat boat = Boat;
if (boat == null)
return;
p = new Point3D(p.X - Offset.X, p.Y - Offset.Y, p.Z - Offset.Z);
if (BaseBoat.IsValidLocation(p, map) && boat.CanFit(p, map, boat.ItemID))
{
Delete();
boat.Owner = from;
boat.Anchored = true;
uint keyValue = boat.CreateKeys(from);
if (boat.PPlank != null)
boat.PPlank.KeyValue = keyValue;
if (boat.SPlank != null)
boat.SPlank.KeyValue = keyValue;
boat.MoveToWorld(p, map);
}
else
{
boat.Delete();
from.SendLocalizedMessage(1043284); // A ship can not be created here.
}
}
}
private class InternalTarget : MultiTarget
{
private readonly BaseBoatDeed m_Deed;
public InternalTarget(BaseBoatDeed deed) : base(deed.MultiID, deed.Offset) => m_Deed = deed;
protected override void OnTarget(Mobile from, object o)
{
if (o is IPoint3D ip)
{
if (ip is Item item)
ip = item.GetWorldTop();
Point3D p = new Point3D(ip);
Region region = Region.Find(p, from.Map);
if (region.IsPartOf<DungeonRegion>())
from.SendLocalizedMessage(502488); // You can not place a ship inside a dungeon.
else if (region.IsPartOf<HouseRegion>() || region.IsPartOf<ChampionSpawnRegion>())
from.SendLocalizedMessage(1042549); // A boat may not be placed in this area.
else
m_Deed.OnPlacement(from, p);
}
}
}
}
}

View file

@ -0,0 +1,191 @@
using Server.Engines.CannedEvil;
using Server.Regions;
using Server.Targeting;
namespace Server.Multis
{
public abstract class BaseDockedBoat : Item
{
private string m_ShipName;
public BaseDockedBoat(int id, Point3D offset, BaseBoat boat) : base(0x14F4)
{
Weight = 1.0;
LootType = LootType.Blessed;
MultiID = id;
Offset = offset;
m_ShipName = boat.ShipName;
}
public BaseDockedBoat(Serial serial) : base(serial)
{
}
[CommandProperty(AccessLevel.GameMaster)]
public int MultiID { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public Point3D Offset { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public string ShipName
{
get => m_ShipName;
set
{
m_ShipName = value;
InvalidateProperties();
}
}
public abstract BaseBoat Boat { get; }
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(1); // version
writer.Write(MultiID);
writer.Write(Offset);
writer.Write(m_ShipName);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 1:
case 0:
{
MultiID = reader.ReadInt();
Offset = reader.ReadPoint3D();
m_ShipName = reader.ReadString();
if (version == 0)
reader.ReadUInt();
break;
}
}
if (LootType == LootType.Newbied)
LootType = LootType.Blessed;
if (Weight == 0.0)
Weight = 1.0;
}
public override void OnDoubleClick(Mobile from)
{
if (!IsChildOf(from.Backpack))
{
from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it.
}
else
{
from.SendLocalizedMessage(502482); // Where do you wish to place the ship?
from.Target = new InternalTarget(this);
}
}
public override void AddNameProperty(ObjectPropertyList list)
{
if (m_ShipName != null)
list.Add(m_ShipName);
else
base.AddNameProperty(list);
}
public override void OnSingleClick(Mobile from)
{
if (m_ShipName != null)
LabelTo(from, m_ShipName);
else
base.OnSingleClick(from);
}
public void OnPlacement(Mobile from, Point3D p)
{
if (Deleted) return;
if (!IsChildOf(from.Backpack))
{
from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it.
}
else
{
Map map = from.Map;
if (map == null)
return;
BaseBoat boat = Boat;
if (boat == null)
return;
p = new Point3D(p.X - Offset.X, p.Y - Offset.Y, p.Z - Offset.Z);
if (BaseBoat.IsValidLocation(p, map) && boat.CanFit(p, map, boat.ItemID) && map != Map.Ilshenar &&
map != Map.Malas)
{
Delete();
boat.Owner = from;
boat.Anchored = true;
boat.ShipName = m_ShipName;
uint keyValue = boat.CreateKeys(from);
if (boat.PPlank != null)
boat.PPlank.KeyValue = keyValue;
if (boat.SPlank != null)
boat.SPlank.KeyValue = keyValue;
boat.MoveToWorld(p, map);
}
else
{
boat.Delete();
from.SendLocalizedMessage(1043284); // A ship can not be created here.
}
}
}
private class InternalTarget : MultiTarget
{
private readonly BaseDockedBoat m_Model;
public InternalTarget(BaseDockedBoat model) : base(model.MultiID, model.Offset) => m_Model = model;
protected override void OnTarget(Mobile from, object o)
{
if (o is IPoint3D ip)
{
if (ip is Item item)
ip = item.GetWorldTop();
Point3D p = new Point3D(ip);
Region region = Region.Find(p, from.Map);
if (region.IsPartOf<DungeonRegion>())
from.SendLocalizedMessage(502488); // You can not place a ship inside a dungeon.
else if (region.IsPartOf<HouseRegion>() || region.IsPartOf<ChampionSpawnRegion>())
from.SendLocalizedMessage(1042549); // A boat may not be placed in this area.
else
m_Model.OnPlacement(from, p);
}
}
}
}
}

View file

@ -0,0 +1,38 @@
using Server.Gumps;
using Server.Network;
namespace Server.Multis
{
public class ConfirmDryDockGump : Gump
{
private readonly BaseBoat m_Boat;
private readonly Mobile m_From;
public ConfirmDryDockGump(Mobile from, BaseBoat boat) : base(150, 200)
{
m_From = from;
m_Boat = boat;
m_From.CloseGump<ConfirmDryDockGump>();
AddPage(0);
AddBackground(0, 0, 220, 170, 5054);
AddBackground(10, 10, 200, 150, 3000);
AddHtmlLocalized(20, 20, 180, 80, 1018319, true); // Do you wish to dry dock this boat?
AddHtmlLocalized(55, 100, 140, 25, 1011011); // CONTINUE
AddButton(20, 100, 4005, 4007, 2);
AddHtmlLocalized(55, 125, 140, 25, 1011012); // CANCEL
AddButton(20, 125, 4005, 4007, 1);
}
public override void OnResponse(NetState state, RelayInfo info)
{
if (info.ButtonID == 2)
m_Boat.EndDryDock(m_From);
}
}
}

View file

@ -0,0 +1,112 @@
using Server.Multis;
using Server.Network;
namespace Server.Items
{
public class Hold : Container
{
private BaseBoat m_Boat;
public Hold(BaseBoat boat) : base(0x3EAE)
{
m_Boat = boat;
Movable = false;
}
public Hold(Serial serial) : base(serial)
{
}
public override bool IsDecoContainer => false;
public void SetFacing(Direction dir)
{
ItemID = dir switch
{
Direction.East => 0x3E65,
Direction.West => 0x3E93,
Direction.North => 0x3EAE,
Direction.South => 0x3EB9,
_ => ItemID
};
}
public override bool OnDragDrop(Mobile from, Item item)
{
if (m_Boat?.Contains(from) != true || m_Boat.IsMoving)
return false;
return base.OnDragDrop(from, item);
}
public override bool OnDragDropInto(Mobile from, Item item, Point3D p)
{
if (m_Boat?.Contains(from) != true || m_Boat.IsMoving)
return false;
return base.OnDragDropInto(from, item, p);
}
public override bool CheckItemUse(Mobile from, Item item)
{
if (item != this && (m_Boat?.Contains(from) != true || m_Boat.IsMoving))
return false;
return base.CheckItemUse(from, item);
}
public override bool CheckLift(Mobile from, Item item, ref LRReason reject)
{
if (m_Boat?.Contains(from) != true || m_Boat.IsMoving)
return false;
return base.CheckLift(from, item, ref reject);
}
public override void OnAfterDelete()
{
m_Boat?.Delete();
}
public override void OnDoubleClick(Mobile from)
{
if (m_Boat?.Contains(from) != true)
m_Boat.TillerMan?.Say(502490); // You must be on the ship to open the hold.
else if (m_Boat.IsMoving)
m_Boat.TillerMan?.Say(502491); // I can not open the hold while the ship is moving.
else
base.OnDoubleClick(from);
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
writer.Write(m_Boat);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 0:
{
m_Boat = reader.ReadItem() as BaseBoat;
if (m_Boat == null || Parent != null)
Delete();
Movable = false;
break;
}
}
}
}
}

View file

@ -0,0 +1,99 @@
namespace Server.Multis
{
public class LargeBoat : BaseBoat
{
[Constructible]
public LargeBoat()
{
}
public LargeBoat(Serial serial) : base(serial)
{
}
public override int NorthID => 0x10;
public override int EastID => 0x11;
public override int SouthID => 0x12;
public override int WestID => 0x13;
public override int HoldDistance => 5;
public override int TillerManDistance => -5;
public override Point2D StarboardOffset => new Point2D(2, -1);
public override Point2D PortOffset => new Point2D(-2, -1);
public override Point3D MarkOffset => new Point3D(0, 0, 3);
public override BaseDockedBoat DockedBoat => new LargeDockedBoat(this);
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
}
public class LargeBoatDeed : BaseBoatDeed
{
[Constructible]
public LargeBoatDeed() : base(0x10, new Point3D(0, -1, 0))
{
}
public LargeBoatDeed(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1041209; // large ship deed
public override BaseBoat Boat => new LargeBoat();
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
}
public class LargeDockedBoat : BaseDockedBoat
{
public LargeDockedBoat(BaseBoat boat) : base(0x10, new Point3D(0, -1, 0), boat)
{
}
public LargeDockedBoat(Serial serial) : base(serial)
{
}
public override BaseBoat Boat => new LargeBoat();
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
}
}

View file

@ -0,0 +1,99 @@
namespace Server.Multis
{
public class LargeDragonBoat : BaseBoat
{
[Constructible]
public LargeDragonBoat()
{
}
public LargeDragonBoat(Serial serial) : base(serial)
{
}
public override int NorthID => 0x14;
public override int EastID => 0x15;
public override int SouthID => 0x16;
public override int WestID => 0x17;
public override int HoldDistance => 5;
public override int TillerManDistance => -5;
public override Point2D StarboardOffset => new Point2D(2, -1);
public override Point2D PortOffset => new Point2D(-2, -1);
public override Point3D MarkOffset => new Point3D(0, 0, 3);
public override BaseDockedBoat DockedBoat => new LargeDockedDragonBoat(this);
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
}
public class LargeDragonBoatDeed : BaseBoatDeed
{
[Constructible]
public LargeDragonBoatDeed() : base(0x14, new Point3D(0, -1, 0))
{
}
public LargeDragonBoatDeed(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1041210; // large dragon ship deed
public override BaseBoat Boat => new LargeDragonBoat();
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
}
public class LargeDockedDragonBoat : BaseDockedBoat
{
public LargeDockedDragonBoat(BaseBoat boat) : base(0x14, new Point3D(0, -1, 0), boat)
{
}
public LargeDockedDragonBoat(Serial serial) : base(serial)
{
}
public override BaseBoat Boat => new LargeDragonBoat();
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
}
}

View file

@ -0,0 +1,99 @@
namespace Server.Multis
{
public class MediumBoat : BaseBoat
{
[Constructible]
public MediumBoat()
{
}
public MediumBoat(Serial serial) : base(serial)
{
}
public override int NorthID => 0x8;
public override int EastID => 0x9;
public override int SouthID => 0xA;
public override int WestID => 0xB;
public override int HoldDistance => 4;
public override int TillerManDistance => -5;
public override Point2D StarboardOffset => new Point2D(2, 0);
public override Point2D PortOffset => new Point2D(-2, 0);
public override Point3D MarkOffset => new Point3D(0, 1, 3);
public override BaseDockedBoat DockedBoat => new MediumDockedBoat(this);
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
}
public class MediumBoatDeed : BaseBoatDeed
{
[Constructible]
public MediumBoatDeed() : base(0x8, Point3D.Zero)
{
}
public MediumBoatDeed(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1041207; // medium ship deed
public override BaseBoat Boat => new MediumBoat();
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
}
public class MediumDockedBoat : BaseDockedBoat
{
public MediumDockedBoat(BaseBoat boat) : base(0x8, Point3D.Zero, boat)
{
}
public MediumDockedBoat(Serial serial) : base(serial)
{
}
public override BaseBoat Boat => new MediumBoat();
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
}
}

View file

@ -0,0 +1,99 @@
namespace Server.Multis
{
public class MediumDragonBoat : BaseBoat
{
[Constructible]
public MediumDragonBoat()
{
}
public MediumDragonBoat(Serial serial) : base(serial)
{
}
public override int NorthID => 0xC;
public override int EastID => 0xD;
public override int SouthID => 0xE;
public override int WestID => 0xF;
public override int HoldDistance => 4;
public override int TillerManDistance => -5;
public override Point2D StarboardOffset => new Point2D(2, 0);
public override Point2D PortOffset => new Point2D(-2, 0);
public override Point3D MarkOffset => new Point3D(0, 1, 3);
public override BaseDockedBoat DockedBoat => new MediumDockedDragonBoat(this);
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
}
public class MediumDragonBoatDeed : BaseBoatDeed
{
[Constructible]
public MediumDragonBoatDeed() : base(0xC, Point3D.Zero)
{
}
public MediumDragonBoatDeed(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1041208; // medium dragon ship deed
public override BaseBoat Boat => new MediumDragonBoat();
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
}
public class MediumDockedDragonBoat : BaseDockedBoat
{
public MediumDockedDragonBoat(BaseBoat boat) : base(0xC, Point3D.Zero, boat)
{
}
public MediumDockedDragonBoat(Serial serial) : base(serial)
{
}
public override BaseBoat Boat => new MediumDragonBoat();
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
}
}

View file

@ -0,0 +1,298 @@
using System;
using System.Linq;
using Server.Factions;
using Server.Multis;
using Server.Network;
using Server.Spells;
namespace Server.Items
{
public enum PlankSide
{
Port,
Starboard
}
public class Plank : Item, ILockable
{
private Timer m_CloseTimer;
public Plank(BaseBoat boat, PlankSide side, uint keyValue) : base(0x3EB1 + (int)side)
{
Boat = boat;
Side = side;
KeyValue = keyValue;
Locked = true;
Movable = false;
}
public Plank(Serial serial) : base(serial)
{
}
[CommandProperty(AccessLevel.GameMaster)]
public BaseBoat Boat { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public PlankSide Side { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public bool IsOpen => ItemID == 0x3ED5 || ItemID == 0x3ED4 || ItemID == 0x3E84 || ItemID == 0x3E89;
[CommandProperty(AccessLevel.GameMaster)]
public bool Starboard => Side == PlankSide.Starboard;
[CommandProperty(AccessLevel.GameMaster)]
public bool Locked { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public uint KeyValue { get; set; }
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
writer.Write(Boat);
writer.Write((int)Side);
writer.Write(Locked);
writer.Write(KeyValue);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 0:
{
Boat = reader.ReadItem() as BaseBoat;
Side = (PlankSide)reader.ReadInt();
Locked = reader.ReadBool();
KeyValue = reader.ReadUInt();
if (Boat == null)
Delete();
break;
}
}
if (IsOpen)
{
m_CloseTimer = new CloseTimer(this);
m_CloseTimer.Start();
}
}
public void SetFacing(Direction dir)
{
if (IsOpen)
ItemID = dir switch
{
Direction.North => Starboard ? 0x3ED4 : 0x3ED5,
Direction.East => Starboard ? 0x3E84 : 0x3E89,
Direction.South => Starboard ? 0x3ED5 : 0x3ED4,
Direction.West => Starboard ? 0x3E89 : 0x3E84,
_ => ItemID
};
else
ItemID = dir switch
{
Direction.North => Starboard ? 0x3EB2 : 0x3EB1,
Direction.East => Starboard ? 0x3E85 : 0x3E8A,
Direction.South => Starboard ? 0x3EB1 : 0x3EB2,
Direction.West => Starboard ? 0x3E8A : 0x3E85,
_ => ItemID
};
}
public void Open()
{
if (IsOpen || Deleted)
return;
m_CloseTimer?.Stop();
m_CloseTimer = new CloseTimer(this);
m_CloseTimer.Start();
ItemID = ItemID switch
{
0x3EB1 => 0x3ED5,
0x3E8A => 0x3E89,
0x3EB2 => 0x3ED4,
0x3E85 => 0x3E84,
_ => ItemID
};
Boat?.Refresh();
}
public override bool OnMoveOver(Mobile from)
{
if (IsOpen)
{
if (from is BaseFactionGuard)
return false;
if ((from.Direction & Direction.Running) != 0 || Boat?.Contains(from) == false)
return true;
Map map = Map;
if (map == null)
return false;
int rx = 0, ry = 0;
if (ItemID == 0x3ED4)
rx = 1;
else if (ItemID == 0x3ED5)
rx = -1;
else if (ItemID == 0x3E84)
ry = 1;
else if (ItemID == 0x3E89)
ry = -1;
for (int i = 1; i <= 6; ++i)
{
int x = X + i * rx;
int y = Y + i * ry;
int z;
for (int j = -8; j <= 8; ++j)
{
z = from.Z + j;
if (map.CanFit(x, y, z, 16, false, false) && !SpellHelper.CheckMulti(new Point3D(x, y, z), map) &&
!Region.Find(new Point3D(x, y, z), map).IsPartOf<StrongholdRegion>())
{
if (i == 1 && j >= -2 && j <= 2)
return true;
from.Location = new Point3D(x, y, z);
return false;
}
}
z = map.GetAverageZ(x, y);
if (map.CanFit(x, y, z, 16, false, false) && !SpellHelper.CheckMulti(new Point3D(x, y, z), map) &&
!Region.Find(new Point3D(x, y, z), map).IsPartOf<StrongholdRegion>())
{
if (i == 1)
return true;
from.Location = new Point3D(x, y, z);
return false;
}
}
return true;
}
return false;
}
public bool CanClose() => Map != null && !Deleted && GetObjectsInRange(0).All(o => o == this);
public void Close()
{
if (!IsOpen || !CanClose() || Deleted)
return;
m_CloseTimer?.Stop();
m_CloseTimer = null;
ItemID = ItemID switch
{
0x3ED5 => 0x3EB1,
0x3E89 => 0x3E8A,
0x3ED4 => 0x3EB2,
0x3E84 => 0x3E85,
_ => ItemID
};
Boat?.Refresh();
}
public override void OnDoubleClickDead(Mobile from)
{
OnDoubleClick(from);
}
public override void OnDoubleClick(Mobile from)
{
if (Boat == null)
return;
if (from.InRange(GetWorldLocation(), 8))
{
if (Boat.Contains(from))
{
if (IsOpen)
Close();
else
Open();
}
else
{
if (!IsOpen)
{
if (!Locked)
{
Open();
}
else if (from.AccessLevel >= AccessLevel.GameMaster)
{
from.LocalOverheadMessage(MessageType.Regular, 0x00,
502502); // That is locked but your godly powers allow access
Open();
}
else
{
from.LocalOverheadMessage(MessageType.Regular, 0x00, 502503); // That is locked.
}
}
else if (!Locked)
{
from.Location = new Point3D(X, Y, Z + 3);
}
else if (from.AccessLevel >= AccessLevel.GameMaster)
{
from.LocalOverheadMessage(MessageType.Regular, 0x00,
502502); // That is locked but your godly powers allow access
from.Location = new Point3D(X, Y, Z + 3);
}
else
{
from.LocalOverheadMessage(MessageType.Regular, 0x00, 502503); // That is locked.
}
}
}
}
private class CloseTimer : Timer
{
private readonly Plank m_Plank;
public CloseTimer(Plank plank) : base(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(5.0))
{
m_Plank = plank;
Priority = TimerPriority.OneSecond;
}
protected override void OnTick()
{
m_Plank.Close();
}
}
}
}

View file

@ -0,0 +1,16 @@
using Server.Prompts;
namespace Server.Multis
{
public class RenameBoatPrompt : Prompt
{
private readonly BaseBoat m_Boat;
public RenameBoatPrompt(BaseBoat boat) => m_Boat = boat;
public override void OnResponse(Mobile from, string text)
{
m_Boat.EndRename(from, text);
}
}
}

View file

@ -0,0 +1,99 @@
namespace Server.Multis
{
public class SmallBoat : BaseBoat
{
[Constructible]
public SmallBoat()
{
}
public SmallBoat(Serial serial) : base(serial)
{
}
public override int NorthID => 0x0;
public override int EastID => 0x1;
public override int SouthID => 0x2;
public override int WestID => 0x3;
public override int HoldDistance => 4;
public override int TillerManDistance => -4;
public override Point2D StarboardOffset => new Point2D(2, 0);
public override Point2D PortOffset => new Point2D(-2, 0);
public override Point3D MarkOffset => new Point3D(0, 1, 3);
public override BaseDockedBoat DockedBoat => new SmallDockedBoat(this);
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
}
public class SmallBoatDeed : BaseBoatDeed
{
[Constructible]
public SmallBoatDeed() : base(0x0, Point3D.Zero)
{
}
public SmallBoatDeed(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1041205; // small ship deed
public override BaseBoat Boat => new SmallBoat();
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
}
public class SmallDockedBoat : BaseDockedBoat
{
public SmallDockedBoat(BaseBoat boat) : base(0x0, Point3D.Zero, boat)
{
}
public SmallDockedBoat(Serial serial) : base(serial)
{
}
public override BaseBoat Boat => new SmallBoat();
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
}
}

View file

@ -0,0 +1,99 @@
namespace Server.Multis
{
public class SmallDragonBoat : BaseBoat
{
[Constructible]
public SmallDragonBoat()
{
}
public SmallDragonBoat(Serial serial) : base(serial)
{
}
public override int NorthID => 0x4;
public override int EastID => 0x5;
public override int SouthID => 0x6;
public override int WestID => 0x7;
public override int HoldDistance => 4;
public override int TillerManDistance => -4;
public override Point2D StarboardOffset => new Point2D(2, 0);
public override Point2D PortOffset => new Point2D(-2, 0);
public override Point3D MarkOffset => new Point3D(0, 1, 3);
public override BaseDockedBoat DockedBoat => new SmallDockedDragonBoat(this);
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
}
public class SmallDragonBoatDeed : BaseBoatDeed
{
[Constructible]
public SmallDragonBoatDeed() : base(0x4, Point3D.Zero)
{
}
public SmallDragonBoatDeed(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1041206; // small dragon ship deed
public override BaseBoat Boat => new SmallDragonBoat();
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
}
public class SmallDockedDragonBoat : BaseDockedBoat
{
public SmallDockedDragonBoat(BaseBoat boat) : base(0x4, Point3D.Zero, boat)
{
}
public SmallDockedDragonBoat(Serial serial) : base(serial)
{
}
public override BaseBoat Boat => new SmallDragonBoat();
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
}
}

View file

@ -0,0 +1,176 @@
namespace Server.Misc
{
public class Strandedness
{
private static readonly Point2D[] m_Felucca =
{
new Point2D(2528, 3568), new Point2D(2376, 3400), new Point2D(2528, 3896),
new Point2D(2168, 3904), new Point2D(1136, 3416), new Point2D(1432, 3648),
new Point2D(1416, 4000), new Point2D(4512, 3936), new Point2D(4440, 3120),
new Point2D(4192, 3672), new Point2D(4720, 3472), new Point2D(3744, 2768),
new Point2D(3480, 2432), new Point2D(3560, 2136), new Point2D(3792, 2112),
new Point2D(2800, 2296), new Point2D(2736, 2016), new Point2D(4576, 1456),
new Point2D(4680, 1152), new Point2D(4304, 1104), new Point2D(4496, 984),
new Point2D(4248, 696), new Point2D(4040, 616), new Point2D(3896, 248),
new Point2D(4176, 384), new Point2D(3672, 1104), new Point2D(3520, 1152),
new Point2D(3720, 1360), new Point2D(2184, 2152), new Point2D(1952, 2088),
new Point2D(2056, 1936), new Point2D(1720, 1992), new Point2D(472, 2064),
new Point2D(656, 2096), new Point2D(3008, 3592), new Point2D(2784, 3472),
new Point2D(5456, 2400), new Point2D(5976, 2424), new Point2D(5328, 3112),
new Point2D(5792, 3152), new Point2D(2120, 3616), new Point2D(2136, 3128),
new Point2D(1632, 3528), new Point2D(1328, 3160), new Point2D(1072, 3136),
new Point2D(1128, 2976), new Point2D(960, 2576), new Point2D(752, 1832),
new Point2D(184, 1488), new Point2D(592, 1440), new Point2D(368, 1216),
new Point2D(232, 752), new Point2D(696, 744), new Point2D(304, 1000),
new Point2D(840, 376), new Point2D(1192, 624), new Point2D(1200, 192),
new Point2D(1512, 240), new Point2D(1336, 456), new Point2D(1536, 648),
new Point2D(1104, 952), new Point2D(1864, 264), new Point2D(2136, 200),
new Point2D(2160, 528), new Point2D(1904, 512), new Point2D(2240, 784),
new Point2D(2536, 776), new Point2D(2488, 216), new Point2D(2336, 72),
new Point2D(2648, 288), new Point2D(2680, 576), new Point2D(2896, 88),
new Point2D(2840, 344), new Point2D(3136, 72), new Point2D(2968, 520),
new Point2D(3192, 328), new Point2D(3448, 208), new Point2D(3432, 608),
new Point2D(3184, 752), new Point2D(2800, 704), new Point2D(2768, 1016),
new Point2D(2448, 1232), new Point2D(2272, 920), new Point2D(2072, 1080),
new Point2D(2048, 1264), new Point2D(1808, 1528), new Point2D(1496, 1880),
new Point2D(1656, 2168), new Point2D(2096, 2320), new Point2D(1816, 2528),
new Point2D(1840, 2640), new Point2D(1928, 2952), new Point2D(2120, 2712)
};
private static readonly Point2D[] m_Trammel = m_Felucca;
private static readonly Point2D[] m_Ilshenar =
{
new Point2D(1252, 1180), new Point2D(1562, 1090), new Point2D(1444, 1016),
new Point2D(1324, 968), new Point2D(1418, 806), new Point2D(1722, 874),
new Point2D(1456, 684), new Point2D(1036, 866), new Point2D(612, 476),
new Point2D(1476, 372), new Point2D(762, 472), new Point2D(812, 1162),
new Point2D(1422, 1144), new Point2D(1254, 1066), new Point2D(1598, 870),
new Point2D(1358, 866), new Point2D(510, 302), new Point2D(510, 392)
};
private static readonly Point2D[] m_Tokuno =
{
// Makoto-Jima
new Point2D(837, 1351), new Point2D(941, 1241), new Point2D(959, 1185),
new Point2D(923, 1091), new Point2D(904, 983), new Point2D(845, 944),
new Point2D(829, 896), new Point2D(794, 852), new Point2D(766, 821),
new Point2D(695, 814), new Point2D(576, 835), new Point2D(518, 840),
new Point2D(519, 902), new Point2D(502, 950), new Point2D(503, 1045),
new Point2D(547, 1131), new Point2D(518, 1204), new Point2D(506, 1243),
new Point2D(526, 1271), new Point2D(562, 1295), new Point2D(616, 1335),
new Point2D(789, 1347), new Point2D(712, 1359),
// Homare-Jima
new Point2D(202, 498), new Point2D(116, 600), new Point2D(107, 699),
new Point2D(162, 799), new Point2D(158, 889), new Point2D(169, 989),
new Point2D(194, 1101), new Point2D(250, 1163), new Point2D(295, 1176),
new Point2D(280, 1194), new Point2D(286, 1102), new Point2D(250, 1000),
new Point2D(260, 906), new Point2D(360, 838), new Point2D(389, 763),
new Point2D(415, 662), new Point2D(500, 597), new Point2D(570, 572),
new Point2D(631, 577), new Point2D(692, 500), new Point2D(723, 445),
new Point2D(672, 379), new Point2D(626, 332), new Point2D(494, 291),
new Point2D(371, 336), new Point2D(324, 334), new Point2D(270, 362),
// Isamu-Jima
new Point2D(1240, 1076), new Point2D(1189, 1115), new Point2D(1046, 1039),
new Point2D(1025, 885), new Point2D(907, 809), new Point2D(840, 506),
new Point2D(799, 396), new Point2D(720, 258), new Point2D(744, 158),
new Point2D(904, 37), new Point2D(974, 91), new Point2D(1020, 187),
new Point2D(1035, 288), new Point2D(1104, 395), new Point2D(1215, 462),
new Point2D(1275, 488), new Point2D(1348, 611), new Point2D(1363, 739),
new Point2D(1364, 765), new Point2D(1364, 876), new Point2D(1300, 936),
new Point2D(1240, 1003)
};
public static void Initialize()
{
EventSink.Login += EventSink_Login;
}
private static bool IsStranded(Mobile from)
{
Map map = from.Map;
if (map == null)
return false;
object surface = map.GetTopSurface(from.Location);
if (surface is LandTile tile)
{
int id = tile.ID;
return (id >= 168 && id <= 171)
|| (id >= 310 && id <= 311);
}
if (surface is StaticTile staticTile)
{
int id = staticTile.ID;
return id >= 0x1796 && id <= 0x17B2;
}
return false;
}
public static void EventSink_Login(Mobile from)
{
if (!IsStranded(from))
return;
Map map = from.Map;
Point2D[] list;
if (map == Map.Felucca)
list = m_Felucca;
else if (map == Map.Trammel)
list = m_Trammel;
else if (map == Map.Ilshenar)
list = m_Ilshenar;
else if (map == Map.Tokuno)
list = m_Tokuno;
else
return;
Point2D p = Point2D.Zero;
double pdist = double.MaxValue;
for (int i = 0; i < list.Length; ++i)
{
double dist = from.GetDistanceToSqrt(list[i]);
if (dist < pdist)
{
p = list[i];
pdist = dist;
}
}
int x = p.X, y = p.Y;
int z;
bool canFit;
z = map.GetAverageZ(x, y);
canFit = map.CanSpawnMobile(x, y, z);
for (int i = 1; !canFit && i <= 40; i += 2)
for (int xo = -1; !canFit && xo <= 1; ++xo)
for (int yo = -1; !canFit && yo <= 1; ++yo)
{
if (xo == 0 && yo == 0)
continue;
x = p.X + xo * i;
y = p.Y + yo * i;
z = map.GetAverageZ(x, y);
canFit = map.CanSpawnMobile(x, y, z);
}
if (canFit)
from.Location = new Point3D(x, y, z);
}
}
}

View file

@ -0,0 +1,115 @@
using Server.Multis;
using Server.Network;
namespace Server.Items
{
public class TillerMan : Item
{
private BaseBoat m_Boat;
public TillerMan(BaseBoat boat) : base(0x3E4E)
{
m_Boat = boat;
Movable = false;
}
public TillerMan(Serial serial) : base(serial)
{
}
public void SetFacing(Direction dir)
{
ItemID = dir switch
{
Direction.South => 0x3E4B,
Direction.North => 0x3E4E,
Direction.West => 0x3E50,
Direction.East => 0x3E55,
_ => ItemID
};
}
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
list.Add(m_Boat.Status);
}
public void Say(int number)
{
PublicOverheadMessage(MessageType.Regular, 0x3B2, number);
}
public void Say(int number, string args)
{
PublicOverheadMessage(MessageType.Regular, 0x3B2, number, args);
}
public override void AddNameProperty(ObjectPropertyList list)
{
if (m_Boat?.ShipName != null)
list.Add(1042884, m_Boat.ShipName); // the tiller man of the ~1_SHIP_NAME~
else
base.AddNameProperty(list);
}
public override void OnSingleClick(Mobile from)
{
if (m_Boat?.ShipName != null)
LabelTo(from, 1042884, m_Boat.ShipName); // the tiller man of the ~1_SHIP_NAME~
else
base.OnSingleClick(from);
}
public override void OnDoubleClick(Mobile from)
{
if (m_Boat?.Contains(from) == true)
m_Boat.BeginRename(from);
else
m_Boat?.BeginDryDock(from);
}
public override bool OnDragDrop(Mobile from, Item dropped)
{
if (dropped is MapItem item && m_Boat?.CanCommand(from) == true && m_Boat.Contains(from))
m_Boat.AssociateMap(item);
return false;
}
public override void OnAfterDelete()
{
m_Boat?.Delete();
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
writer.Write(m_Boat);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 0:
{
m_Boat = reader.ReadItem() as BaseBoat;
if (m_Boat == null)
Delete();
break;
}
}
}
}
}