From 4cba2c8d56c346d5fc8bca0e0c566fb5dfda9fdb Mon Sep 17 00:00:00 2001 From: eos Date: Sun, 1 Jan 2012 03:34:02 +0000 Subject: [PATCH] Plant gump issues http://jira.runuo.com/browse/RUNUO-12 House decay stages should pass at random intervals http://jira.runuo.com/browse/RUNUO-113 Nature's Fury cast issues http://jira.runuo.com/browse/RUNUO-114 Animal Form inaccuracies and issue with Talisman of the Fey http://jira.runuo.com/browse/RUNUO-115 BaseWaterContainer fill messages and behavior http://jira.runuo.com/browse/RUNUO-116 AdminGump filter for accounts owning houses http://jira.runuo.com/browse/RUNUO-118 Seeds should be stackable http://jira.runuo.com/browse/RUNUO-119 Typo in case of a jailbreak http://jira.runuo.com/browse/RUNUO-120 Prevent creation of invalid account names http://jira.runuo.com/browse/RUNUO-121 --- Scripts/Accounting/AccountHandler.cs | 20 ++- Scripts/Engines/Help/HelpGump.cs | 4 +- Scripts/Engines/Plants/MainPlantGump.cs | 10 +- Scripts/Engines/Plants/PlantItem.cs | 2 +- Scripts/Engines/Plants/PlantPourTarget.cs | 3 + Scripts/Engines/Plants/Seed.cs | 86 +++++++--- .../Quests/Core/Items/HornOfRetreat.cs | 2 +- Scripts/Gumps/AdminGump.cs | 30 +++- Scripts/Items/Food/Beverage.cs | 30 ++-- .../Rares/Containers/BaseWaterContainer.cs | 8 + .../Special/Solen Items/BraceletOfBinding.cs | 2 +- Scripts/Multis/BaseHouse.cs | 148 +++++++++++++++--- Scripts/Multis/DynamicDecay.cs | 74 +++++++++ Scripts/Multis/HouseSign.cs | 9 ++ Scripts/Spells/Base/SpellHelper.cs | 2 +- Scripts/Spells/Ninjitsu/AnimalForm.cs | 30 +++- .../Spells/Spellweaving/Mobiles/NatureFury.cs | 21 +-- Scripts/Spells/Spellweaving/NatureFury.cs | 96 ++++++------ 18 files changed, 440 insertions(+), 137 deletions(-) create mode 100644 Scripts/Multis/DynamicDecay.cs diff --git a/Scripts/Accounting/AccountHandler.cs b/Scripts/Accounting/AccountHandler.cs index 105ab493b..155796518 100644 --- a/Scripts/Accounting/AccountHandler.cs +++ b/Scripts/Accounting/AccountHandler.cs @@ -251,17 +251,31 @@ namespace Server.Misc return m_IPTable; } - } + } + + private static readonly char[] m_ForbiddenChars = new char[] + { + '<', '>', ':', '"', '/', '\\', '|', '?', '*' + }; + + private static bool IsForbiddenChar( char c ) + { + for ( int i = 0; i < m_ForbiddenChars.Length; ++i ) + if ( c == m_ForbiddenChars[i] ) + return true; + + return false; + } private static Account CreateAccount( NetState state, string un, string pw ) { if ( un.Length == 0 || pw.Length == 0 ) return null; - bool isSafe = true; + bool isSafe = !( un.StartsWith( " " ) || un.EndsWith( " " ) || un.EndsWith( "." ) ); for ( int i = 0; isSafe && i < un.Length; ++i ) - isSafe = ( un[i] >= 0x20 && un[i] < 0x80 ); + isSafe = ( un[i] >= 0x20 && un[i] < 0x80 && !IsForbiddenChar( un[i] ) ); for ( int i = 0; isSafe && i < pw.Length; ++i ) isSafe = ( pw[i] >= 0x20 && pw[i] < 0x80 ); diff --git a/Scripts/Engines/Help/HelpGump.cs b/Scripts/Engines/Help/HelpGump.cs index 5dfa08833..785450c68 100644 --- a/Scripts/Engines/Help/HelpGump.cs +++ b/Scripts/Engines/Help/HelpGump.cs @@ -233,7 +233,7 @@ namespace Server.Engines.Help } else if ( from.Region.IsPartOf( typeof( Server.Regions.Jail ) ) ) { - from.SendLocalizedMessage( 1041530, "", 0x35 ); // You'll need a better jailbreak plan then that! + from.SendLocalizedMessage( 1114345, "", 0x35 ); // You'll need a better jailbreak plan than that! } else if ( Factions.Sigil.ExistsOn( from ) ) { @@ -290,7 +290,7 @@ namespace Server.Engines.Help { if ( from.Region.IsPartOf( typeof( Regions.Jail ) ) ) { - from.SendLocalizedMessage( 1041530, "", 0x35 ); // You'll need a better jailbreak plan then that! + from.SendLocalizedMessage( 1114345, "", 0x35 ); // You'll need a better jailbreak plan than that! } else if ( from.Region.IsPartOf( "Haven Island" ) ) { diff --git a/Scripts/Engines/Plants/MainPlantGump.cs b/Scripts/Engines/Plants/MainPlantGump.cs index 0eb19ad57..0184ca97a 100644 --- a/Scripts/Engines/Plants/MainPlantGump.cs +++ b/Scripts/Engines/Plants/MainPlantGump.cs @@ -44,19 +44,19 @@ namespace Server.Engines.Plants AddPlusMinus( 196, 67, system.Water ); AddButton( 209, 91, 0xD4, 0xD4, 7, GumpButtonType.Reply, 0 ); // Poison potion - AddItem( 197, 91, 0xF0A ); + AddItem( 201, 91, 0xF0A ); AddLevel( 196, 91, system.PoisonPotion ); AddButton( 209, 115, 0xD4, 0xD4, 8, GumpButtonType.Reply, 0 ); // Cure potion - AddItem( 192, 115, 0xF07 ); + AddItem( 201, 115, 0xF07 ); AddLevel( 196, 115, system.CurePotion ); AddButton( 209, 139, 0xD4, 0xD4, 9, GumpButtonType.Reply, 0 ); // Heal potion - AddItem( 190, 139, 0xF0C ); + AddItem( 201, 139, 0xF0C ); AddLevel( 196, 139, system.HealPotion ); AddButton( 209, 163, 0xD4, 0xD4, 10, GumpButtonType.Reply, 0 ); // Strength potion - AddItem( 193, 163, 0xF09 ); + AddItem( 201, 163, 0xF09 ); AddLevel( 196, 163, system.StrengthPotion ); AddImage( 48, 47, 0xD2 ); @@ -317,6 +317,8 @@ namespace Server.Engines.Plants from.SendLocalizedMessage( 1060808, "#" + m_Plant.GetLocalizedPlantStatus().ToString() ); // Target the container you wish to use to water the ~1_val~. } + from.SendGump( new MainPlantGump( m_Plant ) ); + break; } case 7: // Poison potion diff --git a/Scripts/Engines/Plants/PlantItem.cs b/Scripts/Engines/Plants/PlantItem.cs index 11b6dbb36..41b705247 100644 --- a/Scripts/Engines/Plants/PlantItem.cs +++ b/Scripts/Engines/Plants/PlantItem.cs @@ -386,7 +386,7 @@ namespace Server.Engines.Plants m_PlantHue = seed.PlantHue; m_ShowType = seed.ShowType; - seed.Delete(); + seed.Consume(); PlantStatus = PlantStatus.Seed; diff --git a/Scripts/Engines/Plants/PlantPourTarget.cs b/Scripts/Engines/Plants/PlantPourTarget.cs index a27b2ac9c..16f49f49b 100644 --- a/Scripts/Engines/Plants/PlantPourTarget.cs +++ b/Scripts/Engines/Plants/PlantPourTarget.cs @@ -25,6 +25,9 @@ namespace Server.Engines.Plants { if ( !m_Plant.Deleted && m_Plant.PlantStatus < PlantStatus.DecorativePlant && from.InRange( m_Plant.GetWorldLocation(), 3 ) && m_Plant.IsUsableBy( from ) ) { + if ( from.HasGump( typeof( MainPlantGump ) ) ) + from.CloseGump( typeof( MainPlantGump ) ); + from.SendGump( new MainPlantGump( m_Plant ) ); } } diff --git a/Scripts/Engines/Plants/Seed.cs b/Scripts/Engines/Plants/Seed.cs index b812d3236..f05e3615e 100644 --- a/Scripts/Engines/Plants/Seed.cs +++ b/Scripts/Engines/Plants/Seed.cs @@ -1,4 +1,5 @@ using System; +using System.Text; using Server; using Server.Targeting; @@ -76,6 +77,7 @@ namespace Server.Engines.Plants public Seed( PlantType plantType, PlantHue plantHue, bool showType ) : base( 0xDCF ) { Weight = 1.0; + Stackable = Core.SA; m_PlantType = plantType; m_PlantHue = plantHue; @@ -90,7 +92,7 @@ namespace Server.Engines.Plants public override bool ForceShowProperties{ get{ return ObjectPropertyList.Enabled; } } - public override void AddNameProperty( ObjectPropertyList list ) + private int GetLabel( out string args ) { PlantHueInfo hueInfo = PlantHueInfo.GetInfo( m_PlantHue ); @@ -98,30 +100,50 @@ namespace Server.Engines.Plants if ( title == 0 ) // Not a bonsai title = hueInfo.Name; + int label; + + if ( Amount == 1 ) + label = m_ShowType ? 1061917 : 1060838; // ~1_COLOR~ ~2_TYPE~ seed : ~1_val~ seed + else + label = m_ShowType ? 1113492 : 1113490; // ~1_amount~ ~2_color~ ~3_type~ seeds : ~1_amount~ ~2_val~ seeds + + if ( hueInfo.IsBright() ) + ++label; + + StringBuilder ab = new StringBuilder(); + + if ( Amount != 1 ) + { + ab.Append( Amount ); + ab.Append( '\t' ); + } + + ab.Append( '#' ); + ab.Append( title ); + if ( m_ShowType ) { PlantTypeInfo typeInfo = PlantTypeInfo.GetInfo( m_PlantType ); - list.Add( hueInfo.IsBright() ? 1061918 : 1061917, String.Concat( "#", title.ToString(), "\t#", typeInfo.Name.ToString() ) ); // [bright] ~1_COLOR~ ~2_TYPE~ seed - } - else - { - list.Add( hueInfo.IsBright() ? 1060839 : 1060838, String.Concat( "#", title.ToString() ) ); // [bright] ~1_val~ seed + + ab.Append( "\t#" ); + ab.Append( typeInfo.Name ); } + + args = ab.ToString(); + + return label; } - public override void OnSingleClick ( Mobile from ) + public override void AddNameProperty( ObjectPropertyList list ) { - PlantHueInfo hueInfo = PlantHueInfo.GetInfo( m_PlantHue ); + string args; + list.Add( GetLabel( out args ), args ); + } - if ( m_ShowType ) - { - PlantTypeInfo typeInfo = PlantTypeInfo.GetInfo( m_PlantType ); - LabelTo( from, hueInfo.IsBright() ? 1061918 : 1061917, String.Concat( "#", hueInfo.Name.ToString(), "\t#", typeInfo.Name.ToString() ) ); // [bright] ~1_COLOR~ ~2_TYPE~ seed - } - else - { - LabelTo( from, hueInfo.IsBright() ? 1060839 : 1060838, String.Concat( "#", hueInfo.Name.ToString() ) ); // [bright] ~1_val~ seed - } + public override void OnSingleClick( Mobile from ) + { + string args; + LabelTo( from, GetLabel( out args ), args ); } public override void OnDoubleClick( Mobile from ) @@ -136,6 +158,31 @@ namespace Server.Engines.Plants LabelTo( from, 1061916 ); // Choose a bowl of dirt to plant this seed in. } + public override bool StackWith( Mobile from, Item dropped, bool playSound ) + { + if ( dropped is Seed ) + { + Seed other = (Seed)dropped; + + if ( other.PlantType == m_PlantType && other.PlantHue == m_PlantHue && other.ShowType == m_ShowType ) + return base.StackWith( from, dropped, playSound ); + } + + return false; + } + + public override void OnAfterDuped( Item newItem ) + { + Seed newSeed = newItem as Seed; + + if ( newSeed == null ) + return; + + newSeed.PlantType = m_PlantType; + newSeed.PlantHue = m_PlantHue; + newSeed.ShowType = m_ShowType; + } + private class InternalTarget : Target { private Seed m_Seed; @@ -178,7 +225,7 @@ namespace Server.Engines.Plants { base.Serialize( writer ); - writer.Write( (int) 0 ); // version + writer.Write( (int) 1 ); // version writer.Write( (int) m_PlantType ); writer.Write( (int) m_PlantHue ); @@ -197,6 +244,9 @@ namespace Server.Engines.Plants if ( Weight != 1.0 ) Weight = 1.0; + + if ( version < 1 ) + Stackable = Core.SA; } } } \ No newline at end of file diff --git a/Scripts/Engines/Quests/Core/Items/HornOfRetreat.cs b/Scripts/Engines/Quests/Core/Items/HornOfRetreat.cs index 7b9e0bba5..5126c4dff 100644 --- a/Scripts/Engines/Quests/Core/Items/HornOfRetreat.cs +++ b/Scripts/Engines/Quests/Core/Items/HornOfRetreat.cs @@ -174,7 +174,7 @@ namespace Server.Engines.Quests { if ( m.Region.IsPartOf( typeof( Regions.Jail ) ) ) { - m.SendLocalizedMessage( 1042632 ); // You'll need a better jailbreak plan then that! + m.SendLocalizedMessage( 1114345 ); // You'll need a better jailbreak plan than that! } else if ( m == m_Caster ) { diff --git a/Scripts/Gumps/AdminGump.cs b/Scripts/Gumps/AdminGump.cs index 5b2f787ec..1a8f6fee1 100644 --- a/Scripts/Gumps/AdminGump.cs +++ b/Scripts/Gumps/AdminGump.cs @@ -10,6 +10,7 @@ using Server.Prompts; using Server.Network; using Server.Accounting; using Server.Commands; +using Server.Multis; namespace Server.Gumps { @@ -756,7 +757,8 @@ namespace Server.Gumps AddButtonLabeled( 10, 390, GetButtonID( 5, 27 ), "Ban marked" ); AddButtonLabeled( 10, 410, GetButtonID( 5, 28 ), "Delete marked" ); - AddButtonLabeled( 210, 400, GetButtonID( 5, 29 ), "Mark all" ); + AddButtonLabeled( 210, 390, GetButtonID( 5, 29 ), "Mark all" ); + AddButtonLabeled( 210, 410, GetButtonID( 5, 33 ), "Unmark house owners" ); } for ( int i = 0, index = (listPage * 12); i < 12 && index >= 0 && index < m_List.Count; ++i, ++index ) @@ -2383,6 +2385,32 @@ namespace Server.Gumps break; } + case 33: // Unmark house owners + { + ArrayList list = m_List; + ArrayList rads = m_State as ArrayList; + + if ( list == null || rads == null ) + break; + + ArrayList newRads = new ArrayList(); + + foreach ( Account acct in rads ) + { + bool hasHouse = false; + + for ( int i = 0; i < acct.Length && !hasHouse; ++i ) + if ( acct[i] != null && BaseHouse.HasHouse( acct[i] ) ) + hasHouse = true; + + if ( !hasHouse ) + newRads.Add( acct ); + } + + from.SendGump( new AdminGump( from, AdminGumpPage.Accounts, m_ListPage, m_List, null, newRads ) ); + + break; + } default: { index -= 50; diff --git a/Scripts/Items/Food/Beverage.cs b/Scripts/Items/Food/Beverage.cs index 868bd5b93..6d7735f13 100644 --- a/Scripts/Items/Food/Beverage.cs +++ b/Scripts/Items/Food/Beverage.cs @@ -741,14 +741,14 @@ namespace Server.Items { BaseWaterContainer bwc = targ as BaseWaterContainer; - if( Quantity == 0 || ( this.Content == BeverageType.Water && !this.IsFull ) ) + if( Quantity == 0 || ( Content == BeverageType.Water && !IsFull ) ) { - int I_Need = Math.Min( ( MaxQuantity - Quantity ), bwc.Quantity ); + int iNeed = Math.Min( ( MaxQuantity - Quantity ), bwc.Quantity ); - if( ( I_Need > 0 ) && !bwc.IsEmpty && !IsFull ) + if( iNeed > 0 && !bwc.IsEmpty && !IsFull ) { - bwc.Quantity -= I_Need; - Quantity += I_Need; + bwc.Quantity -= iNeed; + Quantity += iNeed; Content = BeverageType.Water; from.PlaySound( 0x4E ); @@ -1026,15 +1026,23 @@ namespace Server.Items else if( targ is BaseWaterContainer ) { BaseWaterContainer bwc = targ as BaseWaterContainer; - - if( ( !this.IsEmpty || this.Content == BeverageType.Water ) && bwc.Items.Count == 0 ) + + if( Content != BeverageType.Water ) { - int It_Needs = Math.Min( ( bwc.MaxQuantity - bwc.Quantity ), Quantity ); + from.SendLocalizedMessage( 500842 ); // Can't pour that in there. + } + else if( bwc.Items.Count != 0 ) + { + from.SendLocalizedMessage( 500841 ); // That has something in it. + } + else + { + int itNeeds = Math.Min( ( bwc.MaxQuantity - bwc.Quantity ), Quantity ); - if( It_Needs > 0 && ( !IsEmpty && !bwc.IsFull ) ) + if( itNeeds > 0 ) { - bwc.Quantity += It_Needs; - Quantity -= It_Needs; + bwc.Quantity += itNeeds; + Quantity -= itNeeds; from.PlaySound( 0x4E ); } diff --git a/Scripts/Items/Special/Rares/Containers/BaseWaterContainer.cs b/Scripts/Items/Special/Rares/Containers/BaseWaterContainer.cs index 02c7bdc57..48c2d9943 100644 --- a/Scripts/Items/Special/Rares/Containers/BaseWaterContainer.cs +++ b/Scripts/Items/Special/Rares/Containers/BaseWaterContainer.cs @@ -31,6 +31,14 @@ ItemID = ( IsEmpty ) ? voidItem_ID : fullItem_ID; + if( !IsEmpty ) + { + IEntity rootParent = RootParentEntity; + + if( rootParent != null && rootParent.Map != null && rootParent.Map != Map.Internal ) + MoveToWorld( rootParent.Location, rootParent.Map ); + } + InvalidateProperties(); } } diff --git a/Scripts/Items/Special/Solen Items/BraceletOfBinding.cs b/Scripts/Items/Special/Solen Items/BraceletOfBinding.cs index 78bccb881..0cf8ff501 100644 --- a/Scripts/Items/Special/Solen Items/BraceletOfBinding.cs +++ b/Scripts/Items/Special/Solen Items/BraceletOfBinding.cs @@ -306,7 +306,7 @@ namespace Server.Items } else if ( from.Region.IsPartOf( typeof( Server.Regions.Jail ) ) ) { - from.SendLocalizedMessage( 1041530, "", 0x35 ); // You'll need a better jailbreak plan then that! + from.SendLocalizedMessage( 1114345, "", 0x35 ); // You'll need a better jailbreak plan than that! return false; } else if ( boundRoot.Region.IsPartOf( typeof( Server.Regions.Jail ) ) ) diff --git a/Scripts/Multis/BaseHouse.cs b/Scripts/Multis/BaseHouse.cs index 3f3ab72d8..896f20eb0 100644 --- a/Scripts/Multis/BaseHouse.cs +++ b/Scripts/Multis/BaseHouse.cs @@ -24,6 +24,34 @@ namespace Server.Multis public static int MaxFriends { get { return !Core.AOS ? 50 : 140; } } public static int MaxBans { get { return !Core.AOS ? 50 : 140; } } + #region Dynamic decay system + private DecayLevel m_CurrentStage; + private DateTime m_NextDecayStage; + + [CommandProperty( AccessLevel.GameMaster )] + public DateTime NextDecayStage + { + get { return m_NextDecayStage; } + set { m_NextDecayStage = value; } + } + + public void ResetDynamicDecay() + { + m_CurrentStage = DecayLevel.Ageless; + m_NextDecayStage = DateTime.MinValue; + } + + public void SetDynamicDecay( DecayLevel level ) + { + m_CurrentStage = level; + + if ( DynamicDecay.Decays( level ) ) + m_NextDecayStage = DateTime.Now + DynamicDecay.GetRandomDuration( level ); + else + m_NextDecayStage = DateTime.MinValue; + } + #endregion + public const bool DecayEnabled = true; public static void Decay_OnTick() @@ -128,37 +156,73 @@ namespace Server.Multis } } + private DecayLevel m_LastDecayLevel; + [CommandProperty( AccessLevel.GameMaster )] public virtual DecayLevel DecayLevel { get { + DecayLevel result; + if ( !CanDecay ) { + if ( DynamicDecay.Enabled ) + ResetDynamicDecay(); + m_LastRefreshed = DateTime.Now; - return DecayLevel.Ageless; + result = DecayLevel.Ageless; + } + else if ( DynamicDecay.Enabled ) + { + DecayLevel stage = m_CurrentStage; + + if ( stage == DecayLevel.Ageless || ( DynamicDecay.Decays( stage ) && m_NextDecayStage <= DateTime.Now ) ) + SetDynamicDecay( ++stage ); + + if ( stage == DecayLevel.Collapsed && ( HasRentedVendors || VendorInventories.Count > 0 ) ) + result = DecayLevel.DemolitionPending; + else + result = stage; + } + else + { + result = GetOldDecayLevel(); } - TimeSpan timeAfterRefresh = DateTime.Now - m_LastRefreshed; - int percent = (int) ((timeAfterRefresh.Ticks * 1000) / DecayPeriod.Ticks); + if ( result != m_LastDecayLevel ) + { + m_LastDecayLevel = result; - if ( percent >= 1000 ) // 100.0% - return ( HasRentedVendors || VendorInventories.Count > 0 ) ? DecayLevel.DemolitionPending : DecayLevel.Collapsed; - else if ( percent >= 950 ) // 95.0% - 99.9% - return DecayLevel.IDOC; - else if ( percent >= 750 ) // 75.0% - 94.9% - return DecayLevel.Greatly; - else if ( percent >= 500 ) // 50.0% - 74.9% - return DecayLevel.Fairly; - else if ( percent >= 250 ) // 25.0% - 49.9% - return DecayLevel.Somewhat; - else if ( percent >= 005 ) // 00.5% - 24.9% - return DecayLevel.Slightly; + if ( m_Sign != null && !m_Sign.GettingProperties ) + m_Sign.InvalidateProperties(); + } - return DecayLevel.LikeNew; + return result; } } + public DecayLevel GetOldDecayLevel() + { + TimeSpan timeAfterRefresh = DateTime.Now - m_LastRefreshed; + int percent = (int) ((timeAfterRefresh.Ticks * 1000) / DecayPeriod.Ticks); + + if ( percent >= 1000 ) // 100.0% + return ( HasRentedVendors || VendorInventories.Count > 0 ) ? DecayLevel.DemolitionPending : DecayLevel.Collapsed; + else if ( percent >= 950 ) // 95.0% - 99.9% + return DecayLevel.IDOC; + else if ( percent >= 750 ) // 75.0% - 94.9% + return DecayLevel.Greatly; + else if ( percent >= 500 ) // 50.0% - 74.9% + return DecayLevel.Fairly; + else if ( percent >= 250 ) // 25.0% - 49.9% + return DecayLevel.Somewhat; + else if ( percent >= 005 ) // 00.5% - 24.9% + return DecayLevel.Slightly; + + return DecayLevel.LikeNew; + } + public virtual bool RefreshDecay() { if ( DecayType == DecayType.Condemned ) @@ -168,6 +232,12 @@ namespace Server.Multis m_LastRefreshed = DateTime.Now; + if ( DynamicDecay.Enabled ) + ResetDynamicDecay(); + + if ( m_Sign != null ) + m_Sign.InvalidateProperties(); + return ( oldLevel > DecayLevel.LikeNew ); } @@ -2336,7 +2406,17 @@ namespace Server.Multis { base.Serialize( writer ); - writer.Write( (int) 14 ); // version + writer.Write( (int) 15 ); // version + + if ( !DynamicDecay.Enabled ) + { + writer.Write( (int) -1 ); + } + else + { + writer.Write( (int) m_CurrentStage ); + writer.Write( m_NextDecayStage ); + } writer.Write( (Point3D) m_RelativeBanLocation ); @@ -2434,9 +2514,23 @@ namespace Server.Multis int version = reader.ReadInt(); int count; + bool loadedDynamicDecay = false; switch ( version ) { + case 15: + { + int stage = reader.ReadInt(); + + if ( stage != -1 ) + { + m_CurrentStage = (DecayLevel)stage; + m_NextDecayStage = reader.ReadDateTime(); + loadedDynamicDecay = true; + } + + goto case 14; + } case 14: { m_RelativeBanLocation = reader.ReadPoint3D(); @@ -2631,6 +2725,16 @@ namespace Server.Multis if ( version < 11 ) m_LastRefreshed = DateTime.Now + TimeSpan.FromHours( 24 * Utility.RandomDouble() ); + if ( DynamicDecay.Enabled && !loadedDynamicDecay ) + { + DecayLevel old = GetOldDecayLevel(); + + if ( old == DecayLevel.DemolitionPending ) + old = DecayLevel.Collapsed; + + SetDynamicDecay( old ); + } + if ( !CheckDecay() ) { if ( RelocatedEntities.Count > 0 ) @@ -2788,7 +2892,11 @@ namespace Server.Multis { get { - return m_Region.GoLocation; + if ( m_Region != null ) + return m_Region.GoLocation; + + Point3D rel = m_RelativeBanLocation; + return new Point3D( this.X + rel.X, this.Y + rel.Y, this.Z + rel.Z ); } set { @@ -2806,7 +2914,9 @@ namespace Server.Multis set { m_RelativeBanLocation = value; - m_Region.GoLocation = new Point3D( this.X + value.X, this.Y + value.Y, this.Z + value.Z ); + + if ( m_Region != null ) + m_Region.GoLocation = new Point3D( this.X + value.X, this.Y + value.Y, this.Z + value.Z ); } } diff --git a/Scripts/Multis/DynamicDecay.cs b/Scripts/Multis/DynamicDecay.cs new file mode 100644 index 000000000..1a470f217 --- /dev/null +++ b/Scripts/Multis/DynamicDecay.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using Server; + +namespace Server.Multis +{ + public class DynamicDecay + { + public static bool Enabled { get { return Core.ML; } } + + private static Dictionary m_Stages; + + static DynamicDecay() + { + m_Stages = new Dictionary(); + + Register( DecayLevel.LikeNew, TimeSpan.FromHours( 1 ), TimeSpan.FromHours( 1 ) ); + Register( DecayLevel.Slightly, TimeSpan.FromDays( 1 ), TimeSpan.FromDays( 2 ) ); + Register( DecayLevel.Somewhat, TimeSpan.FromDays( 1 ), TimeSpan.FromDays( 2 ) ); + Register( DecayLevel.Fairly, TimeSpan.FromDays( 1 ), TimeSpan.FromDays( 2 ) ); + Register( DecayLevel.Greatly, TimeSpan.FromDays( 1 ), TimeSpan.FromDays( 2 ) ); + Register( DecayLevel.IDOC, TimeSpan.FromHours( 12 ), TimeSpan.FromHours( 24 ) ); + } + + public static void Register( DecayLevel level, TimeSpan min, TimeSpan max ) + { + DecayStageInfo info = new DecayStageInfo( min, max ); + + if ( m_Stages.ContainsKey( level ) ) + m_Stages[level] = info; + else + m_Stages.Add( level, info ); + } + + public static bool Decays( DecayLevel level ) + { + return m_Stages.ContainsKey( level ); + } + + public static TimeSpan GetRandomDuration( DecayLevel level ) + { + if ( !m_Stages.ContainsKey( level ) ) + return TimeSpan.Zero; + + DecayStageInfo info = m_Stages[level]; + long min = info.MinDuration.Ticks; + long max = info.MaxDuration.Ticks; + + return TimeSpan.FromTicks( min + (long)( Utility.RandomDouble() * ( max - min ) ) ); + } + } + + public class DecayStageInfo + { + private TimeSpan m_MinDuration; + private TimeSpan m_MaxDuration; + + public TimeSpan MinDuration + { + get { return m_MinDuration; } + } + + public TimeSpan MaxDuration + { + get { return m_MaxDuration; } + } + + public DecayStageInfo( TimeSpan min, TimeSpan max ) + { + m_MinDuration = min; + m_MaxDuration = max; + } + } +} diff --git a/Scripts/Multis/HouseSign.cs b/Scripts/Multis/HouseSign.cs index ff1a9872d..179e6fa49 100644 --- a/Scripts/Multis/HouseSign.cs +++ b/Scripts/Multis/HouseSign.cs @@ -71,6 +71,13 @@ namespace Server.Multis public override bool ForceShowProperties{ get{ return ObjectPropertyList.Enabled; } } + private bool m_GettingProperties; + + public bool GettingProperties + { + get { return m_GettingProperties; } + } + public override void GetProperties( ObjectPropertyList list ) { base.GetProperties( list ); @@ -82,7 +89,9 @@ namespace Server.Multis { list.Add( m_Owner.Public ? 1061641 : 1061642 ); // This House is Open to the Public : This is a Private Home + m_GettingProperties = true; DecayLevel level = m_Owner.DecayLevel; + m_GettingProperties = false; if ( level == DecayLevel.DemolitionPending ) { diff --git a/Scripts/Spells/Base/SpellHelper.cs b/Scripts/Spells/Base/SpellHelper.cs index 6ccb18a1c..bb8aefd7f 100644 --- a/Scripts/Spells/Base/SpellHelper.cs +++ b/Scripts/Spells/Base/SpellHelper.cs @@ -609,7 +609,7 @@ namespace Server.Spells if( caster != null && caster.AccessLevel == AccessLevel.Player && caster.Region.IsPartOf( typeof( Regions.Jail ) ) ) { - caster.SendLocalizedMessage( 1042632 ); // You'll need a better jailbreak plan then that! + caster.SendLocalizedMessage( 1114345 ); // You'll need a better jailbreak plan than that! return false; } diff --git a/Scripts/Spells/Ninjitsu/AnimalForm.cs b/Scripts/Spells/Ninjitsu/AnimalForm.cs index 5ac37db40..c792a1791 100644 --- a/Scripts/Spells/Ninjitsu/AnimalForm.cs +++ b/Scripts/Spells/Ninjitsu/AnimalForm.cs @@ -69,11 +69,19 @@ namespace Server.Spells.Ninjitsu return false; } + private bool CasterIsMoving() + { + return (DateTime.Now - Caster.LastMoveTime <= Caster.ComputeMovementSpeed(Caster.Direction)); + } + + private bool m_WasMoving; + public override void OnBeginCast() { base.OnBeginCast(); Caster.FixedEffect(0x37C4, 10, 14, 4, 3); + m_WasMoving = CasterIsMoving(); } public override bool CheckFizzle() @@ -112,7 +120,9 @@ namespace Server.Spells.Ninjitsu } else if (Caster is PlayerMobile) { - if (GetLastAnimalForm(Caster) == -1 || DateTime.Now - Caster.LastMoveTime > Caster.ComputeMovementSpeed(Caster.Direction)) + bool skipGump = (m_WasMoving || CasterIsMoving()); + + if (GetLastAnimalForm(Caster) == -1 || !skipGump) { Caster.CloseGump(typeof(AnimalFormGump)); Caster.SendGump(new AnimalFormGump(Caster, m_Entries, this)); @@ -120,17 +130,27 @@ namespace Server.Spells.Ninjitsu else { if (Morph(Caster, GetLastAnimalForm(Caster)) == MorphResult.Fail) + { DoFizzle(); + } else + { + Caster.FixedParticles(0x3728, 10, 13, 2023, EffectLayer.Waist); Caster.Mana -= mana; + } } } else { if (Morph(Caster, GetLastAnimalForm(Caster)) == MorphResult.Fail) + { DoFizzle(); + } else + { + Caster.FixedParticles(0x3728, 10, 13, 2023, EffectLayer.Waist); Caster.Mana -= mana; + } } } @@ -189,12 +209,13 @@ namespace Server.Spells.Ninjitsu m.CheckSkill(SkillName.Ninjitsu, 0.0, 37.5); + if (!BaseFormTalisman.EntryEnabled(m, entry.Type)) + return MorphResult.Success; // Still consumes mana, just no effect + BaseMount.Dismount(m); m.BodyMod = entry.BodyMod; - - if (entry.HueMod > 0) - m.HueMod = entry.HueMod; + m.HueMod = entry.HueMod; if (entry.SpeedBoost) m.Send(SpeedControl.MountSpeed); @@ -461,6 +482,7 @@ namespace Server.Spells.Ninjitsu } else { + m_Caster.FixedParticles(0x3728, 10, 13, 2023, EffectLayer.Waist); m_Caster.Mana -= mana; } } diff --git a/Scripts/Spells/Spellweaving/Mobiles/NatureFury.cs b/Scripts/Spells/Spellweaving/Mobiles/NatureFury.cs index 3bd29c311..ba62e1ee4 100644 --- a/Scripts/Spells/Spellweaving/Mobiles/NatureFury.cs +++ b/Scripts/Spells/Spellweaving/Mobiles/NatureFury.cs @@ -17,23 +17,10 @@ namespace Server.Mobiles public override bool AlwaysMurderer { get { return true; } } - private Mobile m_Target; - - public override Mobile ConstantFocus { get { return m_Target; } } - - public override void OnThink() - { - if( m_Target != null && (!m_Target.Alive || m_Target.Deleted || !InRange( m_Target, 24 ) || !CanSee( m_Target )) ) - m_Target = null; //Go kill other stuffs - - base.OnThink(); - } - [Constructable] - public NatureFury( Mobile target ) + public NatureFury() : base( AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4 ) { - m_Target = target; Name = "a nature's fury"; Body = 0x33; Hue = 0x4001; @@ -62,12 +49,6 @@ namespace Server.Mobiles ControlSlots = 1; } - [Constructable] - public NatureFury() - : this( null ) //Null makes it act like any other mob - { - } - public override void MoveToWorld( Point3D loc, Map map ) { base.MoveToWorld( loc, map ); diff --git a/Scripts/Spells/Spellweaving/NatureFury.cs b/Scripts/Spells/Spellweaving/NatureFury.cs index 0a03dac8c..93ca3af86 100644 --- a/Scripts/Spells/Spellweaving/NatureFury.cs +++ b/Scripts/Spells/Spellweaving/NatureFury.cs @@ -1,7 +1,7 @@ using System; using Server.Mobiles; using Server.Targeting; -using Server.Multis; +using Server.Regions; namespace Server.Spells.Spellweaving { @@ -23,26 +23,12 @@ namespace Server.Spells.Spellweaving { } - private bool m_MobileTarg; - - public override int GetMana() - { - int mana = base.GetMana(); - - if( m_MobileTarg ) - mana *= 2; - - return mana; - } - - - public override bool CheckCast() { - if( !base.CheckCast() ) + if ( !base.CheckCast() ) return false; - if( (Caster.Followers + 1) > Caster.FollowersMax ) + if ( ( Caster.Followers + 1 ) > Caster.FollowersMax ) { Caster.SendLocalizedMessage( 1049645 ); // You have too many followers to summon that creature. return false; @@ -58,46 +44,29 @@ namespace Server.Spells.Spellweaving public void Target( IPoint3D point ) { - //What happens if you cast it on yourself? OSI ANSWER: You're an idiot for wasting the mana, and it'll just look for another target. - Mobile m = point as Mobile; Point3D p = new Point3D( point ); Map map = Caster.Map; - m_MobileTarg = (m != null); + if ( map == null ) + return; - BaseHouse house = BaseHouse.FindHouseAt( p, map, 0 ); - if ( house != null) - if ( !house.IsFriend ( Caster ) ) - return; - if (m != null) //say "Target can not be seen" if you target directly a mobile, like in OSI - { - Caster.SendLocalizedMessage( 500237 ); // Target can not be seen. - } - else if ( map == null || !map.CanSpawnMobile( p.X, p.Y, p.Z ) ) + HouseRegion r = Region.Find( p, map ).GetRegion( typeof( HouseRegion ) ) as HouseRegion; + + if ( r != null && r.House != null && !r.House.IsFriend( Caster ) ) + return; + + if ( !map.CanSpawnMobile( p.X, p.Y, p.Z ) ) { Caster.SendLocalizedMessage( 501942 ); // That location is blocked. } - else if( SpellHelper.CheckTown( p, Caster ) && (m_MobileTarg ? CheckHSequence( m ) : CheckSequence()) ) + else if ( SpellHelper.CheckTown( p, Caster ) && CheckSequence() ) { - TimeSpan duration = TimeSpan.FromSeconds( Caster.Skills.Spellweaving.Value/24 + 25 + FocusLevel*2 ); + TimeSpan duration = TimeSpan.FromSeconds( Caster.Skills.Spellweaving.Value / 24 + 25 + FocusLevel * 2 ); - if( m == Caster ) - m = null; + NatureFury nf = new NatureFury(); + BaseCreature.Summon( nf, false, Caster, p, 0x5CB, duration ); - NatureFury nf = new NatureFury( m ); - - BaseCreature.Summon( nf, false, Caster, p , 0x5CB, duration ); - - Timer t = null; - - t = Timer.DelayCall( TimeSpan.FromSeconds( 5.0 ), TimeSpan.FromSeconds( 5.0 ), delegate - { - if( !nf.Alive || nf.Deleted || nf.DamageMin > 20 ) //sanity - t.Stop(); - - nf.DamageMin++; - nf.DamageMax++; - } ); + new InternalTimer( nf ).Start(); } FinishSequence(); @@ -107,22 +76,47 @@ namespace Server.Spells.Spellweaving { private NatureFurySpell m_Owner; - public InternalTarget( NatureFurySpell owner ) : base( 10, true, TargetFlags.None ) + public InternalTarget( NatureFurySpell owner ) + : base( 10, true, TargetFlags.None ) { m_Owner = owner; - CheckLOS = true; } protected override void OnTarget( Mobile from, object o ) { - if( o is IPoint3D ) + if ( o is IPoint3D ) m_Owner.Target( (IPoint3D)o ); } + protected override void OnTargetFinish( Mobile from ) { - if( m_Owner != null ) + if ( m_Owner != null ) m_Owner.FinishSequence(); } } + + private class InternalTimer : Timer + { + private NatureFury m_NatureFury; + + public InternalTimer( NatureFury nf ) + : base( TimeSpan.FromSeconds( 5.0 ), TimeSpan.FromSeconds( 5.0 ) ) + { + m_NatureFury = nf; + } + + protected override void OnTick() + { + if ( m_NatureFury.Deleted || !m_NatureFury.Alive || m_NatureFury.DamageMin > 20 ) + { + Stop(); + } + else + { + ++m_NatureFury.DamageMin; + ++m_NatureFury.DamageMax; + } + } + } } } \ No newline at end of file