Overwrite
Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
This commit is contained in:
417
Scripts/Services/MondainsLegacyQuests/BaseEscort.cs
Normal file
417
Scripts/Services/MondainsLegacyQuests/BaseEscort.cs
Normal file
@@ -0,0 +1,417 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Server.ContextMenus;
|
||||
using Server.Mobiles;
|
||||
using Server.Services.Virtues;
|
||||
|
||||
namespace Server.Engines.Quests
|
||||
{
|
||||
public class BaseEscort : MondainQuester
|
||||
{
|
||||
private static readonly TimeSpan m_EscortDelay = TimeSpan.FromMinutes(5.0);
|
||||
private static readonly Dictionary<Mobile, Mobile> m_EscortTable = new Dictionary<Mobile, Mobile>();
|
||||
private Timer m_DeleteTimer;
|
||||
private bool m_Checked;
|
||||
|
||||
public BaseQuest Quest { get; set; }
|
||||
public DateTime LastSeenEscorter { get; set; }
|
||||
|
||||
public BaseEscort()
|
||||
: base()
|
||||
{
|
||||
AI = AIType.AI_Melee;
|
||||
FightMode = FightMode.Aggressor;
|
||||
RangePerception = 22;
|
||||
RangeFight = 1;
|
||||
ActiveSpeed = 0.2;
|
||||
PassiveSpeed = 1.0;
|
||||
|
||||
ControlSlots = 0;
|
||||
}
|
||||
|
||||
public BaseEscort(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool InitialInnocent { get { return true; } }
|
||||
public override bool IsInvulnerable { get { return false; } }
|
||||
public override bool Commandable { get { return false; } }
|
||||
|
||||
public override Type[] Quests { get { return null; } }
|
||||
|
||||
public override bool CanAutoStable { get { return false; } }
|
||||
public override bool CanDetectHidden { get { return false; } }
|
||||
|
||||
public override void OnTalk(PlayerMobile player)
|
||||
{
|
||||
if (AcceptEscorter(player))
|
||||
base.OnTalk(player);
|
||||
}
|
||||
|
||||
public override bool CanBeRenamedBy(Mobile from)
|
||||
{
|
||||
return (from.AccessLevel >= AccessLevel.GameMaster);
|
||||
}
|
||||
|
||||
public override void AddCustomContextEntries(Mobile from, List<ContextMenuEntry> list)
|
||||
{
|
||||
if (from.Alive && from == ControlMaster)
|
||||
list.Add(new AbandonEscortEntry(this));
|
||||
|
||||
base.AddCustomContextEntries(from, list);
|
||||
}
|
||||
|
||||
public override void OnAfterDelete()
|
||||
{
|
||||
if (Quest != null)
|
||||
{
|
||||
Quest.RemoveQuest();
|
||||
|
||||
if (Quest.Owner != null)
|
||||
m_EscortTable.Remove(Quest.Owner);
|
||||
}
|
||||
|
||||
base.OnAfterDelete();
|
||||
}
|
||||
|
||||
public override void OnThink()
|
||||
{
|
||||
base.OnThink();
|
||||
|
||||
CheckAtDestination();
|
||||
}
|
||||
|
||||
public override bool CanBeDamaged()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void InitBody()
|
||||
{
|
||||
SetStr(90, 100);
|
||||
SetDex(90, 100);
|
||||
SetInt(15, 25);
|
||||
|
||||
Hue = Utility.RandomSkinHue();
|
||||
Female = Utility.RandomBool();
|
||||
Name = NameList.RandomName(Female ? "female" : "male");
|
||||
Race = Race.Human;
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
Utility.AssignRandomFacialHair(this);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write((int)0); // version
|
||||
|
||||
writer.Write(m_DeleteTimer != null);
|
||||
|
||||
if (m_DeleteTimer != null)
|
||||
writer.WriteDeltaTime(m_DeleteTimer.Next);
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
|
||||
if (reader.ReadBool())
|
||||
{
|
||||
DateTime deleteTime = reader.ReadDeltaTime();
|
||||
m_DeleteTimer = Timer.DelayCall(deleteTime - DateTime.UtcNow, new TimerCallback(Delete));
|
||||
}
|
||||
}
|
||||
|
||||
public void AddHash(PlayerMobile player)
|
||||
{
|
||||
m_EscortTable[player] = this;
|
||||
}
|
||||
|
||||
public virtual void StartFollow()
|
||||
{
|
||||
StartFollow(ControlMaster);
|
||||
}
|
||||
|
||||
public virtual void StartFollow(Mobile escorter)
|
||||
{
|
||||
ActiveSpeed = 0.1;
|
||||
PassiveSpeed = 0.2;
|
||||
|
||||
ControlOrder = OrderType.Follow;
|
||||
ControlTarget = escorter;
|
||||
|
||||
CurrentSpeed = 0.1;
|
||||
}
|
||||
|
||||
public virtual void StopFollow()
|
||||
{
|
||||
ActiveSpeed = 0.2;
|
||||
PassiveSpeed = 1.0;
|
||||
|
||||
ControlOrder = OrderType.None;
|
||||
ControlTarget = null;
|
||||
|
||||
CurrentSpeed = 1.0;
|
||||
|
||||
SetControlMaster(null);
|
||||
}
|
||||
|
||||
public virtual void BeginDelete(Mobile m)
|
||||
{
|
||||
StopFollow();
|
||||
|
||||
if (m != null)
|
||||
m_EscortTable.Remove(m);
|
||||
|
||||
m_DeleteTimer = Timer.DelayCall(TimeSpan.FromSeconds(45.0), new TimerCallback(Delete));
|
||||
}
|
||||
|
||||
public virtual bool AcceptEscorter(Mobile m)
|
||||
{
|
||||
if (!m.Alive)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (m_DeleteTimer != null)
|
||||
{
|
||||
Say(500898); // I am sorry, but I do not wish to go anywhere.
|
||||
return false;
|
||||
}
|
||||
else if (Controlled)
|
||||
{
|
||||
if (m == ControlMaster)
|
||||
m.SendGump(new MondainQuestGump(Quest, MondainQuestGump.Section.InProgress, false));
|
||||
else
|
||||
Say(500897); // I am already being led!
|
||||
|
||||
return false;
|
||||
}
|
||||
else if (!m.InRange(Location, 5))
|
||||
{
|
||||
Say(500348); // I am too far away to do that.
|
||||
return false;
|
||||
}
|
||||
else if (m_EscortTable.ContainsKey(m))
|
||||
{
|
||||
Say(500896); // I see you already have an escort.
|
||||
return false;
|
||||
}
|
||||
else if (m is PlayerMobile && (((PlayerMobile)m).LastEscortTime + m_EscortDelay) >= DateTime.UtcNow)
|
||||
{
|
||||
int minutes = (int)Math.Ceiling(((((PlayerMobile)m).LastEscortTime + m_EscortDelay) - DateTime.UtcNow).TotalMinutes);
|
||||
|
||||
Say("You must rest {0} minute{1} before we set out on this journey.", minutes, minutes == 1 ? "" : "s");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual EscortObjective GetObjective()
|
||||
{
|
||||
if (Quest != null)
|
||||
{
|
||||
for (int i = 0; i < Quest.Objectives.Count; i++)
|
||||
{
|
||||
EscortObjective escort = Quest.Objectives[i] as EscortObjective;
|
||||
|
||||
if (escort != null && !escort.Completed && !escort.Failed)
|
||||
return escort;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual Mobile GetEscorter()
|
||||
{
|
||||
Mobile master = ControlMaster;
|
||||
|
||||
if (master == null || !Controlled)
|
||||
{
|
||||
return master;
|
||||
}
|
||||
else if (master.Map != Map || !master.InRange(Location, 30) || !master.Alive)
|
||||
{
|
||||
TimeSpan lastSeenDelay = DateTime.UtcNow - LastSeenEscorter;
|
||||
|
||||
if (lastSeenDelay >= TimeSpan.FromMinutes(2.0))
|
||||
{
|
||||
EscortObjective escort = GetObjective();
|
||||
|
||||
if (escort != null)
|
||||
{
|
||||
master.SendLocalizedMessage(1071194); // You have failed your escort quest…
|
||||
master.PlaySound(0x5B3);
|
||||
escort.Fail();
|
||||
}
|
||||
|
||||
master.SendLocalizedMessage(1042473); // You have lost the person you were escorting.
|
||||
Say(1005653); // Hmmm. I seem to have lost my master.
|
||||
|
||||
StopFollow();
|
||||
m_EscortTable.Remove(master);
|
||||
m_DeleteTimer = Timer.DelayCall(TimeSpan.FromSeconds(5.0), new TimerCallback(Delete));
|
||||
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
ControlOrder = OrderType.Stay;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ControlOrder != OrderType.Follow)
|
||||
StartFollow(master);
|
||||
|
||||
LastSeenEscorter = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
return master;
|
||||
}
|
||||
|
||||
public virtual Region GetDestination()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual bool CheckAtDestination()
|
||||
{
|
||||
if (Quest != null)
|
||||
{
|
||||
EscortObjective escort = GetObjective();
|
||||
|
||||
if (escort == null)
|
||||
return false;
|
||||
|
||||
Mobile escorter = GetEscorter();
|
||||
|
||||
if (escorter == null)
|
||||
return false;
|
||||
|
||||
if (escort.Region != null && escort.Region.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.
|
||||
|
||||
escort.Complete();
|
||||
|
||||
if (Quest.Completed)
|
||||
{
|
||||
escorter.SendLocalizedMessage(1046258, null, 0x23); // Your quest is complete.
|
||||
|
||||
if (QuestHelper.AnyRewards(Quest))
|
||||
escorter.SendGump(new MondainQuestGump(Quest, MondainQuestGump.Section.Rewards, false, true));
|
||||
else
|
||||
Quest.GiveRewards();
|
||||
|
||||
escorter.PlaySound(Quest.CompleteSound);
|
||||
|
||||
StopFollow();
|
||||
m_EscortTable.Remove(escorter);
|
||||
m_DeleteTimer = Timer.DelayCall(TimeSpan.FromSeconds(5.0), new TimerCallback(Delete));
|
||||
|
||||
// fame
|
||||
Misc.Titles.AwardFame(escorter, escort.Fame, true);
|
||||
|
||||
// compassion
|
||||
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, escort.Compassion, ref gainedPath))
|
||||
{
|
||||
pm.SendLocalizedMessage(1074949, null, 0x2A); // You have demonstrated your compassion! Your kind actions have been noted.
|
||||
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
pm.SendLocalizedMessage(1053003); // You have achieved the highest path of compassion and can no longer gain any further.
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
escorter.PlaySound(Quest.UpdateSound);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (!m_Checked)
|
||||
{
|
||||
Region region = GetDestination();
|
||||
|
||||
if (region != null && region.Contains(Location))
|
||||
{
|
||||
m_DeleteTimer = Timer.DelayCall(TimeSpan.FromSeconds(5.0), new TimerCallback(Delete));
|
||||
m_Checked = true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private class AbandonEscortEntry : ContextMenuEntry
|
||||
{
|
||||
private readonly BaseEscort m_Mobile;
|
||||
|
||||
public AbandonEscortEntry(BaseEscort m)
|
||||
: base(6102, 3)
|
||||
{
|
||||
m_Mobile = m;
|
||||
}
|
||||
|
||||
public override void OnClick()
|
||||
{
|
||||
Owner.From.SendLocalizedMessage(1071194); // You have failed your escort quest…
|
||||
Owner.From.PlaySound(0x5B3);
|
||||
m_Mobile.Delete();
|
||||
}
|
||||
}
|
||||
|
||||
public static void DeleteEscort(Mobile owner)
|
||||
{
|
||||
PlayerMobile pm = owner as PlayerMobile;
|
||||
|
||||
foreach (var escortquest in pm.Quests.Where(x => x.Quester is BaseEscort))
|
||||
{
|
||||
BaseEscort escort = (BaseEscort)escortquest.Quester;
|
||||
|
||||
Timer.DelayCall(TimeSpan.FromSeconds(3), new TimerCallback(
|
||||
delegate
|
||||
{
|
||||
escort.Say(500901); // Ack! My escort has come to haunt me!
|
||||
owner.SendLocalizedMessage(1071194); // You have failed your escort quest…
|
||||
owner.PlaySound(0x5B3);
|
||||
escort.Delete();
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user