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
This commit is contained in:
eos 2012-01-01 03:34:02 +00:00
parent d2f79e93ea
commit 4cba2c8d56
18 changed files with 440 additions and 137 deletions

View file

@ -253,15 +253,29 @@ namespace Server.Misc
} }
} }
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 ) private static Account CreateAccount( NetState state, string un, string pw )
{ {
if ( un.Length == 0 || pw.Length == 0 ) if ( un.Length == 0 || pw.Length == 0 )
return null; return null;
bool isSafe = true; bool isSafe = !( un.StartsWith( " " ) || un.EndsWith( " " ) || un.EndsWith( "." ) );
for ( int i = 0; isSafe && i < un.Length; ++i ) 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 ) for ( int i = 0; isSafe && i < pw.Length; ++i )
isSafe = ( pw[i] >= 0x20 && pw[i] < 0x80 ); isSafe = ( pw[i] >= 0x20 && pw[i] < 0x80 );

View file

@ -233,7 +233,7 @@ namespace Server.Engines.Help
} }
else if ( from.Region.IsPartOf( typeof( Server.Regions.Jail ) ) ) 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 ) ) else if ( Factions.Sigil.ExistsOn( from ) )
{ {
@ -290,7 +290,7 @@ namespace Server.Engines.Help
{ {
if ( from.Region.IsPartOf( typeof( Regions.Jail ) ) ) 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" ) ) else if ( from.Region.IsPartOf( "Haven Island" ) )
{ {

View file

@ -44,19 +44,19 @@ namespace Server.Engines.Plants
AddPlusMinus( 196, 67, system.Water ); AddPlusMinus( 196, 67, system.Water );
AddButton( 209, 91, 0xD4, 0xD4, 7, GumpButtonType.Reply, 0 ); // Poison potion AddButton( 209, 91, 0xD4, 0xD4, 7, GumpButtonType.Reply, 0 ); // Poison potion
AddItem( 197, 91, 0xF0A ); AddItem( 201, 91, 0xF0A );
AddLevel( 196, 91, system.PoisonPotion ); AddLevel( 196, 91, system.PoisonPotion );
AddButton( 209, 115, 0xD4, 0xD4, 8, GumpButtonType.Reply, 0 ); // Cure potion AddButton( 209, 115, 0xD4, 0xD4, 8, GumpButtonType.Reply, 0 ); // Cure potion
AddItem( 192, 115, 0xF07 ); AddItem( 201, 115, 0xF07 );
AddLevel( 196, 115, system.CurePotion ); AddLevel( 196, 115, system.CurePotion );
AddButton( 209, 139, 0xD4, 0xD4, 9, GumpButtonType.Reply, 0 ); // Heal potion AddButton( 209, 139, 0xD4, 0xD4, 9, GumpButtonType.Reply, 0 ); // Heal potion
AddItem( 190, 139, 0xF0C ); AddItem( 201, 139, 0xF0C );
AddLevel( 196, 139, system.HealPotion ); AddLevel( 196, 139, system.HealPotion );
AddButton( 209, 163, 0xD4, 0xD4, 10, GumpButtonType.Reply, 0 ); // Strength potion AddButton( 209, 163, 0xD4, 0xD4, 10, GumpButtonType.Reply, 0 ); // Strength potion
AddItem( 193, 163, 0xF09 ); AddItem( 201, 163, 0xF09 );
AddLevel( 196, 163, system.StrengthPotion ); AddLevel( 196, 163, system.StrengthPotion );
AddImage( 48, 47, 0xD2 ); 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.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; break;
} }
case 7: // Poison potion case 7: // Poison potion

View file

@ -386,7 +386,7 @@ namespace Server.Engines.Plants
m_PlantHue = seed.PlantHue; m_PlantHue = seed.PlantHue;
m_ShowType = seed.ShowType; m_ShowType = seed.ShowType;
seed.Delete(); seed.Consume();
PlantStatus = PlantStatus.Seed; PlantStatus = PlantStatus.Seed;

View file

@ -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 ( !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 ) ); from.SendGump( new MainPlantGump( m_Plant ) );
} }
} }

View file

@ -1,4 +1,5 @@
using System; using System;
using System.Text;
using Server; using Server;
using Server.Targeting; using Server.Targeting;
@ -76,6 +77,7 @@ namespace Server.Engines.Plants
public Seed( PlantType plantType, PlantHue plantHue, bool showType ) : base( 0xDCF ) public Seed( PlantType plantType, PlantHue plantHue, bool showType ) : base( 0xDCF )
{ {
Weight = 1.0; Weight = 1.0;
Stackable = Core.SA;
m_PlantType = plantType; m_PlantType = plantType;
m_PlantHue = plantHue; m_PlantHue = plantHue;
@ -90,7 +92,7 @@ namespace Server.Engines.Plants
public override bool ForceShowProperties{ get{ return ObjectPropertyList.Enabled; } } 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 ); PlantHueInfo hueInfo = PlantHueInfo.GetInfo( m_PlantHue );
@ -98,30 +100,50 @@ namespace Server.Engines.Plants
if ( title == 0 ) // Not a bonsai if ( title == 0 ) // Not a bonsai
title = hueInfo.Name; 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 ) if ( m_ShowType )
{ {
PlantTypeInfo typeInfo = PlantTypeInfo.GetInfo( m_PlantType ); 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
} ab.Append( "\t#" );
else ab.Append( typeInfo.Name );
{
list.Add( hueInfo.IsBright() ? 1060839 : 1060838, String.Concat( "#", title.ToString() ) ); // [bright] ~1_val~ seed
} }
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 ) public override void OnSingleClick( Mobile from )
{ {
PlantTypeInfo typeInfo = PlantTypeInfo.GetInfo( m_PlantType ); string args;
LabelTo( from, hueInfo.IsBright() ? 1061918 : 1061917, String.Concat( "#", hueInfo.Name.ToString(), "\t#", typeInfo.Name.ToString() ) ); // [bright] ~1_COLOR~ ~2_TYPE~ seed LabelTo( from, GetLabel( out args ), args );
}
else
{
LabelTo( from, hueInfo.IsBright() ? 1060839 : 1060838, String.Concat( "#", hueInfo.Name.ToString() ) ); // [bright] ~1_val~ seed
}
} }
public override void OnDoubleClick( Mobile from ) 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. 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 class InternalTarget : Target
{ {
private Seed m_Seed; private Seed m_Seed;
@ -178,7 +225,7 @@ namespace Server.Engines.Plants
{ {
base.Serialize( writer ); base.Serialize( writer );
writer.Write( (int) 0 ); // version writer.Write( (int) 1 ); // version
writer.Write( (int) m_PlantType ); writer.Write( (int) m_PlantType );
writer.Write( (int) m_PlantHue ); writer.Write( (int) m_PlantHue );
@ -197,6 +244,9 @@ namespace Server.Engines.Plants
if ( Weight != 1.0 ) if ( Weight != 1.0 )
Weight = 1.0; Weight = 1.0;
if ( version < 1 )
Stackable = Core.SA;
} }
} }
} }

View file

@ -174,7 +174,7 @@ namespace Server.Engines.Quests
{ {
if ( m.Region.IsPartOf( typeof( Regions.Jail ) ) ) 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 ) else if ( m == m_Caster )
{ {

View file

@ -10,6 +10,7 @@ using Server.Prompts;
using Server.Network; using Server.Network;
using Server.Accounting; using Server.Accounting;
using Server.Commands; using Server.Commands;
using Server.Multis;
namespace Server.Gumps namespace Server.Gumps
{ {
@ -756,7 +757,8 @@ namespace Server.Gumps
AddButtonLabeled( 10, 390, GetButtonID( 5, 27 ), "Ban marked" ); AddButtonLabeled( 10, 390, GetButtonID( 5, 27 ), "Ban marked" );
AddButtonLabeled( 10, 410, GetButtonID( 5, 28 ), "Delete 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 ) 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; 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: default:
{ {
index -= 50; index -= 50;

View file

@ -741,14 +741,14 @@ namespace Server.Items
{ {
BaseWaterContainer bwc = targ as BaseWaterContainer; 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; bwc.Quantity -= iNeed;
Quantity += I_Need; Quantity += iNeed;
Content = BeverageType.Water; Content = BeverageType.Water;
from.PlaySound( 0x4E ); from.PlaySound( 0x4E );
@ -1027,14 +1027,22 @@ namespace Server.Items
{ {
BaseWaterContainer bwc = targ as 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; bwc.Quantity += itNeeds;
Quantity -= It_Needs; Quantity -= itNeeds;
from.PlaySound( 0x4E ); from.PlaySound( 0x4E );
} }

View file

@ -31,6 +31,14 @@
ItemID = ( IsEmpty ) ? voidItem_ID : fullItem_ID; 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(); InvalidateProperties();
} }
} }

View file

@ -306,7 +306,7 @@ namespace Server.Items
} }
else if ( from.Region.IsPartOf( typeof( Server.Regions.Jail ) ) ) 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; return false;
} }
else if ( boundRoot.Region.IsPartOf( typeof( Server.Regions.Jail ) ) ) else if ( boundRoot.Region.IsPartOf( typeof( Server.Regions.Jail ) ) )

View file

@ -24,6 +24,34 @@ namespace Server.Multis
public static int MaxFriends { get { return !Core.AOS ? 50 : 140; } } public static int MaxFriends { get { return !Core.AOS ? 50 : 140; } }
public static int MaxBans { 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 const bool DecayEnabled = true;
public static void Decay_OnTick() public static void Decay_OnTick()
@ -128,37 +156,73 @@ namespace Server.Multis
} }
} }
private DecayLevel m_LastDecayLevel;
[CommandProperty( AccessLevel.GameMaster )] [CommandProperty( AccessLevel.GameMaster )]
public virtual DecayLevel DecayLevel public virtual DecayLevel DecayLevel
{ {
get get
{ {
DecayLevel result;
if ( !CanDecay ) if ( !CanDecay )
{ {
if ( DynamicDecay.Enabled )
ResetDynamicDecay();
m_LastRefreshed = DateTime.Now; 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; if ( result != m_LastDecayLevel )
int percent = (int) ((timeAfterRefresh.Ticks * 1000) / DecayPeriod.Ticks); {
m_LastDecayLevel = result;
if ( percent >= 1000 ) // 100.0% if ( m_Sign != null && !m_Sign.GettingProperties )
return ( HasRentedVendors || VendorInventories.Count > 0 ) ? DecayLevel.DemolitionPending : DecayLevel.Collapsed; m_Sign.InvalidateProperties();
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; 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() public virtual bool RefreshDecay()
{ {
if ( DecayType == DecayType.Condemned ) if ( DecayType == DecayType.Condemned )
@ -168,6 +232,12 @@ namespace Server.Multis
m_LastRefreshed = DateTime.Now; m_LastRefreshed = DateTime.Now;
if ( DynamicDecay.Enabled )
ResetDynamicDecay();
if ( m_Sign != null )
m_Sign.InvalidateProperties();
return ( oldLevel > DecayLevel.LikeNew ); return ( oldLevel > DecayLevel.LikeNew );
} }
@ -2336,7 +2406,17 @@ namespace Server.Multis
{ {
base.Serialize( writer ); 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 ); writer.Write( (Point3D) m_RelativeBanLocation );
@ -2434,9 +2514,23 @@ namespace Server.Multis
int version = reader.ReadInt(); int version = reader.ReadInt();
int count; int count;
bool loadedDynamicDecay = false;
switch ( version ) 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: case 14:
{ {
m_RelativeBanLocation = reader.ReadPoint3D(); m_RelativeBanLocation = reader.ReadPoint3D();
@ -2631,6 +2725,16 @@ namespace Server.Multis
if ( version < 11 ) if ( version < 11 )
m_LastRefreshed = DateTime.Now + TimeSpan.FromHours( 24 * Utility.RandomDouble() ); 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 ( !CheckDecay() )
{ {
if ( RelocatedEntities.Count > 0 ) if ( RelocatedEntities.Count > 0 )
@ -2788,7 +2892,11 @@ namespace Server.Multis
{ {
get 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 set
{ {
@ -2806,7 +2914,9 @@ namespace Server.Multis
set set
{ {
m_RelativeBanLocation = value; 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 );
} }
} }

View file

@ -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<DecayLevel, DecayStageInfo> m_Stages;
static DynamicDecay()
{
m_Stages = new Dictionary<DecayLevel, DecayStageInfo>();
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;
}
}
}

View file

@ -71,6 +71,13 @@ namespace Server.Multis
public override bool ForceShowProperties{ get{ return ObjectPropertyList.Enabled; } } 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 ) public override void GetProperties( ObjectPropertyList list )
{ {
base.GetProperties( 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 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; DecayLevel level = m_Owner.DecayLevel;
m_GettingProperties = false;
if ( level == DecayLevel.DemolitionPending ) if ( level == DecayLevel.DemolitionPending )
{ {

View file

@ -609,7 +609,7 @@ namespace Server.Spells
if( caster != null && caster.AccessLevel == AccessLevel.Player && caster.Region.IsPartOf( typeof( Regions.Jail ) ) ) 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; return false;
} }

View file

@ -69,11 +69,19 @@ namespace Server.Spells.Ninjitsu
return false; return false;
} }
private bool CasterIsMoving()
{
return (DateTime.Now - Caster.LastMoveTime <= Caster.ComputeMovementSpeed(Caster.Direction));
}
private bool m_WasMoving;
public override void OnBeginCast() public override void OnBeginCast()
{ {
base.OnBeginCast(); base.OnBeginCast();
Caster.FixedEffect(0x37C4, 10, 14, 4, 3); Caster.FixedEffect(0x37C4, 10, 14, 4, 3);
m_WasMoving = CasterIsMoving();
} }
public override bool CheckFizzle() public override bool CheckFizzle()
@ -112,7 +120,9 @@ namespace Server.Spells.Ninjitsu
} }
else if (Caster is PlayerMobile) 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.CloseGump(typeof(AnimalFormGump));
Caster.SendGump(new AnimalFormGump(Caster, m_Entries, this)); Caster.SendGump(new AnimalFormGump(Caster, m_Entries, this));
@ -120,17 +130,27 @@ namespace Server.Spells.Ninjitsu
else else
{ {
if (Morph(Caster, GetLastAnimalForm(Caster)) == MorphResult.Fail) if (Morph(Caster, GetLastAnimalForm(Caster)) == MorphResult.Fail)
{
DoFizzle(); DoFizzle();
}
else else
{
Caster.FixedParticles(0x3728, 10, 13, 2023, EffectLayer.Waist);
Caster.Mana -= mana; Caster.Mana -= mana;
}
} }
} }
else else
{ {
if (Morph(Caster, GetLastAnimalForm(Caster)) == MorphResult.Fail) if (Morph(Caster, GetLastAnimalForm(Caster)) == MorphResult.Fail)
{
DoFizzle(); DoFizzle();
}
else else
{
Caster.FixedParticles(0x3728, 10, 13, 2023, EffectLayer.Waist);
Caster.Mana -= mana; Caster.Mana -= mana;
}
} }
} }
@ -189,12 +209,13 @@ namespace Server.Spells.Ninjitsu
m.CheckSkill(SkillName.Ninjitsu, 0.0, 37.5); 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); BaseMount.Dismount(m);
m.BodyMod = entry.BodyMod; m.BodyMod = entry.BodyMod;
m.HueMod = entry.HueMod;
if (entry.HueMod > 0)
m.HueMod = entry.HueMod;
if (entry.SpeedBoost) if (entry.SpeedBoost)
m.Send(SpeedControl.MountSpeed); m.Send(SpeedControl.MountSpeed);
@ -461,6 +482,7 @@ namespace Server.Spells.Ninjitsu
} }
else else
{ {
m_Caster.FixedParticles(0x3728, 10, 13, 2023, EffectLayer.Waist);
m_Caster.Mana -= mana; m_Caster.Mana -= mana;
} }
} }

View file

@ -17,23 +17,10 @@ namespace Server.Mobiles
public override bool AlwaysMurderer { get { return true; } } 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] [Constructable]
public NatureFury( Mobile target ) public NatureFury()
: base( AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4 ) : base( AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4 )
{ {
m_Target = target;
Name = "a nature's fury"; Name = "a nature's fury";
Body = 0x33; Body = 0x33;
Hue = 0x4001; Hue = 0x4001;
@ -62,12 +49,6 @@ namespace Server.Mobiles
ControlSlots = 1; ControlSlots = 1;
} }
[Constructable]
public NatureFury()
: this( null ) //Null makes it act like any other mob
{
}
public override void MoveToWorld( Point3D loc, Map map ) public override void MoveToWorld( Point3D loc, Map map )
{ {
base.MoveToWorld( loc, map ); base.MoveToWorld( loc, map );

View file

@ -1,7 +1,7 @@
using System; using System;
using Server.Mobiles; using Server.Mobiles;
using Server.Targeting; using Server.Targeting;
using Server.Multis; using Server.Regions;
namespace Server.Spells.Spellweaving 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() public override bool CheckCast()
{ {
if( !base.CheckCast() ) if ( !base.CheckCast() )
return false; 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. Caster.SendLocalizedMessage( 1049645 ); // You have too many followers to summon that creature.
return false; return false;
@ -58,46 +44,29 @@ namespace Server.Spells.Spellweaving
public void Target( IPoint3D point ) 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 ); Point3D p = new Point3D( point );
Map map = Caster.Map; Map map = Caster.Map;
m_MobileTarg = (m != null); if ( map == null )
return;
BaseHouse house = BaseHouse.FindHouseAt( p, map, 0 ); HouseRegion r = Region.Find( p, map ).GetRegion( typeof( HouseRegion ) ) as HouseRegion;
if ( house != null)
if ( !house.IsFriend ( Caster ) ) if ( r != null && r.House != null && !r.House.IsFriend( Caster ) )
return; return;
if (m != null) //say "Target can not be seen" if you target directly a mobile, like in OSI
{ if ( !map.CanSpawnMobile( p.X, p.Y, p.Z ) )
Caster.SendLocalizedMessage( 500237 ); // Target can not be seen.
}
else if ( map == null || !map.CanSpawnMobile( p.X, p.Y, p.Z ) )
{ {
Caster.SendLocalizedMessage( 501942 ); // That location is blocked. 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 ) NatureFury nf = new NatureFury();
m = null; BaseCreature.Summon( nf, false, Caster, p, 0x5CB, duration );
NatureFury nf = new NatureFury( m ); new InternalTimer( nf ).Start();
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++;
} );
} }
FinishSequence(); FinishSequence();
@ -107,22 +76,47 @@ namespace Server.Spells.Spellweaving
{ {
private NatureFurySpell m_Owner; 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; m_Owner = owner;
CheckLOS = true;
} }
protected override void OnTarget( Mobile from, object o ) protected override void OnTarget( Mobile from, object o )
{ {
if( o is IPoint3D ) if ( o is IPoint3D )
m_Owner.Target( (IPoint3D)o ); m_Owner.Target( (IPoint3D)o );
} }
protected override void OnTargetFinish( Mobile from ) protected override void OnTargetFinish( Mobile from )
{ {
if( m_Owner != null ) if ( m_Owner != null )
m_Owner.FinishSequence(); 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;
}
}
}
} }
} }