#W# Source and Scripts added. Added Scripts/Settings.cs to expose some basic tweak able settings.

This commit is contained in:
WarrentyExpired 2026-08-06 11:06:05 -04:00
parent b51c58f514
commit 3045c83799
3512 changed files with 627673 additions and 0 deletions

View file

@ -0,0 +1,69 @@
using System;
using Server.Items;
using Server;
using Server.Misc;
namespace Server.Mobiles
{
public class Actor : BaseCreature
{
[Constructable]
public Actor () : base( AIType.AI_Animal, FightMode.None, 10, 1, 0.2, 0.4 )
{
InitStats( 31, 41, 51 );
SpeechHue = Utility.RandomDyedHue();
Hue = Utility.RandomSkinHue();
if ( this.Female = Utility.RandomBool() )
{
this.Body = 0x191;
this.Name = NameList.RandomName( "female" );
AddItem( new FancyDress( Utility.RandomDyedHue() ) );
Title = "the actress";
}
else
{
this.Body = 0x190;
this.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 override bool ClickTitle{ get{ return false; } }
public Actor( Serial serial ) : base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int) 0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,74 @@
using System;
using Server.Items;
using Server;
using Server.Misc;
namespace Server.Mobiles
{
public class Artist : BaseCreature
{
public override bool CanTeach { get { return true; } }
[Constructable]
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 = Utility.RandomSkinHue();
if( this.Female = Utility.RandomBool() )
{
this.Body = 0x191;
this.Name = NameList.RandomName( "female" );
}
else
{
this.Body = 0x190;
this.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 override bool ClickTitle { get { return false; } }
public Artist( Serial serial )
: base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int)0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,467 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Server.Accounting;
using Server.Items;
using Server.ContextMenus;
using Server.Misc;
using Server.Network;
namespace Server.Mobiles
{
public class Banker : BaseVendor
{
private List<SBInfo> m_SBInfos = new List<SBInfo>();
protected override List<SBInfo> SBInfos{ get { return m_SBInfos; } }
public override NpcGuild NpcGuild{ get{ return NpcGuild.MerchantsGuild; } }
[Constructable]
public Banker() : base( "the banker" )
{
}
public override void InitSBInfo()
{
m_SBInfos.Add( new SBBanker() );
}
public static int GetBalance(Mobile m)
{
double balance = 0;
if (AccountGold.Enabled && m.Account != null)
{
int goldStub;
m.Account.GetGoldBalance(out goldStub, out balance);
if (balance > Int32.MaxValue)
{
return Int32.MaxValue;
}
}
Container bank = m.FindBankNoCreate();
if (bank != null)
{
var gold = bank.FindItemsByType<Gold>();
var checks = bank.FindItemsByType<BankCheck>();
balance += gold.Aggregate(0.0, (c, t) => c + t.Amount);
balance += checks.Aggregate(0.0, (c, t) => c + t.Worth);
}
return (int)Math.Max(0, Math.Min(Int32.MaxValue, balance));
}
public static int GetBalance(Mobile m, out Item[] gold, out Item[] checks)
{
double balance = 0;
if (AccountGold.Enabled && m.Account != null)
{
int goldStub;
m.Account.GetGoldBalance(out goldStub, out balance);
if (balance > Int32.MaxValue)
{
gold = checks = new Item[0];
return Int32.MaxValue;
}
}
Container bank = m.FindBankNoCreate();
if (bank != null)
{
gold = bank.FindItemsByType(typeof(Gold));
checks = bank.FindItemsByType(typeof(BankCheck));
balance += gold.OfType<Gold>().Aggregate(0.0, (c, t) => c + t.Amount);
balance += checks.OfType<BankCheck>().Aggregate(0.0, (c, t) => c + t.Worth);
}
else
{
gold = checks = new Item[0];
}
return (int)Math.Max(0, Math.Min(Int32.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;
}
Item[] gold, checks;
var balance = GetBalance(from, out gold, out checks);
if (balance < amount)
{
return false;
}
for (var 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 (var i = 0; amount > 0 && i < checks.Length; ++i)
{
var 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;
}
var box = from.FindBankNoCreate();
if (box == null)
{
return false;
}
var 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 (var 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;
}
var box = from.FindBankNoCreate();
if (box == null)
{
return 0;
}
var 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 Banker( Serial serial ) : base( serial )
{
}
public override bool HandlesOnSpeech( Mobile from )
{
if ( from.InRange( this.Location, 12 ) )
return true;
return base.HandlesOnSpeech( from );
}
public override void OnSpeech( SpeechEventArgs e )
{
if ( !e.Handled && e.Mobile.InRange( this.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 )
{
this.Say( 500389 ); // I will not do business with a criminal!
break;
}
string[] split = e.Speech.Split( ' ' );
if ( split.Length >= 2 )
{
int amount;
Container pack = e.Mobile.Backpack;
if ( !int.TryParse( split[1], out amount ) )
break;
if ( (!Core.ML && amount > 5000) || (Core.ML && amount > 60000) )
{
this.Say( 500381 ); // Thou canst not withdraw so much at one time!
}
else if (pack == null || pack.Deleted || !(pack.TotalWeight < pack.MaxWeight) || !(pack.TotalItems < pack.MaxItems))
{
this.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))
{
this.Say(500384); // Ah, art thou trying to fool me? Thou hast not so much gold!
}
else
{
pack.DropItem(new Gold(amount));
this.Say(1010005); // Thou hast withdrawn gold from thy account.
}
}
}
break;
}
case 0x0001: // *balance*
{
e.Handled = true;
if ( e.Mobile.Criminal )
{
this.Say( 500389 ); // I will not do business with a criminal!
break;
}
if ( AccountGold.Enabled && e.Mobile.Account != null )
{
this.Say( 1155855, String.Format("{0:#,0}\t{1:#,0}", e.Mobile.Account.TotalPlat, e.Mobile.Account.TotalGold) ); // Thy current bank balance is ~1_AMOUNT~ platinum and ~2_AMOUNT~ gold.
}
else
{
this.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 )
{
this.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 )
{
this.Say( 500389 ); // I will not do business with a criminal!
break;
}
string[] split = e.Speech.Split( ' ' );
if ( split.Length >= 2 )
{
int amount;
if ( !int.TryParse( split[1], out amount ) )
break;
if ( amount < 5000 )
{
this.Say( 1010006 ); // We cannot create checks for such a paltry amount of gold!
}
else if ( amount > 1000000 )
{
this.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 ) )
{
this.Say( 500386 ); // There's not enough room in your bankbox for the check!
check.Delete();
}
else if ( !box.ConsumeTotal( typeof( Gold ), amount ) )
{
this.Say( 500384 ); // Ah, art thou trying to fool me? Thou hast not so much gold!
check.Delete();
}
else
{
this.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( (int) 0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
}
}
}

View file

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

View file

@ -0,0 +1,80 @@
using System;
using Server;
using Server.Items;
using EDI = Server.Mobiles.EscortDestinationInfo;
namespace Server.Mobiles
{
public class BrideGroom : BaseEscortable
{
[Constructable]
public BrideGroom()
{
if ( Female )
Title = "the bride";
else
Title = "the groom";
}
public override bool CanTeach{ get{ return true; } }
public override bool ClickTitle{ get{ return 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 = this.Race.RandomHairHue();
PackGold( 200, 250 );
}
public BrideGroom( Serial serial ) : base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int) 0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,74 @@
using System;
using Server;
using Server.Items;
using EDI = Server.Mobiles.EscortDestinationInfo;
namespace Server.Mobiles
{
public class EscortableMage : BaseEscortable
{
[Constructable]
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 override bool CanTeach{ get{ return true; } }
public override bool ClickTitle{ get{ return 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 EscortableMage( Serial serial ) : base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int) 0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,82 @@
using System;
using Server.Items;
using Server;
using Server.Misc;
namespace Server.Mobiles
{
public class Gypsy : BaseCreature
{
[Constructable]
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 = Utility.RandomSkinHue();
if( this.Female = Utility.RandomBool() )
{
this.Body = 0x191;
this.Name = NameList.RandomName( "female" );
AddItem( new Kilt( Utility.RandomDyedHue() ) );
AddItem( new Shirt( Utility.RandomDyedHue() ) );
AddItem( new ThighBoots() );
Title = "the gypsy";
}
else
{
this.Body = 0x190;
this.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 override bool CanTeach { get { return true; } }
public override bool ClickTitle { get { return false; } }
public Gypsy( Serial serial )
: base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int)0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,76 @@
using System;
using Server.Items;
using Server;
using Server.Misc;
namespace Server.Mobiles
{
public class HarborMaster : BaseCreature
{
public override bool CanTeach { get { return false; } }
[Constructable]
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 = Utility.RandomSkinHue();
Blessed = true;
if( this.Female = Utility.RandomBool() )
{
this.Body = 0x191;
this.Name = NameList.RandomName( "female" );
Title = "the Harbor Mistress";
}
else
{
this.Body = 0x190;
this.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 override bool ClickTitle { get { return false; } }
public HarborMaster( Serial serial )
: base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int)0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,85 @@
using System;
using Server;
using Server.Items;
using EDI=Server.Mobiles.EscortDestinationInfo;
namespace Server.Mobiles
{
public class Merchant : BaseEscortable
{
[Constructable]
public Merchant()
{
Title = "the merchant";
SetSkill( SkillName.ItemID, 55.0, 78.0 );
SetSkill( SkillName.ArmsLore, 55, 78 );
}
public override bool CanTeach { get { return true; } }
public override bool ClickTitle { get { return 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 Merchant( Serial serial )
: base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int)0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,86 @@
using System;
using Server;
using Server.Items;
using EDI = Server.Mobiles.EscortDestinationInfo;
namespace Server.Mobiles
{
public class Messenger : BaseEscortable
{
[Constructable]
public Messenger()
{
Title = "the messenger";
}
public override bool CanTeach{ get{ return true; } }
public override bool ClickTitle{ get{ return 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 ) );
//if ( !Female )
//AddItem( new BodySash( lowHue ) );
//AddItem( new Cloak( GetRandomHue() ) );
//if ( !Female )
//AddItem( new Longsword() );
switch ( Utility.Random( 4 ) )
{
case 0: AddItem( new ShortHair( Utility.RandomHairHue() ) ); break;
case 1: AddItem( new TwoPigTails( Utility.RandomHairHue() ) ); break;
case 2: AddItem( new ReceedingHair( Utility.RandomHairHue() ) ); break;
case 3: AddItem( new KrisnaHair( Utility.RandomHairHue() ) ); break;
}
PackGold( 200, 250 );
}
public Messenger( Serial serial ) : base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int) 0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,38 @@
using System;
using System.Collections;
using Server.Items;
using Server.ContextMenus;
using Server.Misc;
using Server.Network;
namespace Server.Mobiles
{
public class Minter : Banker
{
public override NpcGuild NpcGuild{ get{ return NpcGuild.MerchantsGuild; } }
[Constructable]
public Minter()
{
Title = "the minter";
}
public Minter( Serial serial ) : base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int) 0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,78 @@
using System;
using Server;
using Server.Items;
namespace Server.Mobiles
{
public class Ninja : BaseCreature
{
public override bool CanTeach{ get{ return true; } }
public override bool ClickTitle{ get{ return false; } }
[Constructable]
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 = Utility.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 void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.WriteEncodedInt( 0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,84 @@
using System;
using Server;
using Server.Items;
using EDI = Server.Mobiles.EscortDestinationInfo;
namespace Server.Mobiles
{
public class Noble : BaseEscortable
{
[Constructable]
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 override bool CanTeach{ get{ return true; } }
public override bool ClickTitle{ get{ return 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 Noble( Serial serial ) : base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int) 0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,81 @@
using System;
using Server;
using Server.Items;
using EDI = Server.Mobiles.EscortDestinationInfo;
namespace Server.Mobiles
{
public class Peasant : BaseEscortable
{
[Constructable]
public Peasant()
{
Title = "the peasant";
}
public override bool CanTeach{ get{ return true; } }
public override bool ClickTitle{ get{ return 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 Peasant( Serial serial ) : base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int) 0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,83 @@
using System;
using Server.Items;
using Server.Engines.MLQuests;
namespace Server.Mobiles.Townfolk
{
public class Prisoner : BaseEscortable
{
[Constructable]
public Prisoner()
{
Title = Female ? "the noblewoman" : "the nobleman";
CantWalk = true;
IsPrisoner = true;
}
public override bool CanTeach { get { return true; } }
public override bool ClickTitle { get { return 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 Prisoner( Serial serial )
: base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int) 0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,94 @@
using System;
using Server;
using Server.Items;
namespace Server.Mobiles
{
public class Samurai : BaseCreature
{
public override bool CanTeach{ get{ return true; } }
public override bool ClickTitle{ get{ return false; } }
[Constructable]
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 = Utility.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 void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.WriteEncodedInt( 0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,70 @@
using System;
using Server.Items;
using Server;
using Server.Misc;
namespace Server.Mobiles
{
public class Sculptor : BaseCreature
{
[Constructable]
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 = Utility.RandomSkinHue();
if( this.Female = Utility.RandomBool() )
{
this.Body = 0x191;
this.Name = NameList.RandomName( "female" );
AddItem( new Kilt( Utility.RandomNeutralHue() ) );
}
else
{
this.Body = 0x190;
this.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 override bool ClickTitle { get { return false; } }
public Sculptor( Serial serial )
: base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int)0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,99 @@
using System;
using Server;
using Server.Items;
using EDI = Server.Mobiles.EscortDestinationInfo;
namespace Server.Mobiles
{
public class SeekerOfAdventure : BaseEscortable
{
private static string[] m_Dungeons = new string[]
{
"Covetous", "Deceit", "Despise",
"Destard", "Hythloth", "Shame", // Old Code for Pre-ML shards.
"Wrong"
};
private static string[] m_MLDestinations = new string[]
{
"Cove", "Serpent's Hold", "Jhelom", // ML List
"Nujel'm"
};
public override string[] GetPossibleDestinations()
{
if ( Core.ML )
return m_MLDestinations;
else
return m_Dungeons;
}
[Constructable]
public SeekerOfAdventure()
{
Title = "the seeker of adventure";
}
public override bool ClickTitle{ get{ return false; } } // Do not display 'the seeker of adventure' 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( 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 SeekerOfAdventure( Serial serial ) : base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int) 0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,568 @@
using System;
using System.Text;
using System.Collections.Generic;
using Server;
using Server.Prompts;
using Server.Gumps;
using Server.Network;
using Server.Items;
using Server.Misc;
using Server.Commands;
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 void Initialize()
{
CommandSystem.Register( "TownCriers", AccessLevel.GameMaster, new CommandEventHandler( 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 static GlobalTownCrierEntryList Instance
{
get
{
if ( m_Instance == null )
m_Instance = new GlobalTownCrierEntryList();
return m_Instance;
}
}
public bool IsEmpty{ get{ return ( m_Entries == null || m_Entries.Count == 0 ); } }
public GlobalTownCrierEntryList()
{
}
private List<TownCrierEntry> m_Entries;
public List<TownCrierEntry> Entries
{
get{ return m_Entries; }
}
public TownCrierEntry GetRandomEntry()
{
if ( m_Entries == null || m_Entries.Count == 0 )
return null;
for ( int i = m_Entries.Count - 1; m_Entries != null && i >= 0; --i )
{
if ( i >= m_Entries.Count )
continue;
TownCrierEntry tce = m_Entries[i];
if ( tce.Expired )
RemoveEntry( tce );
}
if ( m_Entries == null || m_Entries.Count == 0 )
return null;
return m_Entries[Utility.Random( m_Entries.Count )];
}
public TownCrierEntry AddEntry( string[] lines, TimeSpan duration )
{
if ( m_Entries == null )
m_Entries = new List<TownCrierEntry>();
TownCrierEntry tce = new TownCrierEntry( lines, duration );
m_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 ( m_Entries == null )
return;
m_Entries.Remove( tce );
if ( m_Entries.Count == 0 )
m_Entries = null;
}
}
public class TownCrierEntry
{
private string[] m_Lines;
private DateTime m_ExpireTime;
public string[] Lines{ get{ return m_Lines; } }
public DateTime ExpireTime{ get{ return m_ExpireTime; } }
public bool Expired{ get{ return ( DateTime.UtcNow >= m_ExpireTime ); } }
public TownCrierEntry( string[] lines, TimeSpan duration )
{
m_Lines = lines;
if ( duration < TimeSpan.Zero )
duration = TimeSpan.Zero;
else if ( duration > TimeSpan.FromDays( 365.0 ) )
duration = TimeSpan.FromDays( 365.0 );
m_ExpireTime = DateTime.UtcNow + duration;
}
}
public class TownCrierDurationPrompt : Prompt
{
private ITownCrierEntryList m_Owner;
public TownCrierDurationPrompt( ITownCrierEntryList owner )
{
m_Owner = owner;
}
public override void OnResponse( Mobile from, string text )
{
TimeSpan ts;
if( !TimeSpan.TryParse( text, out 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 ITownCrierEntryList m_Owner;
private TownCrierEntry m_Entry;
private List<String> m_Lines;
private TimeSpan m_Duration;
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 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 TownCrierGump( Mobile from, ITownCrierEntryList owner ) : base( 50, 50 )
{
m_From = from;
m_Owner = owner;
from.CloseGump( typeof( 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>", false, false );
AddButton( 300 - 8 - 30, 8, 0xFAB, 0xFAD, 1, GumpButtonType.Reply, 0 );
if ( count == 0 )
{
AddHtml( 8, 30, 284, 20, "<basefont color=#FFFFFF>The crier has no news.</basefont>", false, false );
}
else
{
for ( int i = 0; i < entries.Count; ++i )
{
TownCrierEntry tce = (TownCrierEntry)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, GumpButtonType.Reply, 0 );
}
}
}
}
public class TownCrier : Mobile, ITownCrierEntryList
{
private List<TownCrierEntry> m_Entries;
private Timer m_NewsTimer;
private Timer m_AutoShoutTimer;
public List<TownCrierEntry> Entries
{
get{ return m_Entries; }
}
public TownCrierEntry GetRandomEntry()
{
if ( m_Entries == null || m_Entries.Count == 0 )
return GlobalTownCrierEntryList.Instance.GetRandomEntry();
for ( int i = m_Entries.Count - 1; m_Entries != null && i >= 0; --i )
{
if ( i >= m_Entries.Count )
continue;
TownCrierEntry tce = m_Entries[i];
if ( tce.Expired )
RemoveEntry( tce );
}
if ( m_Entries == null || m_Entries.Count == 0 )
return GlobalTownCrierEntryList.Instance.GetRandomEntry();
TownCrierEntry entry = GlobalTownCrierEntryList.Instance.GetRandomEntry();
if ( entry == null || Utility.RandomBool() )
entry = m_Entries[Utility.Random( m_Entries.Count )];
return entry;
}
public void ForceBeginAutoShout()
{
if ( m_AutoShoutTimer == null )
m_AutoShoutTimer = Timer.DelayCall( TimeSpan.FromSeconds( 5.0 ), TimeSpan.FromMinutes( 1.0 ), new TimerCallback( AutoShout_Callback ) );
}
public TownCrierEntry AddEntry( string[] lines, TimeSpan duration )
{
if ( m_Entries == null )
m_Entries = new List<TownCrierEntry>();
TownCrierEntry tce = new TownCrierEntry( lines, duration );
m_Entries.Add( tce );
if ( m_AutoShoutTimer == null )
m_AutoShoutTimer = Timer.DelayCall( TimeSpan.FromSeconds( 5.0 ), TimeSpan.FromMinutes( 1.0 ), new TimerCallback( AutoShout_Callback ) );
return tce;
}
public void RemoveEntry( TownCrierEntry tce )
{
if ( m_Entries == null )
return;
m_Entries.Remove( tce );
if ( m_Entries.Count == 0 )
m_Entries = null;
if ( m_Entries == null && GlobalTownCrierEntryList.Instance.IsEmpty )
{
if ( m_AutoShoutTimer != null )
m_AutoShoutTimer.Stop();
m_AutoShoutTimer = null;
}
}
private void AutoShout_Callback()
{
TownCrierEntry tce = GetRandomEntry();
if ( tce == null )
{
if ( m_AutoShoutTimer != null )
m_AutoShoutTimer.Stop();
m_AutoShoutTimer = null;
}
else if ( m_NewsTimer == null )
{
m_NewsTimer = Timer.DelayCall( TimeSpan.FromSeconds( 1.0 ), TimeSpan.FromSeconds( 3.0 ), new TimerStateCallback( ShoutNews_Callback ), new object[]{ tce, 0 } );
PublicOverheadMessage( MessageType.Regular, 0x3B2, 502976 ); // Hear ye! Hear ye!
}
}
private void ShoutNews_Callback( object state )
{
object[] states = (object[])state;
TownCrierEntry tce = (TownCrierEntry)states[0];
int index = (int)states[1];
if ( index < 0 || index >= tce.Lines.Length )
{
if ( m_NewsTimer != null )
m_NewsTimer.Stop();
m_NewsTimer = null;
}
else
{
PublicOverheadMessage( MessageType.Regular, 0x3B2, false, tce.Lines[index] );
states[1] = index + 1;
}
}
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
{
m_NewsTimer = Timer.DelayCall( TimeSpan.FromSeconds( 1.0 ), TimeSpan.FromSeconds( 3.0 ), new TimerStateCallback( ShoutNews_Callback ), new object[]{ tce, 0 } );
PublicOverheadMessage( MessageType.Regular, 0x3B2, 502978 ); // Some of the latest news!
}
}
}
private static List<TownCrier> m_Instances = new List<TownCrier>();
public static List<TownCrier> Instances
{
get{ return m_Instances; }
}
[Constructable]
public TownCrier()
{
m_Instances.Add( this );
InitStats( 100, 100, 25 );
Title = "the town crier";
Hue = Utility.RandomSkinHue();
if ( !Core.AOS )
NameHue = 0x35;
if ( this.Female = Utility.RandomBool() )
{
this.Body = 0x191;
this.Name = NameList.RandomName( "female" );
}
else
{
this.Body = 0x190;
this.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 override bool CanBeDamaged()
{
return false;
}
public override void OnDelete()
{
m_Instances.Remove( this );
base.OnDelete();
}
public TownCrier( Serial serial ) : base( serial )
{
m_Instances.Add( this );
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int) 0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
if ( Core.AOS && NameHue == 0x35 )
NameHue = -1;
}
}
}