feat: Adds rope teleporter for New Haven Mines (#2439)

### Summary

- Add InteractiveTeleporter that teleports on double-click
- Add support to decorate command
- Add rope teleporters to the New Haven mines in the decoration file
This commit is contained in:
Chuck Thier 2026-05-03 19:23:31 -05:00 committed by GitHub
parent 22dc0937a8
commit b150c48328
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 127 additions and 13 deletions

View file

@ -331,4 +331,13 @@ FlourMillSouthAddon 0x192C
# bellows # bellows
LargeForgeEastAddon 0x1986 LargeForgeEastAddon 0x1986
3644 2619 0 3644 2619 0
3596 2601 0 3596 2601 0
# New Haven Mine Teleporters
# Rope(0x14FA) teleporter
InteractionTeleporter 0x14FA (Name=a rope leading down;PointDest=(5953, 319, 0))
5994 319 0
# Rope(0x14FA) teleporter
InteractionTeleporter 0x14FA (Name=a rope leading up;PointDest=(5994, 319, 0))
5953 319 0

View file

@ -885,6 +885,77 @@ namespace Server.Commands
kt.ItemID = m_ItemID; kt.ItemID = m_ItemID;
} }
} }
else if (item is InteractionTeleporter itp)
{
itp.ItemID = m_ItemID;
for (var i = 0; i < m_Params.Length; ++i)
{
if (m_Params[i].StartsWithOrdinal("PointDest"))
{
var indexOf = m_Params[i].IndexOfOrdinal('=');
if (indexOf >= 0)
{
itp.PointDest = Point3D.Parse(m_Params[i][++indexOf..]);
}
}
else if (m_Params[i].StartsWithOrdinal("MapDest"))
{
var indexOf = m_Params[i].IndexOfOrdinal('=');
if (indexOf >= 0)
{
itp.MapDest = Map.Parse(m_Params[i][++indexOf..]);
}
}
else if (m_Params[i].StartsWithOrdinal("SourceEffect"))
{
var indexOf = m_Params[i].IndexOfOrdinal('=');
if (indexOf >= 0)
{
itp.SourceEffect = Utility.ToBoolean(m_Params[i][++indexOf..]);
}
}
else if (m_Params[i].StartsWithOrdinal("DestEffect"))
{
var indexOf = m_Params[i].IndexOfOrdinal('=');
if (indexOf >= 0)
{
itp.DestEffect = Utility.ToBoolean(m_Params[i][++indexOf..]);
}
}
else if (m_Params[i].StartsWithOrdinal("SoundID"))
{
var indexOf = m_Params[i].IndexOfOrdinal('=');
if (indexOf >= 0)
{
itp.SoundID = Utility.ToInt32(m_Params[i].AsSpan()[++indexOf..]);
}
}
else if (m_Params[i].StartsWithOrdinal("Delay"))
{
var indexOf = m_Params[i].IndexOfOrdinal('=');
if (indexOf >= 0)
{
itp.Delay = TimeSpan.Parse(m_Params[i][++indexOf..]);
}
}
else if (m_Params[i].StartsWithOrdinal("Name"))
{
var indexOf = m_Params[i].IndexOfOrdinal('=');
if (indexOf >= 0)
{
item.Name = m_Params[i][++indexOf..];
}
}
}
}
else if (item is Teleporter tp) else if (item is Teleporter tp)
{ {
for (var i = 0; i < m_Params.Length; ++i) for (var i = 0; i < m_Params.Length; ++i)

View file

@ -128,10 +128,8 @@ public partial class Teleporter : Item
public override int LabelNumber => 1026095; // teleporter public override int LabelNumber => 1026095; // teleporter
public override void GetProperties(IPropertyList list) public virtual void AddProperties(IPropertyList list)
{ {
base.GetProperties(list);
if (Active) if (Active)
{ {
list.Add(1060742); // active list.Add(1060742); // active
@ -154,6 +152,12 @@ public partial class Teleporter : Item
list.Add(1060660, $"{"Creatures"}\t{(Creatures ? "Yes" : "No")}"); list.Add(1060660, $"{"Creatures"}\t{(Creatures ? "Yes" : "No")}");
} }
public override void GetProperties(IPropertyList list)
{
base.GetProperties(list);
AddProperties(list);
}
public override void OnSingleClick(Mobile from) public override void OnSingleClick(Mobile from)
{ {
base.OnSingleClick(from); base.OnSingleClick(from);
@ -377,10 +381,8 @@ public partial class SkillTeleporter : Teleporter
return false; return false;
} }
public override void GetProperties(IPropertyList list) public override void AddProperties(IPropertyList list)
{ {
base.GetProperties(list);
var skillIndex = (int)_skill; var skillIndex = (int)_skill;
string skillName; string skillName;
@ -487,10 +489,8 @@ public partial class KeywordTeleporter : Teleporter
public override bool OnMoveOver(Mobile m) => true; public override bool OnMoveOver(Mobile m) => true;
public override void GetProperties(IPropertyList list) public override void AddProperties(IPropertyList list)
{ {
base.GetProperties(list);
list.Add(1060661, $"{"Range"}\t{_range}"); list.Add(1060661, $"{"Range"}\t{_range}");
if (_keyword >= 0) if (_keyword >= 0)
@ -934,10 +934,8 @@ public partial class ConditionTeleporter : Teleporter
return true; return true;
} }
public override void GetProperties(IPropertyList list) public override void AddProperties(IPropertyList list)
{ {
base.GetProperties(list);
using var props = ValueStringBuilder.Create(128); using var props = ValueStringBuilder.Create(128);
if (GetFlag(ConditionFlag.DenyMounted)) if (GetFlag(ConditionFlag.DenyMounted))
@ -1026,3 +1024,35 @@ public partial class ConditionTeleporter : Teleporter
DeadOnly = 0x100 DeadOnly = 0x100
} }
} }
[SerializationGenerator(0, false)]
public partial class InteractionTeleporter : Teleporter
{
[Constructible]
public InteractionTeleporter()
{
Visible = true;
}
[Constructible]
public InteractionTeleporter(Point3D pointDest, Map mapDest = null) : base(pointDest, mapDest)
{
Visible = true;
}
public override bool OnMoveOver(Mobile m) => true;
public override void AddProperties(IPropertyList list) {}
public override void OnDoubleClick(Mobile m)
{
base.OnDoubleClick(m);
if (Active && CanTeleport(m) && m.InRange(GetWorldLocation(), 2))
{
StartTeleport(m);
}
}
public override void OnDoubleClickDead(Mobile m) => OnDoubleClick(m);
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Items.InteractionTeleporter"
}