diff --git a/Scripts/Items/Misc/AcidSlime.cs b/Scripts/Items/Misc/AcidSlime.cs new file mode 100644 index 000000000..2aa47f712 --- /dev/null +++ b/Scripts/Items/Misc/AcidSlime.cs @@ -0,0 +1,97 @@ +using System; +using Server; +using Server.Mobiles; +using Server.Spells; +using System.Collections; +using System.Collections.Generic; + +namespace Server.Items +{ + public class AcidSlime : Item + { + private TimeSpan m_Duration; + private int m_MinDamage; + private int m_MaxDamage; + private DateTime m_Created; + private bool m_Drying; + private Timer m_Timer; + + [Constructable] + public AcidSlime() : this( TimeSpan.FromSeconds( 10.0 ), 5, 10 ) + { + } + + public override string DefaultName { get { return "slime"; } } + + [Constructable] + public AcidSlime( TimeSpan duration, int minDamage, int maxDamage ) + : base( 0x122A ) + { + Hue = 0x3F; + Movable = false; + m_MinDamage = minDamage; + m_MaxDamage = maxDamage; + m_Created = DateTime.Now; + m_Duration = duration; + m_Timer = Timer.DelayCall( TimeSpan.Zero, TimeSpan.FromSeconds( 1 ), new TimerCallback( OnTick ) ); + } + + public override void OnAfterDelete() + { + if( m_Timer != null ) + m_Timer.Stop(); + } + + private void OnTick() + { + DateTime now = DateTime.Now; + TimeSpan age = now - m_Created; + + if( age > m_Duration ) + Delete(); + else + { + if( !m_Drying && age > (m_Duration - age) ) + { + m_Drying = true; + ItemID = 0x122B; + } + foreach( Mobile m in GetMobilesInRange( 0 ) ) + { + BaseCreature bc = m as BaseCreature; + if( m.Alive && !m.IsDeadBondedPet && (bc == null || bc.Controlled || bc.Summoned) ) + { + Damage ( m ); + } + } + } + } + + public override bool OnMoveOver( Mobile m ) + { + Damage( m ); + return true; + } + + public void Damage ( Mobile m ) + { + int damage = Utility.RandomMinMax( m_MinDamage, m_MaxDamage ); + if ( Core.AOS ) + AOS.Damage( m, damage, 0, 0, 0, 100, 0 ); + else + m.Damage( damage ); + } + + public AcidSlime( Serial serial ) : base( serial ) + { + } + + public override void Serialize( GenericWriter writer ) + { + } + + public override void Deserialize( GenericReader reader ) + { + } + } +} diff --git a/Scripts/Items/Misc/BankCheck.cs b/Scripts/Items/Misc/BankCheck.cs index fa88ea1f9..16aa604b0 100644 --- a/Scripts/Items/Misc/BankCheck.cs +++ b/Scripts/Items/Misc/BankCheck.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using Server; using Server.Items; using Server.Mobiles; @@ -68,7 +69,14 @@ namespace Server.Items { base.GetProperties( list ); - list.Add( 1060738, Core.ML ? m_Worth.ToString( "N0" ) : m_Worth.ToString() ); // value: ~1_val~ + string worth; + + if ( Core.ML ) + worth = m_Worth.ToString( "N0", CultureInfo.GetCultureInfo( "en-US" ) ); + else + worth = m_Worth.ToString(); + + list.Add( 1060738, worth ); // value: ~1_val~ } public override void OnSingleClick( Mobile from ) diff --git a/Scripts/Items/Misc/PoolOfAcid.cs b/Scripts/Items/Misc/PoolOfAcid.cs index 855e38ae1..b385d100b 100644 --- a/Scripts/Items/Misc/PoolOfAcid.cs +++ b/Scripts/Items/Misc/PoolOfAcid.cs @@ -12,70 +12,10 @@ namespace Server.Items private TimeSpan m_Duration; private int m_MinDamage; private int m_MaxDamage; - private DateTime m_Created; - private bool m_Drying; - private Timer m_Timer; - [CommandProperty( AccessLevel.GameMaster )] - public bool Drying - { - get - { - return m_Drying; - } - set - { - m_Drying = value; - - if( m_Drying ) - ItemID = 0x122A; - else - ItemID = 0x122B; - } - } - - - [CommandProperty( AccessLevel.GameMaster )] - public TimeSpan Duration{ get{ return m_Duration; } set{ m_Duration = value; } } - - [CommandProperty( AccessLevel.GameMaster )] - public int MinDamage - { - get - { - return m_MinDamage; - } - set - { - if ( value < 1 ) - value = 1; - - m_MinDamage = value; - } - } - - [CommandProperty( AccessLevel.GameMaster )] - public int MaxDamage - { - get - { - return m_MaxDamage; - } - set - { - if ( value < 1 ) - value = 1; - - if ( value < MinDamage ) - value = MinDamage; - - m_MaxDamage = value; - } - } - [Constructable] public PoolOfAcid() : this( TimeSpan.FromSeconds( 10.0 ), 2, 5 ) { @@ -113,37 +53,31 @@ namespace Server.Items Delete(); else { - if( !Drying && age > (m_Duration - age) ) - Drying = true; - - List toDamage = new List(); - + if( !m_Drying && age > (m_Duration - age) ) + { + m_Drying = true; + ItemID = 0x122B; + } foreach( Mobile m in GetMobilesInRange( 0 ) ) { BaseCreature bc = m as BaseCreature; if( m.Alive && !m.IsDeadBondedPet && (bc == null || bc.Controlled || bc.Summoned) ) { - toDamage.Add( m ); + Damage ( m ); } } - - for( int i = 0; i < toDamage.Count; i++ ) - Damage( toDamage[i] ); - } } - - public override bool OnMoveOver( Mobile m ) { Damage( m ); return true; } - public void Damage( Mobile m ) + public void Damage ( Mobile m ) { - m.Damage( Utility.RandomMinMax( MinDamage, MaxDamage ) ); + m.Damage( Utility.RandomMinMax( m_MinDamage, m_MaxDamage ) ); } public PoolOfAcid( Serial serial ) : base( serial ) diff --git a/Scripts/Items/Skill Items/Magical/Potions/Explosion Potions/BaseExplosionPotion.cs b/Scripts/Items/Skill Items/Magical/Potions/Explosion Potions/BaseExplosionPotion.cs index 235eb0beb..642fb912c 100644 --- a/Scripts/Items/Skill Items/Magical/Potions/Explosion Potions/BaseExplosionPotion.cs +++ b/Scripts/Items/Skill Items/Magical/Potions/Explosion Potions/BaseExplosionPotion.cs @@ -128,6 +128,7 @@ namespace Server.Items } Explode( from, true, loc, map ); + m_Timer = null; } else { diff --git a/Scripts/Items/Weapons/BaseWeapon.cs b/Scripts/Items/Weapons/BaseWeapon.cs index 979e688f7..e20bc474f 100644 --- a/Scripts/Items/Weapons/BaseWeapon.cs +++ b/Scripts/Items/Weapons/BaseWeapon.cs @@ -3362,7 +3362,7 @@ namespace Server.Items Type resourceType = typeRes; if ( resourceType == null ) - resourceType = craftItem.Ressources.GetAt( 0 ).ItemType; + resourceType = craftItem.Resources.GetAt( 0 ).ItemType; if ( Core.AOS ) { diff --git a/Scripts/Mobiles/Monsters/Ants/BlackSolenQueen.cs b/Scripts/Mobiles/Monsters/Ants/BlackSolenQueen.cs index 4bfad5767..921bd358b 100644 --- a/Scripts/Mobiles/Monsters/Ants/BlackSolenQueen.cs +++ b/Scripts/Mobiles/Monsters/Ants/BlackSolenQueen.cs @@ -107,7 +107,7 @@ namespace Server.Mobiles } else if ( from != null && from != this && InRange( from, 1 ) ) { - SpillAcid( TimeSpan.FromSeconds( 10 ), 30, 30, from ); + SpillAcid( from, 1 ); } } @@ -116,7 +116,7 @@ namespace Server.Mobiles public override bool OnBeforeDeath() { - SpillAcid( TimeSpan.FromSeconds( 10 ), 30, 30, 1, 4 ); + SpillAcid( 4 ); return base.OnBeforeDeath(); } diff --git a/Scripts/Mobiles/Monsters/Ants/BlackSolenWarrior.cs b/Scripts/Mobiles/Monsters/Ants/BlackSolenWarrior.cs index 06e7f15bf..736652a44 100644 --- a/Scripts/Mobiles/Monsters/Ants/BlackSolenWarrior.cs +++ b/Scripts/Mobiles/Monsters/Ants/BlackSolenWarrior.cs @@ -108,7 +108,7 @@ namespace Server.Mobiles } else if ( from != null && from != this && InRange( from, 1 ) ) { - SpillAcid( TimeSpan.FromSeconds( 10 ), 30, 30, from ); + SpillAcid( from, 1 ); } } @@ -117,7 +117,7 @@ namespace Server.Mobiles public override bool OnBeforeDeath() { - SpillAcid( TimeSpan.FromSeconds( 10 ), 30, 30, 1, 4 ); + SpillAcid( 4 ); return base.OnBeforeDeath(); } diff --git a/Scripts/Mobiles/Monsters/Ants/RedSolenQueen.cs b/Scripts/Mobiles/Monsters/Ants/RedSolenQueen.cs index b5a8641f6..3f1a2bbc6 100644 --- a/Scripts/Mobiles/Monsters/Ants/RedSolenQueen.cs +++ b/Scripts/Mobiles/Monsters/Ants/RedSolenQueen.cs @@ -107,7 +107,7 @@ namespace Server.Mobiles } else if ( from != null && from != this && InRange( from, 1 ) ) { - SpillAcid( TimeSpan.FromSeconds( 10 ), 30, 30, from ); + SpillAcid( from, 1 ); } } @@ -116,7 +116,7 @@ namespace Server.Mobiles public override bool OnBeforeDeath() { - SpillAcid( TimeSpan.FromSeconds( 10 ), 30, 30, 1, 4 ); + SpillAcid( 4 ); return base.OnBeforeDeath(); } diff --git a/Scripts/Mobiles/Monsters/Ants/RedSolenWarrior.cs b/Scripts/Mobiles/Monsters/Ants/RedSolenWarrior.cs index cf553bf8a..ae86ed4c6 100644 --- a/Scripts/Mobiles/Monsters/Ants/RedSolenWarrior.cs +++ b/Scripts/Mobiles/Monsters/Ants/RedSolenWarrior.cs @@ -107,7 +107,7 @@ namespace Server.Mobiles } else if ( from != null && from != this && InRange( from, 1 ) ) { - SpillAcid( TimeSpan.FromSeconds( 10 ), 30, 30, from ); + SpillAcid( from, 1 ); } } @@ -116,7 +116,7 @@ namespace Server.Mobiles public override bool OnBeforeDeath() { - SpillAcid( TimeSpan.FromSeconds( 10 ), 30, 30, 1, 4 ); + SpillAcid( 4 ); return base.OnBeforeDeath(); } diff --git a/Scripts/Mobiles/Townfolk/BaseEscortable.cs b/Scripts/Mobiles/Townfolk/BaseEscortable.cs index f6991f05d..5031e911f 100644 --- a/Scripts/Mobiles/Townfolk/BaseEscortable.cs +++ b/Scripts/Mobiles/Townfolk/BaseEscortable.cs @@ -11,584 +11,599 @@ namespace Server.Mobiles { public class BaseEscortable : BaseCreature { - private EDI m_Destination; - private string m_DestinationString; + 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 + [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[] + { + "Cove", "Britain", "Jhelom", + "Minoc", "Ocllo", "Trinsic", + "Vesper", "Yew", "Skara Brae", //Original List, will need to add it back for Pre-ML shards + "Nujel'm", "Moonglow", "Magincia" + }; + + 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()) { - get{ return m_Destination == null ? null : m_Destination.Name; } - set{ m_DestinationString = value; m_Destination = EDI.Find( value ); } + 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; } - private static string[] m_TownNames = new string[] - { - "Cove", "Britain", "Jhelom", - "Minoc", "Ocllo", "Trinsic", - "Vesper", "Yew", "Skara Brae", - "Nujel'm", "Moonglow", "Magincia" - }; + return false; + } - [Constructable] - public BaseEscortable() : base( AIType.AI_Melee, FightMode.Aggressor, 22, 1, 0.2, 1.0 ) + 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) { - InitBody(); - InitOutfit(); + 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; } - public virtual void InitBody() + 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); + + EDI dest = GetDestination(); + + if (dest != null && !e.Handled && e.Mobile.InRange(this.Location, 3)) { - SetStr( 90, 100 ); - SetDex( 90, 100 ); - SetInt( 15, 25 ); + if (e.HasKeyword(0x1D)) // *destination* + e.Handled = SayDestinationTo(e.Mobile); + else if (e.HasKeyword(0x1E)) // *i will take thee* + e.Handled = AcceptEscorter(e.Mobile); + } + } - Hue = Utility.RandomSkinHue(); + public override void OnAfterDelete() + { + if (m_DeleteTimer != null) + m_DeleteTimer.Stop(); - if ( Female = Utility.RandomBool() ) + 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; + } + + 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; + + 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 (master == null) + return null; + + if (master.Deleted || master.Map != this.Map || !master.InRange(Location, 30) || !master.Alive) + { + StopFollow(); + + TimeSpan lastSeenDelay = DateTime.Now - m_LastSeenEscorter; + + 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. + + 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.Now; + return master; + } + + public virtual void BeginDelete() + { + if (m_DeleteTimer != null) + m_DeleteTimer.Stop(); + + m_DeleteTime = DateTime.Now + TimeSpan.FromSeconds(30.0); + + m_DeleteTimer = new DeleteTimer(this, m_DeleteTime - DateTime.Now); + m_DeleteTimer.Start(); + } + + public virtual bool CheckAtDestination() + { + 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.Now > pm.NextCompassionDay) { - Body = 401; - Name = NameList.RandomName( "female" ); + 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.Now + TimeSpan.FromDays(1.0); // in one day CompassionGains gets reset to 0 + ++pm.CompassionGains; } else { - Body = 400; - Name = NameList.RandomName( "male" ); + pm.SendLocalizedMessage(1053003); // You have achieved the highest path of compassion and can no longer gain any further. } } - 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 ); + return true; } - public virtual bool SayDestinationTo( Mobile m ) + return false; + } + + public BaseEscortable(Serial serial) + : base(serial) + { + } + + public override void Serialize(GenericWriter writer) + { + base.Serialize(writer); + + writer.Write((int)0); // 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); + } + + 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()) { - EDI dest = GetDestination(); + m_DeleteTime = reader.ReadDeltaTime(); + m_DeleteTimer = new DeleteTimer(this, m_DeleteTime - DateTime.Now); + m_DeleteTimer.Start(); + } + } - if ( dest == null || !m.Alive ) - return false; + public override bool CanBeRenamedBy(Mobile from) + { + return (from.AccessLevel >= AccessLevel.GameMaster); + } - Mobile escorter = GetEscorter(); + public override void AddCustomContextEntries(Mobile from, List list) + { + EDI dest = GetDestination(); - 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; - } + if (dest != null && from.Alive) + { + Mobile escorter = GetEscorter(); - return false; + 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)); } - private static Hashtable m_EscortTable = new Hashtable(); + base.AddCustomContextEntries(from, list); + } - public static Hashtable EscortTable + 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) { - get{ return m_EscortTable; } + picked = possible[Utility.Random(possible.Length)]; + EDI test = EDI.Find(picked); + + if (test != null && test.Contains(Location)) + picked = null; } - private static TimeSpan m_EscortDelay = TimeSpan.FromMinutes( 5.0 ); + return picked; + } - public virtual bool AcceptEscorter( Mobile m ) + 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) { - EDI dest = GetDestination(); + m_Mobile = m; - 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; + Priority = TimerPriority.OneSecond; } - public override bool HandlesOnSpeech( Mobile from ) + protected override void OnTick() { - 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; - } - - 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; - - 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 ( master == null ) - return null; - - if ( master.Deleted || master.Map != this.Map || !master.InRange( Location, 30 ) || !master.Alive ) - { - StopFollow(); - - TimeSpan lastSeenDelay = DateTime.Now - m_LastSeenEscorter; - - 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. - - 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.Now; - return master; - } - - public virtual void BeginDelete() - { - if ( m_DeleteTimer != null ) - m_DeleteTimer.Stop(); - - m_DeleteTime = DateTime.Now + TimeSpan.FromSeconds( 30.0 ); - - m_DeleteTimer = new DeleteTimer( this, m_DeleteTime - DateTime.Now ); - m_DeleteTimer.Start(); - } - - public virtual bool CheckAtDestination() - { - 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.Now > 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.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. - } - } - - return true; - } - - return false; - } - - public BaseEscortable( Serial serial ) : base( serial ) - { - } - - public override void Serialize( GenericWriter writer ) - { - base.Serialize( writer ); - - writer.Write( (int) 0 ); // 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 ); - } - - 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() - { - return m_TownNames; - } - - public virtual string PickRandomDestination() - { - if ( Map.Felucca.Regions.Count == 0 || Map == null || Map == Map.Internal || Location == Point3D.Zero ) - return null; // Not yet fully initialized - - string[] possible = GetPossibleDestinations(); - string picked = null; - - while ( picked == null ) - { - picked = possible[Utility.Random( possible.Length )]; - EDI test = EDI.Find( picked ); - - if ( test != 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(); - } + m_Mobile.Delete(); } } + } public class EscortDestinationInfo { - private string m_Name; - private Region m_Region; - //private Rectangle2D[] m_Bounds; + private string m_Name; + private Region m_Region; + //private Rectangle2D[] m_Bounds; - public string Name + 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) { - get{ return m_Name; } + if (r.Name == null) + continue; + + if (r is Regions.DungeonRegion || r is Regions.TownRegion) + m_Table[r.Name] = new EscortDestinationInfo(r.Name, r); } + } - public Region Region - { - get{ return m_Region; } - } + public static EDI Find(string name) + { + if (m_Table == null) + LoadTable(); - /*public Rectangle2D[] Bounds - { - get{ return m_Bounds; } - }*/ + if (name == null || m_Table == null) + return null; - 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]; - } + return (EscortDestinationInfo)m_Table[name]; + } } public class AskDestinationEntry : ContextMenuEntry { - private BaseEscortable m_Mobile; - private Mobile m_From; + private BaseEscortable m_Mobile; + private Mobile m_From; - public AskDestinationEntry( BaseEscortable m, Mobile from ) : base( 6100, 3 ) - { - m_Mobile = m; - m_From = 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 override void OnClick() + { + m_Mobile.SayDestinationTo(m_From); + } } public class AcceptEscortEntry : ContextMenuEntry { - private BaseEscortable m_Mobile; - private Mobile m_From; + private BaseEscortable m_Mobile; + private Mobile m_From; - public AcceptEscortEntry( BaseEscortable m, Mobile from ) : base( 6101, 3 ) - { - m_Mobile = m; - m_From = 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 override void OnClick() + { + m_Mobile.AcceptEscorter(m_From); + } } public class AbandonEscortEntry : ContextMenuEntry { - private BaseEscortable m_Mobile; - private Mobile m_From; + private BaseEscortable m_Mobile; + private Mobile m_From; - public AbandonEscortEntry( BaseEscortable m, Mobile from ) : base( 6102, 3 ) - { - m_Mobile = m; - m_From = 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 override void OnClick() + { + m_Mobile.Delete(); // OSI just seems to delete instantly + } } } \ No newline at end of file diff --git a/Scripts/Mobiles/Townfolk/SeekerOfAdventure.cs b/Scripts/Mobiles/Townfolk/SeekerOfAdventure.cs index 91735d1a1..a7e47a44e 100644 --- a/Scripts/Mobiles/Townfolk/SeekerOfAdventure.cs +++ b/Scripts/Mobiles/Townfolk/SeekerOfAdventure.cs @@ -8,15 +8,24 @@ namespace Server.Mobiles public class SeekerOfAdventure : BaseEscortable { private static string[] m_Dungeons = new string[] - { - "Covetous", "Deceit", "Despise", - "Destard", "Hythloth", "Shame", - "Wrong" - }; + { + "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() { - return m_Dungeons; + if ( Core.ML ) + return m_MLDestinations; + else + return m_Dungeons; } [Constructable] diff --git a/Scripts/Mobiles/Vendors/PlayerVendor.cs b/Scripts/Mobiles/Vendors/PlayerVendor.cs index fd6e237d0..168110b00 100644 --- a/Scripts/Mobiles/Vendors/PlayerVendor.cs +++ b/Scripts/Mobiles/Vendors/PlayerVendor.cs @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Globalization; using Server; using Server.Items; using Server.Mobiles; @@ -33,6 +34,17 @@ namespace Server.Mobiles public Item Item{ get{ return m_Item; } } public int Price{ get{ return m_Price; } } + public string FormattedPrice + { + get + { + if ( Core.ML ) + return m_Price.ToString( "N0", CultureInfo.GetCultureInfo( "en-US" ) ); + + return m_Price.ToString(); + } + } + public string Description { get{ return m_Description; } @@ -197,7 +209,7 @@ namespace Server.Mobiles else if ( vi.IsForFree ) list.Add( 1043306 ); // Price: FREE! else - list.Add( 1043304, vi.Price.ToString() ); // Price: ~1_COST~ + list.Add( 1043304, vi.FormattedPrice ); // Price: ~1_COST~ } public override void GetChildProperties( ObjectPropertyList list, Item item ) @@ -230,7 +242,7 @@ namespace Server.Mobiles else if ( vi.IsForFree ) item.LabelTo( from, 1043306 ); // Price: FREE! else - item.LabelTo( from, 1043304, vi.Price.ToString() ); // Price: ~1_COST~ + item.LabelTo( from, 1043304, vi.FormattedPrice ); // Price: ~1_COST~ if ( !String.IsNullOrEmpty( vi.Description ) ) { diff --git a/Scripts/Spells/Base/SpellHelper.cs b/Scripts/Spells/Base/SpellHelper.cs index 19a0a50b1..50c8168c2 100644 --- a/Scripts/Spells/Base/SpellHelper.cs +++ b/Scripts/Spells/Base/SpellHelper.cs @@ -169,6 +169,19 @@ namespace Server.Spells return false; } + + public static bool CanRevealCaster( Mobile m ) + { + if ( m is BaseCreature ) + { + BaseCreature c = (BaseCreature)m; + + if ( !c.Controlled ) + return true; + } + + return false; + } public static void GetSurfaceTop( ref IPoint3D p ) { @@ -532,19 +545,21 @@ namespace Server.Spells new TravelValidator( IsDoomFerry ), new TravelValidator( IsFactionStronghold ), new TravelValidator( IsChampionSpawn ), - new TravelValidator( IsTokunoDungeon ) + new TravelValidator( IsTokunoDungeon ), + new TravelValidator( IsLampRoom ), + new TravelValidator( IsGuardianRoom ), }; private static bool[,] m_Rules = new bool[,] { - /*T2A(Fel) Ilshenar Wind(Tram), Wind(Fel), Dungeons(Fel), Solen(Tram), Solen(Fel), CrystalCave(Malas), Gauntlet(Malas), Gauntlet(Ferry), Stronghold, ChampionSpawn, Dungeons(Tokuno[Malas]) */ -/* Recall From */ { false, true, true, false, false, true, false, false, false, false, true, true, true }, -/* Recall To */ { false, false, false, false, false, false, false, false, false, false, false, false, false }, -/* Gate From */ { false, false, false, false, false, false, false, false, false, false, false, false, false }, -/* Gate To */ { false, false, false, false, false, false, false, false, false, false, false, false, false }, -/* Mark In */ { false, false, false, false, false, false, false, false, false, false, false, false, false }, -/* Tele From */ { true, true, true, true, true, true, true, false, true, true, false, true, true }, -/* Tele To */ { true, true, true, true, true, true, true, false, true, false, false, true, true }, + /*T2A(Fel) Ilshenar Wind(Tram), Wind(Fel), Dungeons(Fel), Solen(Tram), Solen(Fel), CrystalCave(Malas), Gauntlet(Malas), Gauntlet(Ferry), Stronghold, ChampionSpawn, Dungeons(Tokuno[Malas]), LampRoom(Doom), GuardianRoom(Doom) */ +/* Recall From */ { false, true, true, false, false, true, false, false, false, false, true, true, true, false, false }, +/* Recall To */ { false, false, false, false, false, false, false, false, false, false, false, false, false, false, false }, +/* Gate From */ { false, false, false, false, false, false, false, false, false, false, false, false, false, false, false }, +/* Gate To */ { false, false, false, false, false, false, false, false, false, false, false, false, false, false, false }, +/* Mark In */ { false, false, false, false, false, false, false, false, false, false, false, false, false, false, false }, +/* Tele From */ { true, true, true, true, true, true, true, false, true, true, false, true, true, true, true }, +/* Tele To */ { true, true, true, true, true, true, true, false, true, false, false, true, true, true, true }, }; public static bool CheckTravel( Mobile caster, TravelCheckType type ) @@ -736,6 +751,26 @@ namespace Server.Spells return (x >= 0 && y >= 0 && x < 256 && y < 256); } + public static bool IsLampRoom( Map map, Point3D loc ) + { + if ( map != Map.Malas ) + return false; + + int x = loc.X, y = loc.Y; + + return ( x >= 465 && y >= 92 && x < 474 && y < 102 ); + } + + public static bool IsGuardianRoom( Map map, Point3D loc ) + { + if ( map != Map.Malas ) + return false; + + int x = loc.X, y = loc.Y; + + return ( x >= 356 && y >= 5 && x < 375 && y < 25 ); + } + public static bool IsInvalid( Map map, Point3D loc ) { if( map == null || map == Map.Internal )