778 lines
No EOL
18 KiB
C#
778 lines
No EOL
18 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using Server;
|
|
using Server.Items;
|
|
using Server.Network;
|
|
using Server.ContextMenus;
|
|
using EDI = Server.Mobiles.EscortDestinationInfo;
|
|
using Server.Engines.MLQuests;
|
|
using Server.Engines.MLQuests.Definitions;
|
|
using Server.Engines.MLQuests.Objectives;
|
|
|
|
namespace Server.Mobiles
|
|
{
|
|
public class BaseEscortable : BaseCreature
|
|
{
|
|
public static readonly TimeSpan EscortDelay = TimeSpan.FromMinutes( 5.0 );
|
|
public static readonly TimeSpan AbandonDelay = MLQuestSystem.Enabled ? TimeSpan.FromMinutes( 1.0 ) : TimeSpan.FromMinutes( 2.0 );
|
|
public static readonly TimeSpan DeleteTime = MLQuestSystem.Enabled ? TimeSpan.FromSeconds( 100 ) : TimeSpan.FromSeconds( 30 );
|
|
|
|
public override bool StaticMLQuester { get { return false; } } // Suppress automatic quest registration on creation/deserialization
|
|
|
|
private MLQuest m_MLQuest;
|
|
|
|
protected override List<MLQuest> ConstructQuestList()
|
|
{
|
|
if ( m_MLQuest == null )
|
|
{
|
|
Region reg = Region;
|
|
Type[] list = reg.IsPartOf( "Haven Island" ) ? m_MLQuestTypesNH : m_MLQuestTypes;
|
|
|
|
int randomIdx = Utility.Random( list.Length );
|
|
|
|
for ( int i = 0; i < list.Length; ++i )
|
|
{
|
|
Type questType = list[randomIdx];
|
|
|
|
MLQuest quest = MLQuestSystem.FindQuest( questType );
|
|
|
|
if ( quest != null )
|
|
{
|
|
bool okay = true;
|
|
|
|
foreach ( BaseObjective obj in quest.Objectives )
|
|
{
|
|
if ( obj is EscortObjective && ( (EscortObjective)obj ).Destination.Contains( reg ) )
|
|
{
|
|
okay = false; // We're already there!
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( okay )
|
|
{
|
|
m_MLQuest = quest;
|
|
break;
|
|
}
|
|
}
|
|
else if ( MLQuestSystem.Debug )
|
|
{
|
|
Console.WriteLine( "Warning: Escortable cannot be assigned quest type '{0}', it is not registered", questType.Name );
|
|
}
|
|
|
|
randomIdx = ( randomIdx + 1 ) % list.Length;
|
|
}
|
|
|
|
if ( m_MLQuest == null )
|
|
{
|
|
if ( MLQuestSystem.Debug )
|
|
Console.WriteLine( "Warning: No suitable quest found for escort {0}", Serial );
|
|
|
|
return null;
|
|
}
|
|
}
|
|
|
|
List<MLQuest> result = new List<MLQuest>();
|
|
result.Add( m_MLQuest );
|
|
|
|
return result;
|
|
}
|
|
|
|
public override bool CanShout { get { return ( !Controlled && !IsBeingDeleted ); } }
|
|
|
|
public override void Shout( PlayerMobile pm )
|
|
{
|
|
/*
|
|
* 1072301 - You there! Care to hear how to earn some easy gold?
|
|
* 1072302 - Adventurer! I have an offer for you.
|
|
* 1072303 - Wait! I have an opportunity for you to make some gold!
|
|
*/
|
|
MLQuestSystem.Tell( this, pm, Utility.Random( 1072301, 3 ) );
|
|
}
|
|
|
|
private EDI m_Destination;
|
|
private string m_DestinationString;
|
|
|
|
private DateTime m_DeleteTime;
|
|
private Timer m_DeleteTimer;
|
|
|
|
private bool m_DeleteCorpse = false;
|
|
|
|
public bool IsBeingDeleted
|
|
{
|
|
get { return ( m_DeleteTimer != null ); }
|
|
}
|
|
|
|
public override bool Commandable { get { return false; } } // Our master cannot boss us around!
|
|
public override bool DeleteCorpseOnDeath { get { return m_DeleteCorpse; } }
|
|
|
|
[CommandProperty(AccessLevel.GameMaster)]
|
|
public string Destination
|
|
{
|
|
get { return m_Destination == null ? null : m_Destination.Name; }
|
|
set { m_DestinationString = value; m_Destination = EDI.Find(value); }
|
|
}
|
|
|
|
// Classic list
|
|
// Used when: !MLQuestSystem.Enabled && !Core.ML
|
|
private static string[] m_TownNames = new string[]
|
|
{
|
|
"Cove", "Britain", "Jhelom",
|
|
"Minoc", "Ocllo", "Trinsic",
|
|
"Vesper", "Yew", "Skara Brae",
|
|
"Nujel'm", "Moonglow", "Magincia"
|
|
};
|
|
|
|
// ML list, pre-ML quest system
|
|
// Used when: !MLQuestSystem.Enabled && Core.ML
|
|
private static string[] m_MLTownNames = new string[]
|
|
{
|
|
"Cove", "Serpent's Hold", "Jhelom",
|
|
"Nujel'm"
|
|
};
|
|
|
|
// ML quest system general list
|
|
// Used when: MLQuestSystem.Enabled && !Region.IsPartOf( "Haven Island" )
|
|
private static Type[] m_MLQuestTypes =
|
|
{
|
|
typeof( EscortToYew ),
|
|
typeof( EscortToVesper ),
|
|
typeof( EscortToTrinsic ),
|
|
typeof( EscortToSkaraBrae ),
|
|
typeof( EscortToSerpentsHold ),
|
|
typeof( EscortToNujelm ),
|
|
typeof( EscortToMoonglow ),
|
|
typeof( EscortToMinoc ),
|
|
typeof( EscortToMagincia ),
|
|
typeof( EscortToJhelom ),
|
|
typeof( EscortToCove ),
|
|
typeof( EscortToBritain )
|
|
// Ocllo was removed in pub 56
|
|
//typeof( EscortToOcllo )
|
|
};
|
|
|
|
// ML quest system New Haven list
|
|
// Used when: MLQuestSystem.Enabled && Region.IsPartOf( "Haven Island" )
|
|
private static Type[] m_MLQuestTypesNH =
|
|
{
|
|
typeof( EscortToNHAlchemist ),
|
|
typeof( EscortToNHBard ),
|
|
typeof( EscortToNHWarrior ),
|
|
typeof( EscortToNHTailor ),
|
|
typeof( EscortToNHCarpenter ),
|
|
typeof( EscortToNHMapmaker ),
|
|
typeof( EscortToNHMage ),
|
|
typeof( EscortToNHInn ),
|
|
// Farm destination was removed
|
|
//typeof( EscortToNHFarm ),
|
|
typeof( EscortToNHDocks ),
|
|
typeof( EscortToNHBowyer ),
|
|
typeof( EscortToNHBank )
|
|
};
|
|
|
|
[Constructable]
|
|
public BaseEscortable()
|
|
: base(AIType.AI_Melee, FightMode.Aggressor, 22, 1, 0.2, 1.0)
|
|
{
|
|
InitBody();
|
|
InitOutfit();
|
|
|
|
Fame = 200;
|
|
Karma = 4000;
|
|
}
|
|
|
|
public virtual void InitBody()
|
|
{
|
|
SetStr(90, 100);
|
|
SetDex(90, 100);
|
|
SetInt(15, 25);
|
|
|
|
Hue = Utility.RandomSkinHue();
|
|
|
|
if (Female = Utility.RandomBool())
|
|
{
|
|
Body = 401;
|
|
Name = NameList.RandomName("female");
|
|
}
|
|
else
|
|
{
|
|
Body = 400;
|
|
Name = NameList.RandomName("male");
|
|
}
|
|
}
|
|
|
|
public virtual void InitOutfit()
|
|
{
|
|
AddItem(new FancyShirt(Utility.RandomNeutralHue()));
|
|
AddItem(new ShortPants(Utility.RandomNeutralHue()));
|
|
AddItem(new Boots(Utility.RandomNeutralHue()));
|
|
|
|
Utility.AssignRandomHair(this);
|
|
|
|
PackGold(200, 250);
|
|
}
|
|
|
|
public virtual bool SayDestinationTo(Mobile m)
|
|
{
|
|
EDI dest = GetDestination();
|
|
|
|
if (dest == null || !m.Alive)
|
|
return false;
|
|
|
|
Mobile escorter = GetEscorter();
|
|
|
|
if (escorter == null)
|
|
{
|
|
Say("I am looking to go to {0}, will you take me?", (dest.Name == "Ocllo" && m.Map == Map.Trammel) ? "Haven" : dest.Name);
|
|
return true;
|
|
}
|
|
else if (escorter == m)
|
|
{
|
|
Say("Lead on! Payment will be made when we arrive in {0}.", (dest.Name == "Ocllo" && m.Map == Map.Trammel) ? "Haven" : dest.Name);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private static Hashtable m_EscortTable = new Hashtable();
|
|
|
|
public static Hashtable EscortTable
|
|
{
|
|
get { return m_EscortTable; }
|
|
}
|
|
|
|
public virtual bool AcceptEscorter(Mobile m)
|
|
{
|
|
EDI dest = GetDestination();
|
|
|
|
if (dest == null)
|
|
return false;
|
|
|
|
Mobile escorter = GetEscorter();
|
|
|
|
if (escorter != null || !m.Alive)
|
|
return false;
|
|
|
|
BaseEscortable escortable = (BaseEscortable)m_EscortTable[m];
|
|
|
|
if (escortable != null && !escortable.Deleted && escortable.GetEscorter() == m)
|
|
{
|
|
Say("I see you already have an escort.");
|
|
return false;
|
|
}
|
|
else if (m is PlayerMobile && (((PlayerMobile)m).LastEscortTime + EscortDelay) >= DateTime.UtcNow)
|
|
{
|
|
int minutes = (int)Math.Ceiling(((((PlayerMobile)m).LastEscortTime + EscortDelay) - DateTime.UtcNow).TotalMinutes);
|
|
|
|
Say("You must rest {0} minute{1} before we set out on this journey.", minutes, minutes == 1 ? "" : "s");
|
|
return false;
|
|
}
|
|
else if (SetControlMaster(m))
|
|
{
|
|
m_LastSeenEscorter = DateTime.UtcNow;
|
|
|
|
if (m is PlayerMobile)
|
|
((PlayerMobile)m).LastEscortTime = DateTime.UtcNow;
|
|
|
|
Say("Lead on! Payment will be made when we arrive in {0}.", (dest.Name == "Ocllo" && m.Map == Map.Trammel) ? "Haven" : dest.Name);
|
|
m_EscortTable[m] = this;
|
|
StartFollow();
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public override bool HandlesOnSpeech(Mobile from)
|
|
{
|
|
if ( MLQuestSystem.Enabled )
|
|
return false;
|
|
|
|
if (from.InRange(this.Location, 3))
|
|
return true;
|
|
|
|
return base.HandlesOnSpeech(from);
|
|
}
|
|
|
|
public override void OnSpeech(SpeechEventArgs e)
|
|
{
|
|
base.OnSpeech(e);
|
|
|
|
EDI dest = GetDestination();
|
|
|
|
if (dest != null && !e.Handled && e.Mobile.InRange(this.Location, 3))
|
|
{
|
|
if (e.HasKeyword(0x1D)) // *destination*
|
|
e.Handled = SayDestinationTo(e.Mobile);
|
|
else if (e.HasKeyword(0x1E)) // *i will take thee*
|
|
e.Handled = AcceptEscorter(e.Mobile);
|
|
}
|
|
}
|
|
|
|
public override void OnAfterDelete()
|
|
{
|
|
if (m_DeleteTimer != null)
|
|
m_DeleteTimer.Stop();
|
|
|
|
m_DeleteTimer = null;
|
|
|
|
base.OnAfterDelete();
|
|
}
|
|
|
|
public override void OnThink()
|
|
{
|
|
base.OnThink();
|
|
CheckAtDestination();
|
|
}
|
|
|
|
protected override bool OnMove(Direction d)
|
|
{
|
|
if (!base.OnMove(d))
|
|
return false;
|
|
|
|
CheckAtDestination();
|
|
|
|
return true;
|
|
}
|
|
|
|
// TODO: Pre-ML methods below, might be mergeable with the ML methods in EscortObjective
|
|
|
|
public virtual void StartFollow()
|
|
{
|
|
StartFollow(GetEscorter());
|
|
}
|
|
|
|
public virtual void StartFollow(Mobile escorter)
|
|
{
|
|
if (escorter == null)
|
|
return;
|
|
|
|
ActiveSpeed = 0.1;
|
|
PassiveSpeed = 0.2;
|
|
|
|
ControlOrder = OrderType.Follow;
|
|
ControlTarget = escorter;
|
|
|
|
if ((IsPrisoner == true) && (CantWalk == true))
|
|
{
|
|
CantWalk = false;
|
|
}
|
|
CurrentSpeed = 0.1;
|
|
}
|
|
|
|
public virtual void StopFollow()
|
|
{
|
|
ActiveSpeed = 0.2;
|
|
PassiveSpeed = 1.0;
|
|
|
|
ControlOrder = OrderType.None;
|
|
ControlTarget = null;
|
|
|
|
CurrentSpeed = 1.0;
|
|
}
|
|
|
|
private DateTime m_LastSeenEscorter;
|
|
|
|
public virtual Mobile GetEscorter()
|
|
{
|
|
if ( !Controlled )
|
|
return null;
|
|
|
|
Mobile master = ControlMaster;
|
|
|
|
if ( MLQuestSystem.Enabled || master == null )
|
|
return master;
|
|
|
|
if (master.Deleted || master.Map != this.Map || !master.InRange(Location, 30) || !master.Alive)
|
|
{
|
|
StopFollow();
|
|
|
|
TimeSpan lastSeenDelay = DateTime.UtcNow - m_LastSeenEscorter;
|
|
|
|
if (lastSeenDelay >= AbandonDelay)
|
|
{
|
|
master.SendLocalizedMessage(1042473); // You have lost the person you were escorting.
|
|
Say(1005653); // Hmmm. I seem to have lost my master.
|
|
|
|
SetControlMaster(null);
|
|
m_EscortTable.Remove(master);
|
|
|
|
Timer.DelayCall(TimeSpan.FromSeconds(5.0), new TimerCallback(Delete));
|
|
return null;
|
|
}
|
|
else
|
|
{
|
|
ControlOrder = OrderType.Stay;
|
|
return master;
|
|
}
|
|
}
|
|
|
|
if (ControlOrder != OrderType.Follow)
|
|
StartFollow(master);
|
|
|
|
m_LastSeenEscorter = DateTime.UtcNow;
|
|
return master;
|
|
}
|
|
|
|
public virtual void BeginDelete()
|
|
{
|
|
if (m_DeleteTimer != null)
|
|
m_DeleteTimer.Stop();
|
|
|
|
m_DeleteTime = DateTime.UtcNow + DeleteTime;
|
|
|
|
m_DeleteTimer = new DeleteTimer(this, m_DeleteTime - DateTime.UtcNow);
|
|
m_DeleteTimer.Start();
|
|
}
|
|
|
|
public virtual bool CheckAtDestination()
|
|
{
|
|
if ( MLQuestSystem.Enabled )
|
|
return false;
|
|
|
|
EDI dest = GetDestination();
|
|
|
|
if (dest == null)
|
|
return false;
|
|
|
|
Mobile escorter = GetEscorter();
|
|
|
|
if (escorter == null)
|
|
return false;
|
|
|
|
if (dest.Contains(Location))
|
|
{
|
|
Say(1042809, escorter.Name); // We have arrived! I thank thee, ~1_PLAYER_NAME~! I have no further need of thy services. Here is thy pay.
|
|
|
|
// not going anywhere
|
|
m_Destination = null;
|
|
m_DestinationString = null;
|
|
|
|
Container cont = escorter.Backpack;
|
|
|
|
if (cont == null)
|
|
cont = escorter.BankBox;
|
|
|
|
Gold gold = new Gold(500, 1000);
|
|
|
|
if (!cont.TryDropItem(escorter, gold, false))
|
|
gold.MoveToWorld(escorter.Location, escorter.Map);
|
|
|
|
StopFollow();
|
|
SetControlMaster(null);
|
|
m_EscortTable.Remove(escorter);
|
|
BeginDelete();
|
|
|
|
Misc.Titles.AwardFame(escorter, 10, true);
|
|
|
|
bool gainedPath = false;
|
|
|
|
PlayerMobile pm = escorter as PlayerMobile;
|
|
|
|
if (pm != null)
|
|
{
|
|
if (pm.CompassionGains > 0 && DateTime.UtcNow > pm.NextCompassionDay)
|
|
{
|
|
pm.NextCompassionDay = DateTime.MinValue;
|
|
pm.CompassionGains = 0;
|
|
}
|
|
|
|
if (pm.CompassionGains >= 5) // have already gained 5 times in one day, can gain no more
|
|
{
|
|
pm.SendLocalizedMessage(1053004); // You must wait about a day before you can gain in compassion again.
|
|
}
|
|
else if (VirtueHelper.Award(pm, VirtueName.Compassion, this.IsPrisoner ? 400 : 200, ref gainedPath))
|
|
{
|
|
if (gainedPath)
|
|
pm.SendLocalizedMessage(1053005); // You have achieved a path in compassion!
|
|
else
|
|
pm.SendLocalizedMessage(1053002); // You have gained in compassion.
|
|
|
|
pm.NextCompassionDay = DateTime.UtcNow + TimeSpan.FromDays(1.0); // in one day CompassionGains gets reset to 0
|
|
++pm.CompassionGains;
|
|
|
|
if (pm.CompassionGains >= 5)
|
|
pm.SendLocalizedMessage(1053004); // You must wait about a day before you can gain in compassion again.
|
|
}
|
|
else
|
|
{
|
|
pm.SendLocalizedMessage(1053003); // You have achieved the highest path of compassion and can no longer gain any further.
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public override bool OnBeforeDeath()
|
|
{
|
|
m_DeleteCorpse = ( Controlled || IsBeingDeleted );
|
|
|
|
return base.OnBeforeDeath();
|
|
}
|
|
|
|
public BaseEscortable(Serial serial)
|
|
: base(serial)
|
|
{
|
|
}
|
|
|
|
public override void Serialize(GenericWriter writer)
|
|
{
|
|
base.Serialize(writer);
|
|
|
|
writer.Write((int)1); // version
|
|
|
|
EDI dest = GetDestination();
|
|
|
|
writer.Write(dest != null);
|
|
|
|
if (dest != null)
|
|
writer.Write(dest.Name);
|
|
|
|
writer.Write(m_DeleteTimer != null);
|
|
|
|
if (m_DeleteTimer != null)
|
|
writer.WriteDeltaTime(m_DeleteTime);
|
|
|
|
MLQuestSystem.WriteQuestRef( writer, StaticMLQuester ? null : m_MLQuest );
|
|
}
|
|
|
|
public override void Deserialize(GenericReader reader)
|
|
{
|
|
base.Deserialize(reader);
|
|
|
|
int version = reader.ReadInt();
|
|
|
|
if (reader.ReadBool())
|
|
m_DestinationString = reader.ReadString(); // NOTE: We cannot EDI.Find here, regions have not yet been loaded :-(
|
|
|
|
if (reader.ReadBool())
|
|
{
|
|
m_DeleteTime = reader.ReadDeltaTime();
|
|
m_DeleteTimer = new DeleteTimer(this, m_DeleteTime - DateTime.UtcNow);
|
|
m_DeleteTimer.Start();
|
|
}
|
|
|
|
if ( version >= 1 )
|
|
{
|
|
MLQuest quest = MLQuestSystem.ReadQuestRef( reader );
|
|
|
|
if ( MLQuestSystem.Enabled && quest != null && !StaticMLQuester )
|
|
m_MLQuest = quest;
|
|
}
|
|
}
|
|
|
|
public override bool CanBeRenamedBy(Mobile from)
|
|
{
|
|
return (from.AccessLevel >= AccessLevel.GameMaster);
|
|
}
|
|
|
|
public override void AddCustomContextEntries( Mobile from, List<ContextMenuEntry> list )
|
|
{
|
|
if ( from.Alive )
|
|
{
|
|
Mobile escorter = GetEscorter();
|
|
|
|
if ( !MLQuestSystem.Enabled && GetDestination() != null )
|
|
{
|
|
if ( escorter == null || escorter == from )
|
|
list.Add( new AskDestinationEntry( this, from ) );
|
|
|
|
if ( escorter == null )
|
|
list.Add( new AcceptEscortEntry( this, from ) );
|
|
}
|
|
|
|
if ( escorter == from )
|
|
list.Add( new AbandonEscortEntry( this, from ) );
|
|
}
|
|
|
|
base.AddCustomContextEntries( from, list );
|
|
}
|
|
|
|
public virtual string[] GetPossibleDestinations()
|
|
{
|
|
if (!Core.ML)
|
|
return m_TownNames;
|
|
else
|
|
return m_MLTownNames;
|
|
}
|
|
|
|
public virtual string PickRandomDestination()
|
|
{
|
|
if (Map.Felucca.Regions.Count == 0 || Map == null || Map == Map.Internal || Location == Point3D.Zero)
|
|
return null; // Not yet fully initialized
|
|
|
|
string[] possible = GetPossibleDestinations();
|
|
string picked = null;
|
|
|
|
while (picked == null)
|
|
{
|
|
picked = possible[Utility.Random(possible.Length)];
|
|
EDI test = EDI.Find(picked);
|
|
|
|
if (test != null && test.Contains(Location))
|
|
picked = null;
|
|
}
|
|
|
|
return picked;
|
|
}
|
|
|
|
public EDI GetDestination()
|
|
{
|
|
if ( MLQuestSystem.Enabled )
|
|
return null;
|
|
|
|
if (m_DestinationString == null && m_DeleteTimer == null)
|
|
m_DestinationString = PickRandomDestination();
|
|
|
|
if (m_Destination != null && m_Destination.Name == m_DestinationString)
|
|
return m_Destination;
|
|
|
|
if (Map.Felucca.Regions.Count > 0)
|
|
return (m_Destination = EDI.Find(m_DestinationString));
|
|
|
|
return (m_Destination = null);
|
|
}
|
|
|
|
private class DeleteTimer : Timer
|
|
{
|
|
private Mobile m_Mobile;
|
|
|
|
public DeleteTimer(Mobile m, TimeSpan delay)
|
|
: base(delay)
|
|
{
|
|
m_Mobile = m;
|
|
|
|
Priority = TimerPriority.OneSecond;
|
|
}
|
|
|
|
protected override void OnTick()
|
|
{
|
|
m_Mobile.Delete();
|
|
}
|
|
}
|
|
}
|
|
|
|
public class EscortDestinationInfo
|
|
{
|
|
private string m_Name;
|
|
private Region m_Region;
|
|
//private Rectangle2D[] m_Bounds;
|
|
|
|
public string Name
|
|
{
|
|
get { return m_Name; }
|
|
}
|
|
|
|
public Region Region
|
|
{
|
|
get { return m_Region; }
|
|
}
|
|
|
|
/*public Rectangle2D[] Bounds
|
|
{
|
|
get{ return m_Bounds; }
|
|
}*/
|
|
|
|
public bool Contains(Point3D p)
|
|
{
|
|
return m_Region.Contains(p);
|
|
}
|
|
|
|
public EscortDestinationInfo(string name, Region region)
|
|
{
|
|
m_Name = name;
|
|
m_Region = region;
|
|
}
|
|
|
|
private static Hashtable m_Table;
|
|
|
|
public static void LoadTable()
|
|
{
|
|
ICollection list = Map.Felucca.Regions.Values;
|
|
|
|
if (list.Count == 0)
|
|
return;
|
|
|
|
m_Table = new Hashtable();
|
|
|
|
foreach (Region r in list)
|
|
{
|
|
if (r.Name == null)
|
|
continue;
|
|
|
|
if (r is Regions.DungeonRegion || r is Regions.TownRegion)
|
|
m_Table[r.Name] = new EscortDestinationInfo(r.Name, r);
|
|
}
|
|
}
|
|
|
|
public static EDI Find(string name)
|
|
{
|
|
if (m_Table == null)
|
|
LoadTable();
|
|
|
|
if (name == null || m_Table == null)
|
|
return null;
|
|
|
|
return (EscortDestinationInfo)m_Table[name];
|
|
}
|
|
}
|
|
|
|
public class AskDestinationEntry : ContextMenuEntry
|
|
{
|
|
private BaseEscortable m_Mobile;
|
|
private Mobile m_From;
|
|
|
|
public AskDestinationEntry(BaseEscortable m, Mobile from)
|
|
: base(6100, 3)
|
|
{
|
|
m_Mobile = m;
|
|
m_From = from;
|
|
}
|
|
|
|
public override void OnClick()
|
|
{
|
|
m_Mobile.SayDestinationTo(m_From);
|
|
}
|
|
}
|
|
|
|
public class AcceptEscortEntry : ContextMenuEntry
|
|
{
|
|
private BaseEscortable m_Mobile;
|
|
private Mobile m_From;
|
|
|
|
public AcceptEscortEntry(BaseEscortable m, Mobile from)
|
|
: base(6101, 3)
|
|
{
|
|
m_Mobile = m;
|
|
m_From = from;
|
|
}
|
|
|
|
public override void OnClick()
|
|
{
|
|
m_Mobile.AcceptEscorter(m_From);
|
|
}
|
|
}
|
|
|
|
public class AbandonEscortEntry : ContextMenuEntry
|
|
{
|
|
private BaseEscortable m_Mobile;
|
|
private Mobile m_From;
|
|
|
|
public AbandonEscortEntry(BaseEscortable m, Mobile from)
|
|
: base(6102, 3)
|
|
{
|
|
m_Mobile = m;
|
|
m_From = from;
|
|
}
|
|
|
|
public override void OnClick()
|
|
{
|
|
m_Mobile.Delete(); // OSI just seems to delete instantly
|
|
}
|
|
}
|
|
} |