- PreventInaccess class, moves staff characters to jail or green acres in Felucca or Trammel randomly if they disconnect during the login process.

- Added a [TileAvg command, which tiles items/mobiles on the average Z of the map instead of a fixed Z.
- For all the tile commands ([Tile, [TileRXYZ, [TileXYZ, [TileZ, [TileAvg), added outline commands to only put items/mobiles on the outside of the area ([Outline, [OutlineRXYZ, [OutlineXYZ, [OutlineZ, [OutlineAvg).
- Removed the [OpenBrowser confirmation messages when using the command on multiple mobiles at the same time.
- Added a label showing the type of the object currently being viewed to the top of the properties gump.
- Added SA skills (Mysticism, Throwing and Imbuing) to the [Skills gump.
- Fixed DeathRobe decay when automatically dropped by self looting your corpse.
- Removed the (summoned) property on mouseover from clones summoned through Mirror Image.
- The Z of the Magincia destination of the public moongates is now calculated when the server starts, so both old and new maps will have the correct Z (34 and 31 respectively).
- KeywordTeleporters no longer teleport if you're not within the trigger range when the delay ends.
- Added WaitTeleporter, which is a KeywordTeleporter supporting adding messages when a character starts the process and showing the remaining time. When a character logs and times out, any running teleport timer is stopped.
- Fixed BaseWaterContainer single click behavior.
- Fixed MageAI reveal behavior.
- House placement will now return the correct message when targeting inside a TempNoHousingRegion.
- Tracking will no longer be able to track characters with higher access after they hide.
- Added CorpseNameOverride to BaseCreature to override the name used for the generated corpse.
- Pet ghosts will no longer be deleted when (auto)stabled.
This commit is contained in:
eos 2012-02-12 01:59:30 +00:00
parent 68922c1eeb
commit 72c4dc6018
15 changed files with 685 additions and 155 deletions

View file

@ -18,14 +18,26 @@ namespace Server.Commands
CommandSystem.Register( "TileRXYZ", AccessLevel.GameMaster, new CommandEventHandler( TileRXYZ_OnCommand ) );
CommandSystem.Register( "TileXYZ", AccessLevel.GameMaster, new CommandEventHandler( TileXYZ_OnCommand ) );
CommandSystem.Register( "TileZ", AccessLevel.GameMaster, new CommandEventHandler( TileZ_OnCommand ) );
CommandSystem.Register( "TileAvg", AccessLevel.GameMaster, new CommandEventHandler( TileAvg_OnCommand ) );
CommandSystem.Register( "Outline", AccessLevel.GameMaster, new CommandEventHandler( Outline_OnCommand ) );
CommandSystem.Register( "OutlineRXYZ", AccessLevel.GameMaster, new CommandEventHandler( OutlineRXYZ_OnCommand ) );
CommandSystem.Register( "OutlineXYZ", AccessLevel.GameMaster, new CommandEventHandler( OutlineXYZ_OnCommand ) );
CommandSystem.Register( "OutlineZ", AccessLevel.GameMaster, new CommandEventHandler( OutlineZ_OnCommand ) );
CommandSystem.Register( "OutlineAvg", AccessLevel.GameMaster, new CommandEventHandler( OutlineAvg_OnCommand ) );
}
public static void Invoke( Mobile from, Point3D start, Point3D end, string[] args )
{
Invoke( from, start, end, args, null );
Invoke( from, start, end, args, null, false, false );
}
public static void Invoke( Mobile from, Point3D start, Point3D end, string[] args, List<Container> packs )
{
Invoke( from, start, end, args, packs, false, false );
}
public static void Invoke( Mobile from, Point3D start, Point3D end, string[] args, List<Container> packs, bool outline, bool mapAvg )
{
StringBuilder sb = new StringBuilder();
@ -83,7 +95,7 @@ namespace Server.Commands
DateTime time = DateTime.Now;
int built = BuildObjects( from, type, start, end, args, props, packs );
int built = BuildObjects( from, type, start, end, args, props, packs, outline, mapAvg );
if ( built > 0 )
from.SendMessage( "{0} object{1} generated in {2:F1} seconds.", built, built != 1 ? "s" : "", (DateTime.Now - time).TotalSeconds );
@ -108,6 +120,11 @@ namespace Server.Commands
}
public static int BuildObjects( Mobile from, Type type, Point3D start, Point3D end, string[] args, string[,] props, List<Container> packs )
{
return BuildObjects( from, type, start, end, args, props, packs, false, false );
}
public static int BuildObjects( Mobile from, Type type, Point3D start, Point3D end, string[] args, string[,] props, List<Container> packs, bool outline, bool mapAvg )
{
Utility.FixPoints( ref start, ref end );
@ -169,7 +186,7 @@ namespace Server.Commands
if ( paramValues == null )
continue;
int built = Build( from, start, end, ctor, paramValues, props, realProps, packs );
int built = Build( from, start, end, ctor, paramValues, props, realProps, packs, outline, mapAvg );
if ( built > 0 )
return built;
@ -270,12 +287,30 @@ namespace Server.Commands
}
public static int Build( Mobile from, Point3D start, Point3D end, ConstructorInfo ctor, object[] values, string[,] props, PropertyInfo[] realProps, List<Container> packs )
{
return Build( from, start, end, ctor, values, props, realProps, packs, false, false );
}
public static int Build( Mobile from, Point3D start, Point3D end, ConstructorInfo ctor, object[] values, string[,] props, PropertyInfo[] realProps, List<Container> packs, bool outline, bool mapAvg )
{
try
{
Map map = from.Map;
int objectCount = ( packs == null ? (((end.X - start.X) + 1) * ((end.Y - start.Y) + 1)) : packs.Count );
int width = end.X - start.X + 1;
int height = end.Y - start.Y + 1;
if ( outline && ( width < 3 || height < 3 ) )
outline = false;
int objectCount;
if ( packs != null )
objectCount = packs.Count;
else if ( outline )
objectCount = ( width + height - 2 ) * 2;
else
objectCount = width * height;
if ( objectCount >= 20 )
from.SendMessage( "Constructing {0} objects, please wait.", objectCount );
@ -292,7 +327,7 @@ namespace Server.Commands
IEntity built = Build( from, ctor, values, props, realProps, ref sendError );
sb.AppendFormat( "0x{0:X}; ", built.Serial.Value );
if ( built is Item ) {
Container pack = packs[i];
pack.DropItem( (Item)built );
@ -305,21 +340,29 @@ namespace Server.Commands
}
else
{
int z = start.Z;
for ( int x = start.X; x <= end.X; ++x )
{
for ( int y = start.Y; y <= end.Y; ++y )
{
if ( outline && x != start.X && x != end.X && y != start.Y && y != end.Y )
continue;
if ( mapAvg )
z = map.GetAverageZ( x, y );
IEntity built = Build( from, ctor, values, props, realProps, ref sendError );
sb.AppendFormat( "0x{0:X}; ", built.Serial.Value );
if ( built is Item ) {
Item item = (Item)built;
item.MoveToWorld( new Point3D( x, y, start.Z ), map );
item.MoveToWorld( new Point3D( x, y, z ), map );
}
else if ( built is Mobile ) {
Mobile m = (Mobile)built;
m.MoveToWorld( new Point3D( x, y, start.Z ), map );
m.MoveToWorld( new Point3D( x, y, z ), map );
}
}
}
@ -410,51 +453,60 @@ namespace Server.Commands
}
}
private enum TileZType
{
Start,
Fixed,
MapAverage
}
private class TileState
{
public bool m_UseFixedZ;
public TileZType m_ZType;
public int m_FixedZ;
public string[] m_Args;
public bool m_Outline;
public TileState( string[] args ) : this( false, 0, args )
public TileState( TileZType zType, int fixedZ, string[] args, bool outline )
{
}
public TileState( int fixedZ, string[] args ) : this( true, fixedZ, args )
{
}
public TileState( bool useFixedZ, int fixedZ, string[] args )
{
m_UseFixedZ = useFixedZ;
m_ZType = zType;
m_FixedZ = fixedZ;
m_Args = args;
m_Outline = outline;
}
}
private static void TileBox_Callback( Mobile from, Map map, Point3D start, Point3D end, object state )
{
TileState ts = (TileState)state;
bool mapAvg = false;
if ( ts.m_UseFixedZ )
start.Z = end.Z = ts.m_FixedZ;
switch ( ts.m_ZType )
{
case TileZType.Fixed:
{
start.Z = end.Z = ts.m_FixedZ;
break;
}
case TileZType.MapAverage:
{
mapAvg = true;
break;
}
}
Invoke( from, start, end, ts.m_Args );
Invoke( from, start, end, ts.m_Args, null, ts.m_Outline, mapAvg );
}
[Usage( "Tile <name> [params] [set {<propertyName> <value> ...}]" )]
[Description( "Tiles an item or npc by name into a targeted bounding box. Optional constructor parameters. Optional set property list." )]
public static void Tile_OnCommand( CommandEventArgs e )
private static void Internal_OnCommand( CommandEventArgs e, bool outline )
{
if ( e.Length >= 1 )
BoundingBoxPicker.Begin( e.Mobile, new BoundingBoxCallback( TileBox_Callback ), new TileState( e.Arguments ) );
BoundingBoxPicker.Begin( e.Mobile, new BoundingBoxCallback( TileBox_Callback ), new TileState( TileZType.Start, 0, e.Arguments, outline ) );
else
e.Mobile.SendMessage( "Format: Add <type> [params] [set {<propertyName> <value> ...}]" );
e.Mobile.SendMessage( "Format: {0} <type> [params] [set {{<propertyName> <value> ...}}]", outline ? "Outline" : "Tile" );
}
[Usage( "TileRXYZ <x> <y> <w> <h> <z> <name> [params] [set {<propertyName> <value> ...}]" )]
[Description( "Tiles an item or npc by name into a given bounding box, (x, y) parameters are relative to your characters position. Optional constructor parameters. Optional set property list." )]
public static void TileRXYZ_OnCommand( CommandEventArgs e )
private static void InternalRXYZ_OnCommand( CommandEventArgs e, bool outline )
{
if ( e.Length >= 6 )
{
@ -466,17 +518,15 @@ namespace Server.Commands
for ( int i = 0; i < subArgs.Length; ++i )
subArgs[i] = e.Arguments[i + 5];
Add.Invoke( e.Mobile, p, p2, subArgs );
Add.Invoke( e.Mobile, p, p2, subArgs, null, outline, false );
}
else
{
e.Mobile.SendMessage( "Format: TileRXYZ <x> <y> <w> <h> <z> <type> [params] [set {<propertyName> <value> ...}]" );
e.Mobile.SendMessage( "Format: {0}RXYZ <x> <y> <w> <h> <z> <type> [params] [set {{<propertyName> <value> ...}}]", outline ? "Outline" : "Tile" );
}
}
[Usage( "TileXYZ <x> <y> <w> <h> <z> <name> [params] [set {<propertyName> <value> ...}]" )]
[Description( "Tiles an item or npc by name into a given bounding box. Optional constructor parameters. Optional set property list." )]
public static void TileXYZ_OnCommand( CommandEventArgs e )
private static void InternalXYZ_OnCommand( CommandEventArgs e, bool outline )
{
if ( e.Length >= 6 )
{
@ -488,17 +538,15 @@ namespace Server.Commands
for ( int i = 0; i < subArgs.Length; ++i )
subArgs[i] = e.Arguments[i + 5];
Add.Invoke( e.Mobile, p, p2, subArgs );
Add.Invoke( e.Mobile, p, p2, subArgs, null, outline, false );
}
else
{
e.Mobile.SendMessage( "Format: TileXYZ <x> <y> <w> <h> <z> <type> [params] [set {<propertyName> <value> ...}]" );
e.Mobile.SendMessage( "Format: {0}XYZ <x> <y> <w> <h> <z> <type> [params] [set {{<propertyName> <value> ...}}]", outline ? "Outline" : "Tile" );
}
}
[Usage( "TileZ <z> <name> [params] [set {<propertyName> <value> ...}]" )]
[Description( "Tiles an item or npc by name into a targeted bounding box at a fixed Z location. Optional constructor parameters. Optional set property list." )]
public static void TileZ_OnCommand( CommandEventArgs e )
private static void InternalZ_OnCommand( CommandEventArgs e, bool outline )
{
if ( e.Length >= 2 )
{
@ -507,14 +555,92 @@ namespace Server.Commands
for ( int i = 0; i < subArgs.Length; ++i )
subArgs[i] = e.Arguments[i + 1];
BoundingBoxPicker.Begin( e.Mobile, new BoundingBoxCallback( TileBox_Callback ), new TileState( e.GetInt32( 0 ), subArgs ) );
BoundingBoxPicker.Begin( e.Mobile, new BoundingBoxCallback( TileBox_Callback ), new TileState( TileZType.Fixed, e.GetInt32( 0 ), subArgs, outline ) );
}
else
{
e.Mobile.SendMessage( "Format: TileZ <z> <type> [params] [set {<propertyName> <value> ...}]" );
e.Mobile.SendMessage( "Format: {0}Z <z> <type> [params] [set {{<propertyName> <value> ...}}]", outline ? "Outline" : "Tile" );
}
}
private static void InternalAvg_OnCommand( CommandEventArgs e, bool outline )
{
if ( e.Length >= 1 )
BoundingBoxPicker.Begin( e.Mobile, new BoundingBoxCallback( TileBox_Callback ), new TileState( TileZType.MapAverage, 0, e.Arguments, outline ) );
else
e.Mobile.SendMessage( "Format: {0}Avg <type> [params] [set {{<propertyName> <value> ...}}]", outline ? "Outline" : "Tile" );
}
[Usage( "Tile <name> [params] [set {<propertyName> <value> ...}]" )]
[Description( "Tiles an item or npc by name into a targeted bounding box. Optional constructor parameters. Optional set property list." )]
public static void Tile_OnCommand( CommandEventArgs e )
{
Internal_OnCommand( e, false );
}
[Usage( "TileRXYZ <x> <y> <w> <h> <z> <name> [params] [set {<propertyName> <value> ...}]" )]
[Description( "Tiles an item or npc by name into a given bounding box, (x, y) parameters are relative to your characters position. Optional constructor parameters. Optional set property list." )]
public static void TileRXYZ_OnCommand( CommandEventArgs e )
{
InternalRXYZ_OnCommand( e, false );
}
[Usage( "TileXYZ <x> <y> <w> <h> <z> <name> [params] [set {<propertyName> <value> ...}]" )]
[Description( "Tiles an item or npc by name into a given bounding box. Optional constructor parameters. Optional set property list." )]
public static void TileXYZ_OnCommand( CommandEventArgs e )
{
InternalXYZ_OnCommand( e, false );
}
[Usage( "TileZ <z> <name> [params] [set {<propertyName> <value> ...}]" )]
[Description( "Tiles an item or npc by name into a targeted bounding box at a fixed Z location. Optional constructor parameters. Optional set property list." )]
public static void TileZ_OnCommand( CommandEventArgs e )
{
InternalZ_OnCommand( e, false );
}
[Usage( "TileAvg <name> [params] [set {<propertyName> <value> ...}]" )]
[Description( "Tiles an item or npc by name into a targeted bounding box on the map's average Z elevation. Optional constructor parameters. Optional set property list." )]
public static void TileAvg_OnCommand( CommandEventArgs e )
{
InternalAvg_OnCommand( e, false );
}
[Usage( "Outline <name> [params] [set {<propertyName> <value> ...}]" )]
[Description( "Tiles an item or npc by name around a targeted bounding box. Optional constructor parameters. Optional set property list." )]
public static void Outline_OnCommand( CommandEventArgs e )
{
Internal_OnCommand( e, true );
}
[Usage( "OutlineRXYZ <x> <y> <w> <h> <z> <name> [params] [set {<propertyName> <value> ...}]" )]
[Description( "Tiles an item or npc by name around a given bounding box, (x, y) parameters are relative to your characters position. Optional constructor parameters. Optional set property list." )]
public static void OutlineRXYZ_OnCommand( CommandEventArgs e )
{
InternalRXYZ_OnCommand( e, true );
}
[Usage( "OutlineXYZ <x> <y> <w> <h> <z> <name> [params] [set {<propertyName> <value> ...}]" )]
[Description( "Tiles an item or npc by name around a given bounding box. Optional constructor parameters. Optional set property list." )]
public static void OutlineXYZ_OnCommand( CommandEventArgs e )
{
InternalXYZ_OnCommand( e, true );
}
[Usage( "OutlineZ <z> <name> [params] [set {<propertyName> <value> ...}]" )]
[Description( "Tiles an item or npc by name around a targeted bounding box at a fixed Z location. Optional constructor parameters. Optional set property list." )]
public static void OutlineZ_OnCommand( CommandEventArgs e )
{
InternalZ_OnCommand( e, true );
}
[Usage( "OutlineAvg <name> [params] [set {<propertyName> <value> ...}]" )]
[Description( "Tiles an item or npc by name around a targeted bounding box on the map's average Z elevation. Optional constructor parameters. Optional set property list." )]
public static void OutlineAvg_OnCommand( CommandEventArgs e )
{
InternalAvg_OnCommand( e, true );
}
private static Type m_EntityType = typeof( IEntity );
public static bool IsEntity( Type t )

View file

@ -213,20 +213,25 @@ namespace Server.Commands.Generic
object[] states = (object[])state;
Mobile gm = (Mobile)states[0];
string url = (string)states[1];
bool echo = (bool)states[2];
if ( okay )
{
gm.SendMessage( "{0} : has opened their web browser to : {1}", from.Name, url );
if ( echo )
gm.SendMessage( "{0} : has opened their web browser to : {1}", from.Name, url );
from.LaunchBrowser( url );
}
else
{
if ( echo )
gm.SendMessage( "{0} : has chosen not to open their web browser to : {1}", from.Name, url );
from.SendMessage( "You have chosen not to open your web browser." );
gm.SendMessage( "{0} : has chosen not to open their web browser to : {1}", from.Name, url );
}
}
public override void Execute( CommandEventArgs e, object obj )
public void Execute( CommandEventArgs e, object obj, bool echo )
{
if ( e.Length == 1 )
{
@ -246,8 +251,13 @@ namespace Server.Commands.Generic
string url = e.GetString( 0 );
CommandLogging.WriteLine( from, "{0} {1} requesting to open web browser of {2} to {3}", from.AccessLevel, CommandLogging.Format( from ), CommandLogging.Format( mob ), url );
AddResponse( "Awaiting user confirmation..." );
mob.SendGump( new WarningGump( 1060637, 30720, String.Format( "A game master is requesting to open your web browser to the following URL:<br>{0}", url ), 0xFFC000, 320, 240, new WarningGumpCallback( OpenBrowser_Callback ), new object[]{ from, url } ) );
if ( echo )
AddResponse( "Awaiting user confirmation..." );
else
AddResponse( "Open web browser request sent." );
mob.SendGump( new WarningGump( 1060637, 30720, String.Format( "A game master is requesting to open your web browser to the following URL:<br>{0}", url ), 0xFFC000, 320, 240, new WarningGumpCallback( OpenBrowser_Callback ), new object[]{ from, url, echo } ) );
}
}
else
@ -260,6 +270,17 @@ namespace Server.Commands.Generic
LogFailure( "Format: OpenBrowser <url>" );
}
}
public override void Execute( CommandEventArgs e, object obj )
{
Execute( e, obj, true );
}
public override void ExecuteList( CommandEventArgs e, ArrayList list )
{
for ( int i = 0; i < list.Count; ++i )
Execute( e, list[i], false );
}
}
public class IncreaseCommand : BaseCommand

View file

@ -17,6 +17,7 @@ namespace Server.Gumps
private int m_Page;
private Mobile m_Mobile;
private object m_Object;
private Type m_Type;
private Stack m_Stack;
public static readonly bool OldStyle = PropsConfig.OldStyle;
@ -54,6 +55,7 @@ namespace Server.Gumps
public static readonly int BorderSize = PropsConfig.BorderSize;
private static bool PrevLabel = OldStyle, NextLabel = OldStyle;
private static bool TypeLabel = !OldStyle;
private static readonly int PrevLabelOffsetX = PrevWidth + 1;
private static readonly int PrevLabelOffsetY = 0;
@ -78,6 +80,7 @@ namespace Server.Gumps
{
m_Mobile = mobile;
m_Object = o;
m_Type = o.GetType();
m_List = BuildList();
Initialize( 0 );
@ -87,6 +90,7 @@ namespace Server.Gumps
{
m_Mobile = mobile;
m_Object = o;
m_Type = o.GetType();
m_Stack = stack;
m_List = BuildList();
@ -105,6 +109,10 @@ namespace Server.Gumps
{
m_Mobile = mobile;
m_Object = o;
if ( o != null )
m_Type = o.GetType();
m_List = list;
m_Stack = stack;
@ -155,7 +163,10 @@ namespace Server.Gumps
x += PrevWidth + OffsetSize;
if ( !OldStyle )
AddImageTiled( x - (OldStyle ? OffsetSize : 0), y, emptyWidth + (OldStyle ? OffsetSize * 2 : 0), EntryHeight, HeaderGumpID );
AddImageTiled( x, y, emptyWidth, EntryHeight, HeaderGumpID );
if ( TypeLabel && m_Type != null )
AddHtml( x, y, emptyWidth, EntryHeight, String.Format( "<BASEFONT COLOR=#FAFAFA><CENTER>{0}</CENTER></BASEFONT>", m_Type.Name ), false, false );
x += emptyWidth + OffsetSize;
@ -506,13 +517,15 @@ namespace Server.Gumps
private ArrayList BuildList()
{
Type type = m_Object.GetType();
PropertyInfo[] props = type.GetProperties( BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public );
ArrayList groups = GetGroups( type, props );
ArrayList list = new ArrayList();
if ( m_Type == null )
return list;
PropertyInfo[] props = m_Type.GetProperties( BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public );
ArrayList groups = GetGroups( m_Type, props );
for ( int i = 0; i < groups.Count; ++i )
{
DictionaryEntry de = (DictionaryEntry)groups[i];

View file

@ -471,7 +471,8 @@ namespace Server.Gumps
SkillName.Fletching,
SkillName.Inscribe,
SkillName.Tailoring,
SkillName.Tinkering
SkillName.Tinkering,
SkillName.Imbuing
} ),
new SkillsGumpGroup( "Bardic", new SkillName[]
{
@ -491,7 +492,8 @@ namespace Server.Gumps
SkillName.SpiritSpeak,
SkillName.Ninjitsu,
SkillName.Bushido,
SkillName.Spellweaving
SkillName.Spellweaving,
SkillName.Mysticism
} ),
new SkillsGumpGroup( "Miscellaneous", new SkillName[]
{
@ -514,7 +516,8 @@ namespace Server.Gumps
SkillName.Parry,
SkillName.Swords,
SkillName.Tactics,
SkillName.Wrestling
SkillName.Wrestling,
SkillName.Throwing
} ),
new SkillsGumpGroup( "Actions", new SkillName[]
{

View file

@ -102,9 +102,9 @@ namespace Server.Items
{
private Timer m_DecayTimer;
private DateTime m_DecayTime;
private static TimeSpan m_DefaultDecayTime = TimeSpan.FromMinutes(1.0);
public override bool DisplayLootType
{
get{ return false; }
@ -123,25 +123,30 @@ namespace Server.Items
from.SendLocalizedMessage( 502440 ); // Scissors can not be used on that to produce anything.
return false;
}
public void BeginDecay( TimeSpan delay )
public void BeginDecay()
{
BeginDecay( m_DefaultDecayTime );
}
private void BeginDecay( TimeSpan delay )
{
if ( m_DecayTimer != null )
m_DecayTimer.Stop();
m_DecayTime = DateTime.Now + delay;
m_DecayTimer = new InternalTimer( this, delay );
m_DecayTimer.Start();
}
public override bool OnDroppedToWorld( Mobile from, Point3D p )
{
BeginDecay( m_DefaultDecayTime );
return true;
}
public override bool OnDroppedToMobile( Mobile from, Mobile target )
{
if (m_DecayTimer != null )
@ -189,7 +194,7 @@ namespace Server.Items
base.Serialize( writer );
writer.Write( (int) 2 ); // version
writer.Write( m_DecayTimer != null );
if( m_DecayTimer != null )
@ -201,7 +206,7 @@ namespace Server.Items
base.Deserialize( reader );
int version = reader.ReadInt();
switch ( version )
{
case 2:
@ -603,7 +608,7 @@ namespace Server.Items
public MonkRobe() : this( 0x21E )
{
}
[Constructable]
public MonkRobe( int hue ) : base( 0x2687, hue )
{
@ -634,7 +639,7 @@ namespace Server.Items
int version = reader.ReadInt();
}
}
[Flipable( 0x1f01, 0x1f02 )]
public class PlainDress : BaseOuterTorso
{

View file

@ -438,6 +438,14 @@ namespace Server.Items
public static string GetCorpseName( Mobile m )
{
if ( m is BaseCreature )
{
BaseCreature bc = (BaseCreature)m;
if ( bc.CorpseNameOverride != null )
return bc.CorpseNameOverride;
}
Type t = m.GetType();
object[] attrs = t.GetCustomAttributes( typeof( CorpseNameAttribute ), true );
@ -1040,7 +1048,10 @@ namespace Server.Items
Map map = from.Map;
if ( map != null && map != Map.Internal )
{
robe.MoveToWorld( from.Location, map );
robe.BeginDecay();
}
}
Container pack = from.Backpack;

View file

@ -237,7 +237,8 @@ namespace Server.Items
new PMEntry( new Point3D( 2701, 692, 5 ), 1012007 ), // Minoc
new PMEntry( new Point3D( 1828, 2948,-20), 1012008 ), // Trinsic
new PMEntry( new Point3D( 643, 2067, 5 ), 1012009 ), // Skara Brae
new PMEntry( new Point3D( 3563, 2139, 34), 1012010 ), // Magincia
/* Dynamic Z for Magincia to support both old and new maps. */
new PMEntry( new Point3D( 3563, 2139, Map.Trammel.GetAverageZ( 3563, 2139 ) ), 1012010 ), // (New) Magincia
new PMEntry( new Point3D( 3450, 2677, 25), 1078098 ) // New Haven
} );
@ -251,7 +252,8 @@ namespace Server.Items
new PMEntry( new Point3D( 2701, 692, 5 ), 1012007 ), // Minoc
new PMEntry( new Point3D( 1828, 2948,-20), 1012008 ), // Trinsic
new PMEntry( new Point3D( 643, 2067, 5 ), 1012009 ), // Skara Brae
new PMEntry( new Point3D( 3563, 2139, 34), 1012010 ), // Magincia
/* Dynamic Z for Magincia to support both old and new maps. */
new PMEntry( new Point3D( 3563, 2139, Map.Felucca.GetAverageZ( 3563, 2139 ) ), 1012010 ), // (New) Magincia
new PMEntry( new Point3D( 2711, 2234, 0 ), 1019001 ) // Buccaneer's Den
} );

View file

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using Server;
using Server.Network;
using Server.Spells;
@ -147,12 +148,7 @@ namespace Server.Items
if ( m_Delay == TimeSpan.Zero )
DoTeleport( m );
else
Timer.DelayCall( m_Delay, new TimerStateCallback( DoTeleport_Callback ), m );
}
private void DoTeleport_Callback( object state )
{
DoTeleport( (Mobile) state );
Timer.DelayCall<Mobile>( m_Delay, DoTeleport, m );
}
public virtual void DoTeleport( Mobile m )
@ -192,7 +188,7 @@ namespace Server.Items
else if ( m_CombatCheck && SpellHelper.CheckCombat( m ) )
{
m.SendLocalizedMessage( 1005564, "", 0x22 ); // Wouldst thou flee during the heat of battle??
return true;
return true;
}
StartTeleport( m );
@ -455,6 +451,14 @@ namespace Server.Items
}
}
public override void DoTeleport( Mobile m )
{
if ( !m.InRange( GetWorldLocation(), m_Range ) || m.Map != Map )
return;
base.DoTeleport( m );
}
public override bool OnMoveOver( Mobile m )
{
return true;
@ -514,4 +518,188 @@ namespace Server.Items
}
}
}
public class WaitTeleporter : KeywordTeleporter
{
private static Dictionary<Mobile, TeleportingInfo> m_Table;
public static void Initialize()
{
m_Table = new Dictionary<Mobile, TeleportingInfo>();
EventSink.Logout += new LogoutEventHandler( EventSink_Logout );
}
public static void EventSink_Logout( LogoutEventArgs e )
{
Mobile from = e.Mobile;
TeleportingInfo info;
if ( from == null || !m_Table.TryGetValue( from, out info ) )
return;
info.Timer.Stop();
m_Table.Remove( from );
}
private int m_StartNumber;
private string m_StartMessage;
private int m_ProgressNumber;
private string m_ProgressMessage;
private bool m_ShowTimeRemaining;
[CommandProperty( AccessLevel.GameMaster )]
public int StartNumber
{
get { return m_StartNumber; }
set { m_StartNumber = value; }
}
[CommandProperty( AccessLevel.GameMaster )]
public string StartMessage
{
get { return m_StartMessage; }
set { m_StartMessage = value; }
}
[CommandProperty( AccessLevel.GameMaster )]
public int ProgressNumber
{
get { return m_ProgressNumber; }
set { m_ProgressNumber = value; }
}
[CommandProperty( AccessLevel.GameMaster )]
public string ProgressMessage
{
get { return m_ProgressMessage; }
set { m_ProgressMessage = value; }
}
[CommandProperty( AccessLevel.GameMaster )]
public bool ShowTimeRemaining
{
get { return m_ShowTimeRemaining; }
set { m_ShowTimeRemaining = value; }
}
[Constructable]
public WaitTeleporter()
{
}
public static string FormatTime( TimeSpan ts )
{
if ( ts.TotalHours >= 1 )
{
int h = (int)ts.TotalHours;
return String.Format( "{0} hour{1}", h, ( h == 1 ) ? "" : "s" );
}
else if ( ts.TotalMinutes >= 1 )
{
int m = (int)ts.TotalMinutes;
return String.Format( "{0} minute{1}", m, ( m == 1 ) ? "" : "s" );
}
int s = Math.Max( (int)ts.TotalSeconds, 0 );
return String.Format( "{0} second{1}", s, ( s == 1 ) ? "" : "s" );
}
private void EndLock( Mobile m )
{
m.EndAction( this );
}
public override void StartTeleport( Mobile m )
{
TeleportingInfo info;
if ( m_Table.TryGetValue( m, out info ) )
{
if ( info.Teleporter == this )
{
if ( m.BeginAction( this ) )
{
if ( m_ProgressMessage != null )
m.SendMessage( m_ProgressMessage );
else if ( m_ProgressNumber != 0 )
m.SendLocalizedMessage( m_ProgressNumber );
if ( m_ShowTimeRemaining )
m.SendMessage( "Time remaining: {0}", FormatTime( m_Table[m].Timer.Next - DateTime.Now ) );
Timer.DelayCall<Mobile>( TimeSpan.FromSeconds( 5 ), EndLock, m );
}
return;
}
else
{
info.Timer.Stop();
}
}
if ( m_StartMessage != null )
m.SendMessage( m_StartMessage );
else if ( m_StartNumber != 0 )
m.SendLocalizedMessage( m_StartNumber );
if ( Delay == TimeSpan.Zero )
DoTeleport( m );
else
m_Table[m] = new TeleportingInfo( this, Timer.DelayCall<Mobile>( Delay, DoTeleport, m ) );
}
public override void DoTeleport( Mobile m )
{
m_Table.Remove( m );
base.DoTeleport( m );
}
public WaitTeleporter( Serial serial ) : base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int) 0 ); // version
writer.Write( m_StartNumber );
writer.Write( m_StartMessage );
writer.Write( m_ProgressNumber );
writer.Write( m_ProgressMessage );
writer.Write( m_ShowTimeRemaining );
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
m_StartNumber = reader.ReadInt();
m_StartMessage = reader.ReadString();
m_ProgressNumber = reader.ReadInt();
m_ProgressMessage = reader.ReadString();
m_ShowTimeRemaining = reader.ReadBool();
}
private class TeleportingInfo
{
private WaitTeleporter m_Teleporter;
private Timer m_Timer;
public WaitTeleporter Teleporter { get { return m_Teleporter; } }
public Timer Timer { get { return m_Timer; } }
public TeleportingInfo( WaitTeleporter tele, Timer t )
{
m_Teleporter = tele;
m_Timer = t;
}
}
}
}

View file

@ -64,7 +64,29 @@
{
if( IsEmpty )
{
base.OnDoubleClick( from );
base.OnSingleClick( from );
}
else
{
if( Name == null )
LabelTo( from, LabelNumber );
else
LabelTo( from, Name );
}
}
public override void OnAosSingleClick( Mobile from )
{
if( IsEmpty )
{
base.OnAosSingleClick( from );
}
else
{
if( Name == null )
LabelTo( from, LabelNumber );
else
LabelTo( from, Name );
}
}

View file

@ -357,75 +357,66 @@ namespace Server.Mobiles
if( spell != null )
return spell;
if (m_Mobile.Combatant.Hidden && Utility.RandomDouble() < .25)
switch (Utility.Random(16))
{
spell = new RevealSpell(m_Mobile, null);
}
else
{
switch (Utility.Random(16))
{
case 0:
case 1: // Poison them
{
//m_Mobile.DebugSay( "Attempting to poison" );
case 0:
case 1: // Poison them
{
//m_Mobile.DebugSay( "Attempting to poison" );
if (!c.Poisoned)
spell = new PoisonSpell(m_Mobile, null);
if (!c.Poisoned)
spell = new PoisonSpell(m_Mobile, null);
break;
}
case 2: // Bless ourselves.
{
//m_Mobile.DebugSay( "Blessing myself" );
break;
}
case 2: // Bless ourselves.
{
//m_Mobile.DebugSay( "Blessing myself" );
spell = new BlessSpell(m_Mobile, null);
break;
}
case 3:
case 4: // Curse them.
{
//m_Mobile.DebugSay( "Attempting to curse" );
spell = new BlessSpell(m_Mobile, null);
break;
}
case 3:
case 4: // Curse them.
{
//m_Mobile.DebugSay( "Attempting to curse" );
spell = GetRandomCurse();
break;
}
case 5: // Paralyze them.
{
//m_Mobile.DebugSay( "Attempting to paralyze" );
spell = GetRandomCurse();
break;
}
case 5: // Paralyze them.
{
//m_Mobile.DebugSay( "Attempting to paralyze" );
if (m_Mobile.Skills[SkillName.Magery].Value > 50.0)
spell = new ParalyzeSpell(m_Mobile, null);
if (m_Mobile.Skills[SkillName.Magery].Value > 50.0)
spell = new ParalyzeSpell(m_Mobile, null);
break;
}
case 6: // Drain mana
{
//m_Mobile.DebugSay( "Attempting to drain mana" );
break;
}
case 6: // Drain mana
{
//m_Mobile.DebugSay( "Attempting to drain mana" );
spell = GetRandomManaDrainSpell();
break;
}
case 7:
{
//m_Mobile.DebugSay( "Attempting to Invis" );
spell = GetRandomManaDrainSpell();
break;
}
case 7:
{
//m_Mobile.DebugSay( "Attempting to Invis" );
if (spell == null && Utility.RandomBool())
{
spell = new InvisibilitySpell(m_Mobile, null);
}
if (Utility.RandomBool())
spell = new InvisibilitySpell(m_Mobile, null);
break;
}
break;
}
default: // Damage them.
{
//m_Mobile.DebugSay( "Just doing damage" );
default: // Damage them.
{
//m_Mobile.DebugSay( "Just doing damage" );
spell = GetRandomDamage();
break;
}
}
spell = GetRandomDamage();
break;
}
}
return spell;
@ -551,15 +542,25 @@ namespace Server.Mobiles
return spell;
}
private TimeSpan GetDelay()
private TimeSpan GetDelay( Spell spell )
{
double del = ScaleByMagery( 3.0 );
double min = 6.0 - ( del * 0.75 );
double max = 6.0 - ( del * 1.25 );
if( SmartAI || ( spell is DispelSpell ) )
{
return TimeSpan.FromSeconds( m_Mobile.ActiveSpeed );
}
else
{
double del = ScaleByMagery( 3.0 );
double min = 6.0 - ( del * 0.75 );
double max = 6.0 - ( del * 1.25 );
return TimeSpan.FromSeconds( min + ( ( max - min ) * Utility.RandomDouble() ) );
return TimeSpan.FromSeconds( min + ( ( max - min ) * Utility.RandomDouble() ) );
}
}
private Mobile m_LastTarget;
private Point3D m_LastTargetLoc;
public override bool DoActionCombat()
{
Mobile c = m_Mobile.Combatant;
@ -592,7 +593,7 @@ namespace Server.Mobiles
if( AcquireFocusMob( m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true ) )
{
m_Mobile.DebugSay( "Nobody else is around" );
m_Mobile.DebugSay( "I will switch to {0}", m_Mobile.FocusMob.Name );
m_Mobile.Combatant = c = m_Mobile.FocusMob;
m_Mobile.FocusMob = null;
}
@ -708,25 +709,45 @@ namespace Server.Mobiles
if( spell != null )
spell.Cast();
TimeSpan delay;
if( SmartAI || ( spell is DispelSpell ) )
delay = TimeSpan.FromSeconds( m_Mobile.ActiveSpeed );
else
delay = GetDelay();
m_NextCastTime = DateTime.Now;
m_NextCastTime = DateTime.Now + GetDelay( spell );
}
else if( m_Mobile.Spell == null || !m_Mobile.Spell.IsCasting )
{
RunTo( c );
}
m_LastTarget = c;
m_LastTargetLoc = c.Location;
return true;
}
private LandTarget m_RevealTarget;
public override bool DoActionGuard()
{
if( m_LastTarget != null && m_LastTarget.Hidden )
{
Map map = m_Mobile.Map;
if( map == null || !m_Mobile.InRange( m_LastTargetLoc, Core.ML ? 10 : 12 ) )
{
m_LastTarget = null;
}
else if( m_Mobile.Spell == null && DateTime.Now > m_NextCastTime )
{
m_Mobile.DebugSay( "I am going to reveal my last target" );
m_RevealTarget = new LandTarget( m_LastTargetLoc, map );
Spell spell = new RevealSpell( m_Mobile, null );
if( spell.Cast() )
m_LastTarget = null; // only do it once
m_NextCastTime = DateTime.Now + GetDelay( spell );
}
}
if( AcquireFocusMob( m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true ) )
{
m_Mobile.DebugSay( "I am going to attack {0}", m_Mobile.FocusMob.Name );
@ -934,7 +955,7 @@ namespace Server.Mobiles
if( targ == null )
return false;
bool isReveal = (targ is RevealSpell.InternalTarget);
bool isReveal = ( targ is RevealSpell.InternalTarget );
bool isDispel = ( targ is DispelSpell.InternalTarget );
bool isParalyze = ( targ is ParalyzeSpell.InternalTarget );
bool isTeleport = ( targ is TeleportSpell.InternalTarget );
@ -956,7 +977,7 @@ namespace Server.Mobiles
else if( toTarget != null && m_Mobile.InRange( toTarget, 10 ) )
RunFrom( toTarget );
}
else if( SmartAI && ( isParalyze || isTeleport || isReveal ) )
else if( SmartAI && ( isParalyze || isTeleport ) )
{
toTarget = FindDispelTarget( true );
@ -1000,6 +1021,13 @@ namespace Server.Mobiles
{
targ.Invoke( m_Mobile, m_Mobile );
}
else if( isReveal && m_RevealTarget != null )
{
targ.Invoke( m_Mobile, m_RevealTarget );
if( SmartAI )
m_Mobile.NextReacquireTime = DateTime.Now;
}
else if( isTeleport && toTarget != null )
{
Map map = m_Mobile.Map;

View file

@ -243,10 +243,18 @@ namespace Server.Mobiles
private bool m_IsPrisoner;
private string m_CorpseNameOverride;
#endregion
public virtual InhumanSpeech SpeechType{ get{ return null; } }
[CommandProperty( AccessLevel.GameMaster )]
public string CorpseNameOverride
{
get { return m_CorpseNameOverride; }
set { m_CorpseNameOverride = value; }
}
[CommandProperty( AccessLevel.GameMaster, AccessLevel.Administrator )]
public bool IsStabled
{
@ -1560,7 +1568,7 @@ namespace Server.Mobiles
{
base.Serialize( writer );
writer.Write( (int) 17 ); // version
writer.Write( (int) 18 ); // version
writer.Write( (int)m_CurrentAI );
writer.Write( (int)m_DefaultAI );
@ -1676,6 +1684,9 @@ namespace Server.Mobiles
writer.Write( TimeSpan.Zero );
else
writer.Write( DeleteTimeLeft );
// Version 18
writer.Write( m_CorpseNameOverride );
}
private static double[] m_StandardActiveSpeeds = new double[]
@ -1897,6 +1908,9 @@ namespace Server.Mobiles
m_DeleteTimer.Start();
}
if ( version >= 18 )
m_CorpseNameOverride = reader.ReadString();
if( version <= 14 && m_Paragon && Hue == 0x31 )
{
Hue = Paragon.Hue; //Paragon hue fixed, should now be 0x501.
@ -4186,7 +4200,7 @@ namespace Server.Mobiles
list.Add( 1080078 ); // guarding
}
if ( Summoned && !IsAnimatedDead && !IsNecroFamiliar )
if ( Summoned && !IsAnimatedDead && !IsNecroFamiliar && !( this is Clone ) )
list.Add( 1049646 ); // (summoned)
else if ( Controlled && Commandable )
{
@ -5314,7 +5328,7 @@ namespace Server.Mobiles
{
Mobile owner = c.ControlMaster;
if ( owner == null || owner.Deleted || owner.Map != c.Map || !owner.InRange( c, 12 ) || !c.CanSee( owner ) || !c.InLOS( owner ) )
if ( !c.IsStabled && ( owner == null || owner.Deleted || owner.Map != c.Map || !owner.InRange( c, 12 ) || !c.CanSee( owner ) || !c.InLOS( owner ) ) )
{
if ( c.OwnerAbandonTime == DateTime.MinValue )
c.OwnerAbandonTime = DateTime.Now;

View file

@ -32,6 +32,8 @@ namespace Server.Multis.Deeds
if ( from.AccessLevel >= AccessLevel.GameMaster || reg.AllowHousing( from, p ) )
m_Deed.OnPlacement( from, p );
else if ( reg.IsPartOf( typeof( TempNoHousingRegion ) ) )
from.SendLocalizedMessage( 501270 ); // Lord British has decreed a 'no build' period, thus you cannot build this house at this time.
else if ( reg.IsPartOf( typeof( TreasureRegion ) ) )
from.SendLocalizedMessage( 1043287 ); // The house could not be created here. Either something is blocking the house, or the house would not be on valid terrain.
else if ( reg.IsPartOf( typeof( HouseRaffleRegion ) ) )

View file

@ -248,6 +248,8 @@ namespace Server.Items
if ( from.AccessLevel >= AccessLevel.GameMaster || reg.AllowHousing( from, p ) )
m_Placed = m_Entry.OnPlacement( from, p );
else if ( reg.IsPartOf( typeof( TempNoHousingRegion ) ) )
from.SendLocalizedMessage( 501270 ); // Lord British has decreed a 'no build' period, thus you cannot build this house at this time.
else if ( reg.IsPartOf( typeof( TreasureRegion ) ) )
from.SendLocalizedMessage( 1043287 ); // The house could not be created here. Either something is blocking the house, or the house would not be on valid terrain.
else if ( reg.IsPartOf( typeof( HouseRaffleRegion ) ) )

View file

@ -381,7 +381,7 @@ namespace Server.SkillHandlers
Stop();
return;
}
else if ( m_From.NetState == null || m_From.Deleted || m_Target.Deleted || m_From.Map != m_Target.Map || !m_From.InRange( m_Target, m_Range ) )
else if ( m_From.NetState == null || m_From.Deleted || m_Target.Deleted || m_From.Map != m_Target.Map || !m_From.InRange( m_Target, m_Range ) || ( m_Target.Hidden && m_Target.AccessLevel > m_From.AccessLevel ) )
{
m_Arrow.Stop();
Stop();

View file

@ -0,0 +1,93 @@
using System;
using System.Collections.Generic;
using Server;
namespace Server.Misc
{
/*
* This system prevents the inability for server staff to
* access their server due to data overflows during login.
*
* Whenever a staff character's NetState is disposed right after
* the login process, the character is moved to and logged out
* at a "safe" alternative.
*
* The location the character was moved from will be reported
* to the player upon the next successful login.
*
* This system does not affect non-staff players.
*/
public static class PreventInaccess
{
public static readonly bool Enabled = true;
private static readonly LocationInfo[] m_Destinations = new LocationInfo[]
{
new LocationInfo( new Point3D( 5275, 1163, 0 ), Map.Felucca ), // Jail
new LocationInfo( new Point3D( 5275, 1163, 0 ), Map.Trammel ),
new LocationInfo( new Point3D( 5445, 1153, 0 ), Map.Felucca ), // Green acres
new LocationInfo( new Point3D( 5445, 1153, 0 ), Map.Trammel )
};
private static Dictionary<Mobile, LocationInfo> m_MoveHistory;
public static void Initialize()
{
m_MoveHistory = new Dictionary<Mobile, LocationInfo>();
if ( Enabled )
EventSink.Login += new LoginEventHandler( OnLogin );
}
public static void OnLogin( LoginEventArgs e )
{
Mobile from = e.Mobile;
if ( from == null || from.AccessLevel < AccessLevel.Counselor )
return;
if ( HasDisconnected( from ) )
{
if ( !m_MoveHistory.ContainsKey( from ) )
m_MoveHistory[from] = new LocationInfo( from.Location, from.Map );
LocationInfo dest = GetRandomDestination();
from.Location = dest.Location;
from.Map = dest.Map;
}
else if ( m_MoveHistory.ContainsKey( from ) )
{
LocationInfo orig = m_MoveHistory[from];
from.SendMessage( "Your character was moved from {0} ({1}) due to a detected client crash.", orig.Location, orig.Map );
m_MoveHistory.Remove( from );
}
}
private static bool HasDisconnected( Mobile m )
{
return ( m.NetState == null || m.NetState.Socket == null );
}
private static LocationInfo GetRandomDestination()
{
return m_Destinations[Utility.Random( m_Destinations.Length )];
}
private class LocationInfo
{
private Point3D m_Location;
private Map m_Map;
public Point3D Location { get { return m_Location; } }
public Map Map { get { return m_Map; } }
public LocationInfo( Point3D loc, Map map )
{
m_Location = loc;
m_Map = map;
}
}
}
}