diff --git a/Scripts/Items/Skill Items/Magical/Misc/PotionKeg.cs b/Scripts/Items/Skill Items/Magical/Misc/PotionKeg.cs index 4a9b5e252..bce3d2322 100644 --- a/Scripts/Items/Skill Items/Magical/Misc/PotionKeg.cs +++ b/Scripts/Items/Skill Items/Magical/Misc/PotionKeg.cs @@ -95,7 +95,7 @@ namespace Server.Items get { if ( m_Held == 0 ) - return 1041641; + return 1041084; // A specially lined keg for potions. else if( m_Type >= PotionEffect.Conflagration ) return 1072658 + (int) m_Type - (int) PotionEffect.Conflagration; else diff --git a/Scripts/Items/Special/Special Scrolls/ScrollofTranscendence.cs b/Scripts/Items/Special/Special Scrolls/ScrollofTranscendence.cs index c31e8116e..aa58ca8e7 100644 --- a/Scripts/Items/Special/Special Scrolls/ScrollofTranscendence.cs +++ b/Scripts/Items/Special/Special Scrolls/ScrollofTranscendence.cs @@ -97,8 +97,8 @@ namespace Server.Items if ( !CanUse( from ) ) return; - double tskill = from.Skills[Skill].Base; - double tcap = from.Skills[Skill].Cap; + double tskill = from.Skills[Skill].Base; // value of skill without item bonuses etc + double tcap = from.Skills[Skill].Cap; // maximum value permitted bool canGain = false; double newValue = Value; @@ -110,9 +110,12 @@ namespace Server.Items { if ( ( from.SkillsTotal + newValue * 10 ) > from.SkillsCap ) { - for ( int i = 0; i <= 54; i++ ) + int ns = from.Skills.Length; // number of items in from.Skills[] + + for ( int i = 0; i < ns; i++ ) { - if ( from.Skills[i].Lock == SkillLock.Down && tskill >= newValue ) + // skill must point down and its value must be enough + if ( from.Skills[i].Lock == SkillLock.Down && from.Skills[i].Base >= newValue ) { from.Skills[i].Base -= newValue; canGain = true; diff --git a/Scripts/Mobiles/Townfolk/BaseEscortable.cs b/Scripts/Mobiles/Townfolk/BaseEscortable.cs index d3ace60da..286f2212d 100644 --- a/Scripts/Mobiles/Townfolk/BaseEscortable.cs +++ b/Scripts/Mobiles/Townfolk/BaseEscortable.cs @@ -9,24 +9,24 @@ using EDI = Server.Mobiles.EscortDestinationInfo; namespace Server.Mobiles { - public class BaseEscortable : BaseCreature - { - private EDI m_Destination; - private string m_DestinationString; + public class BaseEscortable : BaseCreature + { + private EDI m_Destination; + private string m_DestinationString; - private DateTime m_DeleteTime; - private Timer m_DeleteTimer; + private DateTime m_DeleteTime; + private Timer m_DeleteTimer; - public override bool Commandable { get { return false; } } // Our master cannot boss us around! + public override bool Commandable { get { return false; } } // Our master cannot boss us around! - [CommandProperty( AccessLevel.GameMaster )] - public string Destination - { - get { return m_Destination == null ? null : m_Destination.Name; } - set { m_DestinationString = value; m_Destination = EDI.Find( value ); } - } + [CommandProperty(AccessLevel.GameMaster)] + public string Destination + { + get { return m_Destination == null ? null : m_Destination.Name; } + set { m_DestinationString = value; m_Destination = EDI.Find(value); } + } - private static string[] m_TownNames = new string[] + private static string[] m_TownNames = new string[] { "Cove", "Britain", "Jhelom", "Minoc", "Ocllo", "Trinsic", @@ -34,576 +34,580 @@ namespace Server.Mobiles "Nujel'm", "Moonglow", "Magincia" }; - private static string[] m_MLTownNames = new string[] + private static string[] m_MLTownNames = new string[] { "Cove", "Serpent's Hold", "Jhelom", //ML List "Nujel'm" }; - [Constructable] - public BaseEscortable() - : base( AIType.AI_Melee, FightMode.Aggressor, 22, 1, 0.2, 1.0 ) - { - InitBody(); - InitOutfit(); - } - - 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; } - } - - private static TimeSpan m_EscortDelay = TimeSpan.FromMinutes( 5.0 ); - - 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 + m_EscortDelay) >= DateTime.Now ) - { - int minutes = (int)Math.Ceiling( ((((PlayerMobile)m).LastEscortTime + m_EscortDelay) - DateTime.Now).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.Now; - - if( m is PlayerMobile ) - ((PlayerMobile)m).LastEscortTime = DateTime.Now; - - 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; - } + [Constructable] + public BaseEscortable() + : base(AIType.AI_Melee, FightMode.Aggressor, 22, 1, 0.2, 1.0) + { + InitBody(); + InitOutfit(); + } + + 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; } + } + + private static TimeSpan m_EscortDelay = TimeSpan.FromMinutes(5.0); + + 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 + m_EscortDelay) >= DateTime.Now) + { + int minutes = (int)Math.Ceiling(((((PlayerMobile)m).LastEscortTime + m_EscortDelay) - DateTime.Now).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.Now; + + if (m is PlayerMobile) + ((PlayerMobile)m).LastEscortTime = DateTime.Now; + + 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 (from.InRange(this.Location, 3)) + return true; + + return base.HandlesOnSpeech(from); + } + + public override void OnSpeech(SpeechEventArgs e) + { + base.OnSpeech(e); - return false; - } + EDI dest = GetDestination(); - public override bool HandlesOnSpeech( Mobile from ) - { - if( from.InRange( this.Location, 3 ) ) - return true; + 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); + } + } - return base.HandlesOnSpeech( from ); - } + public override void OnAfterDelete() + { + if (m_DeleteTimer != null) + m_DeleteTimer.Stop(); + + m_DeleteTimer = null; + + base.OnAfterDelete(); + } - public override void OnSpeech( SpeechEventArgs e ) - { - base.OnSpeech( e ); + public override void OnThink() + { + base.OnThink(); + CheckAtDestination(); + } + + protected override bool OnMove(Direction d) + { + if (!base.OnMove(d)) + return false; - EDI dest = GetDestination(); + CheckAtDestination(); - 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 ); - } - } + return true; + } - public override void OnAfterDelete() - { - if( m_DeleteTimer != null ) - m_DeleteTimer.Stop(); + public virtual void StartFollow() + { + StartFollow(GetEscorter()); + } - m_DeleteTimer = null; + public virtual void StartFollow(Mobile escorter) + { + if (escorter == null) + return; - base.OnAfterDelete(); - } + ActiveSpeed = 0.1; + PassiveSpeed = 0.2; - public override void OnThink() - { - base.OnThink(); - CheckAtDestination(); - } + ControlOrder = OrderType.Follow; + ControlTarget = escorter; - protected override bool OnMove( Direction d ) - { - if( !base.OnMove( d ) ) - return false; + if ((IsPrisoner == true) && (CantWalk == true)) + { + CantWalk = false; + } + CurrentSpeed = 0.1; + } - CheckAtDestination(); + public virtual void StopFollow() + { + ActiveSpeed = 0.2; + PassiveSpeed = 1.0; - return true; - } + ControlOrder = OrderType.None; + ControlTarget = null; - public virtual void StartFollow() - { - StartFollow( GetEscorter() ); - } + CurrentSpeed = 1.0; + } - public virtual void StartFollow( Mobile escorter ) - { - if( escorter == null ) - return; + private DateTime m_LastSeenEscorter; - ActiveSpeed = 0.1; - PassiveSpeed = 0.2; + public virtual Mobile GetEscorter() + { + if (!Controlled) + return null; - ControlOrder = OrderType.Follow; - ControlTarget = escorter; + Mobile master = ControlMaster; - CurrentSpeed = 0.1; - } + if (master == null) + return null; - public virtual void StopFollow() - { - ActiveSpeed = 0.2; - PassiveSpeed = 1.0; + if (master.Deleted || master.Map != this.Map || !master.InRange(Location, 30) || !master.Alive) + { + StopFollow(); - ControlOrder = OrderType.None; - ControlTarget = null; + TimeSpan lastSeenDelay = DateTime.Now - m_LastSeenEscorter; - CurrentSpeed = 1.0; - } + if (lastSeenDelay >= TimeSpan.FromMinutes(2.0)) + { + master.SendLocalizedMessage(1042473); // You have lost the person you were escorting. + Say(1005653); // Hmmm. I seem to have lost my master. - private DateTime m_LastSeenEscorter; + SetControlMaster(null); + m_EscortTable.Remove(master); - public virtual Mobile GetEscorter() - { - if( !Controlled ) - return null; + Timer.DelayCall(TimeSpan.FromSeconds(5.0), new TimerCallback(Delete)); + return null; + } + else + { + ControlOrder = OrderType.Stay; + return master; + } + } - Mobile master = ControlMaster; + if (ControlOrder != OrderType.Follow) + StartFollow(master); - if( master == null ) - return null; + m_LastSeenEscorter = DateTime.Now; + return master; + } - if( master.Deleted || master.Map != this.Map || !master.InRange( Location, 30 ) || !master.Alive ) - { - StopFollow(); + public virtual void BeginDelete() + { + if (m_DeleteTimer != null) + m_DeleteTimer.Stop(); - TimeSpan lastSeenDelay = DateTime.Now - m_LastSeenEscorter; + m_DeleteTime = DateTime.Now + TimeSpan.FromSeconds(30.0); - if( lastSeenDelay >= TimeSpan.FromMinutes( 2.0 ) ) - { - master.SendLocalizedMessage( 1042473 ); // You have lost the person you were escorting. - Say( 1005653 ); // Hmmm. I seem to have lost my master. + m_DeleteTimer = new DeleteTimer(this, m_DeleteTime - DateTime.Now); + m_DeleteTimer.Start(); + } - SetControlMaster( null ); - m_EscortTable.Remove( master ); + public virtual bool CheckAtDestination() + { + EDI dest = GetDestination(); - Timer.DelayCall( TimeSpan.FromSeconds( 5.0 ), new TimerCallback( Delete ) ); - return null; - } - else - { - ControlOrder = OrderType.Stay; - return master; - } - } + if (dest == null) + return false; - if( ControlOrder != OrderType.Follow ) - StartFollow( master ); + Mobile escorter = GetEscorter(); - m_LastSeenEscorter = DateTime.Now; - return master; - } + if (escorter == null) + return false; - public virtual void BeginDelete() - { - if( m_DeleteTimer != null ) - m_DeleteTimer.Stop(); + 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. - m_DeleteTime = DateTime.Now + TimeSpan.FromSeconds( 30.0 ); + // not going anywhere + m_Destination = null; + m_DestinationString = null; - m_DeleteTimer = new DeleteTimer( this, m_DeleteTime - DateTime.Now ); - m_DeleteTimer.Start(); - } + Container cont = escorter.Backpack; - public virtual bool CheckAtDestination() - { - EDI dest = GetDestination(); + if (cont == null) + cont = escorter.BankBox; - if( dest == null ) - return false; + Gold gold = new Gold(500, 1000); - Mobile escorter = GetEscorter(); + if (!cont.TryDropItem(escorter, gold, false)) + gold.MoveToWorld(escorter.Location, escorter.Map); - if( escorter == null ) - return false; + StopFollow(); + SetControlMaster(null); + m_EscortTable.Remove(escorter); + BeginDelete(); - 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. + Misc.Titles.AwardFame(escorter, 10, true); - // not going anywhere - m_Destination = null; - m_DestinationString = null; + bool gainedPath = false; - Container cont = escorter.Backpack; + PlayerMobile pm = escorter as PlayerMobile; - if( cont == null ) - cont = escorter.BankBox; + if (pm != null) + { + if (pm.CompassionGains > 0 && DateTime.Now > pm.NextCompassionDay) + { + pm.NextCompassionDay = DateTime.MinValue; + pm.CompassionGains = 0; + } - Gold gold = new Gold( 500, 1000 ); + 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. - if( !cont.TryDropItem( escorter, gold, false ) ) - gold.MoveToWorld( escorter.Location, escorter.Map ); + pm.NextCompassionDay = DateTime.Now + TimeSpan.FromDays(1.0); // in one day CompassionGains gets reset to 0 + ++pm.CompassionGains; + } + else + { + pm.SendLocalizedMessage(1053003); // You have achieved the highest path of compassion and can no longer gain any further. + } + } - StopFollow(); - SetControlMaster( null ); - m_EscortTable.Remove( escorter ); - BeginDelete(); + return true; + } - Misc.Titles.AwardFame( escorter, 10, true ); + return false; + } - bool gainedPath = false; + public BaseEscortable(Serial serial) + : base(serial) + { + } - PlayerMobile pm = escorter as PlayerMobile; + public override void Serialize(GenericWriter writer) + { + base.Serialize(writer); - if( pm != null ) - { - if( pm.CompassionGains > 0 && DateTime.Now > pm.NextCompassionDay ) - { - pm.NextCompassionDay = DateTime.MinValue; - pm.CompassionGains = 0; - } + writer.Write((int)0); // version - 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. + EDI dest = GetDestination(); - pm.NextCompassionDay = DateTime.Now + TimeSpan.FromDays( 1.0 ); // in one day CompassionGains gets reset to 0 - ++pm.CompassionGains; - } - else - { - pm.SendLocalizedMessage( 1053003 ); // You have achieved the highest path of compassion and can no longer gain any further. - } - } + writer.Write(dest != null); - return true; - } + if (dest != null) + writer.Write(dest.Name); - return false; - } + writer.Write(m_DeleteTimer != null); - public BaseEscortable( Serial serial ) - : base( serial ) - { - } + if (m_DeleteTimer != null) + writer.WriteDeltaTime(m_DeleteTime); + } - public override void Serialize( GenericWriter writer ) - { - base.Serialize( writer ); + public override void Deserialize(GenericReader reader) + { + base.Deserialize(reader); - writer.Write( (int)0 ); // version + int version = reader.ReadInt(); - EDI dest = GetDestination(); + if (reader.ReadBool()) + m_DestinationString = reader.ReadString(); // NOTE: We cannot EDI.Find here, regions have not yet been loaded :-( - writer.Write( dest != null ); + if (reader.ReadBool()) + { + m_DeleteTime = reader.ReadDeltaTime(); + m_DeleteTimer = new DeleteTimer(this, m_DeleteTime - DateTime.Now); + m_DeleteTimer.Start(); + } + } + + public override bool CanBeRenamedBy(Mobile from) + { + return (from.AccessLevel >= AccessLevel.GameMaster); + } + + public override void AddCustomContextEntries(Mobile from, List list) + { + EDI dest = GetDestination(); + + if (dest != null && from.Alive) + { + Mobile escorter = GetEscorter(); + + 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)); + } + + 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; + } - if( dest != null ) - writer.Write( dest.Name ); - - writer.Write( m_DeleteTimer != null ); - - if( m_DeleteTimer != null ) - writer.WriteDeltaTime( m_DeleteTime ); - } - - 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.Now ); - m_DeleteTimer.Start(); - } - } - - public override bool CanBeRenamedBy( Mobile from ) - { - return (from.AccessLevel >= AccessLevel.GameMaster); - } - - public override void AddCustomContextEntries( Mobile from, List list ) - { - EDI dest = GetDestination(); - - if( dest != null && from.Alive ) - { - Mobile escorter = GetEscorter(); - - 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 ) ); - } - - 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( 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 - } - } + public EDI GetDestination() + { + 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 + } + } } \ No newline at end of file diff --git a/Scripts/Multis/Camps/BaseCamp.cs b/Scripts/Multis/Camps/BaseCamp.cs index db9f5aa62..144bd9afe 100644 --- a/Scripts/Multis/Camps/BaseCamp.cs +++ b/Scripts/Multis/Camps/BaseCamp.cs @@ -13,19 +13,37 @@ namespace Server.Multis private List m_Mobiles; private DateTime m_DecayTime; private Timer m_DecayTimer; + private TimeSpan m_DecayDelay; public virtual int EventRange{ get{ return 10; } } - public virtual TimeSpan DecayDelay{ get{ return TimeSpan.FromMinutes( 30.0 ); } } + public virtual TimeSpan DecayDelay { + get { return m_DecayDelay; } + set { + m_DecayDelay = value; + RefreshDecay( true ); + } + } public BaseCamp( int multiID ) : base( multiID | 0x4000 ) { m_Items = new List(); m_Mobiles = new List(); + m_DecayDelay = TimeSpan.FromMinutes( 30.0 ); RefreshDecay( true ); Timer.DelayCall( TimeSpan.Zero, new TimerCallback( CheckAddComponents ) ); } + public BaseCamp( int multiID, int mode ) : base( multiID | 0x4000*mode ) + { + m_Items = new List(); + m_Mobiles = new List(); + m_DecayDelay = TimeSpan.FromMinutes(30.0); + RefreshDecay(true); + + Timer.DelayCall( TimeSpan.Zero, new TimerCallback( CheckAddComponents ) ); + } + public void CheckAddComponents() { if ( Deleted ) @@ -56,14 +74,16 @@ namespace Server.Multis { m_Items.Add( item ); - item.MoveToWorld( new Point3D( X + xOffset, Y + yOffset, Z + zOffset ), Map ); + int zavg = Map.GetAverageZ(X + xOffset, Y + yOffset); + item.MoveToWorld( new Point3D( X + xOffset, Y + yOffset, zavg + zOffset ), Map ); } public virtual void AddMobile( Mobile m, int wanderRange, int xOffset, int yOffset, int zOffset ) { - m_Mobiles.Add( m ); + m_Mobiles.Add(m); - Point3D loc = new Point3D( X + xOffset, Y + yOffset, Z + zOffset ); + int zavg = Map.GetAverageZ(X + xOffset, Y + yOffset); + Point3D loc = new Point3D(X + xOffset, Y + yOffset, zavg + zOffset); BaseCreature bc = m as BaseCreature; if ( bc != null ) @@ -108,8 +128,15 @@ namespace Server.Multis for ( int i = 0; i < m_Items.Count; ++i ) m_Items[i].Delete(); - for ( int i = 0; i < m_Mobiles.Count; ++i ) - m_Mobiles[i].Delete(); + for ( int i = 0; i < m_Mobiles.Count; ++i ) + { + BaseCreature bc = (BaseCreature)m_Mobiles[i]; + + if ( bc.IsPrisoner == false ) + m_Mobiles[i].Delete(); + else if ( m_Mobiles[i].CantWalk == true ) + m_Mobiles[i].Delete(); + } m_Items.Clear(); m_Mobiles.Clear(); @@ -151,4 +178,36 @@ namespace Server.Multis } } } + + public class LockableBarrel : LockableContainer + { + [Constructable] + public LockableBarrel() + : base(0xE77) + { + Weight = 1.0; + } + + public LockableBarrel(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(); + + if (Weight == 8.0) + Weight = 1.0; + } + } } \ No newline at end of file diff --git a/Scripts/Multis/Camps/BrigandCamp.cs b/Scripts/Multis/Camps/BrigandCamp.cs new file mode 100644 index 000000000..4d4f739cf --- /dev/null +++ b/Scripts/Multis/Camps/BrigandCamp.cs @@ -0,0 +1,197 @@ +using System; +using Server; +using Server.Items; +using Server.Mobiles; + +namespace Server.Multis +{ + public class BrigandCamp : BaseCamp + { + public virtual Mobile Brigands{ get{ return new Brigand(); } } + public virtual Mobile Executioners{ get{ return new Executioner(); } } + + private Mobile m_Prisoner; + + private int m_SpawnRange; + + [Constructable] + public BrigandCamp() : base( 0x10ee, 0 ) // dummy garbage at center + { + } + + public override void AddComponents() + { + BaseCreature bc; + //BaseEscortable be; + + Visible = false; + DecayDelay = TimeSpan.FromMinutes( 5.0 ); + + AddItem(new Static(0x10ee), 0, 0, 0); + AddItem(new Static(0xfac), 0, 7, 0); + + switch ( Utility.Random( 3 ) ) + { + case 0: + { + AddItem( new Item( 0xDE3 ), 0, 7, 0 ); // Campfire + AddItem( new Item( 0x974 ), 0, 7, 1 ); // Cauldron + break; + } + case 1: + { + AddItem( new Item( 0x1E95 ), 0, 7, 1 ); // Rabbit on a spit + break; + } + default: + { + AddItem( new Item( 0x1E94 ), 0, 7, 1 ); // Chicken on a spit + break; + } + } + + AddCampChests(); + + for ( int i = 0; i < 4; i ++ ) + { + AddMobile( Brigands, 6, Utility.RandomMinMax( -7, 7 ), Utility.RandomMinMax( -7, 7 ), 0 ); + } + + switch ( Utility.Random( 2 ) ) + { + case 0: m_Prisoner = new Noble(); break; + default: m_Prisoner = new SeekerOfAdventure(); break; + } + + //be = (BaseEscortable)m_Prisoner; + //be.m_Captive = true; + + bc = (BaseCreature)m_Prisoner; + bc.IsPrisoner = true; + bc.CantWalk = true; + + m_Prisoner.YellHue = Utility.RandomList( 0x57, 0x67, 0x77, 0x87, 0x117 ); + AddMobile( m_Prisoner, 2, Utility.RandomMinMax( -2, 2 ), Utility.RandomMinMax( -2, 2 ), 0 ); + } + + private void AddCampChests() + { + LockableContainer chest = null; + + switch (Utility.Random(3)) + { + case 0: chest = new MetalChest(); break; + case 1: chest = new MetalGoldenChest(); break; + default: chest = new WoodenChest(); break; + } + + chest.LiftOverride = true; + + TreasureMapChest.Fill(chest, 1); + + AddItem(chest, -2, -2, 0); + + LockableContainer crates = null; + + switch (Utility.Random(4)) + { + case 0: crates = new SmallCrate(); break; + case 1: crates = new MediumCrate(); break; + case 2: crates = new LargeCrate(); break; + default: crates = new LockableBarrel(); break; + } + + crates.TrapType = TrapType.ExplosionTrap; + crates.TrapPower = Utility.RandomMinMax(30, 40); + crates.TrapLevel = 2; + + crates.RequiredSkill = 76; + crates.LockLevel = 66; + crates.MaxLockLevel = 116; + crates.Locked = true; + + crates.DropItem(new Gold(Utility.RandomMinMax(100, 400))); + crates.DropItem(new Arrow(10)); + crates.DropItem(new Bolt(10)); + + crates.LiftOverride = true; + + if (Utility.RandomDouble() < 0.8) + { + switch (Utility.Random(4)) + { + case 0: crates.DropItem(new LesserCurePotion()); break; + case 1: crates.DropItem(new LesserExplosionPotion()); break; + case 2: crates.DropItem(new LesserHealPotion()); break; + default: crates.DropItem(new LesserPoisonPotion()); break; + } + } + + AddItem(crates, 2, 2, 0); + } + + // Don't refresh decay timer + public override void OnEnter( Mobile m ) + { + if ( m.Player && m_Prisoner != null && m_Prisoner.CantWalk ) + { + int number; + + switch ( Utility.Random( 8 ) ) + { + case 0: number = 502261; break; // HELP! + case 1: number = 502262; break; // Help me! + case 2: number = 502263; break; // Canst thou aid me?! + case 3: number = 502264; break; // Help a poor prisoner! + case 4: number = 502265; break; // Help! Please! + case 5: number = 502266; break; // Aaah! Help me! + case 6: number = 502267; break; // Go and get some help! + default: number = 502268; break; // Quickly, I beg thee! Unlock my chains! If thou dost look at me close thou canst see them. + } + m_Prisoner.Yell( number ); + } + } + + // Don't refresh decay timer + public override void OnExit(Mobile m) + { + } + + public BrigandCamp( Serial serial ) : base( serial ) + { + } + + public override void AddItem( Item item, int xOffset, int yOffset, int zOffset ) + { + if ( item != null ) + item.Movable = false; + + base.AddItem( item, xOffset, yOffset, zOffset ); + } + + public override void Serialize( GenericWriter writer ) + { + base.Serialize( writer ); + + writer.Write( (int) 0 ); // version + + writer.Write( m_Prisoner ); + } + + public override void Deserialize( GenericReader reader ) + { + base.Deserialize( reader ); + + int version = reader.ReadInt(); + + switch ( version ) + { + case 0: + { + m_Prisoner = reader.ReadMobile(); + break; + } + } + } + } +} diff --git a/Scripts/Multis/Camps/LizardmenCamp.cs b/Scripts/Multis/Camps/LizardmenCamp.cs new file mode 100644 index 000000000..480b9355b --- /dev/null +++ b/Scripts/Multis/Camps/LizardmenCamp.cs @@ -0,0 +1,196 @@ +using System; +using Server; +using Server.Items; +using Server.Mobiles; + +namespace Server.Multis +{ + public class LizardmenCamp : BaseCamp + { + public virtual Mobile Lizardmen{ get{ return new Lizardman(); } } + + private Mobile m_Prisoner; + + private int m_SpawnRange; + + [Constructable] + public LizardmenCamp() : base( 0x10ee , 0 ) // dummy garbage at center + { + } + + public override void AddComponents() + { + BaseCreature bc; + //BaseEscortable be; + + Visible = false; + DecayDelay = TimeSpan.FromMinutes( 5.0 ); + AddItem(new Static(0x10ee), 0, 0, 0); + AddItem(new Static(0xfac), 0, 7, 0); + + switch ( Utility.Random( 3 ) ) + { + case 0: + { + AddItem( new Item( 0xDE3 ), 0, 7, 0 ); // Campfire + AddItem( new Item( 0x974 ), 0, 7, 1); // Cauldron + break; + } + case 1: + { + AddItem( new Item( 0x1E95 ), 0, 7, 1); // Rabbit on a spit + break; + } + default: + { + AddItem( new Item( 0x1E94 ), 0, 7, 1); // Chicken on a spit + break; + } + } + AddItem(new Item(0x41F), 4, 4, 0); // Gruesome Standart South + + AddCampChests(); + + for ( int i = 0; i < 4; i ++ ) + { + AddMobile( Lizardmen, 6, Utility.RandomMinMax( -7, 7 ), Utility.RandomMinMax( -7, 7 ), 0 ); + } + + switch ( Utility.Random( 2 ) ) + { + case 0: m_Prisoner = new Noble(); break; + default: m_Prisoner = new SeekerOfAdventure(); break; + } + + //be = (BaseEscortable)m_Prisoner; + //be.m_Captive = true; + + bc = (BaseCreature)m_Prisoner; + bc.IsPrisoner = true; + bc.CantWalk = true; + + m_Prisoner.YellHue = Utility.RandomList( 0x57, 0x67, 0x77, 0x87, 0x117 ); + AddMobile( m_Prisoner, 2, Utility.RandomMinMax( -2, 2 ), Utility.RandomMinMax( -2, 2 ), 0 ); + } + + private void AddCampChests() + { + LockableContainer chest = null; + + switch ( Utility.Random( 3 ) ) + { + case 0: chest = new MetalChest(); break; + case 1: chest = new MetalGoldenChest(); break; + default: chest = new WoodenChest(); break; + } + + chest.LiftOverride = true; + + TreasureMapChest.Fill( chest, 1 ); + + AddItem( chest, 2, -2, 0 ); + + LockableContainer crates = null; + + switch ( Utility.Random( 4 ) ) + { + case 0: crates = new SmallCrate(); break; + case 1: crates = new MediumCrate(); break; + case 2: crates = new LargeCrate(); break; + default: crates = new LockableBarrel(); break; + } + + crates.TrapType = TrapType.ExplosionTrap; + crates.TrapPower = Utility.RandomMinMax( 30, 40 ); + crates.TrapLevel = 2; + + crates.RequiredSkill = 76; + crates.LockLevel = 66; + crates.MaxLockLevel = 116; + crates.Locked = true; + + crates.DropItem( new Gold( Utility.RandomMinMax( 100, 400 ) ) ); + crates.DropItem( new Arrow( 10 ) ); + crates.DropItem( new Bolt( 10 ) ); + + crates.LiftOverride = true; + + if ( Utility.RandomDouble() < 0.8 ) + { + switch ( Utility.Random( 4 ) ) + { + case 0: crates.DropItem( new LesserCurePotion() ); break; + case 1: crates.DropItem( new LesserExplosionPotion() ); break; + case 2: crates.DropItem( new LesserHealPotion() ); break; + default: crates.DropItem(new LesserPoisonPotion()); break; + } + } + + AddItem( crates, -2, 2, 0 ); + } + + // Don't refresh decay timer + public override void OnEnter(Mobile m) + { + if ( m.Player && m_Prisoner != null && m_Prisoner.CantWalk ) + { + int number; + + switch ( Utility.Random( 8 ) ) + { + case 0: number = 502261; break; // HELP! + case 1: number = 502262; break; // Help me! + case 2: number = 502263; break; // Canst thou aid me?! + case 3: number = 502264; break; // Help a poor prisoner! + case 4: number = 502265; break; // Help! Please! + case 5: number = 502266; break; // Aaah! Help me! + case 6: number = 502267; break; // Go and get some help! + default: number = 502268; break; // Quickly, I beg thee! Unlock my chains! If thou dost look at me close thou canst see them. + } + m_Prisoner.Yell( number ); + } + } + + // Don't refresh decay timer + public override void OnExit(Mobile m) + { + } + + public LizardmenCamp( Serial serial ) : base( serial ) + { + } + + public override void AddItem( Item item, int xOffset, int yOffset, int zOffset ) + { + if ( item != null ) + item.Movable = false; + + base.AddItem( item, xOffset, yOffset, zOffset ); + } + + public override void Serialize( GenericWriter writer ) + { + base.Serialize( writer ); + + writer.Write( (int) 0 ); // version + + writer.Write( m_Prisoner ); + } + + public override void Deserialize( GenericReader reader ) + { + base.Deserialize( reader ); + + int version = reader.ReadInt(); + + switch ( version ) + { + case 0: + { + m_Prisoner = reader.ReadMobile(); + break; + } + } + } + } +} diff --git a/Scripts/Multis/Camps/OrcCamp.cs b/Scripts/Multis/Camps/OrcCamp.cs index affbdd919..d448d8599 100644 --- a/Scripts/Multis/Camps/OrcCamp.cs +++ b/Scripts/Multis/Camps/OrcCamp.cs @@ -4,90 +4,178 @@ using Server.Items; using Server.Mobiles; namespace Server.Multis -{ +{ public class OrcCamp : BaseCamp { + public virtual Mobile Orcs{ get{ return new Orc(); } } + private Mobile m_Prisoner; - private BaseDoor m_Gate; - + + private int m_SpawnRange; + [Constructable] - public OrcCamp() : base( 0x1D4C ) + public OrcCamp() : base( 0x10ee, 0 ) // dummy garbage at center { } public override void AddComponents() { BaseCreature bc; + //BaseEscortable be; - IronGate gate = new IronGate( DoorFacing.EastCCW ); - m_Gate = gate; - - gate.KeyValue = Key.RandomValue(); - gate.Locked = true; - - AddItem( gate, -2, 1, 0 ); - - MetalChest chest = new MetalChest(); - - chest.ItemID = 0xE7C; - chest.LiftOverride = true; - chest.DropItem( new Key( KeyType.Iron, gate.KeyValue ) ); - - TreasureMapChest.Fill( chest, 2 ); - - AddItem( chest, 4, 4, 1 ); - - AddMobile( new Orc(), 15, 0, -2, 0 ); - AddMobile( new Orc(), 15, 0, 1, 0 ); - AddMobile( new OrcishMage(), 15, 0, -1, 0 ); - AddMobile( new OrcCaptain(), 15, 0, 0, 0 ); + Visible = false; + DecayDelay = TimeSpan.FromMinutes(5.0); + AddItem(new Static(0x10ee), 0, 0, 0); + AddItem(new Static(0xfac), 0, 7, 0); + + switch ( Utility.Random( 3 ) ) + { + case 0: + { + AddItem( new Item( 0xDE3 ), 0, 7, 0 ); // Campfire + AddItem( new Item( 0x974 ), 0, 7, 1 ); // Cauldron + break; + } + case 1: + { + AddItem( new Item( 0x1E95 ), 0, 7, 1 ); // Rabbit on a spit + break; + } + default: + { + AddItem( new Item( 0x1E94 ), 0, 7, 1 ); // Chicken on a spit + break; + } + } + AddItem(new Item(0x428), -5, -4, 0); // Gruesome Standart West + AddCampChests(); + + for ( int i = 0; i < 3; i ++ ) + { + AddMobile( Orcs, 6, Utility.RandomMinMax( -7, 7 ), Utility.RandomMinMax( -7, 7 ), 0 ); + } + AddMobile( new OrcCaptain(), 2, Utility.RandomMinMax( -7, 7 ), Utility.RandomMinMax( -7, 7 ), 0 ); + switch ( Utility.Random( 2 ) ) { case 0: m_Prisoner = new Noble(); break; - case 1: m_Prisoner = new SeekerOfAdventure(); break; + default: m_Prisoner = new SeekerOfAdventure(); break; } - + + //be = (BaseEscortable)m_Prisoner; + //be.m_Captive = true; + bc = (BaseCreature)m_Prisoner; bc.IsPrisoner = true; + bc.CantWalk = true; + m_Prisoner.YellHue = Utility.RandomList( 0x57, 0x67, 0x77, 0x87, 0x117 ); - - AddMobile( m_Prisoner, 2, -2, 0, 0 ); + AddMobile( m_Prisoner, 2, Utility.RandomMinMax( -2, 2 ), Utility.RandomMinMax( -2, 2 ), 0 ); } - public override void OnEnter( Mobile m ) - { - base.OnEnter( m ); + private void AddCampChests() + { + LockableContainer chest = null; - if ( m.Player && m_Prisoner != null && m_Gate != null && m_Gate.Locked ) + switch (Utility.Random(3)) + { + case 0: chest = new MetalChest(); break; + case 1: chest = new MetalGoldenChest(); break; + default: chest = new WoodenChest(); break; + } + + chest.LiftOverride = true; + + TreasureMapChest.Fill(chest, 1); + + AddItem(chest, -2, 2, 0); + + LockableContainer crates = null; + + switch (Utility.Random(4)) + { + case 0: crates = new SmallCrate(); break; + case 1: crates = new MediumCrate(); break; + case 2: crates = new LargeCrate(); break; + default: crates = new LockableBarrel(); break; + } + + crates.TrapType = TrapType.ExplosionTrap; + crates.TrapPower = Utility.RandomMinMax(30, 40); + crates.TrapLevel = 2; + + crates.RequiredSkill = 76; + crates.LockLevel = 66; + crates.MaxLockLevel = 116; + crates.Locked = true; + + crates.DropItem(new Gold(Utility.RandomMinMax(100, 400))); + crates.DropItem(new Arrow(10)); + crates.DropItem(new Bolt(10)); + + crates.LiftOverride = true; + + if (Utility.RandomDouble() < 0.8) + { + switch (Utility.Random(4)) + { + case 0: crates.DropItem(new LesserCurePotion()); break; + case 1: crates.DropItem(new LesserExplosionPotion()); break; + case 2: crates.DropItem(new LesserHealPotion()); break; + default: crates.DropItem(new LesserPoisonPotion()); break; + } + } + + AddItem(crates, 2, -2, 0); + } + + // Don't refresh decay timer + public override void OnEnter(Mobile m) + { + if ( m.Player && m_Prisoner != null && m_Prisoner.CantWalk ) { int number; - switch ( Utility.Random( 4 ) ) + switch ( Utility.Random( 8 ) ) { - default: - case 0: number = 502264; break; // Help a poor prisoner! - case 1: number = 502266; break; // Aaah! Help me! - case 2: number = 1046000; break; // Help! These savages wish to end my life! - case 3: number = 1046003; break; // Quickly! Kill them for me! HELP!! + case 0: number = 502261; break; // HELP! + case 1: number = 502262; break; // Help me! + case 2: number = 502263; break; // Canst thou aid me?! + case 3: number = 502264; break; // Help a poor prisoner! + case 4: number = 502265; break; // Help! Please! + case 5: number = 502266; break; // Aaah! Help me! + case 6: number = 502267; break; // Go and get some help! + default: number = 502268; break; // Quickly, I beg thee! Unlock my chains! If thou dost look at me close thou canst see them. } - m_Prisoner.Yell( number ); } } + // Don't refresh decay timer + public override void OnExit(Mobile m) + { + } + public OrcCamp( Serial serial ) : base( serial ) { } - + + public override void AddItem( Item item, int xOffset, int yOffset, int zOffset ) + { + if ( item != null ) + item.Movable = false; + + base.AddItem( item, xOffset, yOffset, zOffset ); + } + public override void Serialize( GenericWriter writer ) { base.Serialize( writer ); - writer.Write( (int) 0 ); // version + writer.Write( (int) 1 ); // version writer.Write( m_Prisoner ); - writer.Write( m_Gate ); } public override void Deserialize( GenericReader reader ) @@ -98,10 +186,15 @@ namespace Server.Multis switch ( version ) { + case 1: + { + m_Prisoner = reader.ReadMobile(); + break; + } case 0: { m_Prisoner = reader.ReadMobile(); - m_Gate = reader.ReadItem() as BaseDoor; + reader.ReadItem(); break; } } diff --git a/Scripts/Multis/Camps/RatCamp.cs b/Scripts/Multis/Camps/RatCamp.cs index 1dc43b4ed..9278e4fe3 100644 --- a/Scripts/Multis/Camps/RatCamp.cs +++ b/Scripts/Multis/Camps/RatCamp.cs @@ -4,90 +4,177 @@ using Server.Items; using Server.Mobiles; namespace Server.Multis -{ +{ public class RatCamp : BaseCamp { + public virtual Mobile Ratmen{ get{ return new Ratman(); } } + private Mobile m_Prisoner; - private BaseDoor m_Gate; - + + private int m_SpawnRange; + [Constructable] - public RatCamp() : base( 0x1D4C ) + public RatCamp() : base( 0x10ee, 0 ) // dummy garbage at center { } public override void AddComponents() { BaseCreature bc; + //BaseEscortable be; - IronGate gate = new IronGate( DoorFacing.EastCCW ); - m_Gate = gate; - - gate.KeyValue = Key.RandomValue(); - gate.Locked = true; - - AddItem( gate, -2, 1, 0 ); - - MetalChest chest = new MetalChest(); - - chest.ItemID = 0xE7C; - chest.LiftOverride = true; - chest.DropItem( new Key( KeyType.Iron, gate.KeyValue ) ); - - TreasureMapChest.Fill( chest, 2 ); - - AddItem( chest, 4, 4, 1 ); - - AddMobile( new Ratman(), 15, 0, -2, 0 ); - AddMobile( new Ratman(), 15, 0, 1, 0 ); - AddMobile( new RatmanMage(), 15, 0, -1, 0 ); - AddMobile( new RatmanArcher(), 15, 0, 0, 0 ); + Visible = false; + DecayDelay = TimeSpan.FromMinutes(5.0); + AddItem(new Static(0x10ee), 0, 0, 0); + AddItem(new Static(0xfac), 0, 6, 0); + + switch ( Utility.Random( 3 ) ) + { + case 0: + { + AddItem( new Item( 0xDE3 ), 0, 6, 0 ); // Campfire + AddItem( new Item( 0x974 ), 0, 6, 1 ); // Cauldron + break; + } + case 1: + { + AddItem( new Item( 0x1E95 ), 0, 6, 1 ); // Rabbit on a spit + break; + } + default: + { + AddItem( new Item( 0x1E94 ), 0, 6, 1 ); // Chicken on a spit + break; + } + } + AddItem(new Item(0x41F), 5, 5, 0); // Gruesome Standart South + AddCampChests(); + + for ( int i = 0; i < 4; i ++ ) + { + AddMobile( Ratmen, 6, Utility.RandomMinMax( -7, 7 ), Utility.RandomMinMax( -7, 7 ), 0 ); + } + switch ( Utility.Random( 2 ) ) { case 0: m_Prisoner = new Noble(); break; - case 1: m_Prisoner = new SeekerOfAdventure(); break; + default: m_Prisoner = new SeekerOfAdventure(); break; } - + + //be = (BaseEscortable)m_Prisoner; + //be.m_Captive = true; + bc = (BaseCreature)m_Prisoner; bc.IsPrisoner = true; + bc.CantWalk = true; + m_Prisoner.YellHue = Utility.RandomList( 0x57, 0x67, 0x77, 0x87, 0x117 ); - - AddMobile( m_Prisoner, 2, -2, 0, 0 ); + AddMobile( m_Prisoner, 2, Utility.RandomMinMax( -2, 2 ), Utility.RandomMinMax( -2, 2 ), 0 ); } - public override void OnEnter( Mobile m ) - { - base.OnEnter( m ); + private void AddCampChests() + { + LockableContainer chest = null; - if ( m.Player && m_Prisoner != null && m_Gate != null && m_Gate.Locked ) + switch (Utility.Random(3)) + { + case 0: chest = new MetalChest(); break; + case 1: chest = new MetalGoldenChest(); break; + default: chest = new WoodenChest(); break; + } + + chest.LiftOverride = true; + + TreasureMapChest.Fill(chest, 1); + + AddItem(chest, -2, -2, 0); + + LockableContainer crates = null; + + switch (Utility.Random(4)) + { + case 0: crates = new SmallCrate(); break; + case 1: crates = new MediumCrate(); break; + case 2: crates = new LargeCrate(); break; + default: crates = new LockableBarrel(); break; + } + + crates.TrapType = TrapType.ExplosionTrap; + crates.TrapPower = Utility.RandomMinMax(30, 40); + crates.TrapLevel = 2; + + crates.RequiredSkill = 76; + crates.LockLevel = 66; + crates.MaxLockLevel = 116; + crates.Locked = true; + + crates.DropItem(new Gold(Utility.RandomMinMax(100, 400))); + crates.DropItem(new Arrow(10)); + crates.DropItem(new Bolt(10)); + + crates.LiftOverride = true; + + if (Utility.RandomDouble() < 0.8) + { + switch (Utility.Random(4)) + { + case 0: crates.DropItem(new LesserCurePotion()); break; + case 1: crates.DropItem(new LesserExplosionPotion()); break; + case 2: crates.DropItem(new LesserHealPotion()); break; + default: crates.DropItem(new LesserPoisonPotion()); break; + } + } + + AddItem(crates, 2, 2, 0); + } + + // Don't refresh decay timer + public override void OnEnter(Mobile m) + { + if ( m.Player && m_Prisoner != null && m_Prisoner.CantWalk ) { int number; - switch ( Utility.Random( 4 ) ) + switch ( Utility.Random( 8 ) ) { - default: - case 0: number = 502264; break; // Help a poor prisoner! - case 1: number = 502266; break; // Aaah! Help me! - case 2: number = 1046000; break; // Help! These savages wish to end my life! - case 3: number = 1046003; break; // Quickly! Kill them for me! HELP!! + case 0: number = 502261; break; // HELP! + case 1: number = 502262; break; // Help me! + case 2: number = 502263; break; // Canst thou aid me?! + case 3: number = 502264; break; // Help a poor prisoner! + case 4: number = 502265; break; // Help! Please! + case 5: number = 502266; break; // Aaah! Help me! + case 6: number = 502267; break; // Go and get some help! + default: number = 502268; break; // Quickly, I beg thee! Unlock my chains! If thou dost look at me close thou canst see them. } - m_Prisoner.Yell( number ); } } + // Don't refresh decay timer + public override void OnExit(Mobile m) + { + } + public RatCamp( Serial serial ) : base( serial ) { } - + + public override void AddItem( Item item, int xOffset, int yOffset, int zOffset ) + { + if ( item != null ) + item.Movable = false; + + base.AddItem( item, xOffset, yOffset, zOffset ); + } + public override void Serialize( GenericWriter writer ) { base.Serialize( writer ); - writer.Write( (int) 0 ); // version + writer.Write( (int) 1 ); // version writer.Write( m_Prisoner ); - writer.Write( m_Gate ); } public override void Deserialize( GenericReader reader ) @@ -98,10 +185,15 @@ namespace Server.Multis switch ( version ) { + case 1: + { + m_Prisoner = reader.ReadMobile(); + break; + } case 0: { m_Prisoner = reader.ReadMobile(); - m_Gate = reader.ReadItem() as BaseDoor; + reader.ReadItem(); break; } }