Hello,
I was wondering what needs to be changed in order to have Escorts announce a message when approached along with still having the "destination" command.

Thanks in advance.
 
Look at these portions of code for example:

From BaseQuest.cs Line 207
Code:
  if (m_Quester is BaseEscort)
            {
                BaseEscort escort = (BaseEscort)m_Quester;

                if (escort.SetControlMaster(m_Owner))
                {
                    escort.Quest = this;
                    escort.LastSeenEscorter = DateTime.UtcNow;
                    escort.StartFollow();
                    escort.AddHash(Owner);

                    string region = escort.GetDestination();

                    if (!string.IsNullOrEmpty(region))
                        escort.Say(1042806, region); // Lead on! Payment will be made when we arrive at ~1_DESTINATION~!
                    else
                        escort.Say(1042806, "destination"); // Lead on! Payment will be made when we arrive at ~1_DESTINATION~!

                    m_Owner.LastEscortTime = DateTime.UtcNow;
                }
            }

            // tick tack    
            StartTimer();
        }

From BaseQuester.cs Line 92
Code:
 public override void AddCustomContextEntries(Mobile from, List<ContextMenuEntry> list)
        {
            base.AddCustomContextEntries(from, list);

            if (from.Alive && from is PlayerMobile && TalkNumber > 0 && CanTalkTo((PlayerMobile)from))
                list.Add(new TalkEntry(this));
        }

        public override void OnMovement(Mobile m, Point3D oldLocation)
        {
            if (m.Alive && m is PlayerMobile)
            {
                PlayerMobile pm = (PlayerMobile)m;

                int range = GetAutoTalkRange(pm);

                if (m.Alive && range >= 0 && InRange(m, range) && !InRange(oldLocation, range) && CanTalkTo(pm))
                    OnTalk(pm, false);
            }
        }
tenor (1).gif
 
Hello, I just came back from a long break, I still want to implement this into my server. The gif was enough to motivate me but sadly I've had no luck.
 
Try something like this, which will be triggered when player is in range.

BaseEscort.cs

public override void OnTalk(PlayerMobile player)
{
if (AcceptEscorter(player))
base.OnTalk(player);
}
around line 54, after the above snippet
add something like this:
public override void Advertise()
{
Say("Pardon me citizen, but I am looking for a companion to assist thee.");
}

or randomize what they say:

public override void Advertise()
{
switch (Utility.Random(5))
{
case 0: Say("Pardon me citizen, but I am looking for a companion to assist thee."); break;
case 1: Say("I'm lost can you help me?"); break;
case 2: Say("Might thou be willing to accompany me on a journey?"); break;
case 3: Say("Hello adventurer I'm hiring an escort, would thou be interested.)"; break;
case 4: Say("Hail friend, I am seeking fellowship for a small expedition, would'st though care to join me?"; break;

}
}
 
Last edited:
Try something like this, which will be triggered when player is in range.

BaseEscort.cs


around line 54, after the above snippet
add something like this:


or randomize what they say:
Thanks for your reply, I've referred to your suggestions and received only one error. Could it be something I'm leaving out? Or something that is missing in BaseEscortable.cs? I probably should've mentioned in the original post; I'm using Pub 57.3 with UOR expansion. BaseEscort.cs is not being used but BaseEscortable.cs is.

Errors:
+ Mobiles/NPCs/BaseEscortable.cs:
CS0115: Line 60: 'BaseEscortable.Advertise(PlayerMobile)': no suitable method found to override
CS0115: Line 66: 'BaseEscortable.Advertise()': no suitable method found to override
 
Baseescortable not tied to the new quest system I believe is the problem...

Can try this instead: (based on movement, range= 4 tiles, and a 30 second spam timer)
[CorpseName("a human's corpse")]
public class XYZ : BaseCreature
{

[section 1] Add this:
private DateTime recoverDelay;
private static bool m_Talked;

string[] Escortsay = new string[] // things to say while greeting
{

"Pardon me citizen, but I am looking for a companion to assist thee.",

"I'm lost can you help me?",

"Might thou be willing to accompany me on a journey?",

"Hello adventurer I'm hiring an escort, would thou be interested.",

"Hail friend, I am seeking fellowship for a small expedition, would'st though care to join me?"
};

[Constructable]
{
}

[section 2] Add this:
public override void OnMovement(Mobile m, Point3D oldLocation)
{
if (m_Talked == false)
{

if (m.InRange(this, 4))
{
m_Talked = true;
SayRandom(Escortsay, this);
this.Move(GetDirectionTo(m.Location));

SpamTimer t = new SpamTimer();
t.Start();
}
}
}

private class SpamTimer : Timer
{
public SpamTimer()
: base(TimeSpan.FromSeconds(30))
{
Priority = TimerPriority.OneSecond;
}

protected override void OnTick()
{
m_Talked = false;
}
}

private static void SayRandom(string[] say, Mobile m)
{
m.Say(say[Utility.Random(say.Length)]);
}



public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
}

public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
 
Last edited:
Baseescortable not tied to the new quest system I believe is the problem...

Can try this instead: (based on movement, range= 4 tiles, and a 30 second spam timer)


[section 1] Add this:




[section 2] Add this:
are these changes all going in the BaseEscortable?
 
Two sections of code to add. First after the public class {}
Second before serialization
Hell yeah. Thanks again for all the help.

TalkingEscorts.png
Questions I have about this system are the 30-second spam timer. This 30 seconds also affects other BaseEscortables. Is there a way to make that timer only affect the one who just spoke? How do I make it so the speech is only triggered by players and not critters/ghosts/hidden players?
 
Last edited:
Hell yeah. Thanks again for all the help.

View attachment 21853
Questions I have about this system are the 30-second spam timer. This 30 seconds also affects other BaseEscortables. Is there a way to make that timer only affect the one who just spoke? How do I make it so the speech is only triggered by players and not critters/ghosts/hidden players?
Good point. You could add the code directly to the NPCs instead of BaseEscortable. This would also allow more customization on what one NPC class would say from the next, which is more realistic since prisoners would plea for help.


Use something like this in the OnMovement method.
public override void OnMovement(Mobile m, Point3D oldLocation)
{
if (m.Alive && !m.Hidden && m is PlayerMobile)
{
PlayerMobile pm = (PlayerMobile)m;
 
Last edited:
Yes! Thank you very much RedBeard! :)

I am not sure of what I am saying here, but I think a cooldown list like it works with bots could be a solution. Each time an escortable is talking, the serial is stored with a timer to remove it from the list. Then it is to validate the cooldown after the range..

Like I said, I am not sure it is the best way.. but it is what came to my mind and developing reading it.. I am thinking of giving it a shot..
 
This is the code I used in Noble.cs (they are the only one we use)

Simple list storing the serial of the NPC and the timer removes it from the list after 30 seconds.

Have fun!

--

C#:
        string[] EscortSays = new string[]
        {
            "Pardon me citizen, but I am looking for a companion to assist thee.",
            "I'm lost can you help me?",
            "Might thou be willing to accompany me on a journey?",
            "Hello adventurer I'm hiring an escort, would thou be interested?",
            "Hail friend, I am seeking fellowship for a small expedition, wouldn't though care to join me?"
        };

        static List<int> CooldownList = new List<int> {};

        public override void OnMovement(Mobile m, Point3D oldLocation)
        {
            if (m.Alive && !m.Hidden && m is PlayerMobile)
            {
                var pm = (PlayerMobile)m;
                if (pm != null)
                {
                    if (m.InRange(this, 4))
                    {
                        if (!CooldownList.Contains(Serial))
                        {
                            SayRandom(EscortSays, this);
                            this.Move(GetDirectionTo(m.Location));

                            CooldownList.Add(Serial);
                            SpamTimer t = new SpamTimer(Serial);
                            t.Start();
                        }
                    }
                }
            }
        }

        private class SpamTimer : Timer
        {
            public int Serial;

            public SpamTimer(int serial)
                : base(TimeSpan.FromSeconds(30))
            {
                Serial      = serial;
                Priority    = TimerPriority.OneSecond;
            }

            protected override void OnTick()
            {
                CooldownList.RemoveAll(x => x == Serial);
            }
        }

        private static void SayRandom(string[] say, Mobile m)
        {
            m.Say(say[Utility.Random(say.Length)]);
        }
Hell yeah. Thanks again for all the help.

View attachment 21853
Questions I have about this system are the 30-second spam timer. This 30 seconds also affects other BaseEscortables. Is there a way to make that timer only affect the one who just spoke? How do I make it so the speech is only triggered by players and not critters/ghosts/hidden players?
 
Awesome! Thank you both for this. I've wanted to have this implemented for a long time. One final question to sum this all up, how would you incorporate the escort's desired location in a message that is given when entering the range?
 
Last edited:
Back