v0.0.1-Alpha (#42)
This commit is contained in:
parent
d30f93c454
commit
a36796c2c1
3552 changed files with 2476 additions and 15223 deletions
66
Projects/Scripts/Mobiles/Townfolk/Actor.cs
Normal file
66
Projects/Scripts/Mobiles/Townfolk/Actor.cs
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
using Server.Items;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class Actor : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Actor() : base(AIType.AI_Animal, FightMode.None, 10, 1, 0.2, 0.4)
|
||||
{
|
||||
InitStats(31, 41, 51);
|
||||
|
||||
SpeechHue = Utility.RandomDyedHue();
|
||||
|
||||
Hue = Race.Human.RandomSkinHue();
|
||||
|
||||
if (Female = Utility.RandomBool())
|
||||
{
|
||||
Body = 0x191;
|
||||
Name = NameList.RandomName("female");
|
||||
AddItem(new FancyDress(Utility.RandomDyedHue()));
|
||||
Title = "the actress";
|
||||
}
|
||||
else
|
||||
{
|
||||
Body = 0x190;
|
||||
Name = NameList.RandomName("male");
|
||||
AddItem(new LongPants(Utility.RandomNeutralHue()));
|
||||
AddItem(new FancyShirt(Utility.RandomDyedHue()));
|
||||
Title = "the actor";
|
||||
}
|
||||
|
||||
AddItem(new Boots(Utility.RandomNeutralHue()));
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
|
||||
Container pack = new Backpack();
|
||||
|
||||
pack.DropItem(new Gold(250, 300));
|
||||
|
||||
pack.Movable = false;
|
||||
|
||||
AddItem(pack);
|
||||
}
|
||||
|
||||
public Actor(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public override bool ClickTitle => false;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
72
Projects/Scripts/Mobiles/Townfolk/Artist.cs
Normal file
72
Projects/Scripts/Mobiles/Townfolk/Artist.cs
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
using Server.Items;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class Artist : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Artist()
|
||||
: base(AIType.AI_Animal, FightMode.None, 10, 1, 0.2, 0.4)
|
||||
{
|
||||
InitStats(31, 41, 51);
|
||||
|
||||
SetSkill(SkillName.Healing, 36, 68);
|
||||
|
||||
|
||||
SpeechHue = Utility.RandomDyedHue();
|
||||
Title = "the artist";
|
||||
Hue = Race.Human.RandomSkinHue();
|
||||
|
||||
|
||||
if (Female = Utility.RandomBool())
|
||||
{
|
||||
Body = 0x191;
|
||||
Name = NameList.RandomName("female");
|
||||
}
|
||||
else
|
||||
{
|
||||
Body = 0x190;
|
||||
Name = NameList.RandomName("male");
|
||||
}
|
||||
|
||||
AddItem(new Doublet(Utility.RandomDyedHue()));
|
||||
AddItem(new Sandals(Utility.RandomNeutralHue()));
|
||||
AddItem(new ShortPants(Utility.RandomNeutralHue()));
|
||||
AddItem(new HalfApron(Utility.RandomDyedHue()));
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
|
||||
Container pack = new Backpack();
|
||||
|
||||
pack.DropItem(new Gold(250, 300));
|
||||
|
||||
pack.Movable = false;
|
||||
|
||||
AddItem(pack);
|
||||
}
|
||||
|
||||
|
||||
public Artist(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool CanTeach => true;
|
||||
|
||||
public override bool ClickTitle => false;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
429
Projects/Scripts/Mobiles/Townfolk/Banker.cs
Normal file
429
Projects/Scripts/Mobiles/Townfolk/Banker.cs
Normal file
|
|
@ -0,0 +1,429 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Server.Accounting;
|
||||
using Server.ContextMenus;
|
||||
using Server.Items;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class Banker : BaseVendor
|
||||
{
|
||||
private List<SBInfo> m_SBInfos = new List<SBInfo>();
|
||||
|
||||
[Constructible]
|
||||
public Banker() : base("the banker")
|
||||
{
|
||||
}
|
||||
|
||||
public Banker(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
protected override List<SBInfo> SBInfos => m_SBInfos;
|
||||
|
||||
public override NpcGuild NpcGuild => NpcGuild.MerchantsGuild;
|
||||
|
||||
public override void InitSBInfo()
|
||||
{
|
||||
m_SBInfos.Add(new SBBanker());
|
||||
}
|
||||
|
||||
public static int GetBalance(Mobile m)
|
||||
{
|
||||
long balance = 0;
|
||||
|
||||
if (AccountGold.Enabled && m.Account != null)
|
||||
{
|
||||
balance = m.Account.GetTotalGold();
|
||||
if (balance >= int.MaxValue) return int.MaxValue;
|
||||
}
|
||||
|
||||
Container bank = m.FindBankNoCreate();
|
||||
|
||||
if (bank != null)
|
||||
{
|
||||
List<Gold> gold = bank.FindItemsByType<Gold>();
|
||||
List<BankCheck> checks = bank.FindItemsByType<BankCheck>();
|
||||
|
||||
balance += gold.Aggregate(0L, (c, t) => c + t.Amount);
|
||||
if (balance >= int.MaxValue)
|
||||
return int.MaxValue;
|
||||
balance += checks.Aggregate(0L, (c, t) => c + t.Worth);
|
||||
}
|
||||
|
||||
return Math.Max(0, (int)Math.Min(int.MaxValue, balance));
|
||||
}
|
||||
|
||||
public static int GetBalance(Mobile m, out Item[] gold, out Item[] checks)
|
||||
{
|
||||
long balance = 0;
|
||||
|
||||
if (AccountGold.Enabled && m.Account != null)
|
||||
{
|
||||
balance = m.Account.GetTotalGold();
|
||||
|
||||
if (balance > int.MaxValue)
|
||||
{
|
||||
gold = checks = new Item[0];
|
||||
return int.MaxValue;
|
||||
}
|
||||
}
|
||||
|
||||
Container bank = m.FindBankNoCreate();
|
||||
|
||||
if (bank != null)
|
||||
{
|
||||
gold = bank.FindItemsByType(typeof(Gold));
|
||||
checks = bank.FindItemsByType(typeof(BankCheck));
|
||||
|
||||
balance += gold.OfType<Gold>().Aggregate(0L, (c, t) => c + t.Amount);
|
||||
if (balance >= int.MaxValue) return int.MaxValue;
|
||||
balance += checks.OfType<BankCheck>().Aggregate(0L, (c, t) => c + t.Worth);
|
||||
}
|
||||
else
|
||||
{
|
||||
gold = checks = new Item[0];
|
||||
}
|
||||
|
||||
return Math.Max(0, (int)Math.Min(int.MaxValue, balance));
|
||||
}
|
||||
|
||||
public static bool Withdraw(Mobile from, int amount)
|
||||
{
|
||||
// If for whatever reason the TOL checks fail, we should still try old methods for withdrawing currency.
|
||||
if (AccountGold.Enabled && from.Account != null && from.Account.WithdrawGold(amount)) return true;
|
||||
|
||||
int balance = GetBalance(from, out Item[] gold, out Item[] checks);
|
||||
|
||||
if (balance < amount) return false;
|
||||
|
||||
for (int i = 0; amount > 0 && i < gold.Length; ++i)
|
||||
if (gold[i].Amount <= amount)
|
||||
{
|
||||
amount -= gold[i].Amount;
|
||||
gold[i].Delete();
|
||||
}
|
||||
else
|
||||
{
|
||||
gold[i].Amount -= amount;
|
||||
amount = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; amount > 0 && i < checks.Length; ++i)
|
||||
{
|
||||
BankCheck check = (BankCheck)checks[i];
|
||||
|
||||
if (check.Worth <= amount)
|
||||
{
|
||||
amount -= check.Worth;
|
||||
check.Delete();
|
||||
}
|
||||
else
|
||||
{
|
||||
check.Worth -= amount;
|
||||
amount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool Deposit(Mobile from, int amount)
|
||||
{
|
||||
// If for whatever reason the TOL checks fail, we should still try old methods for depositing currency.
|
||||
if (AccountGold.Enabled && from.Account != null && from.Account.DepositGold(amount)) return true;
|
||||
|
||||
BankBox box = from.FindBankNoCreate();
|
||||
|
||||
if (box == null) return false;
|
||||
|
||||
List<Item> items = new List<Item>();
|
||||
|
||||
while (amount > 0)
|
||||
{
|
||||
Item item;
|
||||
if (amount < 5000)
|
||||
{
|
||||
item = new Gold(amount);
|
||||
amount = 0;
|
||||
}
|
||||
else if (amount <= 1000000)
|
||||
{
|
||||
item = new BankCheck(amount);
|
||||
amount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
item = new BankCheck(1000000);
|
||||
amount -= 1000000;
|
||||
}
|
||||
|
||||
if (box.TryDropItem(from, item, false))
|
||||
{
|
||||
items.Add(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
item.Delete();
|
||||
foreach (Item curItem in items) curItem.Delete();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static int DepositUpTo(Mobile from, int amount)
|
||||
{
|
||||
// If for whatever reason the TOL checks fail, we should still try old methods for depositing currency.
|
||||
if (AccountGold.Enabled && from.Account != null && from.Account.DepositGold(amount)) return amount;
|
||||
|
||||
BankBox box = from.FindBankNoCreate();
|
||||
|
||||
if (box == null) return 0;
|
||||
|
||||
int amountLeft = amount;
|
||||
while (amountLeft > 0)
|
||||
{
|
||||
Item item;
|
||||
int amountGiven;
|
||||
|
||||
if (amountLeft < 5000)
|
||||
{
|
||||
item = new Gold(amountLeft);
|
||||
amountGiven = amountLeft;
|
||||
}
|
||||
else if (amountLeft <= 1000000)
|
||||
{
|
||||
item = new BankCheck(amountLeft);
|
||||
amountGiven = amountLeft;
|
||||
}
|
||||
else
|
||||
{
|
||||
item = new BankCheck(1000000);
|
||||
amountGiven = 1000000;
|
||||
}
|
||||
|
||||
if (box.TryDropItem(from, item, false))
|
||||
{
|
||||
amountLeft -= amountGiven;
|
||||
}
|
||||
else
|
||||
{
|
||||
item.Delete();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return amount - amountLeft;
|
||||
}
|
||||
|
||||
public static void Deposit(Container cont, int amount)
|
||||
{
|
||||
while (amount > 0)
|
||||
{
|
||||
Item item;
|
||||
|
||||
if (amount < 5000)
|
||||
{
|
||||
item = new Gold(amount);
|
||||
amount = 0;
|
||||
}
|
||||
else if (amount <= 1000000)
|
||||
{
|
||||
item = new BankCheck(amount);
|
||||
amount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
item = new BankCheck(1000000);
|
||||
amount -= 1000000;
|
||||
}
|
||||
|
||||
cont.DropItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool HandlesOnSpeech(Mobile from)
|
||||
{
|
||||
if (from.InRange(Location, 12))
|
||||
return true;
|
||||
|
||||
return base.HandlesOnSpeech(from);
|
||||
}
|
||||
|
||||
public override void OnSpeech(SpeechEventArgs e)
|
||||
{
|
||||
if (!e.Handled && e.Mobile.InRange(Location, 12))
|
||||
for (int i = 0; i < e.Keywords.Length; ++i)
|
||||
{
|
||||
int keyword = e.Keywords[i];
|
||||
|
||||
switch (keyword)
|
||||
{
|
||||
case 0x0000: // *withdraw*
|
||||
{
|
||||
e.Handled = true;
|
||||
|
||||
if (e.Mobile.Criminal)
|
||||
{
|
||||
Say(500389); // I will not do business with a criminal!
|
||||
break;
|
||||
}
|
||||
|
||||
string[] split = e.Speech.Split(' ');
|
||||
|
||||
if (split.Length >= 2)
|
||||
{
|
||||
Container pack = e.Mobile.Backpack;
|
||||
|
||||
if (!int.TryParse(split[1], out int amount))
|
||||
break;
|
||||
|
||||
if (!Core.ML && amount > 5000 || Core.ML && amount > 60000)
|
||||
{
|
||||
Say(500381); // Thou canst not withdraw so much at one time!
|
||||
}
|
||||
else if (pack?.Deleted != false || !(pack.TotalWeight < pack.MaxWeight) ||
|
||||
!(pack.TotalItems < pack.MaxItems))
|
||||
{
|
||||
Say(1048147); // Your backpack can't hold anything else.
|
||||
}
|
||||
else if (amount > 0)
|
||||
{
|
||||
BankBox box = e.Mobile.FindBankNoCreate();
|
||||
|
||||
if (box == null || !Withdraw(e.Mobile, amount))
|
||||
{
|
||||
Say(500384); // Ah, art thou trying to fool me? Thou hast not so much gold!
|
||||
}
|
||||
else
|
||||
{
|
||||
pack.DropItem(new Gold(amount));
|
||||
|
||||
Say(1010005); // Thou hast withdrawn gold from thy account.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x0001: // *balance*
|
||||
{
|
||||
e.Handled = true;
|
||||
|
||||
if (e.Mobile.Criminal)
|
||||
{
|
||||
Say(500389); // I will not do business with a criminal!
|
||||
break;
|
||||
}
|
||||
|
||||
if (AccountGold.Enabled && e.Mobile.Account != null)
|
||||
Say(1155855,
|
||||
$"{e.Mobile.Account.TotalPlat:#,0}\t{e.Mobile.Account.TotalGold:#,0}"); // Thy current bank balance is ~1_AMOUNT~ platinum and ~2_AMOUNT~ gold.
|
||||
else
|
||||
Say(1042759,
|
||||
GetBalance(e.Mobile).ToString("#,0")); // Thy current bank balance is ~1_AMOUNT~ gold.
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x0002: // *bank*
|
||||
{
|
||||
e.Handled = true;
|
||||
|
||||
if (e.Mobile.Criminal)
|
||||
{
|
||||
Say(500378); // Thou art a criminal and cannot access thy bank box.
|
||||
break;
|
||||
}
|
||||
|
||||
e.Mobile.BankBox.Open();
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x0003: // *check*
|
||||
{
|
||||
e.Handled = true;
|
||||
|
||||
if (AccountGold.Enabled)
|
||||
break;
|
||||
|
||||
if (e.Mobile.Criminal)
|
||||
{
|
||||
Say(500389); // I will not do business with a criminal!
|
||||
break;
|
||||
}
|
||||
|
||||
string[] split = e.Speech.Split(' ');
|
||||
|
||||
if (split.Length >= 2)
|
||||
{
|
||||
if (!int.TryParse(split[1], out int amount))
|
||||
break;
|
||||
|
||||
if (amount < 5000)
|
||||
{
|
||||
Say(1010006); // We cannot create checks for such a paltry amount of gold!
|
||||
}
|
||||
else if (amount > 1000000)
|
||||
{
|
||||
Say(1010007); // Our policies prevent us from creating checks worth that much!
|
||||
}
|
||||
else
|
||||
{
|
||||
BankCheck check = new BankCheck(amount);
|
||||
|
||||
BankBox box = e.Mobile.BankBox;
|
||||
|
||||
if (!box.TryDropItem(e.Mobile, check, false))
|
||||
{
|
||||
Say(500386); // There's not enough room in your bankbox for the check!
|
||||
check.Delete();
|
||||
}
|
||||
else if (!box.ConsumeTotal(typeof(Gold), amount))
|
||||
{
|
||||
Say(500384); // Ah, art thou trying to fool me? Thou hast not so much gold!
|
||||
check.Delete();
|
||||
}
|
||||
else
|
||||
{
|
||||
Say(1042673, AffixType.Append, amount.ToString(),
|
||||
""); // Into your bank box I have placed a check in the amount of:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
base.OnSpeech(e);
|
||||
}
|
||||
|
||||
public override void AddCustomContextEntries(Mobile from, List<ContextMenuEntry> list)
|
||||
{
|
||||
if (from.Alive)
|
||||
list.Add(new OpenBankEntry(from, this));
|
||||
|
||||
base.AddCustomContextEntries(from, list);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
743
Projects/Scripts/Mobiles/Townfolk/BaseEscortable.cs
Normal file
743
Projects/Scripts/Mobiles/Townfolk/BaseEscortable.cs
Normal file
|
|
@ -0,0 +1,743 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Server.ContextMenus;
|
||||
using Server.Engines.MLQuests;
|
||||
using Server.Engines.MLQuests.Definitions;
|
||||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Items;
|
||||
using Server.Misc;
|
||||
using Server.Regions;
|
||||
using EDI = Server.Mobiles.EscortDestinationInfo;
|
||||
|
||||
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);
|
||||
|
||||
// Classic list
|
||||
// Used when: !MLQuestSystem.Enabled && !Core.ML
|
||||
private static string[] m_TownNames =
|
||||
{
|
||||
"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 =
|
||||
{
|
||||
"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)
|
||||
};
|
||||
|
||||
private bool m_DeleteCorpse;
|
||||
|
||||
private DateTime m_DeleteTime;
|
||||
private Timer m_DeleteTimer;
|
||||
|
||||
private EDI m_Destination;
|
||||
private string m_DestinationString;
|
||||
|
||||
private DateTime m_LastSeenEscorter;
|
||||
|
||||
private MLQuest m_MLQuest;
|
||||
|
||||
[Constructible]
|
||||
public BaseEscortable()
|
||||
: base(AIType.AI_Melee, FightMode.Aggressor, 22, 1, 0.2, 1.0)
|
||||
{
|
||||
InitBody();
|
||||
InitOutfit();
|
||||
|
||||
Fame = 200;
|
||||
Karma = 4000;
|
||||
}
|
||||
|
||||
public BaseEscortable(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool StaticMLQuester => false; // Suppress automatic quest registration on creation/deserialization
|
||||
|
||||
public override bool CanShout => !Controlled && !IsBeingDeleted;
|
||||
|
||||
public bool IsBeingDeleted => m_DeleteTimer != null;
|
||||
|
||||
public override bool Commandable => false; // Our master cannot boss us around!
|
||||
public override bool DeleteCorpseOnDeath => m_DeleteCorpse;
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public string Destination
|
||||
{
|
||||
get => m_Destination?.Name;
|
||||
set
|
||||
{
|
||||
m_DestinationString = value;
|
||||
m_Destination = EDI.Find(value);
|
||||
}
|
||||
}
|
||||
|
||||
public static Dictionary<Mobile, BaseEscortable> EscortTable{ get; } = new Dictionary<Mobile, BaseEscortable>();
|
||||
|
||||
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 objective && objective.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> { m_MLQuest };
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
public virtual void InitBody()
|
||||
{
|
||||
SetStr(90, 100);
|
||||
SetDex(90, 100);
|
||||
SetInt(15, 25);
|
||||
|
||||
Hue = Race.Human.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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public virtual bool AcceptEscorter(Mobile m)
|
||||
{
|
||||
EDI dest = GetDestination();
|
||||
|
||||
if (dest == null)
|
||||
return false;
|
||||
|
||||
if (GetEscorter() != null || !m.Alive)
|
||||
return false;
|
||||
|
||||
if (EscortTable.TryGetValue(m, out BaseEscortable escortable) && escortable?.Deleted == false && escortable.GetEscorter() == m)
|
||||
{
|
||||
Say("I see you already have an escort.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m is PlayerMobile mobile && mobile.LastEscortTime + EscortDelay >= DateTime.UtcNow)
|
||||
{
|
||||
int minutes =
|
||||
(int)Math.Ceiling((mobile.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;
|
||||
}
|
||||
|
||||
if (SetControlMaster(m))
|
||||
{
|
||||
m_LastSeenEscorter = DateTime.UtcNow;
|
||||
|
||||
if (m is PlayerMobile playerMobile)
|
||||
playerMobile.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);
|
||||
EscortTable[m] = this;
|
||||
StartFollow();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool HandlesOnSpeech(Mobile from)
|
||||
{
|
||||
return !MLQuestSystem.Enabled && (from.InRange(Location, 3) || base.HandlesOnSpeech(from));
|
||||
}
|
||||
|
||||
public override void OnSpeech(SpeechEventArgs e)
|
||||
{
|
||||
base.OnSpeech(e);
|
||||
|
||||
if (GetDestination() == null || e.Handled || !e.Mobile.InRange(Location, 3))
|
||||
return;
|
||||
|
||||
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()
|
||||
{
|
||||
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 && CantWalk) CantWalk = false;
|
||||
CurrentSpeed = 0.1;
|
||||
}
|
||||
|
||||
public virtual void StopFollow()
|
||||
{
|
||||
ActiveSpeed = 0.2;
|
||||
PassiveSpeed = 1.0;
|
||||
|
||||
ControlOrder = OrderType.None;
|
||||
ControlTarget = null;
|
||||
|
||||
CurrentSpeed = 1.0;
|
||||
}
|
||||
|
||||
public virtual Mobile GetEscorter()
|
||||
{
|
||||
if (!Controlled)
|
||||
return null;
|
||||
|
||||
Mobile master = ControlMaster;
|
||||
|
||||
if (MLQuestSystem.Enabled || master == null)
|
||||
return master;
|
||||
|
||||
if (master.Deleted || master.Map != 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);
|
||||
EscortTable.Remove(master);
|
||||
|
||||
Timer.DelayCall(TimeSpan.FromSeconds(5.0), Delete);
|
||||
return null;
|
||||
}
|
||||
|
||||
ControlOrder = OrderType.Stay;
|
||||
return master;
|
||||
}
|
||||
|
||||
if (ControlOrder != OrderType.Follow)
|
||||
StartFollow(master);
|
||||
|
||||
m_LastSeenEscorter = DateTime.UtcNow;
|
||||
return master;
|
||||
}
|
||||
|
||||
public virtual void BeginDelete()
|
||||
{
|
||||
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 ?? escorter.BankBox;
|
||||
|
||||
Gold gold = new Gold(500, 1000);
|
||||
|
||||
if (!cont.TryDropItem(escorter, gold, false))
|
||||
gold.MoveToWorld(escorter.Location, escorter.Map);
|
||||
|
||||
StopFollow();
|
||||
SetControlMaster(null);
|
||||
EscortTable.Remove(escorter);
|
||||
BeginDelete();
|
||||
|
||||
Titles.AwardFame(escorter, 10, true);
|
||||
|
||||
bool gainedPath = false;
|
||||
|
||||
if (escorter is PlayerMobile pm)
|
||||
{
|
||||
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, 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 override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(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));
|
||||
}
|
||||
|
||||
base.AddCustomContextEntries(from, list);
|
||||
}
|
||||
|
||||
public virtual string[] GetPossibleDestinations()
|
||||
{
|
||||
return Core.ML ? m_MLTownNames : m_TownNames;
|
||||
}
|
||||
|
||||
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.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 static Dictionary<string, EscortDestinationInfo> m_Table;
|
||||
|
||||
public EscortDestinationInfo(string name, Region region)
|
||||
{
|
||||
Name = name;
|
||||
Region = region;
|
||||
}
|
||||
|
||||
public string Name{ get; }
|
||||
|
||||
public Region Region{ get; }
|
||||
|
||||
public bool Contains(Point3D p)
|
||||
{
|
||||
return Region.Contains(p);
|
||||
}
|
||||
|
||||
public static void LoadTable()
|
||||
{
|
||||
ICollection list = Map.Felucca.Regions.Values;
|
||||
|
||||
if (list.Count == 0)
|
||||
return;
|
||||
|
||||
m_Table = new Dictionary<string, EscortDestinationInfo>();
|
||||
|
||||
foreach (Region r in list)
|
||||
{
|
||||
if (r.Name != null && (r is DungeonRegion || r is 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;
|
||||
|
||||
m_Table.TryGetValue(name, out EscortDestinationInfo info);
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
||||
public class AskDestinationEntry : ContextMenuEntry
|
||||
{
|
||||
private Mobile m_From;
|
||||
private BaseEscortable m_Mobile;
|
||||
|
||||
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 Mobile m_From;
|
||||
private BaseEscortable m_Mobile;
|
||||
|
||||
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;
|
||||
|
||||
public AbandonEscortEntry(BaseEscortable m)
|
||||
: base(6102, 3)
|
||||
{
|
||||
m_Mobile = m;
|
||||
}
|
||||
|
||||
public override void OnClick()
|
||||
{
|
||||
m_Mobile.Delete(); // OSI just seems to delete instantly
|
||||
}
|
||||
}
|
||||
}
|
||||
77
Projects/Scripts/Mobiles/Townfolk/BrideGroom.cs
Normal file
77
Projects/Scripts/Mobiles/Townfolk/BrideGroom.cs
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
using Server.Items;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class BrideGroom : BaseEscortable
|
||||
{
|
||||
[Constructible]
|
||||
public BrideGroom()
|
||||
{
|
||||
if (Female)
|
||||
Title = "the bride";
|
||||
else
|
||||
Title = "the groom";
|
||||
}
|
||||
|
||||
public BrideGroom(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool CanTeach => true;
|
||||
public override bool ClickTitle => false; // Do not display 'the groom' when single-clicking
|
||||
|
||||
private static int GetRandomHue()
|
||||
{
|
||||
switch (Utility.Random(6))
|
||||
{
|
||||
default:
|
||||
case 0: return 0;
|
||||
case 1: return Utility.RandomBlueHue();
|
||||
case 2: return Utility.RandomGreenHue();
|
||||
case 3: return Utility.RandomRedHue();
|
||||
case 4: return Utility.RandomYellowHue();
|
||||
case 5: return Utility.RandomNeutralHue();
|
||||
}
|
||||
}
|
||||
|
||||
public override void InitOutfit()
|
||||
{
|
||||
if (Female)
|
||||
AddItem(new FancyDress());
|
||||
else
|
||||
AddItem(new FancyShirt());
|
||||
|
||||
int lowHue = GetRandomHue();
|
||||
|
||||
AddItem(new LongPants(lowHue));
|
||||
|
||||
if (Female)
|
||||
AddItem(new Shoes(lowHue));
|
||||
else
|
||||
AddItem(new Boots(lowHue));
|
||||
|
||||
if (Utility.RandomBool())
|
||||
HairItemID = 0x203B;
|
||||
else
|
||||
HairItemID = 0x203C;
|
||||
|
||||
HairHue = Race.RandomHairHue();
|
||||
|
||||
PackGold(200, 250);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
71
Projects/Scripts/Mobiles/Townfolk/EscortableMage.cs
Normal file
71
Projects/Scripts/Mobiles/Townfolk/EscortableMage.cs
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
using Server.Items;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class EscortableMage : BaseEscortable
|
||||
{
|
||||
[Constructible]
|
||||
public EscortableMage()
|
||||
{
|
||||
Title = "the mage";
|
||||
|
||||
SetSkill(SkillName.EvalInt, 80.0, 100.0);
|
||||
SetSkill(SkillName.Inscribe, 80.0, 100.0);
|
||||
SetSkill(SkillName.Magery, 80.0, 100.0);
|
||||
SetSkill(SkillName.Meditation, 80.0, 100.0);
|
||||
SetSkill(SkillName.MagicResist, 80.0, 100.0);
|
||||
}
|
||||
|
||||
public EscortableMage(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool CanTeach => true;
|
||||
public override bool ClickTitle => false; // Do not display 'the mage' when single-clicking
|
||||
|
||||
private static int GetRandomHue()
|
||||
{
|
||||
switch (Utility.Random(5))
|
||||
{
|
||||
default:
|
||||
case 0: return Utility.RandomBlueHue();
|
||||
case 1: return Utility.RandomGreenHue();
|
||||
case 2: return Utility.RandomRedHue();
|
||||
case 3: return Utility.RandomYellowHue();
|
||||
case 4: return Utility.RandomNeutralHue();
|
||||
}
|
||||
}
|
||||
|
||||
public override void InitOutfit()
|
||||
{
|
||||
AddItem(new Robe(GetRandomHue()));
|
||||
|
||||
int lowHue = GetRandomHue();
|
||||
|
||||
AddItem(new ShortPants(lowHue));
|
||||
|
||||
if (Female)
|
||||
AddItem(new ThighBoots(lowHue));
|
||||
else
|
||||
AddItem(new Boots(lowHue));
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
|
||||
PackGold(200, 250);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
77
Projects/Scripts/Mobiles/Townfolk/Gypsy.cs
Normal file
77
Projects/Scripts/Mobiles/Townfolk/Gypsy.cs
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
using Server.Items;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class Gypsy : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Gypsy()
|
||||
: base(AIType.AI_Animal, FightMode.None, 10, 1, 0.2, 0.4)
|
||||
{
|
||||
InitStats(31, 41, 51);
|
||||
|
||||
SpeechHue = Utility.RandomDyedHue();
|
||||
|
||||
SetSkill(SkillName.Cooking, 65, 88);
|
||||
SetSkill(SkillName.Snooping, 65, 88);
|
||||
SetSkill(SkillName.Stealing, 65, 88);
|
||||
|
||||
Hue = Race.Human.RandomSkinHue();
|
||||
|
||||
if (Female = Utility.RandomBool())
|
||||
{
|
||||
Body = 0x191;
|
||||
Name = NameList.RandomName("female");
|
||||
AddItem(new Kilt(Utility.RandomDyedHue()));
|
||||
AddItem(new Shirt(Utility.RandomDyedHue()));
|
||||
AddItem(new ThighBoots());
|
||||
Title = "the gypsy";
|
||||
}
|
||||
else
|
||||
{
|
||||
Body = 0x190;
|
||||
Name = NameList.RandomName("male");
|
||||
AddItem(new ShortPants(Utility.RandomNeutralHue()));
|
||||
AddItem(new Shirt(Utility.RandomDyedHue()));
|
||||
AddItem(new Sandals());
|
||||
Title = "the gypsy";
|
||||
}
|
||||
|
||||
AddItem(new Bandana(Utility.RandomDyedHue()));
|
||||
AddItem(new Dagger());
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
|
||||
Container pack = new Backpack();
|
||||
|
||||
pack.DropItem(new Gold(250, 300));
|
||||
|
||||
pack.Movable = false;
|
||||
|
||||
AddItem(pack);
|
||||
}
|
||||
|
||||
public Gypsy(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public override bool CanTeach => true;
|
||||
public override bool ClickTitle => false;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
74
Projects/Scripts/Mobiles/Townfolk/HarborMaster.cs
Normal file
74
Projects/Scripts/Mobiles/Townfolk/HarborMaster.cs
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
using Server.Items;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class HarborMaster : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public HarborMaster()
|
||||
: base(AIType.AI_Animal, FightMode.None, 10, 1, 0.2, 0.4)
|
||||
{
|
||||
InitStats(31, 41, 51);
|
||||
|
||||
SetSkill(SkillName.Mining, 36, 68);
|
||||
|
||||
|
||||
SpeechHue = Utility.RandomDyedHue();
|
||||
Hue = Race.Human.RandomSkinHue();
|
||||
Blessed = true;
|
||||
|
||||
|
||||
if (Female = Utility.RandomBool())
|
||||
{
|
||||
Body = 0x191;
|
||||
Name = NameList.RandomName("female");
|
||||
Title = "the Harbor Mistress";
|
||||
}
|
||||
else
|
||||
{
|
||||
Body = 0x190;
|
||||
Name = NameList.RandomName("male");
|
||||
Title = "the Harbor Master";
|
||||
}
|
||||
|
||||
AddItem(new Shirt(Utility.RandomDyedHue()));
|
||||
AddItem(new Boots());
|
||||
AddItem(new LongPants(Utility.RandomNeutralHue()));
|
||||
AddItem(new QuarterStaff());
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
|
||||
Container pack = new Backpack();
|
||||
|
||||
pack.DropItem(new Gold(250, 300));
|
||||
|
||||
pack.Movable = false;
|
||||
|
||||
AddItem(pack);
|
||||
}
|
||||
|
||||
|
||||
public HarborMaster(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool CanTeach => false;
|
||||
|
||||
public override bool ClickTitle => false;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
80
Projects/Scripts/Mobiles/Townfolk/Merchant.cs
Normal file
80
Projects/Scripts/Mobiles/Townfolk/Merchant.cs
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
using Server.Items;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class Merchant : BaseEscortable
|
||||
{
|
||||
[Constructible]
|
||||
public Merchant()
|
||||
{
|
||||
Title = "the merchant";
|
||||
SetSkill(SkillName.ItemID, 55.0, 78.0);
|
||||
SetSkill(SkillName.ArmsLore, 55, 78);
|
||||
}
|
||||
|
||||
public Merchant(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool CanTeach => true;
|
||||
public override bool ClickTitle => false; // Do not display 'the merchant' when single-clicking
|
||||
|
||||
private static int GetRandomHue()
|
||||
{
|
||||
switch (Utility.Random(6))
|
||||
{
|
||||
default:
|
||||
case 0: return 0;
|
||||
case 1: return Utility.RandomBlueHue();
|
||||
case 2: return Utility.RandomGreenHue();
|
||||
case 3: return Utility.RandomRedHue();
|
||||
case 4: return Utility.RandomYellowHue();
|
||||
case 5: return Utility.RandomNeutralHue();
|
||||
}
|
||||
}
|
||||
|
||||
public override void InitOutfit()
|
||||
{
|
||||
if (Female)
|
||||
AddItem(new PlainDress());
|
||||
else
|
||||
AddItem(new Shirt(GetRandomHue()));
|
||||
|
||||
int lowHue = GetRandomHue();
|
||||
|
||||
AddItem(new ThighBoots());
|
||||
|
||||
if (Female)
|
||||
AddItem(new FancyDress(lowHue));
|
||||
else
|
||||
AddItem(new FancyShirt(lowHue));
|
||||
AddItem(new LongPants(lowHue));
|
||||
|
||||
if (!Female)
|
||||
AddItem(new BodySash(lowHue));
|
||||
|
||||
|
||||
//if ( !Female )
|
||||
//AddItem( new Longsword() );
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
|
||||
PackGold(200, 250);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
72
Projects/Scripts/Mobiles/Townfolk/Messenger.cs
Normal file
72
Projects/Scripts/Mobiles/Townfolk/Messenger.cs
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
using Server.Items;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class Messenger : BaseEscortable
|
||||
{
|
||||
[Constructible]
|
||||
public Messenger()
|
||||
{
|
||||
Title = "the messenger";
|
||||
}
|
||||
|
||||
public Messenger(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool CanTeach => true;
|
||||
public override bool ClickTitle => false; // Do not display 'the messenger' when single-clicking
|
||||
|
||||
private static int GetRandomHue()
|
||||
{
|
||||
switch (Utility.Random(6))
|
||||
{
|
||||
default:
|
||||
case 0: return 0;
|
||||
case 1: return Utility.RandomBlueHue();
|
||||
case 2: return Utility.RandomGreenHue();
|
||||
case 3: return Utility.RandomRedHue();
|
||||
case 4: return Utility.RandomYellowHue();
|
||||
case 5: return Utility.RandomNeutralHue();
|
||||
}
|
||||
}
|
||||
|
||||
public override void InitOutfit()
|
||||
{
|
||||
if (Female)
|
||||
AddItem(new PlainDress());
|
||||
else
|
||||
AddItem(new Shirt(GetRandomHue()));
|
||||
|
||||
int lowHue = GetRandomHue();
|
||||
|
||||
AddItem(new ShortPants(lowHue));
|
||||
|
||||
if (Female)
|
||||
AddItem(new Boots(lowHue));
|
||||
else
|
||||
AddItem(new Shoes(lowHue));
|
||||
|
||||
int randomHair = Utility.Random(4);
|
||||
HairItemID = randomHair == 4 ? 0x203B : 0x2048 + randomHair;
|
||||
|
||||
HairHue = Race.RandomHairHue();
|
||||
|
||||
PackGold(200, 250);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
31
Projects/Scripts/Mobiles/Townfolk/Minter.cs
Normal file
31
Projects/Scripts/Mobiles/Townfolk/Minter.cs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
namespace Server.Mobiles
|
||||
{
|
||||
public class Minter : Banker
|
||||
{
|
||||
[Constructible]
|
||||
public Minter()
|
||||
{
|
||||
Title = "the minter";
|
||||
}
|
||||
|
||||
public Minter(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override NpcGuild NpcGuild => NpcGuild.MerchantsGuild;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
76
Projects/Scripts/Mobiles/Townfolk/Ninja.cs
Normal file
76
Projects/Scripts/Mobiles/Townfolk/Ninja.cs
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
using Server.Items;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class Ninja : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Ninja() : base(AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4)
|
||||
{
|
||||
Title = "the ninja";
|
||||
|
||||
InitStats(100, 100, 25);
|
||||
|
||||
SetSkill(SkillName.Fencing, 64.0, 80.0);
|
||||
SetSkill(SkillName.Macing, 64.0, 80.0);
|
||||
SetSkill(SkillName.Ninjitsu, 60.0, 80.0);
|
||||
SetSkill(SkillName.Parry, 64.0, 80.0);
|
||||
SetSkill(SkillName.Tactics, 64.0, 85.0);
|
||||
SetSkill(SkillName.Swords, 64.0, 85.0);
|
||||
|
||||
SpeechHue = Utility.RandomDyedHue();
|
||||
|
||||
Hue = Race.Human.RandomSkinHue();
|
||||
|
||||
if (Female = Utility.RandomBool())
|
||||
{
|
||||
Body = 0x191;
|
||||
Name = NameList.RandomName("female");
|
||||
}
|
||||
else
|
||||
{
|
||||
Body = 0x190;
|
||||
Name = NameList.RandomName("male");
|
||||
}
|
||||
|
||||
if (!Female)
|
||||
AddItem(new LeatherNinjaHood());
|
||||
|
||||
AddItem(new LeatherNinjaPants());
|
||||
AddItem(new LeatherNinjaBelt());
|
||||
AddItem(new LeatherNinjaJacket());
|
||||
AddItem(new NinjaTabi());
|
||||
|
||||
int hairHue = Utility.RandomNondyedHue();
|
||||
|
||||
|
||||
Utility.AssignRandomHair(this, hairHue);
|
||||
|
||||
if (Utility.Random(7) != 0)
|
||||
Utility.AssignRandomFacialHair(this, hairHue);
|
||||
|
||||
PackGold(250, 300);
|
||||
}
|
||||
|
||||
public Ninja(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool CanTeach => true;
|
||||
public override bool ClickTitle => false;
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.WriteEncodedInt(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadEncodedInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
81
Projects/Scripts/Mobiles/Townfolk/Noble.cs
Normal file
81
Projects/Scripts/Mobiles/Townfolk/Noble.cs
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
using Server.Items;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class Noble : BaseEscortable
|
||||
{
|
||||
[Constructible]
|
||||
public Noble()
|
||||
{
|
||||
Title = "the noble";
|
||||
|
||||
SetSkill(SkillName.Parry, 80.0, 100.0);
|
||||
SetSkill(SkillName.Swords, 80.0, 100.0);
|
||||
SetSkill(SkillName.Tactics, 80.0, 100.0);
|
||||
}
|
||||
|
||||
public Noble(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool CanTeach => true;
|
||||
public override bool ClickTitle => false; // Do not display 'the noble' when single-clicking
|
||||
|
||||
private static int GetRandomHue()
|
||||
{
|
||||
switch (Utility.Random(6))
|
||||
{
|
||||
default:
|
||||
case 0: return 0;
|
||||
case 1: return Utility.RandomBlueHue();
|
||||
case 2: return Utility.RandomGreenHue();
|
||||
case 3: return Utility.RandomRedHue();
|
||||
case 4: return Utility.RandomYellowHue();
|
||||
case 5: return Utility.RandomNeutralHue();
|
||||
}
|
||||
}
|
||||
|
||||
public override void InitOutfit()
|
||||
{
|
||||
if (Female)
|
||||
AddItem(new FancyDress());
|
||||
else
|
||||
AddItem(new FancyShirt(GetRandomHue()));
|
||||
|
||||
int lowHue = GetRandomHue();
|
||||
|
||||
AddItem(new ShortPants(lowHue));
|
||||
|
||||
if (Female)
|
||||
AddItem(new ThighBoots(lowHue));
|
||||
else
|
||||
AddItem(new Boots(lowHue));
|
||||
|
||||
if (!Female)
|
||||
AddItem(new BodySash(lowHue));
|
||||
|
||||
AddItem(new Cloak(GetRandomHue()));
|
||||
|
||||
if (!Female)
|
||||
AddItem(new Longsword());
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
|
||||
PackGold(200, 250);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
77
Projects/Scripts/Mobiles/Townfolk/Peasant.cs
Normal file
77
Projects/Scripts/Mobiles/Townfolk/Peasant.cs
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
using Server.Items;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class Peasant : BaseEscortable
|
||||
{
|
||||
[Constructible]
|
||||
public Peasant()
|
||||
{
|
||||
Title = "the peasant";
|
||||
}
|
||||
|
||||
public Peasant(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool CanTeach => true;
|
||||
public override bool ClickTitle => false; // Do not display 'the peasant' when single-clicking
|
||||
|
||||
private static int GetRandomHue()
|
||||
{
|
||||
switch (Utility.Random(6))
|
||||
{
|
||||
default:
|
||||
case 0: return 0;
|
||||
case 1: return Utility.RandomBlueHue();
|
||||
case 2: return Utility.RandomGreenHue();
|
||||
case 3: return Utility.RandomRedHue();
|
||||
case 4: return Utility.RandomYellowHue();
|
||||
case 5: return Utility.RandomNeutralHue();
|
||||
}
|
||||
}
|
||||
|
||||
public override void InitOutfit()
|
||||
{
|
||||
if (Female)
|
||||
AddItem(new PlainDress());
|
||||
else
|
||||
AddItem(new Shirt(GetRandomHue()));
|
||||
|
||||
int lowHue = GetRandomHue();
|
||||
|
||||
AddItem(new ShortPants(lowHue));
|
||||
|
||||
if (Female)
|
||||
AddItem(new Boots(lowHue));
|
||||
else
|
||||
AddItem(new Shoes(lowHue));
|
||||
|
||||
//if ( !Female )
|
||||
//AddItem( new BodySash( lowHue ) );
|
||||
|
||||
//AddItem( new Cloak( GetRandomHue() ) );
|
||||
|
||||
//if ( !Female )
|
||||
//AddItem( new Longsword() );
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
|
||||
PackGold(200, 250);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
82
Projects/Scripts/Mobiles/Townfolk/Prisoner.cs
Normal file
82
Projects/Scripts/Mobiles/Townfolk/Prisoner.cs
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
using Server.Engines.MLQuests;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server.Mobiles.Townfolk
|
||||
{
|
||||
public class Prisoner : BaseEscortable
|
||||
{
|
||||
[Constructible]
|
||||
public Prisoner()
|
||||
{
|
||||
Title = Female ? "the noblewoman" : "the nobleman";
|
||||
|
||||
CantWalk = true;
|
||||
IsPrisoner = true;
|
||||
}
|
||||
|
||||
public Prisoner(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool CanTeach => true;
|
||||
public override bool ClickTitle => false;
|
||||
|
||||
public override void InitOutfit()
|
||||
{
|
||||
if (Female)
|
||||
{
|
||||
AddItem(new FancyDress(Utility.RandomNondyedHue()));
|
||||
}
|
||||
else
|
||||
{
|
||||
AddItem(new FancyShirt(Utility.RandomNondyedHue()));
|
||||
AddItem(new LongPants(Utility.RandomNondyedHue()));
|
||||
}
|
||||
|
||||
if (Utility.RandomBool())
|
||||
AddItem(new Boots());
|
||||
else
|
||||
AddItem(new ThighBoots());
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
Utility.AssignRandomFacialHair(this, HairHue);
|
||||
}
|
||||
|
||||
public override void Shout(PlayerMobile pm)
|
||||
{
|
||||
/*
|
||||
* 502261 - HELP!
|
||||
* 502262 - Help me!
|
||||
* 502263 - Canst thou aid me?!
|
||||
* 502264 - Help a poor prisoner!
|
||||
* 502265 - Help! Please!
|
||||
* 502266 - Aaah! Help me!
|
||||
* 502267 - Go and get some help!
|
||||
*/
|
||||
MLQuestSystem.Tell(this, pm, Utility.Random(502261, 7));
|
||||
}
|
||||
|
||||
public override void OnMovement(Mobile m, Point3D oldLocation)
|
||||
{
|
||||
base.OnMovement(m, oldLocation);
|
||||
|
||||
if (CantWalk && InRange(m, 1) && !InRange(oldLocation, 1) && (!m.Hidden || m.AccessLevel == AccessLevel.Player))
|
||||
Say(502268); // Quickly, I beg thee! Unlock my chains! If thou dost look at me close thou canst see them.
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
112
Projects/Scripts/Mobiles/Townfolk/Samurai.cs
Normal file
112
Projects/Scripts/Mobiles/Townfolk/Samurai.cs
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
using Server.Items;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class Samurai : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Samurai() : base(AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4)
|
||||
{
|
||||
Title = "the samurai";
|
||||
|
||||
InitStats(100, 100, 25);
|
||||
|
||||
SetSkill(SkillName.ArmsLore, 64.0, 80.0);
|
||||
SetSkill(SkillName.Bushido, 64.0, 85.0);
|
||||
SetSkill(SkillName.Parry, 64.0, 80.0);
|
||||
SetSkill(SkillName.Swords, 64.0, 85.0);
|
||||
|
||||
SpeechHue = Utility.RandomDyedHue();
|
||||
|
||||
Hue = Race.Human.RandomSkinHue();
|
||||
|
||||
if (Female = Utility.RandomBool())
|
||||
{
|
||||
Body = 0x191;
|
||||
Name = NameList.RandomName("female");
|
||||
}
|
||||
else
|
||||
{
|
||||
Body = 0x190;
|
||||
Name = NameList.RandomName("male");
|
||||
}
|
||||
|
||||
switch (Utility.Random(3))
|
||||
{
|
||||
case 0:
|
||||
AddItem(new Lajatang());
|
||||
break;
|
||||
case 1:
|
||||
AddItem(new Wakizashi());
|
||||
break;
|
||||
case 2:
|
||||
AddItem(new NoDachi());
|
||||
break;
|
||||
}
|
||||
|
||||
switch (Utility.Random(3))
|
||||
{
|
||||
case 0:
|
||||
AddItem(new LeatherSuneate());
|
||||
break;
|
||||
case 1:
|
||||
AddItem(new PlateSuneate());
|
||||
break;
|
||||
case 2:
|
||||
AddItem(new StuddedHaidate());
|
||||
break;
|
||||
}
|
||||
|
||||
switch (Utility.Random(4))
|
||||
{
|
||||
case 0:
|
||||
AddItem(new LeatherJingasa());
|
||||
break;
|
||||
case 1:
|
||||
AddItem(new ChainHatsuburi());
|
||||
break;
|
||||
case 2:
|
||||
AddItem(new HeavyPlateJingasa());
|
||||
break;
|
||||
case 3:
|
||||
AddItem(new DecorativePlateKabuto());
|
||||
break;
|
||||
}
|
||||
|
||||
AddItem(new LeatherDo());
|
||||
AddItem(new LeatherHiroSode());
|
||||
AddItem(new SamuraiTabi(Utility.RandomNondyedHue())); // TODO: Hue
|
||||
|
||||
int hairHue = Utility.RandomNondyedHue();
|
||||
|
||||
|
||||
Utility.AssignRandomHair(this, hairHue);
|
||||
|
||||
if (Utility.Random(7) != 0)
|
||||
Utility.AssignRandomFacialHair(this, hairHue);
|
||||
|
||||
PackGold(250, 300);
|
||||
}
|
||||
|
||||
public Samurai(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool CanTeach => true;
|
||||
public override bool ClickTitle => false;
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.WriteEncodedInt(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadEncodedInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
66
Projects/Scripts/Mobiles/Townfolk/Sculptor.cs
Normal file
66
Projects/Scripts/Mobiles/Townfolk/Sculptor.cs
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
using Server.Items;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class Sculptor : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Sculptor()
|
||||
: base(AIType.AI_Animal, FightMode.None, 10, 1, 0.2, 0.4)
|
||||
{
|
||||
InitStats(31, 41, 51);
|
||||
|
||||
SpeechHue = Utility.RandomDyedHue();
|
||||
Title = "the sculptor";
|
||||
Hue = Race.Human.RandomSkinHue();
|
||||
|
||||
if (Female = Utility.RandomBool())
|
||||
{
|
||||
Body = 0x191;
|
||||
Name = NameList.RandomName("female");
|
||||
AddItem(new Kilt(Utility.RandomNeutralHue()));
|
||||
}
|
||||
else
|
||||
{
|
||||
Body = 0x190;
|
||||
Name = NameList.RandomName("male");
|
||||
AddItem(new LongPants(Utility.RandomNeutralHue()));
|
||||
}
|
||||
|
||||
|
||||
AddItem(new Doublet(Utility.RandomNeutralHue()));
|
||||
AddItem(new HalfApron());
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
|
||||
Container pack = new Backpack();
|
||||
|
||||
pack.DropItem(new Gold(250, 300));
|
||||
|
||||
pack.Movable = false;
|
||||
|
||||
AddItem(pack);
|
||||
}
|
||||
|
||||
public Sculptor(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool ClickTitle => false;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
95
Projects/Scripts/Mobiles/Townfolk/SeekerOfAdventure.cs
Normal file
95
Projects/Scripts/Mobiles/Townfolk/SeekerOfAdventure.cs
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
using Server.Items;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class SeekerOfAdventure : BaseEscortable
|
||||
{
|
||||
private static string[] m_Dungeons =
|
||||
{
|
||||
"Covetous", "Deceit", "Despise",
|
||||
"Destard", "Hythloth", "Shame", // Old Code for Pre-ML shards.
|
||||
"Wrong"
|
||||
};
|
||||
|
||||
private static string[] m_MLDestinations =
|
||||
{
|
||||
"Cove", "Serpent's Hold", "Jhelom", // ML List
|
||||
"Nujel'm"
|
||||
};
|
||||
|
||||
[Constructible]
|
||||
public SeekerOfAdventure()
|
||||
{
|
||||
Title = "the seeker of adventure";
|
||||
}
|
||||
|
||||
public SeekerOfAdventure(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool ClickTitle => false; // Do not display 'the seeker of adventure' when single-clicking
|
||||
|
||||
public override string[] GetPossibleDestinations()
|
||||
{
|
||||
if (Core.ML)
|
||||
return m_MLDestinations;
|
||||
return m_Dungeons;
|
||||
}
|
||||
|
||||
private static int GetRandomHue()
|
||||
{
|
||||
switch (Utility.Random(6))
|
||||
{
|
||||
default:
|
||||
case 0: return 0;
|
||||
case 1: return Utility.RandomBlueHue();
|
||||
case 2: return Utility.RandomGreenHue();
|
||||
case 3: return Utility.RandomRedHue();
|
||||
case 4: return Utility.RandomYellowHue();
|
||||
case 5: return Utility.RandomNeutralHue();
|
||||
}
|
||||
}
|
||||
|
||||
public override void InitOutfit()
|
||||
{
|
||||
if (Female)
|
||||
AddItem(new FancyDress(GetRandomHue()));
|
||||
else
|
||||
AddItem(new FancyShirt(GetRandomHue()));
|
||||
|
||||
int lowHue = GetRandomHue();
|
||||
|
||||
AddItem(new ShortPants(lowHue));
|
||||
|
||||
if (Female)
|
||||
AddItem(new ThighBoots(lowHue));
|
||||
else
|
||||
AddItem(new Boots(lowHue));
|
||||
|
||||
if (!Female)
|
||||
AddItem(new BodySash(lowHue));
|
||||
|
||||
AddItem(new Cloak(GetRandomHue()));
|
||||
|
||||
AddItem(new Longsword());
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
|
||||
PackGold(100, 150);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
537
Projects/Scripts/Mobiles/Townfolk/TownCrier.cs
Normal file
537
Projects/Scripts/Mobiles/Townfolk/TownCrier.cs
Normal file
|
|
@ -0,0 +1,537 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Server.Commands;
|
||||
using Server.Gumps;
|
||||
using Server.Items;
|
||||
using Server.Network;
|
||||
using Server.Prompts;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public interface ITownCrierEntryList
|
||||
{
|
||||
List<TownCrierEntry> Entries{ get; }
|
||||
TownCrierEntry GetRandomEntry();
|
||||
TownCrierEntry AddEntry(string[] lines, TimeSpan duration);
|
||||
void RemoveEntry(TownCrierEntry entry);
|
||||
}
|
||||
|
||||
public class GlobalTownCrierEntryList : ITownCrierEntryList
|
||||
{
|
||||
private static GlobalTownCrierEntryList m_Instance;
|
||||
|
||||
public static GlobalTownCrierEntryList Instance => m_Instance ?? (m_Instance = new GlobalTownCrierEntryList());
|
||||
|
||||
public bool IsEmpty => Entries == null || Entries.Count == 0;
|
||||
|
||||
public List<TownCrierEntry> Entries{ get; private set; }
|
||||
|
||||
public TownCrierEntry GetRandomEntry()
|
||||
{
|
||||
if (Entries == null || Entries.Count == 0)
|
||||
return null;
|
||||
|
||||
for (int i = Entries.Count - 1; Entries != null && i >= 0; --i)
|
||||
{
|
||||
if (i >= Entries.Count)
|
||||
continue;
|
||||
|
||||
TownCrierEntry tce = Entries[i];
|
||||
|
||||
if (tce.Expired)
|
||||
RemoveEntry(tce);
|
||||
}
|
||||
|
||||
if (Entries == null || Entries.Count == 0)
|
||||
return null;
|
||||
|
||||
return Entries[Utility.Random(Entries.Count)];
|
||||
}
|
||||
|
||||
public TownCrierEntry AddEntry(string[] lines, TimeSpan duration)
|
||||
{
|
||||
if (Entries == null)
|
||||
Entries = new List<TownCrierEntry>();
|
||||
|
||||
TownCrierEntry tce = new TownCrierEntry(lines, duration);
|
||||
|
||||
Entries.Add(tce);
|
||||
|
||||
List<TownCrier> instances = TownCrier.Instances;
|
||||
|
||||
for (int i = 0; i < instances.Count; ++i)
|
||||
instances[i].ForceBeginAutoShout();
|
||||
|
||||
return tce;
|
||||
}
|
||||
|
||||
public void RemoveEntry(TownCrierEntry tce)
|
||||
{
|
||||
if (Entries == null)
|
||||
return;
|
||||
|
||||
Entries.Remove(tce);
|
||||
|
||||
if (Entries.Count == 0)
|
||||
Entries = null;
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
CommandSystem.Register("TownCriers", AccessLevel.GameMaster, TownCriers_OnCommand);
|
||||
}
|
||||
|
||||
[Usage("TownCriers")]
|
||||
[Description("Manages the global town crier list.")]
|
||||
public static void TownCriers_OnCommand(CommandEventArgs e)
|
||||
{
|
||||
e.Mobile.SendGump(new TownCrierGump(e.Mobile, Instance));
|
||||
}
|
||||
}
|
||||
|
||||
public class TownCrierEntry
|
||||
{
|
||||
public TownCrierEntry(string[] lines, TimeSpan duration)
|
||||
{
|
||||
Lines = lines;
|
||||
|
||||
if (duration < TimeSpan.Zero)
|
||||
duration = TimeSpan.Zero;
|
||||
else if (duration > TimeSpan.FromDays(365.0))
|
||||
duration = TimeSpan.FromDays(365.0);
|
||||
|
||||
ExpireTime = DateTime.UtcNow + duration;
|
||||
}
|
||||
|
||||
public string[] Lines{ get; }
|
||||
|
||||
public DateTime ExpireTime{ get; }
|
||||
|
||||
public bool Expired => DateTime.UtcNow >= ExpireTime;
|
||||
}
|
||||
|
||||
public class TownCrierDurationPrompt : Prompt
|
||||
{
|
||||
private ITownCrierEntryList m_Owner;
|
||||
|
||||
public TownCrierDurationPrompt(ITownCrierEntryList owner)
|
||||
{
|
||||
m_Owner = owner;
|
||||
}
|
||||
|
||||
public override void OnResponse(Mobile from, string text)
|
||||
{
|
||||
if (!TimeSpan.TryParse(text, out TimeSpan ts))
|
||||
{
|
||||
from.SendMessage("Value was not properly formatted. Use: <hours:minutes:seconds>");
|
||||
from.SendGump(new TownCrierGump(from, m_Owner));
|
||||
return;
|
||||
}
|
||||
|
||||
if (ts < TimeSpan.Zero)
|
||||
ts = TimeSpan.Zero;
|
||||
|
||||
from.SendMessage("Duration set to: {0}", ts);
|
||||
from.SendMessage("Enter the first line to shout:");
|
||||
|
||||
from.Prompt = new TownCrierLinesPrompt(m_Owner, null, new List<string>(), ts);
|
||||
}
|
||||
|
||||
public override void OnCancel(Mobile from)
|
||||
{
|
||||
from.SendLocalizedMessage(502980); // Message entry cancelled.
|
||||
from.SendGump(new TownCrierGump(from, m_Owner));
|
||||
}
|
||||
}
|
||||
|
||||
public class TownCrierLinesPrompt : Prompt
|
||||
{
|
||||
private TimeSpan m_Duration;
|
||||
private TownCrierEntry m_Entry;
|
||||
private List<string> m_Lines;
|
||||
private ITownCrierEntryList m_Owner;
|
||||
|
||||
public TownCrierLinesPrompt(ITownCrierEntryList owner, TownCrierEntry entry, List<string> lines, TimeSpan duration)
|
||||
{
|
||||
m_Owner = owner;
|
||||
m_Entry = entry;
|
||||
m_Lines = lines;
|
||||
m_Duration = duration;
|
||||
}
|
||||
|
||||
public override void OnResponse(Mobile from, string text)
|
||||
{
|
||||
m_Lines.Add(text);
|
||||
|
||||
from.SendMessage("Enter the next line to shout, or press <ESC> if the message is finished.");
|
||||
from.Prompt = new TownCrierLinesPrompt(m_Owner, m_Entry, m_Lines, m_Duration);
|
||||
}
|
||||
|
||||
public override void OnCancel(Mobile from)
|
||||
{
|
||||
if (m_Entry != null)
|
||||
m_Owner.RemoveEntry(m_Entry);
|
||||
|
||||
if (m_Lines.Count > 0)
|
||||
{
|
||||
m_Owner.AddEntry(m_Lines.ToArray(), m_Duration);
|
||||
from.SendMessage("Message has been set.");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_Entry != null)
|
||||
from.SendMessage("Message deleted.");
|
||||
else
|
||||
from.SendLocalizedMessage(502980); // Message entry cancelled.
|
||||
}
|
||||
|
||||
from.SendGump(new TownCrierGump(from, m_Owner));
|
||||
}
|
||||
}
|
||||
|
||||
public class TownCrierGump : Gump
|
||||
{
|
||||
private Mobile m_From;
|
||||
private ITownCrierEntryList m_Owner;
|
||||
|
||||
public TownCrierGump(Mobile from, ITownCrierEntryList owner) : base(50, 50)
|
||||
{
|
||||
m_From = from;
|
||||
m_Owner = owner;
|
||||
|
||||
from.CloseGump<TownCrierGump>();
|
||||
|
||||
AddPage(0);
|
||||
|
||||
List<TownCrierEntry> entries = owner.Entries;
|
||||
|
||||
owner.GetRandomEntry(); // force expiration checks
|
||||
|
||||
int count = 0;
|
||||
|
||||
if (entries != null)
|
||||
count = entries.Count;
|
||||
|
||||
AddImageTiled(0, 0, 300, 38 + (count == 0 ? 20 : count * 85), 0xA40);
|
||||
AddAlphaRegion(1, 1, 298, 36 + (count == 0 ? 20 : count * 85));
|
||||
|
||||
AddHtml(8, 8, 300 - 8 - 30, 20, "<basefont color=#FFFFFF><center>TOWN CRIER MESSAGES</center></basefont>");
|
||||
|
||||
AddButton(300 - 8 - 30, 8, 0xFAB, 0xFAD, 1);
|
||||
|
||||
if (count == 0)
|
||||
AddHtml(8, 30, 284, 20, "<basefont color=#FFFFFF>The crier has no news.</basefont>");
|
||||
else
|
||||
for (int i = 0; i < entries.Count; ++i)
|
||||
{
|
||||
TownCrierEntry tce = entries[i];
|
||||
|
||||
TimeSpan toExpire = tce.ExpireTime - DateTime.UtcNow;
|
||||
|
||||
if (toExpire < TimeSpan.Zero)
|
||||
toExpire = TimeSpan.Zero;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.Append("[Expires: ");
|
||||
|
||||
if (toExpire.TotalHours >= 1)
|
||||
{
|
||||
sb.Append((int)toExpire.TotalHours);
|
||||
sb.Append(':');
|
||||
sb.Append(toExpire.Minutes.ToString("D2"));
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(toExpire.Minutes);
|
||||
}
|
||||
|
||||
sb.Append(':');
|
||||
sb.Append(toExpire.Seconds.ToString("D2"));
|
||||
|
||||
sb.Append("] ");
|
||||
|
||||
for (int j = 0; j < tce.Lines.Length; ++j)
|
||||
{
|
||||
if (j > 0)
|
||||
sb.Append("<br>");
|
||||
|
||||
sb.Append(tce.Lines[j]);
|
||||
}
|
||||
|
||||
AddHtml(8, 35 + i * 85, 254, 80, sb.ToString(), true, true);
|
||||
|
||||
AddButton(300 - 8 - 26, 35 + i * 85, 0x15E1, 0x15E5, 2 + i);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnResponse(NetState sender, RelayInfo info)
|
||||
{
|
||||
if (info.ButtonID == 1)
|
||||
{
|
||||
m_From.SendMessage("Enter the duration for the new message. Format: <hours:minutes:seconds>");
|
||||
m_From.Prompt = new TownCrierDurationPrompt(m_Owner);
|
||||
}
|
||||
else if (info.ButtonID > 1)
|
||||
{
|
||||
List<TownCrierEntry> entries = m_Owner.Entries;
|
||||
int index = info.ButtonID - 2;
|
||||
|
||||
if (entries != null && index < entries.Count)
|
||||
{
|
||||
TownCrierEntry tce = entries[index];
|
||||
TimeSpan ts = tce.ExpireTime - DateTime.UtcNow;
|
||||
|
||||
if (ts < TimeSpan.Zero)
|
||||
ts = TimeSpan.Zero;
|
||||
|
||||
m_From.SendMessage("Editing entry #{0}.", index + 1);
|
||||
m_From.SendMessage("Enter the first line to shout:");
|
||||
m_From.Prompt = new TownCrierLinesPrompt(m_Owner, tce, new List<string>(), ts);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class TownCrier : Mobile, ITownCrierEntryList
|
||||
{
|
||||
private Timer m_AutoShoutTimer;
|
||||
private Timer m_NewsTimer;
|
||||
|
||||
[Constructible]
|
||||
public TownCrier()
|
||||
{
|
||||
Instances.Add(this);
|
||||
|
||||
InitStats(100, 100, 25);
|
||||
|
||||
Title = "the town crier";
|
||||
Hue = Race.Human.RandomSkinHue();
|
||||
|
||||
if (!Core.AOS)
|
||||
NameHue = 0x35;
|
||||
|
||||
if (Female = Utility.RandomBool())
|
||||
{
|
||||
Body = 0x191;
|
||||
Name = NameList.RandomName("female");
|
||||
}
|
||||
else
|
||||
{
|
||||
Body = 0x190;
|
||||
Name = NameList.RandomName("male");
|
||||
}
|
||||
|
||||
AddItem(new FancyShirt(Utility.RandomBlueHue()));
|
||||
|
||||
Item skirt;
|
||||
|
||||
switch (Utility.Random(2))
|
||||
{
|
||||
case 0:
|
||||
skirt = new Skirt();
|
||||
break;
|
||||
default:
|
||||
case 1:
|
||||
skirt = new Kilt();
|
||||
break;
|
||||
}
|
||||
|
||||
skirt.Hue = Utility.RandomGreenHue();
|
||||
|
||||
AddItem(skirt);
|
||||
|
||||
AddItem(new FeatheredHat(Utility.RandomGreenHue()));
|
||||
|
||||
Item boots;
|
||||
|
||||
switch (Utility.Random(2))
|
||||
{
|
||||
case 0:
|
||||
boots = new Boots();
|
||||
break;
|
||||
default:
|
||||
case 1:
|
||||
boots = new ThighBoots();
|
||||
break;
|
||||
}
|
||||
|
||||
AddItem(boots);
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
}
|
||||
|
||||
public TownCrier(Serial serial) : base(serial)
|
||||
{
|
||||
Instances.Add(this);
|
||||
}
|
||||
|
||||
public static List<TownCrier> Instances{ get; } = new List<TownCrier>();
|
||||
|
||||
public List<TownCrierEntry> Entries{ get; private set; }
|
||||
|
||||
public TownCrierEntry GetRandomEntry()
|
||||
{
|
||||
if (Entries == null || Entries.Count == 0)
|
||||
return GlobalTownCrierEntryList.Instance.GetRandomEntry();
|
||||
|
||||
for (int i = Entries.Count - 1; Entries != null && i >= 0; --i)
|
||||
{
|
||||
if (i >= Entries.Count)
|
||||
continue;
|
||||
|
||||
TownCrierEntry tce = Entries[i];
|
||||
|
||||
if (tce.Expired)
|
||||
RemoveEntry(tce);
|
||||
}
|
||||
|
||||
if (Entries == null || Entries.Count == 0)
|
||||
return GlobalTownCrierEntryList.Instance.GetRandomEntry();
|
||||
|
||||
TownCrierEntry entry = GlobalTownCrierEntryList.Instance.GetRandomEntry();
|
||||
|
||||
if (entry == null || Utility.RandomBool())
|
||||
entry = Entries[Utility.Random(Entries.Count)];
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
public TownCrierEntry AddEntry(string[] lines, TimeSpan duration)
|
||||
{
|
||||
if (Entries == null)
|
||||
Entries = new List<TownCrierEntry>();
|
||||
|
||||
TownCrierEntry tce = new TownCrierEntry(lines, duration);
|
||||
|
||||
Entries.Add(tce);
|
||||
|
||||
if (m_AutoShoutTimer == null)
|
||||
m_AutoShoutTimer = Timer.DelayCall(TimeSpan.FromSeconds(5.0), TimeSpan.FromMinutes(1.0), AutoShout_Callback);
|
||||
|
||||
return tce;
|
||||
}
|
||||
|
||||
public void RemoveEntry(TownCrierEntry tce)
|
||||
{
|
||||
if (Entries == null)
|
||||
return;
|
||||
|
||||
Entries.Remove(tce);
|
||||
|
||||
if (Entries.Count == 0)
|
||||
Entries = null;
|
||||
|
||||
if (Entries == null && GlobalTownCrierEntryList.Instance.IsEmpty)
|
||||
{
|
||||
m_AutoShoutTimer?.Stop();
|
||||
|
||||
m_AutoShoutTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void ForceBeginAutoShout()
|
||||
{
|
||||
if (m_AutoShoutTimer == null)
|
||||
m_AutoShoutTimer = Timer.DelayCall(TimeSpan.FromSeconds(5.0), TimeSpan.FromMinutes(1.0), AutoShout_Callback);
|
||||
}
|
||||
|
||||
private void AutoShout_Callback()
|
||||
{
|
||||
TownCrierEntry tce = GetRandomEntry();
|
||||
|
||||
if (tce == null)
|
||||
{
|
||||
m_AutoShoutTimer?.Stop();
|
||||
|
||||
m_AutoShoutTimer = null;
|
||||
}
|
||||
else if (m_NewsTimer == null)
|
||||
{
|
||||
int index = 0;
|
||||
m_NewsTimer = Timer.DelayCall(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(3.0),
|
||||
() => ShoutNews_Callback(tce, index));
|
||||
|
||||
PublicOverheadMessage(MessageType.Regular, 0x3B2, 502976); // Hear ye! Hear ye!
|
||||
}
|
||||
}
|
||||
|
||||
private void ShoutNews_Callback(TownCrierEntry tce, int index)
|
||||
{
|
||||
if (index < 0 || index >= tce.Lines.Length)
|
||||
{
|
||||
m_NewsTimer?.Stop();
|
||||
m_NewsTimer = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
PublicOverheadMessage(MessageType.Regular, 0x3B2, false, tce.Lines[index]);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnDoubleClick(Mobile from)
|
||||
{
|
||||
if (from.AccessLevel >= AccessLevel.GameMaster)
|
||||
from.SendGump(new TownCrierGump(from, this));
|
||||
else
|
||||
base.OnDoubleClick(from);
|
||||
}
|
||||
|
||||
public override bool HandlesOnSpeech(Mobile from)
|
||||
{
|
||||
return m_NewsTimer == null && from.Alive && InRange(from, 12);
|
||||
}
|
||||
|
||||
public override void OnSpeech(SpeechEventArgs e)
|
||||
{
|
||||
if (m_NewsTimer == null && e.HasKeyword(0x30) && e.Mobile.Alive && InRange(e.Mobile, 12)) // *news*
|
||||
{
|
||||
Direction = GetDirectionTo(e.Mobile);
|
||||
|
||||
TownCrierEntry tce = GetRandomEntry();
|
||||
|
||||
if (tce == null)
|
||||
{
|
||||
PublicOverheadMessage(MessageType.Regular, 0x3B2, 1005643); // I have no news at this time.
|
||||
}
|
||||
else
|
||||
{
|
||||
int index = 0;
|
||||
m_NewsTimer = Timer.DelayCall(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(3.0),
|
||||
() => ShoutNews_Callback(tce, index));
|
||||
|
||||
PublicOverheadMessage(MessageType.Regular, 0x3B2, 502978); // Some of the latest news!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanBeDamaged()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void OnDelete()
|
||||
{
|
||||
Instances.Remove(this);
|
||||
base.OnDelete();
|
||||
}
|
||||
|
||||
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 (Core.AOS && NameHue == 0x35)
|
||||
NameHue = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue