Reorganizes Project (#41)

This commit is contained in:
Kamron Batman 2019-08-02 18:13:40 -07:00 committed by GitHub
parent 08bf44af9a
commit 3614a66aee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3499 changed files with 79 additions and 55 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,175 @@
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(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
writer.Write(MultiID);
writer.Write(Offset);
}
public override void Deserialize(GenericReader 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 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,194 @@
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(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(1); // version
writer.Write(MultiID);
writer.Write(Offset);
writer.Write(m_ShipName);
}
public override void Deserialize(GenericReader 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 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 BaseBoat m_Boat;
private 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,119 @@
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)
{
switch (dir)
{
case Direction.East:
ItemID = 0x3E65;
break;
case Direction.West:
ItemID = 0x3E93;
break;
case Direction.North:
ItemID = 0x3EAE;
break;
case Direction.South:
ItemID = 0x3EB9;
break;
}
}
public override bool OnDragDrop(Mobile from, Item item)
{
if (m_Boat == null || !m_Boat.Contains(from) || m_Boat.IsMoving)
return false;
return base.OnDragDrop(from, item);
}
public override bool OnDragDropInto(Mobile from, Item item, Point3D p)
{
if (m_Boat == null || !m_Boat.Contains(from) || m_Boat.IsMoving)
return false;
return base.OnDragDropInto(from, item, p);
}
public override bool CheckItemUse(Mobile from, Item item)
{
if (item != this && (m_Boat == null || !m_Boat.Contains(from) || m_Boat.IsMoving))
return false;
return base.CheckItemUse(from, item);
}
public override bool CheckLift(Mobile from, Item item, ref LRReason reject)
{
if (m_Boat == null || !m_Boat.Contains(from) || 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 == null || !m_Boat.Contains(from))
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(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
writer.Write(m_Boat);
}
public override void Deserialize(GenericReader 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(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(GenericWriter 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(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(GenericWriter 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(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(GenericWriter 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(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(GenericWriter 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(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(GenericWriter 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(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(GenericWriter 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(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(GenericWriter 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(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(GenericWriter 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(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(GenericWriter 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(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(GenericWriter 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(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(GenericWriter 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(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
}
}

View file

@ -0,0 +1,329 @@
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(GenericWriter 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(GenericReader 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)
switch (dir)
{
case Direction.North:
ItemID = Starboard ? 0x3ED4 : 0x3ED5;
break;
case Direction.East:
ItemID = Starboard ? 0x3E84 : 0x3E89;
break;
case Direction.South:
ItemID = Starboard ? 0x3ED5 : 0x3ED4;
break;
case Direction.West:
ItemID = Starboard ? 0x3E89 : 0x3E84;
break;
}
else
switch (dir)
{
case Direction.North:
ItemID = Starboard ? 0x3EB2 : 0x3EB1;
break;
case Direction.East:
ItemID = Starboard ? 0x3E85 : 0x3E8A;
break;
case Direction.South:
ItemID = Starboard ? 0x3EB1 : 0x3EB2;
break;
case Direction.West:
ItemID = Starboard ? 0x3E8A : 0x3E85;
break;
}
}
public void Open()
{
if (IsOpen || Deleted)
return;
m_CloseTimer?.Stop();
m_CloseTimer = new CloseTimer(this);
m_CloseTimer.Start();
switch (ItemID)
{
case 0x3EB1:
ItemID = 0x3ED5;
break;
case 0x3E8A:
ItemID = 0x3E89;
break;
case 0x3EB2:
ItemID = 0x3ED4;
break;
case 0x3E85:
ItemID = 0x3E84;
break;
}
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()
{
return Map != null && !Deleted && GetObjectsInRange(0).Cast<object>().All(o => o == this);
}
public void Close()
{
if (!IsOpen || !CanClose() || Deleted)
return;
m_CloseTimer?.Stop();
m_CloseTimer = null;
switch (ItemID)
{
case 0x3ED5:
ItemID = 0x3EB1;
break;
case 0x3E89:
ItemID = 0x3E8A;
break;
case 0x3ED4:
ItemID = 0x3EB2;
break;
case 0x3E84:
ItemID = 0x3E85;
break;
}
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 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,19 @@
using Server.Prompts;
namespace Server.Multis
{
public class RenameBoatPrompt : Prompt
{
private 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(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(GenericWriter 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(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(GenericWriter 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(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(GenericWriter 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(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(GenericWriter 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(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(GenericWriter 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(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
}
}

View file

@ -0,0 +1,178 @@
namespace Server.Misc
{
public class Strandedness
{
private static 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 Point2D[] m_Trammel = m_Felucca;
private static 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 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(LoginEventArgs e)
{
Mobile from = e.Mobile;
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 = false;
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,122 @@
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)
{
switch (dir)
{
case Direction.South:
ItemID = 0x3E4B;
break;
case Direction.North:
ItemID = 0x3E4E;
break;
case Direction.West:
ItemID = 0x3E50;
break;
case Direction.East:
ItemID = 0x3E55;
break;
}
}
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 != null && m_Boat.Contains(from))
m_Boat.BeginRename(from);
else
m_Boat?.BeginDryDock(from);
}
public override bool OnDragDrop(Mobile from, Item dropped)
{
if (dropped is MapItem item && m_Boat != null && m_Boat.CanCommand(from) && m_Boat.Contains(from))
m_Boat.AssociateMap(item);
return false;
}
public override void OnAfterDelete()
{
m_Boat?.Delete();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); //version
writer.Write(m_Boat);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 0:
{
m_Boat = reader.ReadItem() as BaseBoat;
if (m_Boat == null)
Delete();
break;
}
}
}
}
}

View file

@ -0,0 +1,47 @@
using Server.Items;
using Server.Mobiles;
namespace Server.Multis
{
public class BankerCamp : BaseCamp
{
[Constructible]
public BankerCamp() : base(0x1F6)
{
}
public BankerCamp(Serial serial) : base(serial)
{
}
public override void AddComponents()
{
BaseDoor west, east;
AddItem(west = new LightWoodGate(DoorFacing.WestCW), -4, 4, 7);
AddItem(east = new LightWoodGate(DoorFacing.EastCCW), -3, 4, 7);
west.Link = east;
east.Link = west;
AddItem(new Sign(SignType.Bank, SignFacing.West), -5, 5, -4);
AddMobile(new Banker(), 4, -4, 3, 7);
AddMobile(new Banker(), 5, 4, -2, 0);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,200 @@
using System;
using System.Collections.Generic;
using Server.Items;
using Server.Mobiles;
namespace Server.Multis
{
public abstract class BaseCamp : BaseMulti
{
private TimeSpan m_DecayDelay;
private DateTime m_DecayTime;
private Timer m_DecayTimer;
private List<Item> m_Items;
private List<Mobile> m_Mobiles;
public BaseCamp(int multiID) : base(multiID)
{
m_Items = new List<Item>();
m_Mobiles = new List<Mobile>();
m_DecayDelay = TimeSpan.FromMinutes(30.0);
RefreshDecay(true);
Timer.DelayCall(TimeSpan.Zero, CheckAddComponents);
}
public BaseCamp(Serial serial) : base(serial)
{
}
public virtual int EventRange => 10;
public virtual TimeSpan DecayDelay
{
get => m_DecayDelay;
set
{
m_DecayDelay = value;
RefreshDecay(true);
}
}
public override bool HandlesOnMovement => true;
public void CheckAddComponents()
{
if (Deleted)
return;
AddComponents();
}
public virtual void AddComponents()
{
}
public virtual void RefreshDecay(bool setDecayTime)
{
if (Deleted)
return;
m_DecayTimer?.Stop();
if (setDecayTime)
m_DecayTime = DateTime.UtcNow + DecayDelay;
m_DecayTimer = Timer.DelayCall(DecayDelay, Delete);
}
public virtual void AddItem(Item item, int xOffset, int yOffset, int zOffset)
{
m_Items.Add(item);
int zavg = Map.GetAverageZ(X + xOffset, Y + yOffset);
item.MoveToWorld(new Point3D(X + xOffset, Y + yOffset, zavg + zOffset), Map);
}
public virtual void AddMobile(Mobile m, int wanderRange, int xOffset, int yOffset, int zOffset)
{
m_Mobiles.Add(m);
int zavg = Map.GetAverageZ(X + xOffset, Y + yOffset);
Point3D loc = new Point3D(X + xOffset, Y + yOffset, zavg + zOffset);
if (m is BaseCreature bc)
{
bc.RangeHome = wanderRange;
bc.Home = loc;
}
if (m is BaseVendor)
m.Direction = Direction.South;
m.MoveToWorld(loc, Map);
}
public virtual void OnEnter(Mobile m)
{
RefreshDecay(true);
}
public virtual void OnExit(Mobile m)
{
RefreshDecay(true);
}
public override void OnMovement(Mobile m, Point3D oldLocation)
{
bool inOldRange = Utility.InRange(oldLocation, Location, EventRange);
bool inNewRange = Utility.InRange(m.Location, Location, EventRange);
if (inNewRange && !inOldRange)
OnEnter(m);
else if (inOldRange && !inNewRange)
OnExit(m);
}
public override void OnAfterDelete()
{
base.OnAfterDelete();
for (int i = 0; i < m_Items.Count; ++i)
m_Items[i].Delete();
for (int i = 0; i < m_Mobiles.Count; ++i)
{
BaseCreature bc = (BaseCreature)m_Mobiles[i];
if (bc.IsPrisoner == false)
m_Mobiles[i].Delete();
else if (m_Mobiles[i].CantWalk)
m_Mobiles[i].Delete();
}
m_Items.Clear();
m_Mobiles.Clear();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
writer.Write(m_Items, true);
writer.Write(m_Mobiles, true);
writer.WriteDeltaTime(m_DecayTime);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 0:
{
m_Items = reader.ReadStrongItemList();
m_Mobiles = reader.ReadStrongMobileList();
m_DecayTime = reader.ReadDeltaTime();
RefreshDecay(false);
break;
}
}
}
}
public class LockableBarrel : LockableContainer
{
[Constructible]
public LockableBarrel() : base(0xE77)
{
Weight = 1.0;
}
public LockableBarrel(Serial serial) : base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
if (Weight == 8.0)
Weight = 1.0;
}
}
}

View file

@ -0,0 +1,232 @@
using System;
using Server.Items;
using Server.Mobiles;
namespace Server.Multis
{
public class BrigandCamp : BaseCamp
{
private Mobile m_Prisoner;
[Constructible]
public BrigandCamp() : base(0x10EE) // dummy garbage at center
{
}
public BrigandCamp(Serial serial) : base(serial)
{
}
public virtual Mobile Brigands => new Brigand();
public virtual Mobile Executioners => new Executioner();
public override void AddComponents()
{
BaseCreature bc;
//BaseEscortable be;
Visible = false;
DecayDelay = TimeSpan.FromMinutes(5.0);
AddItem(new Static(0x10ee), 0, 0, 0);
AddItem(new Static(0xfac), 0, 7, 0);
switch (Utility.Random(3))
{
case 0:
{
AddItem(new Item(0xDE3), 0, 7, 0); // Campfire
AddItem(new Item(0x974), 0, 7, 1); // Cauldron
break;
}
case 1:
{
AddItem(new Item(0x1E95), 0, 7, 1); // Rabbit on a spit
break;
}
default:
{
AddItem(new Item(0x1E94), 0, 7, 1); // Chicken on a spit
break;
}
}
AddCampChests();
for (int i = 0; i < 4; i++) AddMobile(Brigands, 6, Utility.RandomMinMax(-7, 7), Utility.RandomMinMax(-7, 7), 0);
switch (Utility.Random(2))
{
case 0:
m_Prisoner = new Noble();
break;
default:
m_Prisoner = new SeekerOfAdventure();
break;
}
//be = (BaseEscortable)m_Prisoner;
//be.m_Captive = true;
bc = (BaseCreature)m_Prisoner;
bc.IsPrisoner = true;
bc.CantWalk = true;
m_Prisoner.YellHue = Utility.RandomList(0x57, 0x67, 0x77, 0x87, 0x117);
AddMobile(m_Prisoner, 2, Utility.RandomMinMax(-2, 2), Utility.RandomMinMax(-2, 2), 0);
}
private void AddCampChests()
{
LockableContainer chest = null;
switch (Utility.Random(3))
{
case 0:
chest = new MetalChest();
break;
case 1:
chest = new MetalGoldenChest();
break;
default:
chest = new WoodenChest();
break;
}
chest.LiftOverride = true;
TreasureMapChest.Fill(chest, 1);
AddItem(chest, -2, -2, 0);
LockableContainer crates = null;
switch (Utility.Random(4))
{
case 0:
crates = new SmallCrate();
break;
case 1:
crates = new MediumCrate();
break;
case 2:
crates = new LargeCrate();
break;
default:
crates = new LockableBarrel();
break;
}
crates.TrapType = TrapType.ExplosionTrap;
crates.TrapPower = Utility.RandomMinMax(30, 40);
crates.TrapLevel = 2;
crates.RequiredSkill = 76;
crates.LockLevel = 66;
crates.MaxLockLevel = 116;
crates.Locked = true;
crates.DropItem(new Gold(Utility.RandomMinMax(100, 400)));
crates.DropItem(new Arrow(10));
crates.DropItem(new Bolt(10));
crates.LiftOverride = true;
if (Utility.RandomDouble() < 0.8)
switch (Utility.Random(4))
{
case 0:
crates.DropItem(new LesserCurePotion());
break;
case 1:
crates.DropItem(new LesserExplosionPotion());
break;
case 2:
crates.DropItem(new LesserHealPotion());
break;
default:
crates.DropItem(new LesserPoisonPotion());
break;
}
AddItem(crates, 2, 2, 0);
}
// Don't refresh decay timer
public override void OnEnter(Mobile m)
{
if (m.Player && m_Prisoner != null && m_Prisoner.CantWalk)
{
int number;
switch (Utility.Random(8))
{
case 0:
number = 502261;
break; // HELP!
case 1:
number = 502262;
break; // Help me!
case 2:
number = 502263;
break; // Canst thou aid me?!
case 3:
number = 502264;
break; // Help a poor prisoner!
case 4:
number = 502265;
break; // Help! Please!
case 5:
number = 502266;
break; // Aaah! Help me!
case 6:
number = 502267;
break; // Go and get some help!
default:
number = 502268;
break; // Quickly, I beg thee! Unlock my chains! If thou dost look at me close thou canst see them.
}
m_Prisoner.Yell(number);
}
}
// Don't refresh decay timer
public override void OnExit(Mobile m)
{
}
public override void AddItem(Item item, int xOffset, int yOffset, int zOffset)
{
if (item != null)
item.Movable = false;
base.AddItem(item, xOffset, yOffset, zOffset);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
writer.Write(m_Prisoner);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 0:
{
m_Prisoner = reader.ReadMobile();
break;
}
}
}
}
}

View file

@ -0,0 +1,47 @@
using Server.Items;
using Server.Mobiles;
namespace Server.Multis
{
public class HealerCamp : BaseCamp
{
[Constructible]
public HealerCamp() : base(0x1F4)
{
}
public HealerCamp(Serial serial) : base(serial)
{
}
public override void AddComponents()
{
BaseDoor west, east;
AddItem(west = new LightWoodGate(DoorFacing.WestCW), -4, 4, 7);
AddItem(east = new LightWoodGate(DoorFacing.EastCCW), -3, 4, 7);
west.Link = east;
east.Link = west;
AddItem(new Sign(SignType.Healer, SignFacing.West), -5, 5, -4);
AddMobile(new Healer(), 4, -4, 3, 7);
AddMobile(new Healer(), 5, 4, -2, 0);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,232 @@
using System;
using Server.Items;
using Server.Mobiles;
namespace Server.Multis
{
public class LizardmenCamp : BaseCamp
{
private Mobile m_Prisoner;
[Constructible]
public LizardmenCamp() : base(0x10EE) // dummy garbage at center
{
}
public LizardmenCamp(Serial serial) : base(serial)
{
}
public virtual Mobile Lizardmen => new Lizardman();
public override void AddComponents()
{
BaseCreature bc;
//BaseEscortable be;
Visible = false;
DecayDelay = TimeSpan.FromMinutes(5.0);
AddItem(new Static(0x10ee), 0, 0, 0);
AddItem(new Static(0xfac), 0, 7, 0);
switch (Utility.Random(3))
{
case 0:
{
AddItem(new Item(0xDE3), 0, 7, 0); // Campfire
AddItem(new Item(0x974), 0, 7, 1); // Cauldron
break;
}
case 1:
{
AddItem(new Item(0x1E95), 0, 7, 1); // Rabbit on a spit
break;
}
default:
{
AddItem(new Item(0x1E94), 0, 7, 1); // Chicken on a spit
break;
}
}
AddItem(new Item(0x41F), 4, 4, 0); // Gruesome Standart South
AddCampChests();
for (int i = 0; i < 4; i++) AddMobile(Lizardmen, 6, Utility.RandomMinMax(-7, 7), Utility.RandomMinMax(-7, 7), 0);
switch (Utility.Random(2))
{
case 0:
m_Prisoner = new Noble();
break;
default:
m_Prisoner = new SeekerOfAdventure();
break;
}
//be = (BaseEscortable)m_Prisoner;
//be.m_Captive = true;
bc = (BaseCreature)m_Prisoner;
bc.IsPrisoner = true;
bc.CantWalk = true;
m_Prisoner.YellHue = Utility.RandomList(0x57, 0x67, 0x77, 0x87, 0x117);
AddMobile(m_Prisoner, 2, Utility.RandomMinMax(-2, 2), Utility.RandomMinMax(-2, 2), 0);
}
private void AddCampChests()
{
LockableContainer chest = null;
switch (Utility.Random(3))
{
case 0:
chest = new MetalChest();
break;
case 1:
chest = new MetalGoldenChest();
break;
default:
chest = new WoodenChest();
break;
}
chest.LiftOverride = true;
TreasureMapChest.Fill(chest, 1);
AddItem(chest, 2, -2, 0);
LockableContainer crates = null;
switch (Utility.Random(4))
{
case 0:
crates = new SmallCrate();
break;
case 1:
crates = new MediumCrate();
break;
case 2:
crates = new LargeCrate();
break;
default:
crates = new LockableBarrel();
break;
}
crates.TrapType = TrapType.ExplosionTrap;
crates.TrapPower = Utility.RandomMinMax(30, 40);
crates.TrapLevel = 2;
crates.RequiredSkill = 76;
crates.LockLevel = 66;
crates.MaxLockLevel = 116;
crates.Locked = true;
crates.DropItem(new Gold(Utility.RandomMinMax(100, 400)));
crates.DropItem(new Arrow(10));
crates.DropItem(new Bolt(10));
crates.LiftOverride = true;
if (Utility.RandomDouble() < 0.8)
switch (Utility.Random(4))
{
case 0:
crates.DropItem(new LesserCurePotion());
break;
case 1:
crates.DropItem(new LesserExplosionPotion());
break;
case 2:
crates.DropItem(new LesserHealPotion());
break;
default:
crates.DropItem(new LesserPoisonPotion());
break;
}
AddItem(crates, -2, 2, 0);
}
// Don't refresh decay timer
public override void OnEnter(Mobile m)
{
if (m.Player && m_Prisoner != null && m_Prisoner.CantWalk)
{
int number;
switch (Utility.Random(8))
{
case 0:
number = 502261;
break; // HELP!
case 1:
number = 502262;
break; // Help me!
case 2:
number = 502263;
break; // Canst thou aid me?!
case 3:
number = 502264;
break; // Help a poor prisoner!
case 4:
number = 502265;
break; // Help! Please!
case 5:
number = 502266;
break; // Aaah! Help me!
case 6:
number = 502267;
break; // Go and get some help!
default:
number = 502268;
break; // Quickly, I beg thee! Unlock my chains! If thou dost look at me close thou canst see them.
}
m_Prisoner.Yell(number);
}
}
// Don't refresh decay timer
public override void OnExit(Mobile m)
{
}
public override void AddItem(Item item, int xOffset, int yOffset, int zOffset)
{
if (item != null)
item.Movable = false;
base.AddItem(item, xOffset, yOffset, zOffset);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
writer.Write(m_Prisoner);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 0:
{
m_Prisoner = reader.ReadMobile();
break;
}
}
}
}
}

View file

@ -0,0 +1,47 @@
using Server.Items;
using Server.Mobiles;
namespace Server.Multis
{
public class MageCamp : BaseCamp
{
[Constructible]
public MageCamp() : base(0x1F5)
{
}
public MageCamp(Serial serial) : base(serial)
{
}
public override void AddComponents()
{
BaseDoor west, east;
AddItem(west = new LightWoodGate(DoorFacing.WestCW), -4, 4, 7);
AddItem(east = new LightWoodGate(DoorFacing.EastCCW), -3, 4, 7);
west.Link = east;
east.Link = west;
AddItem(new Sign(SignType.Mage, SignFacing.West), -5, 5, -4);
AddMobile(new Mage(), 4, -4, 3, 7);
AddMobile(new Mage(), 5, 4, -2, 0);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,239 @@
using System;
using Server.Items;
using Server.Mobiles;
namespace Server.Multis
{
public class OrcCamp : BaseCamp
{
private Mobile m_Prisoner;
[Constructible]
public OrcCamp() : base(0x10EE) // dummy garbage at center
{
}
public OrcCamp(Serial serial) : base(serial)
{
}
public virtual Mobile Orcs => new Orc();
public override void AddComponents()
{
BaseCreature bc;
//BaseEscortable be;
Visible = false;
DecayDelay = TimeSpan.FromMinutes(5.0);
AddItem(new Static(0x10ee), 0, 0, 0);
AddItem(new Static(0xfac), 0, 7, 0);
switch (Utility.Random(3))
{
case 0:
{
AddItem(new Item(0xDE3), 0, 7, 0); // Campfire
AddItem(new Item(0x974), 0, 7, 1); // Cauldron
break;
}
case 1:
{
AddItem(new Item(0x1E95), 0, 7, 1); // Rabbit on a spit
break;
}
default:
{
AddItem(new Item(0x1E94), 0, 7, 1); // Chicken on a spit
break;
}
}
AddItem(new Item(0x428), -5, -4, 0); // Gruesome Standart West
AddCampChests();
for (int i = 0; i < 3; i++) AddMobile(Orcs, 6, Utility.RandomMinMax(-7, 7), Utility.RandomMinMax(-7, 7), 0);
AddMobile(new OrcCaptain(), 2, Utility.RandomMinMax(-7, 7), Utility.RandomMinMax(-7, 7), 0);
switch (Utility.Random(2))
{
case 0:
m_Prisoner = new Noble();
break;
default:
m_Prisoner = new SeekerOfAdventure();
break;
}
//be = (BaseEscortable)m_Prisoner;
//be.m_Captive = true;
bc = (BaseCreature)m_Prisoner;
bc.IsPrisoner = true;
bc.CantWalk = true;
m_Prisoner.YellHue = Utility.RandomList(0x57, 0x67, 0x77, 0x87, 0x117);
AddMobile(m_Prisoner, 2, Utility.RandomMinMax(-2, 2), Utility.RandomMinMax(-2, 2), 0);
}
private void AddCampChests()
{
LockableContainer chest = null;
switch (Utility.Random(3))
{
case 0:
chest = new MetalChest();
break;
case 1:
chest = new MetalGoldenChest();
break;
default:
chest = new WoodenChest();
break;
}
chest.LiftOverride = true;
TreasureMapChest.Fill(chest, 1);
AddItem(chest, -2, 2, 0);
LockableContainer crates = null;
switch (Utility.Random(4))
{
case 0:
crates = new SmallCrate();
break;
case 1:
crates = new MediumCrate();
break;
case 2:
crates = new LargeCrate();
break;
default:
crates = new LockableBarrel();
break;
}
crates.TrapType = TrapType.ExplosionTrap;
crates.TrapPower = Utility.RandomMinMax(30, 40);
crates.TrapLevel = 2;
crates.RequiredSkill = 76;
crates.LockLevel = 66;
crates.MaxLockLevel = 116;
crates.Locked = true;
crates.DropItem(new Gold(Utility.RandomMinMax(100, 400)));
crates.DropItem(new Arrow(10));
crates.DropItem(new Bolt(10));
crates.LiftOverride = true;
if (Utility.RandomDouble() < 0.8)
switch (Utility.Random(4))
{
case 0:
crates.DropItem(new LesserCurePotion());
break;
case 1:
crates.DropItem(new LesserExplosionPotion());
break;
case 2:
crates.DropItem(new LesserHealPotion());
break;
default:
crates.DropItem(new LesserPoisonPotion());
break;
}
AddItem(crates, 2, -2, 0);
}
// Don't refresh decay timer
public override void OnEnter(Mobile m)
{
if (m.Player && m_Prisoner != null && m_Prisoner.CantWalk)
{
int number;
switch (Utility.Random(8))
{
case 0:
number = 502261;
break; // HELP!
case 1:
number = 502262;
break; // Help me!
case 2:
number = 502263;
break; // Canst thou aid me?!
case 3:
number = 502264;
break; // Help a poor prisoner!
case 4:
number = 502265;
break; // Help! Please!
case 5:
number = 502266;
break; // Aaah! Help me!
case 6:
number = 502267;
break; // Go and get some help!
default:
number = 502268;
break; // Quickly, I beg thee! Unlock my chains! If thou dost look at me close thou canst see them.
}
m_Prisoner.Yell(number);
}
}
// Don't refresh decay timer
public override void OnExit(Mobile m)
{
}
public override void AddItem(Item item, int xOffset, int yOffset, int zOffset)
{
if (item != null)
item.Movable = false;
base.AddItem(item, xOffset, yOffset, zOffset);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(1); // version
writer.Write(m_Prisoner);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 1:
{
m_Prisoner = reader.ReadMobile();
break;
}
case 0:
{
m_Prisoner = reader.ReadMobile();
reader.ReadItem();
break;
}
}
}
}
}

View file

@ -0,0 +1,238 @@
using System;
using Server.Items;
using Server.Mobiles;
namespace Server.Multis
{
public class RatCamp : BaseCamp
{
private Mobile m_Prisoner;
[Constructible]
public RatCamp() : base(0x10EE) // dummy garbage at center
{
}
public RatCamp(Serial serial) : base(serial)
{
}
public virtual Mobile Ratmen => new Ratman();
public override void AddComponents()
{
BaseCreature bc;
//BaseEscortable be;
Visible = false;
DecayDelay = TimeSpan.FromMinutes(5.0);
AddItem(new Static(0x10ee), 0, 0, 0);
AddItem(new Static(0xfac), 0, 6, 0);
switch (Utility.Random(3))
{
case 0:
{
AddItem(new Item(0xDE3), 0, 6, 0); // Campfire
AddItem(new Item(0x974), 0, 6, 1); // Cauldron
break;
}
case 1:
{
AddItem(new Item(0x1E95), 0, 6, 1); // Rabbit on a spit
break;
}
default:
{
AddItem(new Item(0x1E94), 0, 6, 1); // Chicken on a spit
break;
}
}
AddItem(new Item(0x41F), 5, 5, 0); // Gruesome Standart South
AddCampChests();
for (int i = 0; i < 4; i++) AddMobile(Ratmen, 6, Utility.RandomMinMax(-7, 7), Utility.RandomMinMax(-7, 7), 0);
switch (Utility.Random(2))
{
case 0:
m_Prisoner = new Noble();
break;
default:
m_Prisoner = new SeekerOfAdventure();
break;
}
//be = (BaseEscortable)m_Prisoner;
//be.m_Captive = true;
bc = (BaseCreature)m_Prisoner;
bc.IsPrisoner = true;
bc.CantWalk = true;
m_Prisoner.YellHue = Utility.RandomList(0x57, 0x67, 0x77, 0x87, 0x117);
AddMobile(m_Prisoner, 2, Utility.RandomMinMax(-2, 2), Utility.RandomMinMax(-2, 2), 0);
}
private void AddCampChests()
{
LockableContainer chest = null;
switch (Utility.Random(3))
{
case 0:
chest = new MetalChest();
break;
case 1:
chest = new MetalGoldenChest();
break;
default:
chest = new WoodenChest();
break;
}
chest.LiftOverride = true;
TreasureMapChest.Fill(chest, 1);
AddItem(chest, -2, -2, 0);
LockableContainer crates = null;
switch (Utility.Random(4))
{
case 0:
crates = new SmallCrate();
break;
case 1:
crates = new MediumCrate();
break;
case 2:
crates = new LargeCrate();
break;
default:
crates = new LockableBarrel();
break;
}
crates.TrapType = TrapType.ExplosionTrap;
crates.TrapPower = Utility.RandomMinMax(30, 40);
crates.TrapLevel = 2;
crates.RequiredSkill = 76;
crates.LockLevel = 66;
crates.MaxLockLevel = 116;
crates.Locked = true;
crates.DropItem(new Gold(Utility.RandomMinMax(100, 400)));
crates.DropItem(new Arrow(10));
crates.DropItem(new Bolt(10));
crates.LiftOverride = true;
if (Utility.RandomDouble() < 0.8)
switch (Utility.Random(4))
{
case 0:
crates.DropItem(new LesserCurePotion());
break;
case 1:
crates.DropItem(new LesserExplosionPotion());
break;
case 2:
crates.DropItem(new LesserHealPotion());
break;
default:
crates.DropItem(new LesserPoisonPotion());
break;
}
AddItem(crates, 2, 2, 0);
}
// Don't refresh decay timer
public override void OnEnter(Mobile m)
{
if (m.Player && m_Prisoner != null && m_Prisoner.CantWalk)
{
int number;
switch (Utility.Random(8))
{
case 0:
number = 502261;
break; // HELP!
case 1:
number = 502262;
break; // Help me!
case 2:
number = 502263;
break; // Canst thou aid me?!
case 3:
number = 502264;
break; // Help a poor prisoner!
case 4:
number = 502265;
break; // Help! Please!
case 5:
number = 502266;
break; // Aaah! Help me!
case 6:
number = 502267;
break; // Go and get some help!
default:
number = 502268;
break; // Quickly, I beg thee! Unlock my chains! If thou dost look at me close thou canst see them.
}
m_Prisoner.Yell(number);
}
}
// Don't refresh decay timer
public override void OnExit(Mobile m)
{
}
public override void AddItem(Item item, int xOffset, int yOffset, int zOffset)
{
if (item != null)
item.Movable = false;
base.AddItem(item, xOffset, yOffset, zOffset);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(1); // version
writer.Write(m_Prisoner);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 1:
{
m_Prisoner = reader.ReadMobile();
break;
}
case 0:
{
m_Prisoner = reader.ReadMobile();
reader.ReadItem();
break;
}
}
}
}
}

View file

@ -0,0 +1,227 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace Server.Multis
{
public class ComponentVerification
{
private int[] m_ItemTable;
private int[] m_MultiTable;
public ComponentVerification()
{
m_ItemTable = CreateTable(TileData.MaxItemValue);
m_MultiTable = CreateTable(0x4000);
LoadItems("Data/Components/walls.txt", "South1", "South2", "South3", "Corner", "East1", "East2", "East3", "Post",
"WindowS", "AltWindowS", "WindowE", "AltWindowE", "SecondAltWindowS", "SecondAltWindowE");
LoadItems("Data/Components/teleprts.txt", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11",
"F12", "F13", "F14", "F15", "F16");
LoadItems("Data/Components/stairs.txt", "Block", "North", "East", "South", "West", "Squared1", "Squared2",
"Rounded1", "Rounded2");
LoadItems("Data/Components/roof.txt", "North", "East", "South", "West", "NSCrosspiece", "EWCrosspiece", "NDent",
"EDent", "SDent", "WDent", "NTPiece", "ETPiece", "STPiece", "WTPiece", "XPiece", "Extra Piece");
LoadItems("Data/Components/floors.txt", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11",
"F12", "F13", "F14", "F15", "F16");
LoadItems("Data/Components/misc.txt", "Piece1", "Piece2", "Piece3", "Piece4", "Piece5", "Piece6", "Piece7",
"Piece8");
LoadItems("Data/Components/doors.txt", "Piece1", "Piece2", "Piece3", "Piece4", "Piece5", "Piece6", "Piece7",
"Piece8");
LoadMultis("Data/Components/stairs.txt", "MultiNorth", "MultiEast", "MultiSouth", "MultiWest");
}
public bool IsItemValid(int itemID)
{
return itemID > 0 && itemID < m_ItemTable.Length && CheckValidity(m_ItemTable[itemID]);
}
public bool IsMultiValid(int multiID)
{
return multiID > 0 && multiID < m_MultiTable.Length && CheckValidity(m_MultiTable[multiID]);
}
public bool CheckValidity(int val)
{
return val != -1 && (val == 0 || ((int)ExpansionInfo.CoreExpansion.CustomHousingFlag & val) != 0);
}
private int[] CreateTable(int length)
{
int[] table = new int[length];
for (int i = 0; i < table.Length; ++i)
table[i] = -1;
return table;
}
private void LoadItems(string path, params string[] itemColumns)
{
LoadSpreadsheet(m_ItemTable, path, itemColumns);
}
private void LoadMultis(string path, params string[] multiColumns)
{
LoadSpreadsheet(m_MultiTable, path, multiColumns);
}
private void LoadSpreadsheet(int[] table, string path, params string[] tileColumns)
{
Spreadsheet ss = new Spreadsheet(path);
int[] tileCIDs = new int[tileColumns.Length];
for (int i = 0; i < tileColumns.Length; ++i)
tileCIDs[i] = ss.GetColumnID(tileColumns[i]);
int featureCID = ss.GetColumnID("FeatureMask");
for (int i = 0; i < ss.Records.Length; ++i)
{
DataRecord record = ss.Records[i];
int fid = record.GetInt32(featureCID);
for (int j = 0; j < tileCIDs.Length; ++j)
{
int itemID = record.GetInt32(tileCIDs[j]);
if (itemID <= 0 || itemID >= table.Length)
continue;
table[itemID] = fid;
}
}
}
}
public class Spreadsheet
{
private ColumnInfo[] m_Columns;
public Spreadsheet(string path)
{
using (StreamReader ip = new StreamReader(path))
{
string[] types = ReadLine(ip);
string[] names = ReadLine(ip);
m_Columns = new ColumnInfo[types.Length];
for (int i = 0; i < m_Columns.Length; ++i)
m_Columns[i] = new ColumnInfo(i, types[i], names[i]);
List<DataRecord> records = new List<DataRecord>();
string[] values;
while ((values = ReadLine(ip)) != null)
{
object[] data = new object[m_Columns.Length];
for (int i = 0; i < m_Columns.Length; ++i)
{
ColumnInfo ci = m_Columns[i];
switch (ci.m_Type)
{
case "int":
{
data[i] = Utility.ToInt32(values[ci.m_DataIndex]);
break;
}
case "string":
{
data[i] = values[ci.m_DataIndex];
break;
}
}
}
records.Add(new DataRecord(this, data));
}
Records = records.ToArray();
}
}
public DataRecord[] Records{ get; }
public int GetColumnID(string name)
{
for (int i = 0; i < m_Columns.Length; ++i)
if (m_Columns[i].m_Name == name)
return i;
return -1;
}
private string[] ReadLine(StreamReader ip)
{
string line;
while ((line = ip.ReadLine()) != null)
{
if (line.Length > 0)
return line.Split('\t');
}
return null;
}
private class ColumnInfo
{
public int m_DataIndex;
public string m_Name;
public string m_Type;
public ColumnInfo(int dataIndex, string type, string name)
{
m_DataIndex = dataIndex;
m_Type = type;
m_Name = name;
}
}
}
public class DataRecord
{
public DataRecord(Spreadsheet ss, object[] data)
{
Spreadsheet = ss;
Data = data;
}
public Spreadsheet Spreadsheet{ get; }
public object[] Data{ get; }
public object this[string name] => this[Spreadsheet.GetColumnID(name)];
public object this[int id] => id < 0 ? null : Data[id];
public int GetInt32(string name)
{
return GetInt32(this[name]);
}
public int GetInt32(int id)
{
return GetInt32(this[id]);
}
public int GetInt32(object obj)
{
return Convert.ToInt32(obj);
}
public string GetString(string name)
{
return this[name] as string;
}
}
}

View file

@ -0,0 +1,879 @@
using System.Collections.Generic;
using Server.Regions;
using Server.Targeting;
namespace Server.Multis.Deeds
{
public class HousePlacementTarget : MultiTarget
{
private HouseDeed m_Deed;
public HousePlacementTarget(HouseDeed 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 reg = Region.Find(new Point3D(p), from.Map);
if (from.AccessLevel >= AccessLevel.GameMaster || reg.AllowHousing(from, p))
m_Deed.OnPlacement(from, p);
else if (reg.IsPartOf<TempNoHousingRegion>())
from.SendLocalizedMessage(
501270); // Lord British has decreed a 'no build' period, thus you cannot build this house at this time.
else if (reg.IsPartOf<TreasureRegion>() || reg.IsPartOf<HouseRegion>())
from.SendLocalizedMessage(
1043287); // The house could not be created here. Either something is blocking the house, or the house would not be on valid terrain.
else if (reg.IsPartOf<HouseRaffleRegion>())
from.SendLocalizedMessage(1150493); // You must have a deed for this plot of land in order to build here.
else
from.SendLocalizedMessage(501265); // Housing can not be created in this area.
}
}
}
public abstract class HouseDeed : Item
{
public HouseDeed(int id, Point3D offset) : base(0x14F0)
{
Weight = 1.0;
LootType = LootType.Newbied;
MultiID = id;
Offset = offset;
}
public HouseDeed(Serial serial) : base(serial)
{
}
[CommandProperty(AccessLevel.GameMaster)]
public int MultiID{ get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public Point3D Offset{ get; set; }
public abstract Rectangle2D[] Area{ get; }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(1); // version
writer.Write(Offset);
writer.Write(MultiID);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 1:
{
Offset = reader.ReadPoint3D();
goto case 0;
}
case 0:
{
MultiID = reader.ReadInt();
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 && BaseHouse.HasAccountHouse(from))
{
from.SendLocalizedMessage(501271); // You already own a house, you may not place another!
}
else
{
from.SendLocalizedMessage(1010433); /* House placement cancellation could result in a
* 60 second delay in the return of your deed.
*/
from.Target = new HousePlacementTarget(this);
}
}
public abstract BaseHouse GetHouse(Mobile owner);
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 if (from.AccessLevel < AccessLevel.GameMaster && BaseHouse.HasAccountHouse(from))
{
from.SendLocalizedMessage(501271); // You already own a house, you may not place another!
}
else
{
Point3D center = new Point3D(p.X - Offset.X, p.Y - Offset.Y, p.Z - Offset.Z);
HousePlacementResult res = HousePlacement.Check(from, MultiID, center, out List<IEntity> toMove);
switch (res)
{
case HousePlacementResult.Valid:
{
BaseHouse house = GetHouse(from);
house.MoveToWorld(center, from.Map);
Delete();
for (int i = 0; i < toMove.Count; ++i)
{
object o = toMove[i];
if (o is Mobile mobile)
mobile.Location = house.BanLocation;
else if (o is Item item)
item.Location = house.BanLocation;
}
break;
}
case HousePlacementResult.BadItem:
case HousePlacementResult.BadLand:
case HousePlacementResult.BadStatic:
case HousePlacementResult.BadRegionHidden:
{
from.SendLocalizedMessage(
1043287); // The house could not be created here. Either something is blocking the house, or the house would not be on valid terrain.
break;
}
case HousePlacementResult.NoSurface:
{
from.SendMessage(
"The house could not be created here. Part of the foundation would not be on any surface.");
break;
}
case HousePlacementResult.BadRegion:
{
from.SendLocalizedMessage(501265); // Housing cannot be created in this area.
break;
}
case HousePlacementResult.BadRegionTemp:
{
from.SendLocalizedMessage(
501270); //Lord British has decreed a 'no build' period, thus you cannot build this house at this time.
break;
}
case HousePlacementResult.BadRegionRaffle:
{
from.SendLocalizedMessage(
1150493); // You must have a deed for this plot of land in order to build here.
break;
}
}
}
}
}
public class StonePlasterHouseDeed : HouseDeed
{
[Constructible]
public StonePlasterHouseDeed() : base(0x64, new Point3D(0, 4, 0))
{
}
public StonePlasterHouseDeed(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1041211;
public override Rectangle2D[] Area => SmallOldHouse.AreaArray;
public override BaseHouse GetHouse(Mobile owner)
{
return new SmallOldHouse(owner, 0x64);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class FieldStoneHouseDeed : HouseDeed
{
[Constructible]
public FieldStoneHouseDeed() : base(0x66, new Point3D(0, 4, 0))
{
}
public FieldStoneHouseDeed(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1041212;
public override Rectangle2D[] Area => SmallOldHouse.AreaArray;
public override BaseHouse GetHouse(Mobile owner)
{
return new SmallOldHouse(owner, 0x66);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class SmallBrickHouseDeed : HouseDeed
{
[Constructible]
public SmallBrickHouseDeed() : base(0x68, new Point3D(0, 4, 0))
{
}
public SmallBrickHouseDeed(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1041213;
public override Rectangle2D[] Area => SmallOldHouse.AreaArray;
public override BaseHouse GetHouse(Mobile owner)
{
return new SmallOldHouse(owner, 0x68);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class WoodHouseDeed : HouseDeed
{
[Constructible]
public WoodHouseDeed() : base(0x6A, new Point3D(0, 4, 0))
{
}
public WoodHouseDeed(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1041214;
public override Rectangle2D[] Area => SmallOldHouse.AreaArray;
public override BaseHouse GetHouse(Mobile owner)
{
return new SmallOldHouse(owner, 0x6A);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class WoodPlasterHouseDeed : HouseDeed
{
[Constructible]
public WoodPlasterHouseDeed() : base(0x6C, new Point3D(0, 4, 0))
{
}
public WoodPlasterHouseDeed(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1041215;
public override Rectangle2D[] Area => SmallOldHouse.AreaArray;
public override BaseHouse GetHouse(Mobile owner)
{
return new SmallOldHouse(owner, 0x6C);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class ThatchedRoofCottageDeed : HouseDeed
{
[Constructible]
public ThatchedRoofCottageDeed() : base(0x6E, new Point3D(0, 4, 0))
{
}
public ThatchedRoofCottageDeed(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1041216;
public override Rectangle2D[] Area => SmallOldHouse.AreaArray;
public override BaseHouse GetHouse(Mobile owner)
{
return new SmallOldHouse(owner, 0x6E);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class BrickHouseDeed : HouseDeed
{
[Constructible]
public BrickHouseDeed() : base(0x74, new Point3D(-1, 7, 0))
{
}
public BrickHouseDeed(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1041219;
public override Rectangle2D[] Area => GuildHouse.AreaArray;
public override BaseHouse GetHouse(Mobile owner)
{
return new GuildHouse(owner);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class TwoStoryWoodPlasterHouseDeed : HouseDeed
{
[Constructible]
public TwoStoryWoodPlasterHouseDeed() : base(0x76, new Point3D(-3, 7, 0))
{
}
public TwoStoryWoodPlasterHouseDeed(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1041220;
public override Rectangle2D[] Area => TwoStoryHouse.AreaArray;
public override BaseHouse GetHouse(Mobile owner)
{
return new TwoStoryHouse(owner, 0x76);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class TwoStoryStonePlasterHouseDeed : HouseDeed
{
[Constructible]
public TwoStoryStonePlasterHouseDeed() : base(0x78, new Point3D(-3, 7, 0))
{
}
public TwoStoryStonePlasterHouseDeed(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1041221;
public override Rectangle2D[] Area => TwoStoryHouse.AreaArray;
public override BaseHouse GetHouse(Mobile owner)
{
return new TwoStoryHouse(owner, 0x78);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class TowerDeed : HouseDeed
{
[Constructible]
public TowerDeed() : base(0x7A, new Point3D(0, 7, 0))
{
}
public TowerDeed(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1041222;
public override Rectangle2D[] Area => Tower.AreaArray;
public override BaseHouse GetHouse(Mobile owner)
{
return new Tower(owner);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class KeepDeed : HouseDeed
{
[Constructible]
public KeepDeed() : base(0x7C, new Point3D(0, 11, 0))
{
}
public KeepDeed(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1041223;
public override Rectangle2D[] Area => Keep.AreaArray;
public override BaseHouse GetHouse(Mobile owner)
{
return new Keep(owner);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class CastleDeed : HouseDeed
{
[Constructible]
public CastleDeed() : base(0x7E, new Point3D(0, 16, 0))
{
}
public CastleDeed(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1041224;
public override Rectangle2D[] Area => Castle.AreaArray;
public override BaseHouse GetHouse(Mobile owner)
{
return new Castle(owner);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class LargePatioDeed : HouseDeed
{
[Constructible]
public LargePatioDeed() : base(0x8C, new Point3D(-4, 7, 0))
{
}
public LargePatioDeed(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1041231;
public override Rectangle2D[] Area => LargePatioHouse.AreaArray;
public override BaseHouse GetHouse(Mobile owner)
{
return new LargePatioHouse(owner);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class LargeMarbleDeed : HouseDeed
{
[Constructible]
public LargeMarbleDeed() : base(0x96, new Point3D(-4, 7, 0))
{
}
public LargeMarbleDeed(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1041236;
public override Rectangle2D[] Area => LargeMarbleHouse.AreaArray;
public override BaseHouse GetHouse(Mobile owner)
{
return new LargeMarbleHouse(owner);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class SmallTowerDeed : HouseDeed
{
[Constructible]
public SmallTowerDeed() : base(0x98, new Point3D(3, 4, 0))
{
}
public SmallTowerDeed(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1041237;
public override Rectangle2D[] Area => SmallTower.AreaArray;
public override BaseHouse GetHouse(Mobile owner)
{
return new SmallTower(owner);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class LogCabinDeed : HouseDeed
{
[Constructible]
public LogCabinDeed() : base(0x9A, new Point3D(1, 6, 0))
{
}
public LogCabinDeed(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1041238;
public override Rectangle2D[] Area => LogCabin.AreaArray;
public override BaseHouse GetHouse(Mobile owner)
{
return new LogCabin(owner);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class SandstonePatioDeed : HouseDeed
{
[Constructible]
public SandstonePatioDeed() : base(0x9C, new Point3D(-1, 4, 0))
{
}
public SandstonePatioDeed(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1041239;
public override Rectangle2D[] Area => SandStonePatio.AreaArray;
public override BaseHouse GetHouse(Mobile owner)
{
return new SandStonePatio(owner);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class VillaDeed : HouseDeed
{
[Constructible]
public VillaDeed() : base(0x9E, new Point3D(3, 6, 0))
{
}
public VillaDeed(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1041240;
public override Rectangle2D[] Area => TwoStoryVilla.AreaArray;
public override BaseHouse GetHouse(Mobile owner)
{
return new TwoStoryVilla(owner);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class StoneWorkshopDeed : HouseDeed
{
[Constructible]
public StoneWorkshopDeed() : base(0xA0, new Point3D(-1, 4, 0))
{
}
public StoneWorkshopDeed(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1041241;
public override Rectangle2D[] Area => SmallShop.AreaArray2;
public override BaseHouse GetHouse(Mobile owner)
{
return new SmallShop(owner, 0xA0);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class MarbleWorkshopDeed : HouseDeed
{
[Constructible]
public MarbleWorkshopDeed() : base(0xA2, new Point3D(-1, 4, 0))
{
}
public MarbleWorkshopDeed(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1041242;
public override Rectangle2D[] Area => SmallShop.AreaArray1;
public override BaseHouse GetHouse(Mobile owner)
{
return new SmallShop(owner, 0xA2);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
namespace Server.Multis
{
public class DynamicDecay
{
private static Dictionary<DecayLevel, DecayStageInfo> m_Stages;
static DynamicDecay()
{
m_Stages = new Dictionary<DecayLevel, DecayStageInfo>();
Register(DecayLevel.LikeNew, TimeSpan.FromHours(1), TimeSpan.FromHours(1));
Register(DecayLevel.Slightly, TimeSpan.FromDays(1), TimeSpan.FromDays(2));
Register(DecayLevel.Somewhat, TimeSpan.FromDays(1), TimeSpan.FromDays(2));
Register(DecayLevel.Fairly, TimeSpan.FromDays(1), TimeSpan.FromDays(2));
Register(DecayLevel.Greatly, TimeSpan.FromDays(1), TimeSpan.FromDays(2));
Register(DecayLevel.IDOC, TimeSpan.FromHours(12), TimeSpan.FromHours(24));
}
public static bool Enabled => Core.ML;
public static void Register(DecayLevel level, TimeSpan min, TimeSpan max)
{
m_Stages[level] = new DecayStageInfo(min, max);
}
public static bool Decays(DecayLevel level)
{
return m_Stages.ContainsKey(level);
}
public static TimeSpan GetRandomDuration(DecayLevel level)
{
if (!m_Stages.TryGetValue(level, out DecayStageInfo info))
return TimeSpan.Zero;
long min = info.MinDuration.Ticks;
long max = info.MaxDuration.Ticks;
return TimeSpan.FromTicks(min + (long)(Utility.RandomDouble() * (max - min)));
}
}
public class DecayStageInfo
{
public DecayStageInfo(TimeSpan min, TimeSpan max)
{
MinDuration = min;
MaxDuration = max;
}
public TimeSpan MinDuration{ get; }
public TimeSpan MaxDuration{ get; }
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,361 @@
using System.Collections.Generic;
using Server.Regions;
using Server.Spells;
namespace Server.Multis
{
public enum HousePlacementResult
{
Valid,
BadRegion,
BadLand,
BadStatic,
BadItem,
NoSurface,
BadRegionHidden,
BadRegionTemp,
InvalidCastleKeep,
BadRegionRaffle
}
public class HousePlacement
{
private const int YardSize = 5;
// Any land tile which matches one of these ID numbers is considered a road and cannot be placed over.
private static int[] m_RoadIDs =
{
0x0071, 0x0078,
0x00E8, 0x00EB,
0x07AE, 0x07B1,
0x3FF4, 0x3FF4,
0x3FF8, 0x3FFB,
0x0442, 0x0479, // Sand stones
0x0501, 0x0510, // Sand stones
0x0009, 0x0015, // Furrows
0x0150, 0x015C // Furrows
};
public static HousePlacementResult Check(Mobile from, int multiID, Point3D center, out List<IEntity> toMove)
{
// If this spot is considered valid, every item and mobile in this list will be moved under the house sign
toMove = new List<IEntity>();
Map map = from.Map;
if (map == null || map == Map.Internal)
return HousePlacementResult.BadLand; // A house cannot go here
if (from.AccessLevel >= AccessLevel.GameMaster)
return HousePlacementResult.Valid; // Staff can place anywhere
if (map == Map.Ilshenar || SpellHelper.IsFeluccaT2A(map, center))
return HousePlacementResult.BadRegion; // No houses in Ilshenar/T2A
if (map == Map.Malas && (multiID == 0x007C || multiID == 0x007E))
return HousePlacementResult.InvalidCastleKeep;
if (Region.Find(center, map).IsPartOf<NoHousingRegion>())
return HousePlacementResult.BadRegion;
// This holds data describing the internal structure of the house
MultiComponentList mcl = MultiData.GetComponents(multiID);
if (multiID >= 0x13EC && multiID < 0x1D00)
HouseFoundation.AddStairsTo(ref mcl); // this is a AOS house, add the stairs
// Location of the nortwest-most corner of the house
Point3D start = new Point3D(center.X + mcl.Min.X, center.Y + mcl.Min.Y, center.Z);
// These are storage lists. They hold items and mobiles found in the map for further processing
List<Item> items = new List<Item>();
List<Mobile> mobiles = new List<Mobile>();
// These are also storage lists. They hold location values indicating the yard and border locations.
List<Point2D> yard = new List<Point2D>(), borders = new List<Point2D>();
/* RULES:
*
* 1) All tiles which are around the -outside- of the foundation must not have anything impassable.
* 2) No impassable object or land tile may come in direct contact with any part of the house.
* 3) Five tiles from the front and back of the house must be completely clear of all house tiles.
* 4) The foundation must rest flatly on a surface. Any bumps around the foundation are not allowed.
* 5) No foundation tile may reside over terrain which is viewed as a road.
*/
for (int x = 0; x < mcl.Width; ++x)
for (int y = 0; y < mcl.Height; ++y)
{
int tileX = start.X + x;
int tileY = start.Y + y;
StaticTile[] addTiles = mcl.Tiles[x][y];
if (addTiles.Length == 0)
continue; // There are no tiles here, continue checking somewhere else
Point3D testPoint = new Point3D(tileX, tileY, center.Z);
Region reg = Region.Find(testPoint, map);
if (!reg.AllowHousing(from, testPoint)) // Cannot place houses in dungeons, towns, treasure map areas etc
{
if (reg.IsPartOf<TempNoHousingRegion>())
return HousePlacementResult.BadRegionTemp;
if (reg.IsPartOf<TreasureRegion>() || reg.IsPartOf<HouseRegion>())
return HousePlacementResult.BadRegionHidden;
if (reg.IsPartOf<HouseRaffleRegion>())
return HousePlacementResult.BadRegionRaffle;
return HousePlacementResult.BadRegion;
}
LandTile landTile = map.Tiles.GetLandTile(tileX, tileY);
int landID = landTile.ID & TileData.MaxLandValue;
StaticTile[] oldTiles = map.Tiles.GetStaticTiles(tileX, tileY, true);
Sector sector = map.GetSector(tileX, tileY);
items.Clear();
for (int i = 0; i < sector.Items.Count; ++i)
{
Item item = sector.Items[i];
if (item.Visible && item.X == tileX && item.Y == tileY)
items.Add(item);
}
mobiles.Clear();
for (int i = 0; i < sector.Mobiles.Count; ++i)
{
Mobile m = sector.Mobiles[i];
if (m.X == tileX && m.Y == tileY)
mobiles.Add(m);
}
int landStartZ = 0, landAvgZ = 0, landTopZ = 0;
map.GetAverageZ(tileX, tileY, ref landStartZ, ref landAvgZ, ref landTopZ);
bool hasFoundation = false;
for (int i = 0; i < addTiles.Length; ++i)
{
StaticTile addTile = addTiles[i];
if (addTile.ID == 0x1) // Nodraw
continue;
TileFlag addTileFlags = TileData.ItemTable[addTile.ID & TileData.MaxItemValue].Flags;
bool isFoundation = addTile.Z == 0 && (addTileFlags & TileFlag.Wall) != 0;
bool hasSurface = false;
if (isFoundation)
hasFoundation = true;
int addTileZ = center.Z + addTile.Z;
int addTileTop = addTileZ + addTile.Height;
if ((addTileFlags & TileFlag.Surface) != 0)
addTileTop += 16;
if (addTileTop > landStartZ && landAvgZ > addTileZ)
return HousePlacementResult.BadLand; // Broke rule #2
if (isFoundation &&
(TileData.LandTable[landTile.ID & TileData.MaxLandValue].Flags & TileFlag.Impassable) == 0 &&
landAvgZ == center.Z)
hasSurface = true;
for (int j = 0; j < oldTiles.Length; ++j)
{
StaticTile oldTile = oldTiles[j];
ItemData id = TileData.ItemTable[oldTile.ID & TileData.MaxItemValue];
if ((id.Impassable || id.Surface && (id.Flags & TileFlag.Background) == 0) &&
addTileTop > oldTile.Z && oldTile.Z + id.CalcHeight > addTileZ)
return HousePlacementResult.BadStatic; // Broke rule #2
/*else if ( isFoundation && !hasSurface && (id.Flags & TileFlag.Surface) != 0 && (oldTile.Z + id.CalcHeight) == center.Z )
hasSurface = true;*/
}
for (int j = 0; j < items.Count; ++j)
{
Item item = items[j];
ItemData id = item.ItemData;
if (addTileTop > item.Z && item.Z + id.CalcHeight > addTileZ)
{
if (item.Movable)
toMove.Add(item);
else if (id.Impassable || id.Surface && (id.Flags & TileFlag.Background) == 0)
return HousePlacementResult.BadItem; // Broke rule #2
}
/*else if ( isFoundation && !hasSurface && (id.Flags & TileFlag.Surface) != 0 && (item.Z + id.CalcHeight) == center.Z )
{
hasSurface = true;
}*/
}
if (isFoundation && !hasSurface)
return HousePlacementResult.NoSurface; // Broke rule #4
for (int j = 0; j < mobiles.Count; ++j)
{
Mobile m = mobiles[j];
if (addTileTop > m.Z && m.Z + 16 > addTileZ)
toMove.Add(m);
}
}
for (int i = 0; i < m_RoadIDs.Length; i += 2)
if (landID >= m_RoadIDs[i] && landID <= m_RoadIDs[i + 1])
return HousePlacementResult.BadLand; // Broke rule #5
if (hasFoundation)
{
for (int xOffset = -1; xOffset <= 1; ++xOffset)
for (int yOffset = -YardSize; yOffset <= YardSize; ++yOffset)
{
Point2D yardPoint = new Point2D(tileX + xOffset, tileY + yOffset);
if (!yard.Contains(yardPoint))
yard.Add(yardPoint);
}
for (int xOffset = -1; xOffset <= 1; ++xOffset)
for (int yOffset = -1; yOffset <= 1; ++yOffset)
{
if (xOffset == 0 && yOffset == 0)
continue;
// To ease this rule, we will not add to the border list if the tile here is under a base floor (z<=8)
int vx = x + xOffset;
int vy = y + yOffset;
if (vx >= 0 && vx < mcl.Width && vy >= 0 && vy < mcl.Height)
{
StaticTile[] breakTiles = mcl.Tiles[vx][vy];
bool shouldBreak = false;
for (int i = 0; !shouldBreak && i < breakTiles.Length; ++i)
{
StaticTile breakTile = breakTiles[i];
if (breakTile.Height == 0 && breakTile.Z <= 8 &&
TileData.ItemTable[breakTile.ID & TileData.MaxItemValue].Surface)
shouldBreak = true;
}
if (shouldBreak)
continue;
}
Point2D borderPoint = new Point2D(tileX + xOffset, tileY + yOffset);
if (!borders.Contains(borderPoint))
borders.Add(borderPoint);
}
}
}
for (int i = 0; i < borders.Count; ++i)
{
Point2D borderPoint = borders[i];
LandTile landTile = map.Tiles.GetLandTile(borderPoint.X, borderPoint.Y);
int landID = landTile.ID & TileData.MaxLandValue;
if ((TileData.LandTable[landID].Flags & TileFlag.Impassable) != 0)
return HousePlacementResult.BadLand;
for (int j = 0; j < m_RoadIDs.Length; j += 2)
if (landID >= m_RoadIDs[j] && landID <= m_RoadIDs[j + 1])
return HousePlacementResult.BadLand; // Broke rule #5
StaticTile[] tiles = map.Tiles.GetStaticTiles(borderPoint.X, borderPoint.Y, true);
for (int j = 0; j < tiles.Length; ++j)
{
StaticTile tile = tiles[j];
ItemData id = TileData.ItemTable[tile.ID & TileData.MaxItemValue];
if (id.Impassable || id.Surface && (id.Flags & TileFlag.Background) == 0 &&
tile.Z + id.CalcHeight > center.Z + 2)
return HousePlacementResult.BadStatic; // Broke rule #1
}
Sector sector = map.GetSector(borderPoint.X, borderPoint.Y);
List<Item> sectorItems = sector.Items;
for (int j = 0; j < sectorItems.Count; ++j)
{
Item item = sectorItems[j];
if (item.X != borderPoint.X || item.Y != borderPoint.Y || item.Movable)
continue;
ItemData id = item.ItemData;
if (id.Impassable || id.Surface && (id.Flags & TileFlag.Background) == 0 &&
item.Z + id.CalcHeight > center.Z + 2)
return HousePlacementResult.BadItem; // Broke rule #1
}
}
List<Sector> _sectors = new List<Sector>();
List<BaseHouse> _houses = new List<BaseHouse>();
for (int i = 0; i < yard.Count; i++)
{
Sector sector = map.GetSector(yard[i]);
if (!_sectors.Contains(sector))
{
_sectors.Add(sector);
for (int j = 0; j < sector.Multis?.Count; j++)
if (sector.Multis[j] is BaseHouse)
{
BaseHouse _house = (BaseHouse)sector.Multis[j];
if (!_houses.Contains(_house)) _houses.Add(_house);
}
}
}
for (int i = 0; i < yard.Count; ++i)
foreach (BaseHouse b in _houses)
if (b.Contains(yard[i]))
return HousePlacementResult.BadStatic; // Broke rule #3
/*Point2D yardPoint = yard[i];
IPooledEnumerable eable = map.GetMultiTilesAt( yardPoint.X, yardPoint.Y );
foreach ( StaticTile[] tile in eable )
{
for ( int j = 0; j < tile.Length; ++j )
{
if ( (TileData.ItemTable[tile[j].ID & TileData.MaxItemValue].Flags & (TileFlag.Impassable | TileFlag.Surface)) != 0 )
{
eable.Free();
return HousePlacementResult.BadStatic; // Broke rule #3
}
}
}
eable.Free();*/
return HousePlacementResult.Valid;
}
}
}

View file

@ -0,0 +1,858 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Server.Gumps;
using Server.Mobiles;
using Server.Multis;
using Server.Network;
using Server.Regions;
using Server.Targeting;
namespace Server.Items
{
public class HousePlacementTool : Item
{
[Constructible]
public HousePlacementTool() : base(0x14F6)
{
Weight = 3.0;
LootType = LootType.Blessed;
}
public HousePlacementTool(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1060651; // a house placement tool
public override void OnDoubleClick(Mobile from)
{
if (IsChildOf(from.Backpack))
from.SendGump(new HousePlacementCategoryGump(from));
else
from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it.
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
if (Weight == 0.0)
Weight = 3.0;
}
}
public class HousePlacementCategoryGump : Gump
{
private const int LabelColor = 0x7FFF;
private const int LabelColorDisabled = 0x4210;
private Mobile m_From;
public HousePlacementCategoryGump(Mobile from) : base(50, 50)
{
m_From = from;
from.CloseGump<HousePlacementCategoryGump>();
from.CloseGump<HousePlacementListGump>();
AddPage(0);
AddBackground(0, 0, 270, 145, 5054);
AddImageTiled(10, 10, 250, 125, 2624);
AddAlphaRegion(10, 10, 250, 125);
AddHtmlLocalized(10, 10, 250, 20, 1060239, LabelColor); // <CENTER>HOUSE PLACEMENT TOOL</CENTER>
AddButton(10, 110, 4017, 4019, 0);
AddHtmlLocalized(45, 110, 150, 20, 3000363, LabelColor); // Close
AddButton(10, 40, 4005, 4007, 1);
AddHtmlLocalized(45, 40, 200, 20, 1060390, LabelColor); // Classic Houses
AddButton(10, 60, 4005, 4007, 2);
AddHtmlLocalized(45, 60, 200, 20, 1060391, LabelColor); // 2-Story Customizable Houses
AddButton(10, 80, 4005, 4007, 3);
AddHtmlLocalized(45, 80, 200, 20, 1060392, LabelColor); // 3-Story Customizable Houses
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (!m_From.CheckAlive() || m_From.Backpack?.FindItemByType<HousePlacementTool>() == null)
return;
switch (info.ButtonID)
{
case 1: // Classic Houses
{
m_From.SendGump(new HousePlacementListGump(m_From, HousePlacementEntry.ClassicHouses));
break;
}
case 2: // 2-Story Customizable Houses
{
m_From.SendGump(new HousePlacementListGump(m_From, HousePlacementEntry.TwoStoryFoundations));
break;
}
case 3: // 3-Story Customizable Houses
{
m_From.SendGump(new HousePlacementListGump(m_From, HousePlacementEntry.ThreeStoryFoundations));
break;
}
}
}
}
public class HousePlacementListGump : Gump
{
private const int LabelColor = 0x7FFF;
private const int LabelHue = 0x480;
private HousePlacementEntry[] m_Entries;
private Mobile m_From;
public HousePlacementListGump(Mobile from, HousePlacementEntry[] entries) : base(50, 50)
{
m_From = from;
m_Entries = entries;
from.CloseGump<HousePlacementCategoryGump>();
from.CloseGump<HousePlacementListGump>();
AddPage(0);
AddBackground(0, 0, 520, 420, 5054);
AddImageTiled(10, 10, 500, 20, 2624);
AddAlphaRegion(10, 10, 500, 20);
AddHtmlLocalized(10, 10, 500, 20, 1060239, LabelColor); // <CENTER>HOUSE PLACEMENT TOOL</CENTER>
AddImageTiled(10, 40, 500, 20, 2624);
AddAlphaRegion(10, 40, 500, 20);
AddHtmlLocalized(50, 40, 225, 20, 1060235, LabelColor); // House Description
AddHtmlLocalized(275, 40, 75, 20, 1060236, LabelColor); // Storage
AddHtmlLocalized(350, 40, 75, 20, 1060237, LabelColor); // Lockdowns
AddHtmlLocalized(425, 40, 75, 20, 1060034, LabelColor); // Cost
AddImageTiled(10, 70, 500, 280, 2624);
AddAlphaRegion(10, 70, 500, 280);
AddImageTiled(10, 360, 500, 20, 2624);
AddAlphaRegion(10, 360, 500, 20);
AddHtmlLocalized(10, 360, 250, 20, 1060645, LabelColor); // Bank Balance:
AddLabel(250, 360, LabelHue, Banker.GetBalance(from).ToString());
AddImageTiled(10, 390, 500, 20, 2624);
AddAlphaRegion(10, 390, 500, 20);
AddButton(10, 390, 4017, 4019, 0);
AddHtmlLocalized(50, 390, 100, 20, 3000363, LabelColor); // Close
for (int i = 0; i < entries.Length; ++i)
{
int page = 1 + i / 14;
int index = i % 14;
if (index == 0)
{
if (page > 1)
{
AddButton(450, 390, 4005, 4007, 0, GumpButtonType.Page, page);
AddHtmlLocalized(400, 390, 100, 20, 3000406, LabelColor); // Next
}
AddPage(page);
if (page > 1)
{
AddButton(200, 390, 4014, 4016, 0, GumpButtonType.Page, page - 1);
AddHtmlLocalized(250, 390, 100, 20, 3000405, LabelColor); // Previous
}
}
HousePlacementEntry entry = entries[i];
int y = 70 + index * 20;
AddButton(10, y, 4005, 4007, 1 + i);
AddHtmlLocalized(50, y, 225, 20, entry.Description, LabelColor);
AddLabel(275, y, LabelHue, entry.Storage.ToString());
AddLabel(350, y, LabelHue, entry.Lockdowns.ToString());
AddLabel(425, y, LabelHue, entry.Cost.ToString());
}
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (!m_From.CheckAlive() || m_From.Backpack?.FindItemByType<HousePlacementTool>() == null)
return;
int index = info.ButtonID - 1;
if (index >= 0 && index < m_Entries.Length)
{
if (m_From.AccessLevel < AccessLevel.GameMaster && BaseHouse.HasAccountHouse(m_From))
m_From.SendLocalizedMessage(501271); // You already own a house, you may not place another!
else
m_From.Target = new NewHousePlacementTarget(m_Entries, m_Entries[index]);
}
else
{
m_From.SendGump(new HousePlacementCategoryGump(m_From));
}
}
}
public class NewHousePlacementTarget : MultiTarget
{
private HousePlacementEntry[] m_Entries;
private HousePlacementEntry m_Entry;
private bool m_Placed;
public NewHousePlacementTarget(HousePlacementEntry[] entries, HousePlacementEntry entry) : base(entry.MultiID,
entry.Offset)
{
Range = 14;
m_Entries = entries;
m_Entry = entry;
}
protected override void OnTarget(Mobile from, object o)
{
if (!from.CheckAlive() || from.Backpack?.FindItemByType<HousePlacementTool>() == null)
return;
if (o is IPoint3D ip)
{
if (ip is Item item)
ip = item.GetWorldTop();
Point3D p = new Point3D(ip);
Region reg = Region.Find(new Point3D(p), from.Map);
if (from.AccessLevel >= AccessLevel.GameMaster || reg.AllowHousing(from, p))
m_Placed = m_Entry.OnPlacement(from, p);
else if (reg.IsPartOf<TempNoHousingRegion>())
from.SendLocalizedMessage(
501270); // Lord British has decreed a 'no build' period, thus you cannot build this house at this time.
else if (reg.IsPartOf<TreasureRegion>() || reg.IsPartOf<HouseRegion>())
from.SendLocalizedMessage(
1043287); // The house could not be created here. Either something is blocking the house, or the house would not be on valid terrain.
else if (reg.IsPartOf<HouseRaffleRegion>())
from.SendLocalizedMessage(1150493); // You must have a deed for this plot of land in order to build here.
else
from.SendLocalizedMessage(501265); // Housing can not be created in this area.
}
}
protected override void OnTargetFinish(Mobile from)
{
if (!from.CheckAlive() || from.Backpack?.FindItemByType<HousePlacementTool>() == null)
return;
if (!m_Placed)
from.SendGump(new HousePlacementListGump(from, m_Entries));
}
}
public class HousePlacementEntry
{
private static Dictionary<Type, object> m_Table;
private int m_Lockdowns;
private int m_NewLockdowns;
private int m_NewStorage;
private int m_Storage;
static HousePlacementEntry()
{
m_Table = new Dictionary<Type, object>();
FillTable(ClassicHouses);
FillTable(TwoStoryFoundations);
FillTable(ThreeStoryFoundations);
}
public HousePlacementEntry(Type type, int description, int storage, int lockdowns, int newStorage, int newLockdowns,
int vendors, int cost, int xOffset, int yOffset, int zOffset, int multiID)
{
Type = type;
Description = description;
m_Storage = storage;
m_Lockdowns = lockdowns;
m_NewStorage = newStorage;
m_NewLockdowns = newLockdowns;
Vendors = vendors;
Cost = cost;
Offset = new Point3D(xOffset, yOffset, zOffset);
MultiID = multiID;
}
public Type Type{ get; }
public int Description{ get; }
public int Storage => BaseHouse.NewVendorSystem ? m_NewStorage : m_Storage;
public int Lockdowns => BaseHouse.NewVendorSystem ? m_NewLockdowns : m_Lockdowns;
public int Vendors{ get; }
public int Cost{ get; }
public int MultiID{ get; }
public Point3D Offset{ get; }
public static HousePlacementEntry[] ClassicHouses{ get; } =
{
new HousePlacementEntry(typeof(SmallOldHouse), 1011303, 425, 212, 489, 244, 10, 37000, 0, 4, 0, 0x0064),
new HousePlacementEntry(typeof(SmallOldHouse), 1011304, 425, 212, 489, 244, 10, 37000, 0, 4, 0, 0x0066),
new HousePlacementEntry(typeof(SmallOldHouse), 1011305, 425, 212, 489, 244, 10, 36750, 0, 4, 0, 0x0068),
new HousePlacementEntry(typeof(SmallOldHouse), 1011306, 425, 212, 489, 244, 10, 35250, 0, 4, 0, 0x006A),
new HousePlacementEntry(typeof(SmallOldHouse), 1011307, 425, 212, 489, 244, 10, 36750, 0, 4, 0, 0x006C),
new HousePlacementEntry(typeof(SmallOldHouse), 1011308, 425, 212, 489, 244, 10, 36750, 0, 4, 0, 0x006E),
new HousePlacementEntry(typeof(SmallShop), 1011321, 425, 212, 489, 244, 10, 50500, -1, 4, 0, 0x00A0),
new HousePlacementEntry(typeof(SmallShop), 1011322, 425, 212, 489, 244, 10, 52500, 0, 4, 0, 0x00A2),
new HousePlacementEntry(typeof(SmallTower), 1011317, 580, 290, 667, 333, 14, 73500, 3, 4, 0, 0x0098),
new HousePlacementEntry(typeof(TwoStoryVilla), 1011319, 1100, 550, 1265, 632, 24, 113750, 3, 6, 0, 0x009E),
new HousePlacementEntry(typeof(SandStonePatio), 1011320, 850, 425, 1265, 632, 24, 76500, -1, 4, 0, 0x009C),
new HousePlacementEntry(typeof(LogCabin), 1011318, 1100, 550, 1265, 632, 24, 81750, 1, 6, 0, 0x009A),
new HousePlacementEntry(typeof(GuildHouse), 1011309, 1370, 685, 1576, 788, 28, 131500, -1, 7, 0, 0x0074),
new HousePlacementEntry(typeof(TwoStoryHouse), 1011310, 1370, 685, 1576, 788, 28, 162750, -3, 7, 0, 0x0076),
new HousePlacementEntry(typeof(TwoStoryHouse), 1011311, 1370, 685, 1576, 788, 28, 162000, -3, 7, 0, 0x0078),
new HousePlacementEntry(typeof(LargePatioHouse), 1011315, 1370, 685, 1576, 788, 28, 129250, -4, 7, 0, 0x008C),
new HousePlacementEntry(typeof(LargeMarbleHouse), 1011316, 1370, 685, 1576, 788, 28, 160500, -4, 7, 0, 0x0096),
new HousePlacementEntry(typeof(Tower), 1011312, 2119, 1059, 2437, 1218, 42, 366500, 0, 7, 0, 0x007A),
new HousePlacementEntry(typeof(Keep), 1011313, 2625, 1312, 3019, 1509, 52, 572750, 0, 11, 0, 0x007C),
new HousePlacementEntry(typeof(Castle), 1011314, 4076, 2038, 4688, 2344, 78, 865250, 0, 16, 0, 0x007E)
};
public static HousePlacementEntry[] TwoStoryFoundations{ get; } =
{
new HousePlacementEntry(typeof(HouseFoundation), 1060241, 425, 212, 489, 244, 10, 30500, 0, 4, 0,
0x13EC), // 7x7 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060242, 580, 290, 667, 333, 14, 34500, 0, 5, 0,
0x13ED), // 7x8 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060243, 650, 325, 748, 374, 16, 38500, 0, 5, 0,
0x13EE), // 7x9 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060244, 700, 350, 805, 402, 16, 42500, 0, 6, 0,
0x13EF), // 7x10 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060245, 750, 375, 863, 431, 16, 46500, 0, 6, 0,
0x13F0), // 7x11 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060246, 800, 400, 920, 460, 18, 50500, 0, 7, 0,
0x13F1), // 7x12 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060253, 580, 290, 667, 333, 14, 34500, 0, 4, 0,
0x13F8), // 8x7 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060254, 650, 325, 748, 374, 16, 39000, 0, 5, 0,
0x13F9), // 8x8 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060255, 700, 350, 805, 402, 16, 43500, 0, 5, 0,
0x13FA), // 8x9 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060256, 750, 375, 863, 431, 16, 48000, 0, 6, 0,
0x13FB), // 8x10 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060257, 800, 400, 920, 460, 18, 52500, 0, 6, 0,
0x13FC), // 8x11 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060258, 850, 425, 1265, 632, 24, 57000, 0, 7, 0,
0x13FD), // 8x12 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060259, 1100, 550, 1265, 632, 24, 61500, 0, 7, 0,
0x13FE), // 8x13 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060265, 650, 325, 748, 374, 16, 38500, 0, 4, 0,
0x1404), // 9x7 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060266, 700, 350, 805, 402, 16, 43500, 0, 5, 0,
0x1405), // 9x8 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060267, 750, 375, 863, 431, 16, 48500, 0, 5, 0,
0x1406), // 9x9 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060268, 800, 400, 920, 460, 18, 53500, 0, 6, 0,
0x1407), // 9x10 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060269, 850, 425, 1265, 632, 24, 58500, 0, 6, 0,
0x1408), // 9x11 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060270, 1100, 550, 1265, 632, 24, 63500, 0, 7, 0,
0x1409), // 9x12 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060271, 1100, 550, 1265, 632, 24, 68500, 0, 7, 0,
0x140A), // 9x13 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060277, 700, 350, 805, 402, 16, 42500, 0, 4, 0,
0x1410), // 10x7 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060278, 750, 375, 863, 431, 16, 48000, 0, 5, 0,
0x1411), // 10x8 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060279, 800, 400, 920, 460, 18, 53500, 0, 5, 0,
0x1412), // 10x9 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060280, 850, 425, 1265, 632, 24, 59000, 0, 6, 0,
0x1413), // 10x10 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060281, 1100, 550, 1265, 632, 24, 64500, 0, 6, 0,
0x1414), // 10x11 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060282, 1100, 550, 1265, 632, 24, 70000, 0, 7, 0,
0x1415), // 10x12 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060283, 1150, 575, 1323, 661, 24, 75500, 0, 7, 0,
0x1416), // 10x13 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060289, 750, 375, 863, 431, 16, 46500, 0, 4, 0,
0x141C), // 11x7 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060290, 800, 400, 920, 460, 18, 52500, 0, 5, 0,
0x141D), // 11x8 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060291, 850, 425, 1265, 632, 24, 58500, 0, 5, 0,
0x141E), // 11x9 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060292, 1100, 550, 1265, 632, 24, 64500, 0, 6, 0,
0x141F), // 11x10 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060293, 1100, 550, 1265, 632, 24, 70500, 0, 6, 0,
0x1420), // 11x11 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060294, 1150, 575, 1323, 661, 24, 76500, 0, 7, 0,
0x1421), // 11x12 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060295, 1200, 600, 1380, 690, 26, 82500, 0, 7, 0,
0x1422), // 11x13 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060301, 800, 400, 920, 460, 18, 50500, 0, 4, 0,
0x1428), // 12x7 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060302, 850, 425, 1265, 632, 24, 57000, 0, 5, 0,
0x1429), // 12x8 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060303, 1100, 550, 1265, 632, 24, 63500, 0, 5, 0,
0x142A), // 12x9 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060304, 1100, 550, 1265, 632, 24, 70000, 0, 6, 0,
0x142B), // 12x10 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060305, 1150, 575, 1323, 661, 24, 76500, 0, 6, 0,
0x142C), // 12x11 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060306, 1200, 600, 1380, 690, 26, 83000, 0, 7, 0,
0x142D), // 12x12 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060307, 1250, 625, 1438, 719, 26, 89500, 0, 7, 0,
0x142E), // 12x13 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060314, 1100, 550, 1265, 632, 24, 61500, 0, 5, 0,
0x1435), // 13x8 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060315, 1100, 550, 1265, 632, 24, 68500, 0, 5, 0,
0x1436), // 13x9 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060316, 1150, 575, 1323, 661, 24, 75500, 0, 6, 0,
0x1437), // 13x10 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060317, 1200, 600, 1380, 690, 26, 82500, 0, 6, 0,
0x1438), // 13x11 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060318, 1250, 625, 1438, 719, 26, 89500, 0, 7, 0,
0x1439), // 13x12 2-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060319, 1300, 650, 1495, 747, 28, 96500, 0, 7, 0,
0x143A) // 13x13 2-Story Customizable House
};
public static HousePlacementEntry[] ThreeStoryFoundations{ get; } =
{
new HousePlacementEntry(typeof(HouseFoundation), 1060272, 1150, 575, 1323, 661, 24, 73500, 0, 8, 0,
0x140B), // 9x14 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060284, 1200, 600, 1380, 690, 26, 81000, 0, 8, 0,
0x1417), // 10x14 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060285, 1250, 625, 1438, 719, 26, 86500, 0, 8, 0,
0x1418), // 10x15 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060296, 1250, 625, 1438, 719, 26, 88500, 0, 8, 0,
0x1423), // 11x14 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060297, 1300, 650, 1495, 747, 28, 94500, 0, 8, 0,
0x1424), // 11x15 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060298, 1350, 675, 1553, 776, 28, 100500, 0, 9, 0,
0x1425), // 11x16 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060308, 1300, 650, 1495, 747, 28, 96000, 0, 8, 0,
0x142F), // 12x14 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060309, 1350, 675, 1553, 776, 28, 102500, 0, 8, 0,
0x1430), // 12x15 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060310, 1370, 685, 1576, 788, 28, 109000, 0, 9, 0,
0x1431), // 12x16 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060311, 1370, 685, 1576, 788, 28, 115500, 0, 9, 0,
0x1432), // 12x17 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060320, 1350, 675, 1553, 776, 28, 103500, 0, 8, 0,
0x143B), // 13x14 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060321, 1370, 685, 1576, 788, 28, 110500, 0, 8, 0,
0x143C), // 13x15 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060322, 1370, 685, 1576, 788, 28, 117500, 0, 9, 0,
0x143D), // 13x16 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060323, 2119, 1059, 2437, 1218, 42, 124500, 0, 9, 0,
0x143E), // 13x17 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060324, 2119, 1059, 2437, 1218, 42, 131500, 0, 10, 0,
0x143F), // 13x18 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060327, 1150, 575, 1323, 661, 24, 73500, 0, 5, 0,
0x1442), // 14x9 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060328, 1200, 600, 1380, 690, 26, 81000, 0, 6, 0,
0x1443), // 14x10 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060329, 1250, 625, 1438, 719, 26, 88500, 0, 6, 0,
0x1444), // 14x11 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060330, 1300, 650, 1495, 747, 28, 96000, 0, 7, 0,
0x1445), // 14x12 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060331, 1350, 675, 1553, 776, 28, 103500, 0, 7, 0,
0x1446), // 14x13 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060332, 1370, 685, 1576, 788, 28, 111000, 0, 8, 0,
0x1447), // 14x14 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060333, 1370, 685, 1576, 788, 28, 118500, 0, 8, 0,
0x1448), // 14x15 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060334, 2119, 1059, 2437, 1218, 42, 126000, 0, 9, 0,
0x1449), // 14x16 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060335, 2119, 1059, 2437, 1218, 42, 133500, 0, 9, 0,
0x144A), // 14x17 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060336, 2119, 1059, 2437, 1218, 42, 141000, 0, 10, 0,
0x144B), // 14x18 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060340, 1250, 625, 1438, 719, 26, 86500, 0, 6, 0,
0x144F), // 15x10 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060341, 1300, 650, 1495, 747, 28, 94500, 0, 6, 0,
0x1450), // 15x11 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060342, 1350, 675, 1553, 776, 28, 102500, 0, 7, 0,
0x1451), // 15x12 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060343, 1370, 685, 1576, 788, 28, 110500, 0, 7, 0,
0x1452), // 15x13 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060344, 1370, 685, 1576, 788, 28, 118500, 0, 8, 0,
0x1453), // 15x14 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060345, 2119, 1059, 2437, 1218, 42, 126500, 0, 8, 0,
0x1454), // 15x15 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060346, 2119, 1059, 2437, 1218, 42, 134500, 0, 9, 0,
0x1455), // 15x16 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060347, 2119, 1059, 2437, 1218, 42, 142500, 0, 9, 0,
0x1456), // 15x17 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060348, 2119, 1059, 2437, 1218, 42, 150500, 0, 10, 0,
0x1457), // 15x18 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060353, 1350, 675, 1553, 776, 28, 100500, 0, 6, 0,
0x145C), // 16x11 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060354, 1370, 685, 1576, 788, 28, 109000, 0, 7, 0,
0x145D), // 16x12 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060355, 1370, 685, 1576, 788, 28, 117500, 0, 7, 0,
0x145E), // 16x13 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060356, 2119, 1059, 2437, 1218, 42, 126000, 0, 8, 0,
0x145F), // 16x14 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060357, 2119, 1059, 2437, 1218, 42, 134500, 0, 8, 0,
0x1460), // 16x15 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060358, 2119, 1059, 2437, 1218, 42, 143000, 0, 9, 0,
0x1461), // 16x16 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060359, 2119, 1059, 2437, 1218, 42, 151500, 0, 9, 0,
0x1462), // 16x17 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060360, 2119, 1059, 2437, 1218, 42, 160000, 0, 10, 0,
0x1463), // 16x18 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060366, 1370, 685, 1576, 788, 28, 115500, 0, 7, 0,
0x1469), // 17x12 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060367, 2119, 1059, 2437, 1218, 42, 124500, 0, 7, 0,
0x146A), // 17x13 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060368, 2119, 1059, 2437, 1218, 42, 133500, 0, 8, 0,
0x146B), // 17x14 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060369, 2119, 1059, 2437, 1218, 42, 142500, 0, 8, 0,
0x146C), // 17x15 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060370, 2119, 1059, 2437, 1218, 42, 151500, 0, 9, 0,
0x146D), // 17x16 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060371, 2119, 1059, 2437, 1218, 42, 160500, 0, 9, 0,
0x146E), // 17x17 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060372, 2119, 1059, 2437, 1218, 42, 169500, 0, 10, 0,
0x146F), // 17x18 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060379, 2119, 1059, 2437, 1218, 42, 131500, 0, 7, 0,
0x1476), // 18x13 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060380, 2119, 1059, 2437, 1218, 42, 141000, 0, 8, 0,
0x1477), // 18x14 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060381, 2119, 1059, 2437, 1218, 42, 150500, 0, 8, 0,
0x1478), // 18x15 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060382, 2119, 1059, 2437, 1218, 42, 160000, 0, 9, 0,
0x1479), // 18x16 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060383, 2119, 1059, 2437, 1218, 42, 169500, 0, 9, 0,
0x147A), // 18x17 3-Story Customizable House
new HousePlacementEntry(typeof(HouseFoundation), 1060384, 2119, 1059, 2437, 1218, 42, 179000, 0, 10, 0,
0x147B) // 18x18 3-Story Customizable House
};
public BaseHouse ConstructHouse(Mobile from)
{
try
{
object[] args;
if (Type == typeof(HouseFoundation))
args = new object[] { from, MultiID, m_Storage, m_Lockdowns };
else if (Type == typeof(SmallOldHouse) || Type == typeof(SmallShop) || Type == typeof(TwoStoryHouse))
args = new object[] { from, MultiID };
else
args = new object[] { from };
return Activator.CreateInstance(Type, args) as BaseHouse;
}
catch
{
// ignored
}
return null;
}
public void PlacementWarning_Callback(Mobile from, bool okay, PreviewHouse prevHouse)
{
if (!from.CheckAlive() || from.Backpack?.FindItemByType<HousePlacementTool>() == null)
return;
if (!okay)
{
prevHouse.Delete();
return;
}
if (prevHouse.Deleted)
{
/* Too much time has passed and the test house you created has been deleted.
* Please try again!
*/
from.SendGump(new NoticeGump(1060637, 30720, 1060647, 32512, 320, 180));
return;
}
Point3D center = prevHouse.Location;
prevHouse.Delete();
//Point3D center = new Point3D( p.X - m_Offset.X, p.Y - m_Offset.Y, p.Z - m_Offset.Z );
HousePlacementResult res = HousePlacement.Check(from, MultiID, center, out List<IEntity> toMove);
switch (res)
{
case HousePlacementResult.Valid:
{
if (from.AccessLevel < AccessLevel.GameMaster && BaseHouse.HasAccountHouse(from))
{
from.SendLocalizedMessage(501271); // You already own a house, you may not place another!
}
else
{
BaseHouse house = ConstructHouse(from);
if (house == null)
return;
house.Price = Cost;
if (from.AccessLevel >= AccessLevel.GameMaster)
{
from.SendMessage("{0} gold would have been withdrawn from your bank if you were not a GM.",
Cost.ToString());
}
else
{
if (Banker.Withdraw(from, Cost))
{
from.SendLocalizedMessage(1060398,
Cost.ToString()); // ~1_AMOUNT~ gold has been withdrawn from your bank box.
}
else
{
house.RemoveKeys(from);
house.Delete();
from.SendLocalizedMessage(
1060646); // You do not have the funds available in your bank box to purchase this house. Try placing a smaller house, or adding gold or checks to your bank box.
return;
}
}
house.MoveToWorld(center, from.Map);
for (int i = 0; i < toMove.Count; ++i)
{
object o = toMove[i];
if (o is Mobile mobile)
mobile.Location = house.BanLocation;
else if (o is Item item)
item.Location = house.BanLocation;
}
}
break;
}
case HousePlacementResult.BadItem:
case HousePlacementResult.BadLand:
case HousePlacementResult.BadStatic:
case HousePlacementResult.BadRegionHidden:
case HousePlacementResult.NoSurface:
{
from.SendLocalizedMessage(
1043287); // The house could not be created here. Either something is blocking the house, or the house would not be on valid terrain.
break;
}
case HousePlacementResult.BadRegion:
{
from.SendLocalizedMessage(501265); // Housing cannot be created in this area.
break;
}
case HousePlacementResult.BadRegionTemp:
{
from.SendLocalizedMessage(
501270); // Lord British has decreed a 'no build' period, thus you cannot build this house at this time.
break;
}
case HousePlacementResult.BadRegionRaffle:
{
from.SendLocalizedMessage(1150493); // You must have a deed for this plot of land in order to build here.
break;
}
case HousePlacementResult.InvalidCastleKeep:
{
from.SendLocalizedMessage(1061122); // Castles and keeps cannot be created here.
break;
}
}
}
public bool OnPlacement(Mobile from, Point3D p)
{
if (!from.CheckAlive() || from.Backpack?.FindItemByType<HousePlacementTool>() == null)
return false;
Point3D center = new Point3D(p.X - Offset.X, p.Y - Offset.Y, p.Z - Offset.Z);
HousePlacementResult res = HousePlacement.Check(from, MultiID, center, out List<IEntity> toMove);
switch (res)
{
case HousePlacementResult.Valid:
{
if (from.AccessLevel < AccessLevel.GameMaster && BaseHouse.HasAccountHouse(from))
{
from.SendLocalizedMessage(501271); // You already own a house, you may not place another!
}
else
{
from.SendLocalizedMessage(1011576); // This is a valid location.
PreviewHouse prev = new PreviewHouse(MultiID);
MultiComponentList mcl = prev.Components;
Point3D banLoc = new Point3D(center.X + mcl.Min.X, center.Y + mcl.Max.Y + 1, center.Z);
for (int i = 0; i < mcl.List.Length; ++i)
{
MultiTileEntry entry = mcl.List[i];
int itemID = entry.m_ItemID;
if (itemID >= 0xBA3 && itemID <= 0xC0E)
{
banLoc = new Point3D(center.X + entry.m_OffsetX, center.Y + entry.m_OffsetY, center.Z);
break;
}
}
for (int i = 0; i < toMove.Count; ++i)
{
object o = toMove[i];
if (o is Mobile mobile)
mobile.Location = banLoc;
else if (o is Item item)
item.Location = banLoc;
}
prev.MoveToWorld(center, from.Map);
/* You are about to place a new house.
* Placing this house will condemn any and all of your other houses that you may have.
* All of your houses on all shards will be affected.
*
* In addition, you will not be able to place another house or have one transferred to you for one (1) real-life week.
*
* Once you accept these terms, these effects cannot be reversed.
* Re-deeding or transferring your new house will not uncondemn your other house(s) nor will the one week timer be removed.
*
* If you are absolutely certain you wish to proceed, click the button next to OKAY below.
* If you do not wish to trade for this house, click CANCEL.
*/
from.SendGump(new WarningGump(1060635, 30720, 1049583, 32512, 420, 280, okay => PlacementWarning_Callback(from, okay, prev)));
return true;
}
break;
}
case HousePlacementResult.BadItem:
case HousePlacementResult.BadLand:
case HousePlacementResult.BadStatic:
case HousePlacementResult.BadRegionHidden:
case HousePlacementResult.NoSurface:
{
from.SendLocalizedMessage(
1043287); // The house could not be created here. Either something is blocking the house, or the house would not be on valid terrain.
break;
}
case HousePlacementResult.BadRegion:
{
from.SendLocalizedMessage(501265); // Housing cannot be created in this area.
break;
}
case HousePlacementResult.BadRegionTemp:
{
from.SendLocalizedMessage(
501270); //Lord British has decreed a 'no build' period, thus you cannot build this house at this time.
break;
}
case HousePlacementResult.BadRegionRaffle:
{
from.SendLocalizedMessage(1150493); // You must have a deed for this plot of land in order to build here.
break;
}
case HousePlacementResult.InvalidCastleKeep:
{
from.SendLocalizedMessage(1061122); // Castles and keeps cannot be created here.
break;
}
}
return false;
}
public static HousePlacementEntry Find(BaseHouse house)
{
m_Table.TryGetValue(house.GetType(), out object obj);
if (obj is HousePlacementEntry entry)
return entry;
if (obj is List<HousePlacementEntry> list)
return list.FirstOrDefault(e => e.MultiID == house.ItemID);
if (obj is Dictionary<int, HousePlacementEntry> table)
return table[house.ItemID];
return null;
}
private static void FillTable(HousePlacementEntry[] entries)
{
for (int i = 0; i < entries.Length; ++i)
{
HousePlacementEntry e = entries[i];
if (!m_Table.TryGetValue(e.Type, out object obj))
{
m_Table[e.Type] = e;
}
else if (obj is HousePlacementEntry entry)
{
List<HousePlacementEntry> list = new List<HousePlacementEntry> { entry, e };
m_Table[e.Type] = list;
}
else if (obj is List<HousePlacementEntry> list)
{
if (list.Count == 8)
{
Dictionary<int, HousePlacementEntry> table = new Dictionary<int, HousePlacementEntry>();
foreach (HousePlacementEntry t in list)
table[t.MultiID] = t;
table[e.MultiID] = e;
m_Table[e.Type] = table;
}
else
list.Add(e);
}
else if (obj is Dictionary<int, HousePlacementEntry> table)
{
table[e.MultiID] = e;
}
}
}
}
}

View file

@ -0,0 +1,282 @@
using System;
using System.Collections.Generic;
using Server.ContextMenus;
using Server.Gumps;
namespace Server.Multis
{
public class HouseSign : Item
{
public HouseSign(BaseHouse owner) : base(0xBD2)
{
Owner = owner;
OriginalOwner = Owner.Owner;
Movable = false;
}
public HouseSign(Serial serial) : base(serial)
{
}
public BaseHouse Owner{ get; private set; }
[CommandProperty(AccessLevel.GameMaster)]
public bool RestrictDecay
{
get => Owner?.RestrictDecay == true;
set
{
if (Owner != null)
Owner.RestrictDecay = value;
}
}
[CommandProperty(AccessLevel.GameMaster)]
public Mobile OriginalOwner{ get; private set; }
public override bool ForceShowProperties => ObjectPropertyList.Enabled;
public bool GettingProperties{ get; private set; }
public string GetName()
{
return Name ?? "An Unnamed House";
}
public override void OnAfterDelete()
{
base.OnAfterDelete();
if (Owner?.Deleted == false)
Owner.Delete();
}
public override void AddNameProperty(ObjectPropertyList list)
{
list.Add(1061638); // A House Sign
}
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
list.Add(1061639, Utility.FixHtml(GetName())); // Name: ~1_NAME~
list.Add(1061640, Owner?.Owner == null ? "nobody" : Owner.Owner.Name); // Owner: ~1_OWNER~
if (Owner != null)
{
list.Add(Owner.Public ? 1061641 : 1061642); // This House is Open to the Public : This is a Private Home
GettingProperties = true;
DecayLevel level = Owner.DecayLevel;
GettingProperties = false;
if (level == DecayLevel.DemolitionPending)
{
list.Add(1062497); // Demolition Pending
}
else if (level != DecayLevel.Ageless)
{
if (level == DecayLevel.Collapsed)
level = DecayLevel.IDOC;
list.Add(1062028, $"#{1043009 + (int)level}"); // Condition: This structure is ...
}
}
}
public override void OnSingleClick(Mobile from)
{
if (Owner != null && BaseHouse.DecayEnabled && Owner.DecayPeriod != TimeSpan.Zero)
{
string message;
switch (Owner.DecayLevel)
{
case DecayLevel.Ageless:
message = "ageless";
break;
case DecayLevel.Fairly:
message = "fairly worn";
break;
case DecayLevel.Greatly:
message = "greatly worn";
break;
case DecayLevel.LikeNew:
message = "like new";
break;
case DecayLevel.Slightly:
message = "slightly worn";
break;
case DecayLevel.Somewhat:
message = "somewhat worn";
break;
default:
message = "in danger of collapsing";
break;
}
LabelTo(from, "This house is {0}.", message);
}
base.OnSingleClick(from);
}
public void ShowSign(Mobile m)
{
if (Owner != null)
{
if (Owner.IsFriend(m) && m.AccessLevel < AccessLevel.GameMaster)
{
#region Mondain's Legacy
if (Core.ML && Owner.IsOwner(m) || !Core.ML)
Owner.RefreshDecay();
#endregion
if (!Core.AOS)
m.SendLocalizedMessage(501293); // Welcome back to the house, friend!
}
if (Owner.IsAosRules)
m.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Information, m, Owner));
else
m.SendGump(new HouseGump(m, Owner));
}
}
public void ClaimGump_Callback(Mobile from, bool okay)
{
if (okay && Owner != null && Owner.Owner == null && Owner.DecayLevel != DecayLevel.DemolitionPending)
{
bool canClaim = Owner.CoOwners?.Count > 0 && Owner.IsCoOwner(from) || Owner.IsFriend(from);
if (canClaim && !BaseHouse.HasAccountHouse(from))
{
Owner.Owner = from;
Owner.LastTraded = DateTime.UtcNow;
}
}
ShowSign(from);
}
public override void OnDoubleClick(Mobile m)
{
if (Owner == null)
return;
if (m.AccessLevel < AccessLevel.GameMaster && Owner.Owner == null &&
Owner.DecayLevel != DecayLevel.DemolitionPending)
{
bool canClaim = Owner?.CoOwners.Count > 0 && Owner.IsCoOwner(m) || Owner.IsFriend(m);
if (canClaim && !BaseHouse.HasAccountHouse(m))
m.SendGump(new WarningGump(501036, 32512, 1049719, 32512, 420, 280, okay => ClaimGump_Callback(m, okay)));
}
ShowSign(m);
}
public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
{
base.GetContextMenuEntries(from, list);
if (!BaseHouse.NewVendorSystem || !from.Alive || Owner?.IsAosRules != true)
return;
if (Owner.AreThereAvailableVendorsFor(from))
list.Add(new VendorsEntry(this));
if (Owner.VendorInventories.Count > 0)
list.Add(new ReclaimVendorInventoryEntry(this));
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
writer.Write(Owner);
writer.Write(OriginalOwner);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 0:
{
Owner = reader.ReadItem() as BaseHouse;
OriginalOwner = reader.ReadMobile();
break;
}
}
if (Name == "a house sign")
Name = null;
}
private class VendorsEntry : ContextMenuEntry
{
private HouseSign m_Sign;
public VendorsEntry(HouseSign sign) : base(6211)
{
m_Sign = sign;
}
public override void OnClick()
{
Mobile from = Owner.From;
if (!from.CheckAlive() || m_Sign.Deleted || m_Sign.Owner == null ||
!m_Sign.Owner.AreThereAvailableVendorsFor(from))
return;
if (from.Map != m_Sign.Map || !from.InRange(m_Sign, 5))
from.SendLocalizedMessage(
1062429); // You must be within five paces of the house sign to use this option.
else
from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Vendors, from, m_Sign.Owner));
}
}
private class ReclaimVendorInventoryEntry : ContextMenuEntry
{
private HouseSign m_Sign;
public ReclaimVendorInventoryEntry(HouseSign sign) : base(6213)
{
m_Sign = sign;
}
public override void OnClick()
{
Mobile from = Owner.From;
if (m_Sign.Deleted || m_Sign.Owner == null || m_Sign.Owner.VendorInventories.Count == 0 ||
!from.CheckAlive())
return;
if (from.Map != m_Sign.Map || !from.InRange(m_Sign, 5))
{
from.SendLocalizedMessage(
1062429); // You must be within five paces of the house sign to use this option.
}
else
{
from.CloseGump<VendorInventoryGump>();
from.SendGump(new VendorInventoryGump(m_Sign.Owner, from));
}
}
}
}
}

View file

@ -0,0 +1,172 @@
using System;
using System.Collections.Generic;
using Server.ContextMenus;
using Server.Gumps;
using Server.Mobiles;
using Server.Multis;
namespace Server.Items
{
public class HouseTeleporter : Item, ISecurable
{
public HouseTeleporter(int itemID, Item target = null) : base(itemID)
{
Movable = false;
Level = SecureLevel.Anyone;
Target = target;
}
public HouseTeleporter(Serial serial) : base(serial)
{
}
[CommandProperty(AccessLevel.GameMaster)]
public Item Target{ get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public SecureLevel Level{ get; set; }
public bool CheckAccess(Mobile m)
{
BaseHouse house = BaseHouse.FindHouseAt(this);
return (house == null || house.Public && !house.IsBanned(m) || house.HasAccess(m)) &&
house?.HasSecureAccess(m, Level) == true;
}
public override bool OnMoveOver(Mobile m)
{
if (Target?.Deleted == false)
{
if (CheckAccess(m))
{
if (!m.Hidden || m.AccessLevel == AccessLevel.Player)
new EffectTimer(Location, Map, 2023, 0x1F0, TimeSpan.FromSeconds(0.4)).Start();
new DelayTimer(this, m).Start();
}
else
{
m.SendLocalizedMessage(1061637); // You are not allowed to access this.
}
}
return true;
}
public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
{
base.GetContextMenuEntries(from, list);
SetSecureLevelEntry.AddTo(from, this, list);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(1); // version
writer.Write((int)Level);
writer.Write(Target);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 1:
{
Level = (SecureLevel)reader.ReadInt();
goto case 0;
}
case 0:
{
Target = reader.ReadItem();
if (version < 0)
Level = SecureLevel.Anyone;
break;
}
}
}
private class EffectTimer : Timer
{
private int m_EffectID;
private Point3D m_Location;
private Map m_Map;
private int m_SoundID;
public EffectTimer(Point3D p, Map map, int effectID, int soundID, TimeSpan delay) : base(delay)
{
m_Location = p;
m_Map = map;
m_EffectID = effectID;
m_SoundID = soundID;
}
protected override void OnTick()
{
Effects.SendLocationParticles(EffectItem.Create(m_Location, m_Map, EffectItem.DefaultDuration), 0x3728, 10,
10, m_EffectID, 0);
if (m_SoundID != -1)
Effects.PlaySound(m_Location, m_Map, m_SoundID);
}
}
private class DelayTimer : Timer
{
private Mobile m_Mobile;
private HouseTeleporter m_Teleporter;
public DelayTimer(HouseTeleporter tp, Mobile m) : base(TimeSpan.FromSeconds(1.0))
{
m_Teleporter = tp;
m_Mobile = m;
}
protected override void OnTick()
{
Item target = m_Teleporter.Target;
if (target?.Deleted != false)
return;
Mobile m = m_Mobile;
if (m.Location != m_Teleporter.Location || m.Map != m_Teleporter.Map)
return;
Point3D p = target.GetWorldTop();
Map map = target.Map;
BaseCreature.TeleportPets(m, p, map);
m.MoveToWorld(p, map);
if (m.Hidden && m.AccessLevel != AccessLevel.Player)
return;
Effects.PlaySound(target.Location, target.Map, 0x1FE);
Effects.SendLocationParticles(
EffectItem.Create(m_Teleporter.Location, m_Teleporter.Map, EffectItem.DefaultDuration),
0x3728, 10, 10, 2023, 0);
Effects.SendLocationParticles(
EffectItem.Create(target.Location, target.Map, EffectItem.DefaultDuration), 0x3728, 10, 10,
5023, 0);
new EffectTimer(target.Location, target.Map, 2023, -1, TimeSpan.FromSeconds(0.4)).Start();
}
}
}
}

View file

@ -0,0 +1,614 @@
using Server.Items;
using Server.Multis.Deeds;
namespace Server.Multis
{
public class SmallOldHouse : BaseHouse
{
public static Rectangle2D[] AreaArray = { new Rectangle2D(-3, -3, 7, 7), new Rectangle2D(-1, 4, 3, 1) };
public SmallOldHouse(Mobile owner, int id) : base(id, owner, 425, 3)
{
uint keyValue = CreateKeys(owner);
AddSouthDoor(0, 3, 7, keyValue);
SetSign(2, 4, 5);
}
public SmallOldHouse(Serial serial) : base(serial)
{
}
public override Rectangle2D[] Area => AreaArray;
public override Point3D BaseBanLocation => new Point3D(2, 4, 0);
public override int DefaultPrice => 43800;
public override HousePlacementEntry ConvertEntry => HousePlacementEntry.TwoStoryFoundations[0];
public override HouseDeed GetDeed()
{
switch (ItemID)
{
case 0x64: return new StonePlasterHouseDeed();
case 0x66: return new FieldStoneHouseDeed();
case 0x68: return new SmallBrickHouseDeed();
case 0x6A: return new WoodHouseDeed();
case 0x6C: return new WoodPlasterHouseDeed();
case 0x6E:
default: return new ThatchedRoofCottageDeed();
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); //version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class GuildHouse : BaseHouse
{
public static Rectangle2D[] AreaArray = { new Rectangle2D(-7, -7, 14, 14), new Rectangle2D(-2, 7, 4, 1) };
public GuildHouse(Mobile owner) : base(0x74, owner, 1100, 8)
{
uint keyValue = CreateKeys(owner);
AddSouthDoors(-1, 6, 7, keyValue);
SetSign(4, 8, 16);
AddSouthDoor(-3, -1, 7);
AddSouthDoor(3, -1, 7);
}
public GuildHouse(Serial serial) : base(serial)
{
}
public override int DefaultPrice => 144500;
public override HousePlacementEntry ConvertEntry => HousePlacementEntry.ThreeStoryFoundations[20];
public override int ConvertOffsetX => -1;
public override int ConvertOffsetY => -1;
public override Rectangle2D[] Area => AreaArray;
public override Point3D BaseBanLocation => new Point3D(4, 8, 0);
public override HouseDeed GetDeed()
{
return new BrickHouseDeed();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); //version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class TwoStoryHouse : BaseHouse
{
public static Rectangle2D[] AreaArray =
{ new Rectangle2D(-7, 0, 14, 7), new Rectangle2D(-7, -7, 9, 7), new Rectangle2D(-4, 7, 4, 1) };
public TwoStoryHouse(Mobile owner, int id) : base(id, owner, 1370, 10)
{
uint keyValue = CreateKeys(owner);
AddSouthDoors(-3, 6, 7, keyValue);
SetSign(2, 8, 16);
AddSouthDoor(-3, 0, 7);
AddSouthDoor(id == 0x76 ? -2 : -3, 0, 27);
}
public TwoStoryHouse(Serial serial) : base(serial)
{
}
public override Rectangle2D[] Area => AreaArray;
public override Point3D BaseBanLocation => new Point3D(2, 8, 0);
public override int DefaultPrice => 192400;
public override HouseDeed GetDeed()
{
switch (ItemID)
{
case 0x76: return new TwoStoryWoodPlasterHouseDeed();
case 0x78:
default: return new TwoStoryStonePlasterHouseDeed();
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); //version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class Tower : BaseHouse
{
public static Rectangle2D[] AreaArray =
{
new Rectangle2D(-7, -7, 16, 14), new Rectangle2D(-1, 7, 4, 2), new Rectangle2D(-11, 0, 4, 7),
new Rectangle2D(9, 0, 4, 7)
};
public Tower(Mobile owner) : base(0x7A, owner, 2119, 15)
{
uint keyValue = CreateKeys(owner);
AddSouthDoors(false, 0, 6, 6, keyValue);
SetSign(5, 8, 16);
AddSouthDoor(false, 3, -2, 6);
AddEastDoor(false, 1, 4, 26);
AddEastDoor(false, 1, 4, 46);
}
public Tower(Serial serial) : base(serial)
{
}
public override int DefaultPrice => 433200;
public override HousePlacementEntry ConvertEntry => HousePlacementEntry.ThreeStoryFoundations[37];
public override int ConvertOffsetY => -1;
public override Rectangle2D[] Area => AreaArray;
public override Point3D BaseBanLocation => new Point3D(5, 8, 0);
public override HouseDeed GetDeed()
{
return new TowerDeed();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); //version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class Keep : BaseHouse //warning: ODD shape!
{
public static Rectangle2D[] AreaArray =
{
new Rectangle2D(-11, -11, 7, 8), new Rectangle2D(-11, 5, 7, 8), new Rectangle2D(6, -11, 7, 8),
new Rectangle2D(6, 5, 7, 8), new Rectangle2D(-9, -3, 5, 8), new Rectangle2D(6, -3, 5, 8),
new Rectangle2D(-4, -9, 10, 20), new Rectangle2D(-1, 11, 4, 1)
};
public Keep(Mobile owner) : base(0x7C, owner, 2625, 18)
{
uint keyValue = CreateKeys(owner);
AddSouthDoors(false, 0, 10, 6, keyValue);
SetSign(5, 12, 16);
}
public Keep(Serial serial) : base(serial)
{
}
public override int DefaultPrice => 665200;
public override Rectangle2D[] Area => AreaArray;
public override Point3D BaseBanLocation => new Point3D(5, 13, 0);
public override HouseDeed GetDeed()
{
return new KeepDeed();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); //version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class Castle : BaseHouse
{
public static Rectangle2D[] AreaArray = { new Rectangle2D(-15, -15, 31, 31), new Rectangle2D(-1, 16, 4, 1) };
public Castle(Mobile owner) : base(0x7E, owner, 4076, 28)
{
uint keyValue = CreateKeys(owner);
AddSouthDoors(false, 0, 15, 6, keyValue);
SetSign(5, 17, 16);
AddSouthDoors(false, 0, 11, 6, true);
AddSouthDoors(false, 0, 5, 6, false);
AddSouthDoors(false, -1, -11, 6, false);
}
public Castle(Serial serial) : base(serial)
{
}
public override int DefaultPrice => 1022800;
public override Rectangle2D[] Area => AreaArray;
public override Point3D BaseBanLocation => new Point3D(5, 17, 0);
public override HouseDeed GetDeed()
{
return new CastleDeed();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); //version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class LargePatioHouse : BaseHouse
{
public static Rectangle2D[] AreaArray = { new Rectangle2D(-7, -7, 15, 14), new Rectangle2D(-5, 7, 4, 1) };
public LargePatioHouse(Mobile owner) : base(0x8C, owner, 1100, 8)
{
uint keyValue = CreateKeys(owner);
AddSouthDoors(-4, 6, 7, keyValue);
SetSign(1, 8, 16);
AddEastDoor(1, 4, 7);
AddEastDoor(1, -4, 7);
AddSouthDoor(4, -1, 7);
}
public LargePatioHouse(Serial serial) : base(serial)
{
}
public override int DefaultPrice => 152800;
public override HousePlacementEntry ConvertEntry => HousePlacementEntry.ThreeStoryFoundations[29];
public override int ConvertOffsetY => -1;
public override Rectangle2D[] Area => AreaArray;
public override Point3D BaseBanLocation => new Point3D(1, 8, 0);
public override HouseDeed GetDeed()
{
return new LargePatioDeed();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); //version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class LargeMarbleHouse : BaseHouse
{
public static Rectangle2D[] AreaArray = { new Rectangle2D(-7, -7, 15, 14), new Rectangle2D(-6, 7, 6, 1) };
public LargeMarbleHouse(Mobile owner) : base(0x96, owner, 1370, 10)
{
uint keyValue = CreateKeys(owner);
AddSouthDoors(false, -4, 3, 4, keyValue);
SetSign(1, 8, 11);
}
public LargeMarbleHouse(Serial serial) : base(serial)
{
}
public override int DefaultPrice => 192000;
public override HousePlacementEntry ConvertEntry => HousePlacementEntry.ThreeStoryFoundations[29];
public override int ConvertOffsetY => -1;
public override Rectangle2D[] Area => AreaArray;
public override Point3D BaseBanLocation => new Point3D(1, 8, 0);
public override HouseDeed GetDeed()
{
return new LargeMarbleDeed();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); //version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class SmallTower : BaseHouse
{
public static Rectangle2D[] AreaArray = { new Rectangle2D(-3, -3, 8, 7), new Rectangle2D(2, 4, 3, 1) };
public SmallTower(Mobile owner) : base(0x98, owner, 580, 4)
{
uint keyValue = CreateKeys(owner);
AddSouthDoor(false, 3, 3, 6, keyValue);
SetSign(1, 4, 5);
}
public SmallTower(Serial serial) : base(serial)
{
}
public override int DefaultPrice => 88500;
public override HousePlacementEntry ConvertEntry => HousePlacementEntry.TwoStoryFoundations[6];
public override Rectangle2D[] Area => AreaArray;
public override Point3D BaseBanLocation => new Point3D(1, 4, 0);
public override HouseDeed GetDeed()
{
return new SmallTowerDeed();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); //version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class LogCabin : BaseHouse
{
public static Rectangle2D[] AreaArray = { new Rectangle2D(-3, -6, 8, 13) };
public LogCabin(Mobile owner) : base(0x9A, owner, 1100, 8)
{
uint keyValue = CreateKeys(owner);
AddSouthDoor(1, 4, 8, keyValue);
SetSign(5, 8, 20);
AddSouthDoor(1, 0, 29);
}
public LogCabin(Serial serial) : base(serial)
{
}
public override int DefaultPrice => 97800;
public override HousePlacementEntry ConvertEntry => HousePlacementEntry.TwoStoryFoundations[12];
public override Rectangle2D[] Area => AreaArray;
public override Point3D BaseBanLocation => new Point3D(5, 8, 0);
public override HouseDeed GetDeed()
{
return new LogCabinDeed();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); //version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class SandStonePatio : BaseHouse
{
public static Rectangle2D[] AreaArray = { new Rectangle2D(-5, -4, 12, 8), new Rectangle2D(-2, 4, 3, 1) };
public SandStonePatio(Mobile owner) : base(0x9C, owner, 850, 6)
{
uint keyValue = CreateKeys(owner);
AddSouthDoor(-1, 3, 6, keyValue);
SetSign(4, 6, 24);
}
public SandStonePatio(Serial serial) : base(serial)
{
}
public override int DefaultPrice => 90900;
public override HousePlacementEntry ConvertEntry => HousePlacementEntry.TwoStoryFoundations[35];
public override int ConvertOffsetY => -1;
public override Rectangle2D[] Area => AreaArray;
public override Point3D BaseBanLocation => new Point3D(4, 6, 0);
public override HouseDeed GetDeed()
{
return new SandstonePatioDeed();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); //version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class TwoStoryVilla : BaseHouse
{
public static Rectangle2D[] AreaArray = { new Rectangle2D(-5, -5, 11, 11), new Rectangle2D(2, 6, 4, 1) };
public TwoStoryVilla(Mobile owner) : base(0x9E, owner, 1100, 8)
{
uint keyValue = CreateKeys(owner);
AddSouthDoors(3, 1, 5, keyValue);
SetSign(3, 8, 24);
AddEastDoor(1, 0, 25);
AddSouthDoor(-3, -1, 25);
}
public TwoStoryVilla(Serial serial) : base(serial)
{
}
public override int DefaultPrice => 136500;
public override HousePlacementEntry ConvertEntry => HousePlacementEntry.TwoStoryFoundations[31];
public override Rectangle2D[] Area => AreaArray;
public override Point3D BaseBanLocation => new Point3D(3, 8, 0);
public override HouseDeed GetDeed()
{
return new VillaDeed();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); //version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class SmallShop : BaseHouse
{
public static Rectangle2D[] AreaArray1 = { new Rectangle2D(-3, -3, 7, 7), new Rectangle2D(-1, 4, 4, 1) };
public static Rectangle2D[] AreaArray2 = { new Rectangle2D(-3, -3, 7, 7), new Rectangle2D(-2, 4, 3, 1) };
public SmallShop(Mobile owner, int id) : base(id, owner, 425, 3)
{
uint keyValue = CreateKeys(owner);
BaseDoor door = MakeDoor(false, DoorFacing.EastCW);
door.Locked = true;
door.KeyValue = keyValue;
if (door is BaseHouseDoor houseDoor)
houseDoor.Facing = DoorFacing.EastCCW;
AddDoor(door, -2, 0, id == 0xA2 ? 24 : 27);
//AddSouthDoor( false, -2, 0, 27 - (id == 0xA2 ? 3 : 0), keyValue );
SetSign(3, 4, 7 - (id == 0xA2 ? 2 : 0));
}
public SmallShop(Serial serial) : base(serial)
{
}
public override Rectangle2D[] Area => ItemID == 0x40A2 ? AreaArray1 : AreaArray2;
public override Point3D BaseBanLocation => new Point3D(3, 4, 0);
public override int DefaultPrice => 63000;
public override HousePlacementEntry ConvertEntry => HousePlacementEntry.TwoStoryFoundations[0];
public override HouseDeed GetDeed()
{
switch (ItemID)
{
case 0xA0: return new StoneWorkshopDeed();
case 0xA2:
default: return new MarbleWorkshopDeed();
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); //version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,314 @@
using System;
using System.Collections.Generic;
using Server.Items;
using Server.Network;
namespace Server.Multis
{
public class MovingCrate : Container
{
public static readonly int MaxItemsPerSubcontainer = 20;
public static readonly int Rows = 3;
public static readonly int Columns = 5;
public static readonly int HorizontalSpacing = 25;
public static readonly int VerticalSpacing = 25;
private Timer m_InternalizeTimer;
public MovingCrate(BaseHouse house) : base(0xE3D)
{
Hue = 0x8A5;
Movable = false;
House = house;
}
public MovingCrate(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1061690; // Packing Crate
public BaseHouse House{ get; set; }
public override int DefaultMaxItems => 0;
public override int DefaultMaxWeight => 0;
public override bool IsDecoContainer => false;
/*
public override void AddNameProperties( ObjectPropertyList list )
{
base.AddNameProperties( list );
if ( House != null && House.InternalizedVendors.Count > 0 )
list.Add( 1061833, House.InternalizedVendors.Count.ToString() ); // This packing crate contains ~1_COUNT~ vendors/barkeepers.
}
*/
public override void DropItem(Item dropped)
{
// 1. Try to stack the item
foreach (Item item in Items)
if (item is PackingBox)
{
List<Item> subItems = item.Items;
for (int i = 0; i < subItems.Count; i++)
{
Item subItem = subItems[i];
if (!(subItem is Container) && subItem.StackWith(null, dropped, false))
return;
}
}
// 2. Try to drop the item into an existing container
foreach (Item item in Items)
if (item is PackingBox packingBox)
{
Container box = packingBox;
List<Item> subItems = box.Items;
if (subItems.Count < MaxItemsPerSubcontainer)
{
box.DropItem(dropped);
return;
}
}
// 3. Drop the item into a new container
Container subContainer = new PackingBox();
subContainer.DropItem(dropped);
Point3D location = GetFreeLocation();
if (location != Point3D.Zero)
{
AddItem(subContainer);
subContainer.Location = location;
}
else
{
base.DropItem(subContainer);
}
}
private Point3D GetFreeLocation()
{
bool[,] positions = new bool[Rows, Columns];
foreach (Item item in Items)
if (item is PackingBox)
{
int i = (item.Y - Bounds.Y) / VerticalSpacing;
if (i < 0)
i = 0;
else if (i >= Rows)
i = Rows - 1;
int j = (item.X - Bounds.X) / HorizontalSpacing;
if (j < 0)
j = 0;
else if (j >= Columns)
j = Columns - 1;
positions[i, j] = true;
}
for (int i = 0; i < Rows; i++)
for (int j = 0; j < Columns; j++)
if (!positions[i, j])
{
int x = Bounds.X + j * HorizontalSpacing;
int y = Bounds.Y + i * VerticalSpacing;
return new Point3D(x, y, 0);
}
return Point3D.Zero;
}
public override bool CheckHold(Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight)
{
if (m.AccessLevel < AccessLevel.GameMaster)
{
m.SendLocalizedMessage(1061145); // You cannot place items into a house moving crate.
return false;
}
return base.CheckHold(m, item, message, checkItems, plusItems, plusWeight);
}
public override bool CheckLift(Mobile from, Item item, ref LRReason reject)
{
return House?.Deleted == false && base.CheckLift(from, item, ref reject) && House.IsOwner(from);
}
public override bool CheckItemUse(Mobile from, Item item)
{
return House?.Deleted == false && base.CheckItemUse(from, item) && House.IsOwner(from);
}
public override void OnItemRemoved(Item item)
{
base.OnItemRemoved(item);
if (TotalItems == 0)
Delete();
}
public void RestartTimer()
{
if (m_InternalizeTimer == null)
{
m_InternalizeTimer = new InternalizeTimer(this);
m_InternalizeTimer.Start();
}
else
{
m_InternalizeTimer.Stop();
m_InternalizeTimer.Start();
}
}
public void Hide()
{
if (m_InternalizeTimer != null)
{
m_InternalizeTimer.Stop();
m_InternalizeTimer = null;
}
List<Item> toRemove = new List<Item>();
foreach (Item item in Items)
if (item is PackingBox && item.Items.Count == 0)
toRemove.Add(item);
foreach (Item item in toRemove)
item.Delete();
if (TotalItems == 0)
Delete();
else
Internalize();
}
public override void OnAfterDelete()
{
base.OnAfterDelete();
if (House?.MovingCrate == this)
House.MovingCrate = null;
m_InternalizeTimer?.Stop();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(1);
writer.Write(House);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
House = reader.ReadItem() as BaseHouse;
if (House != null)
{
House.MovingCrate = this;
Timer.DelayCall(TimeSpan.Zero, Hide);
}
else
{
Timer.DelayCall(TimeSpan.Zero, Delete);
}
if (version == 0)
MaxItems = -1; // reset to default
}
public class InternalizeTimer : Timer
{
private MovingCrate m_Crate;
public InternalizeTimer(MovingCrate crate) : base(TimeSpan.FromMinutes(5.0))
{
m_Crate = crate;
Priority = TimerPriority.FiveSeconds;
}
protected override void OnTick()
{
m_Crate.Hide();
}
}
}
public class PackingBox : BaseContainer
{
public PackingBox() : base(0x9A8)
{
Movable = false;
}
public PackingBox(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1061690; // Packing Crate
public override int DefaultGumpID => 0x4B;
public override int DefaultDropSound => 0x42;
public override Rectangle2D Bounds => new Rectangle2D(16, 51, 168, 73);
public override int DefaultMaxItems => 0;
public override int DefaultMaxWeight => 0;
public override void SendCantStoreMessage(Mobile to, Item item)
{
to.SendLocalizedMessage(1061145); // You cannot place items into a house moving crate.
}
public override void OnItemRemoved(Item item)
{
base.OnItemRemoved(item);
if (item.GetBounce() == null && TotalItems == 0)
Delete();
}
public override void OnItemBounceCleared(Item item)
{
base.OnItemBounceCleared(item);
if (TotalItems == 0)
Delete();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(1); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
if (version == 0)
MaxItems = -1; // reset to default
}
}
}

View file

@ -0,0 +1,142 @@
using System;
using System.Collections.Generic;
using Server.Items;
namespace Server.Multis
{
public class PreviewHouse : BaseMulti
{
private List<Item> m_Components;
private Timer m_Timer;
public PreviewHouse(int multiID) : base(multiID)
{
m_Components = new List<Item>();
MultiComponentList mcl = Components;
for (int i = 1; i < mcl.List.Length; ++i)
{
MultiTileEntry entry = mcl.List[i];
if (entry.m_Flags == 0)
{
Item item = new Static((int)entry.m_ItemID);
item.MoveToWorld(new Point3D(X + entry.m_OffsetX, Y + entry.m_OffsetY, Z + entry.m_OffsetZ), Map);
m_Components.Add(item);
}
}
m_Timer = new DecayTimer(this);
m_Timer.Start();
}
public PreviewHouse(Serial serial) : base(serial)
{
}
public override void OnLocationChange(Point3D oldLocation)
{
base.OnLocationChange(oldLocation);
if (m_Components == null)
return;
int xOffset = X - oldLocation.X;
int yOffset = Y - oldLocation.Y;
int zOffset = Z - oldLocation.Z;
for (int i = 0; i < m_Components.Count; ++i)
{
Item item = m_Components[i];
item.MoveToWorld(new Point3D(item.X + xOffset, item.Y + yOffset, item.Z + zOffset), Map);
}
}
public override void OnMapChange()
{
base.OnMapChange();
if (m_Components == null)
return;
for (int i = 0; i < m_Components.Count; ++i)
{
Item item = m_Components[i];
item.Map = Map;
}
}
public override void OnDelete()
{
base.OnDelete();
if (m_Components == null)
return;
for (int i = 0; i < m_Components.Count; ++i)
{
Item item = m_Components[i];
item.Delete();
}
}
public override void OnAfterDelete()
{
m_Timer?.Stop();
m_Timer = null;
base.OnAfterDelete();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
writer.Write(m_Components);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 0:
{
m_Components = reader.ReadStrongItemList();
break;
}
}
Timer.DelayCall(TimeSpan.Zero, Delete);
}
private class DecayTimer : Timer
{
private Item m_Item;
public DecayTimer(Item item) : base(TimeSpan.FromSeconds(20.0))
{
m_Item = item;
Priority = TimerPriority.OneSecond;
}
protected override void OnTick()
{
m_Item.Delete();
}
}
}
}