ML quest system; first SVN release.

Secondary changes:
- Region fixes, mainly for New Haven.
- Recipe system changes.
- Enabled ML craftables.
- Dyeing/cutting restrictions for quest items.
- Moved IsInvulnerable from BaseVendor to BaseCreature.
- Moved RandomBrightHue to Utility.
- Items no longer decay when attached to a spawner.
- Quest item hue is now faked through packets, instead of overriding Hue.
- Re-enabled item drag effects for SA clients.
- Fixed AssignRandomFacialHair bug in Utility.
- Added random hue comments to Utility.
This commit is contained in:
eos 2013-02-03 01:05:17 +00:00
parent 5c7af18dfb
commit 35fbffdb51
167 changed files with 23218 additions and 234 deletions

View file

@ -6,18 +6,109 @@ 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;
if ( MLQuestSystem.Debug )
Console.WriteLine( "DEBUG: Assigning quest to BaseEscortable {0}, Region = {1}", Serial, ( reg == null ) ? "-null-" : reg.Name );
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 )
{
SetMLQuest( quest );
break;
}
}
else if ( MLQuestSystem.Debug )
{
Console.WriteLine( "WARNING: Type {0} should not be eligible as it is not a registered quest", 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
@ -26,26 +117,78 @@ namespace Server.Mobiles
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", //Original List, will need to add it back for Pre-ML shards
"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", //ML List
"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 )
};
public void SetMLQuest( MLQuest quest )
{
m_MLQuest = quest;
quest.Register( this );
}
[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()
@ -109,8 +252,6 @@ namespace Server.Mobiles
get { return m_EscortTable; }
}
private static TimeSpan m_EscortDelay = TimeSpan.FromMinutes(5.0);
public virtual bool AcceptEscorter(Mobile m)
{
EDI dest = GetDestination();
@ -130,9 +271,9 @@ namespace Server.Mobiles
Say("I see you already have an escort.");
return false;
}
else if (m is PlayerMobile && (((PlayerMobile)m).LastEscortTime + m_EscortDelay) >= DateTime.Now)
else if (m is PlayerMobile && (((PlayerMobile)m).LastEscortTime + EscortDelay) >= DateTime.Now)
{
int minutes = (int)Math.Ceiling(((((PlayerMobile)m).LastEscortTime + m_EscortDelay) - DateTime.Now).TotalMinutes);
int minutes = (int)Math.Ceiling(((((PlayerMobile)m).LastEscortTime + EscortDelay) - DateTime.Now).TotalMinutes);
Say("You must rest {0} minute{1} before we set out on this journey.", minutes, minutes == 1 ? "" : "s");
return false;
@ -155,6 +296,9 @@ namespace Server.Mobiles
public override bool HandlesOnSpeech(Mobile from)
{
if ( MLQuestSystem.Enabled )
return false;
if (from.InRange(this.Location, 3))
return true;
@ -202,6 +346,8 @@ namespace Server.Mobiles
return true;
}
// TODO: Pre-ML methods below, might be mergeable with the ML methods in EscortObjective
public virtual void StartFollow()
{
StartFollow(GetEscorter());
@ -240,13 +386,13 @@ namespace Server.Mobiles
public virtual Mobile GetEscorter()
{
if (!Controlled)
if ( !Controlled )
return null;
Mobile master = ControlMaster;
if (master == null)
return null;
if ( MLQuestSystem.Enabled || master == null )
return master;
if (master.Deleted || master.Map != this.Map || !master.InRange(Location, 30) || !master.Alive)
{
@ -254,7 +400,7 @@ namespace Server.Mobiles
TimeSpan lastSeenDelay = DateTime.Now - m_LastSeenEscorter;
if (lastSeenDelay >= TimeSpan.FromMinutes(2.0))
if (lastSeenDelay >= AbandonDelay)
{
master.SendLocalizedMessage(1042473); // You have lost the person you were escorting.
Say(1005653); // Hmmm. I seem to have lost my master.
@ -284,7 +430,7 @@ namespace Server.Mobiles
if (m_DeleteTimer != null)
m_DeleteTimer.Stop();
m_DeleteTime = DateTime.Now + TimeSpan.FromSeconds(30.0);
m_DeleteTime = DateTime.Now + DeleteTime;
m_DeleteTimer = new DeleteTimer(this, m_DeleteTime - DateTime.Now);
m_DeleteTimer.Start();
@ -292,6 +438,9 @@ namespace Server.Mobiles
public virtual bool CheckAtDestination()
{
if ( MLQuestSystem.Enabled )
return false;
EDI dest = GetDestination();
if (dest == null)
@ -352,6 +501,9 @@ namespace Server.Mobiles
pm.NextCompassionDay = DateTime.Now + 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
{
@ -365,6 +517,13 @@ namespace Server.Mobiles
return false;
}
public override bool OnBeforeDeath()
{
m_DeleteCorpse = ( Controlled || IsBeingDeleted );
return base.OnBeforeDeath();
}
public BaseEscortable(Serial serial)
: base(serial)
{
@ -374,7 +533,7 @@ namespace Server.Mobiles
{
base.Serialize(writer);
writer.Write((int)0); // version
writer.Write((int)1); // version
EDI dest = GetDestination();
@ -387,6 +546,8 @@ namespace Server.Mobiles
if (m_DeleteTimer != null)
writer.WriteDeltaTime(m_DeleteTime);
MLQuestSystem.WriteQuestRef( writer, StaticMLQuester ? null : m_MLQuest );
}
public override void Deserialize(GenericReader reader)
@ -404,6 +565,14 @@ namespace Server.Mobiles
m_DeleteTimer = new DeleteTimer(this, m_DeleteTime - DateTime.Now);
m_DeleteTimer.Start();
}
if ( version >= 1 )
{
MLQuest quest = MLQuestSystem.ReadQuestRef( reader );
if ( quest != null && !StaticMLQuester )
SetMLQuest( quest );
}
}
public override bool CanBeRenamedBy(Mobile from)
@ -411,24 +580,26 @@ namespace Server.Mobiles
return (from.AccessLevel >= AccessLevel.GameMaster);
}
public override void AddCustomContextEntries(Mobile from, List<ContextMenuEntry> list)
public override void AddCustomContextEntries( Mobile from, List<ContextMenuEntry> list )
{
EDI dest = GetDestination();
if (dest != null && from.Alive)
if ( from.Alive )
{
Mobile escorter = GetEscorter();
if (escorter == null || escorter == from)
list.Add(new AskDestinationEntry(this, from));
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));
else if (escorter == from)
list.Add(new AbandonEscortEntry(this, from));
if ( escorter == null )
list.Add( new AcceptEscortEntry( this, from ) );
}
if ( escorter == from )
list.Add( new AbandonEscortEntry( this, from ) );
}
base.AddCustomContextEntries(from, list);
base.AddCustomContextEntries( from, list );
}
public virtual string[] GetPossibleDestinations()
@ -461,6 +632,9 @@ namespace Server.Mobiles
public EDI GetDestination()
{
if ( MLQuestSystem.Enabled )
return null;
if (m_DestinationString == null && m_DeleteTimer == null)
m_DestinationString = PickRandomDestination();