Fixes code according to modern code style. Fixes a few expression bugs.

This commit is contained in:
Kamron Batman 2018-09-15 09:58:51 -07:00
parent 89eea25e5f
commit 970fd563b2
3324 changed files with 441118 additions and 433755 deletions

View file

@ -1,10 +0,0 @@
# http://editorconfig.org
root=true
[*]
indent_style = tab
tab_width = 4
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

View file

@ -5,40 +5,42 @@ using Server.Misc;
namespace Server
{
public class AccessRestrictions
{
public static void Initialize()
{
EventSink.SocketConnect += EventSink_SocketConnect;
}
private static void EventSink_SocketConnect( SocketConnectEventArgs e )
{
try
{
IPAddress ip = ((IPEndPoint)e.Socket.RemoteEndPoint).Address;
public class AccessRestrictions
{
public static void Initialize()
{
EventSink.SocketConnect += EventSink_SocketConnect;
}
if ( Firewall.IsBlocked( ip ) )
{
Console.WriteLine( "Client: {0}: Firewall blocked connection attempt.", ip );
e.AllowConnection = false;
return;
}
private static void EventSink_SocketConnect(SocketConnectEventArgs e)
{
try
{
IPAddress ip = ((IPEndPoint)e.Socket.RemoteEndPoint).Address;
if ( IPLimiter.SocketBlock && !IPLimiter.Verify( ip ) )
{
Console.WriteLine( "Client: {0}: Past IP limit threshold", ip );
if (Firewall.IsBlocked(ip))
{
Console.WriteLine("Client: {0}: Firewall blocked connection attempt.", ip);
e.AllowConnection = false;
return;
}
using ( StreamWriter op = new StreamWriter( "ipLimits.log", true ) )
op.WriteLine( "{0}\tPast IP limit threshold\t{1}", ip, DateTime.UtcNow );
e.AllowConnection = false;
}
}
catch
{
e.AllowConnection = false;
}
}
}
if (IPLimiter.SocketBlock && !IPLimiter.Verify(ip))
{
Console.WriteLine("Client: {0}: Past IP limit threshold", ip);
using (StreamWriter op = new StreamWriter("ipLimits.log", true))
{
op.WriteLine("{0}\tPast IP limit threshold\t{1}", ip, DateTime.UtcNow);
}
e.AllowConnection = false;
}
}
catch
{
e.AllowConnection = false;
}
}
}
}

View file

@ -6,121 +6,123 @@ using Server.Network;
namespace Server.Accounting
{
public class AccountAttackLimiter
{
public static bool Enabled = true;
public class AccountAttackLimiter
{
public static bool Enabled = true;
public static void Initialize()
{
if ( !Enabled )
return;
private static List<InvalidAccountAccessLog> m_List = new List<InvalidAccountAccessLog>();
PacketHandlers.RegisterThrottler( 0x80, Throttle_Callback );
PacketHandlers.RegisterThrottler( 0x91, Throttle_Callback );
PacketHandlers.RegisterThrottler( 0xCF, Throttle_Callback );
}
public static void Initialize()
{
if (!Enabled)
return;
public static bool Throttle_Callback( NetState ns )
{
InvalidAccountAccessLog accessLog = FindAccessLog( ns );
PacketHandlers.RegisterThrottler(0x80, Throttle_Callback);
PacketHandlers.RegisterThrottler(0x91, Throttle_Callback);
PacketHandlers.RegisterThrottler(0xCF, Throttle_Callback);
}
if ( accessLog == null )
return true;
public static bool Throttle_Callback(NetState ns)
{
InvalidAccountAccessLog accessLog = FindAccessLog(ns);
return ( DateTime.UtcNow >= (accessLog.LastAccessTime + ComputeThrottle( accessLog.Counts )) );
}
if (accessLog == null)
return true;
private static List<InvalidAccountAccessLog> m_List = new List<InvalidAccountAccessLog>();
return DateTime.UtcNow >= accessLog.LastAccessTime + ComputeThrottle(accessLog.Counts);
}
public static InvalidAccountAccessLog FindAccessLog( NetState ns )
{
if ( ns == null )
return null;
public static InvalidAccountAccessLog FindAccessLog(NetState ns)
{
if (ns == null)
return null;
IPAddress ipAddress = ns.Address;
IPAddress ipAddress = ns.Address;
for ( int i = 0; i < m_List.Count; ++i )
{
InvalidAccountAccessLog accessLog = m_List[i];
for (int i = 0; i < m_List.Count; ++i)
{
InvalidAccountAccessLog accessLog = m_List[i];
if ( accessLog.HasExpired )
m_List.RemoveAt( i-- );
else if ( accessLog.Address.Equals( ipAddress ) )
return accessLog;
}
if (accessLog.HasExpired)
m_List.RemoveAt(i--);
else if (accessLog.Address.Equals(ipAddress))
return accessLog;
}
return null;
}
return null;
}
public static void RegisterInvalidAccess( NetState ns )
{
if ( ns == null || !Enabled )
return;
public static void RegisterInvalidAccess(NetState ns)
{
if (ns == null || !Enabled)
return;
InvalidAccountAccessLog accessLog = FindAccessLog( ns );
InvalidAccountAccessLog accessLog = FindAccessLog(ns);
if ( accessLog == null )
m_List.Add( accessLog = new InvalidAccountAccessLog( ns.Address ) );
if (accessLog == null)
m_List.Add(accessLog = new InvalidAccountAccessLog(ns.Address));
accessLog.Counts += 1;
accessLog.RefreshAccessTime();
accessLog.Counts += 1;
accessLog.RefreshAccessTime();
if ( accessLog.Counts >= 3 ) {
try {
using ( StreamWriter op = new StreamWriter( "throttle.log", true ) ) {
op.WriteLine(
"{0}\t{1}\t{2}",
DateTime.UtcNow,
ns,
accessLog.Counts
);
}
}
catch {
}
}
}
if (accessLog.Counts >= 3)
try
{
using (StreamWriter op = new StreamWriter("throttle.log", true))
{
op.WriteLine(
"{0}\t{1}\t{2}",
DateTime.UtcNow,
ns,
accessLog.Counts
);
}
}
catch
{
}
}
public static TimeSpan ComputeThrottle( int counts )
{
if ( counts >= 15 )
return TimeSpan.FromMinutes( 5.0 );
public static TimeSpan ComputeThrottle(int counts)
{
if (counts >= 15)
return TimeSpan.FromMinutes(5.0);
if ( counts >= 10 )
return TimeSpan.FromMinutes( 1.0 );
if (counts >= 10)
return TimeSpan.FromMinutes(1.0);
if ( counts >= 5 )
return TimeSpan.FromSeconds( 20.0 );
if (counts >= 5)
return TimeSpan.FromSeconds(20.0);
if ( counts >= 3 )
return TimeSpan.FromSeconds( 10.0 );
if (counts >= 3)
return TimeSpan.FromSeconds(10.0);
if ( counts >= 1 )
return TimeSpan.FromSeconds( 2.0 );
if (counts >= 1)
return TimeSpan.FromSeconds(2.0);
return TimeSpan.Zero;
}
}
return TimeSpan.Zero;
}
}
public class InvalidAccountAccessLog
{
public IPAddress Address { get; set; }
public class InvalidAccountAccessLog
{
public InvalidAccountAccessLog(IPAddress address)
{
Address = address;
RefreshAccessTime();
}
public DateTime LastAccessTime { get; set; }
public IPAddress Address{ get; set; }
public bool HasExpired => ( DateTime.UtcNow >= ( LastAccessTime + TimeSpan.FromHours( 1.0 ) ) );
public DateTime LastAccessTime{ get; set; }
public int Counts { get; set; }
public bool HasExpired => DateTime.UtcNow >= LastAccessTime + TimeSpan.FromHours(1.0);
public void RefreshAccessTime()
{
LastAccessTime = DateTime.UtcNow;
}
public int Counts{ get; set; }
public InvalidAccountAccessLog( IPAddress address )
{
Address = address;
RefreshAccessTime();
}
}
public void RefreshAccessTime()
{
LastAccessTime = DateTime.UtcNow;
}
}
}

View file

@ -3,67 +3,71 @@ using System.Xml;
namespace Server.Accounting
{
public class AccountComment
{
private string m_Content;
public class AccountComment
{
private string m_Content;
/// <summary>
/// A string representing who added this comment.
/// </summary>
public string AddedBy { get; }
/// <summary>
/// Constructs a new AccountComment instance.
/// </summary>
/// <param name="addedBy">Initial AddedBy value.</param>
/// <param name="content">Initial Content value.</param>
public AccountComment(string addedBy, string content)
{
AddedBy = addedBy;
m_Content = content;
LastModified = DateTime.UtcNow;
}
/// <summary>
/// Gets or sets the body of this comment. Setting this value will reset LastModified.
/// </summary>
public string Content
{
get => m_Content;
set{ m_Content = value; LastModified = DateTime.UtcNow; }
}
/// <summary>
/// Deserializes an AccountComment instance from an xml element.
/// </summary>
/// <param name="node">The XmlElement instance from which to deserialize.</param>
public AccountComment(XmlElement node)
{
AddedBy = Utility.GetAttribute(node, "addedBy", "empty");
LastModified = Utility.GetXMLDateTime(Utility.GetAttribute(node, "lastModified"), DateTime.UtcNow);
m_Content = Utility.GetText(node, "");
}
/// <summary>
/// The date and time when this account was last modified -or- the comment creation time, if never modified.
/// </summary>
public DateTime LastModified { get; private set; }
/// <summary>
/// A string representing who added this comment.
/// </summary>
public string AddedBy{ get; }
/// <summary>
/// Constructs a new AccountComment instance.
/// </summary>
/// <param name="addedBy">Initial AddedBy value.</param>
/// <param name="content">Initial Content value.</param>
public AccountComment( string addedBy, string content )
{
AddedBy = addedBy;
m_Content = content;
LastModified = DateTime.UtcNow;
}
/// <summary>
/// Gets or sets the body of this comment. Setting this value will reset LastModified.
/// </summary>
public string Content
{
get => m_Content;
set
{
m_Content = value;
LastModified = DateTime.UtcNow;
}
}
/// <summary>
/// Deserializes an AccountComment instance from an xml element.
/// </summary>
/// <param name="node">The XmlElement instance from which to deserialize.</param>
public AccountComment( XmlElement node )
{
AddedBy = Utility.GetAttribute( node, "addedBy", "empty" );
LastModified = Utility.GetXMLDateTime( Utility.GetAttribute( node, "lastModified" ), DateTime.UtcNow );
m_Content = Utility.GetText( node, "" );
}
/// <summary>
/// The date and time when this account was last modified -or- the comment creation time, if never modified.
/// </summary>
public DateTime LastModified{ get; private set; }
/// <summary>
/// Serializes this AccountComment instance to an XmlTextWriter.
/// </summary>
/// <param name="xml">The XmlTextWriter instance from which to serialize.</param>
public void Save( XmlTextWriter xml )
{
xml.WriteStartElement( "comment" );
/// <summary>
/// Serializes this AccountComment instance to an XmlTextWriter.
/// </summary>
/// <param name="xml">The XmlTextWriter instance from which to serialize.</param>
public void Save(XmlTextWriter xml)
{
xml.WriteStartElement("comment");
xml.WriteAttributeString( "addedBy", AddedBy );
xml.WriteAttributeString("addedBy", AddedBy);
xml.WriteAttributeString( "lastModified", XmlConvert.ToString( LastModified, XmlDateTimeSerializationMode.Utc ) );
xml.WriteAttributeString("lastModified", XmlConvert.ToString(LastModified, XmlDateTimeSerializationMode.Utc));
xml.WriteString( m_Content );
xml.WriteString(m_Content);
xml.WriteEndElement();
}
}
xml.WriteEndElement();
}
}
}

View file

@ -10,407 +10,417 @@ using Server.Regions;
namespace Server.Misc
{
public enum PasswordProtection
{
None,
Crypt,
NewCrypt
}
public enum PasswordProtection
{
None,
Crypt,
NewCrypt
}
public class AccountHandler
{
private static int MaxAccountsPerIP = 1;
private static bool AutoAccountCreation = true;
private static bool RestrictDeletion = !TestCenter.Enabled;
private static TimeSpan DeleteDelay = TimeSpan.FromDays( 7.0 );
public class AccountHandler
{
private static int MaxAccountsPerIP = 1;
private static bool AutoAccountCreation = true;
private static bool RestrictDeletion = !TestCenter.Enabled;
private static TimeSpan DeleteDelay = TimeSpan.FromDays(7.0);
public static PasswordProtection ProtectPasswords = PasswordProtection.NewCrypt;
public static PasswordProtection ProtectPasswords = PasswordProtection.NewCrypt;
public static AccessLevel LockdownLevel { get; set; }
private static CityInfo[] StartingCities =
{
new CityInfo("New Haven", "New Haven Bank", 1150168, 3667, 2625, 0),
new CityInfo("Yew", "The Empath Abbey", 1075072, 633, 858, 0),
new CityInfo("Minoc", "The Barnacle", 1075073, 2476, 413, 15),
new CityInfo("Britain", "The Wayfarer's Inn", 1075074, 1602, 1591, 20),
new CityInfo("Moonglow", "The Scholars Inn", 1075075, 4408, 1168, 0),
new CityInfo("Trinsic", "The Traveler's Inn", 1075076, 1845, 2745, 0),
new CityInfo("Jhelom", "The Mercenary Inn", 1075078, 1374, 3826, 0),
new CityInfo("Skara Brae", "The Falconer's Inn", 1075079, 618, 2234, 0),
new CityInfo("Vesper", "The Ironwood Inn", 1075080, 2771, 976, 0)
};
private static CityInfo[] StartingCities = {
new CityInfo( "New Haven", "New Haven Bank", 1150168, 3667, 2625, 0 ),
new CityInfo( "Yew", "The Empath Abbey", 1075072, 633, 858, 0 ),
new CityInfo( "Minoc", "The Barnacle", 1075073, 2476, 413, 15 ),
new CityInfo( "Britain", "The Wayfarer's Inn", 1075074, 1602, 1591, 20 ),
new CityInfo( "Moonglow", "The Scholars Inn", 1075075, 4408, 1168, 0 ),
new CityInfo( "Trinsic", "The Traveler's Inn", 1075076, 1845, 2745, 0 ),
new CityInfo( "Jhelom", "The Mercenary Inn", 1075078, 1374, 3826, 0 ),
new CityInfo( "Skara Brae", "The Falconer's Inn", 1075079, 618, 2234, 0 ),
new CityInfo( "Vesper", "The Ironwood Inn", 1075080, 2771, 976, 0 )
};
/* Old Haven/Magincia Locations
new CityInfo( "Britain", "Sweet Dreams Inn", 1496, 1628, 10 );
// ..
// Trinsic
new CityInfo( "Magincia", "The Great Horns Tavern", 3734, 2222, 20 ),
// Jhelom
// ..
new CityInfo( "Haven", "Buckler's Hideaway", 3667, 2625, 0 )
/* Old Haven/Magincia Locations
new CityInfo( "Britain", "Sweet Dreams Inn", 1496, 1628, 10 );
// ..
// Trinsic
new CityInfo( "Magincia", "The Great Horns Tavern", 3734, 2222, 20 ),
// Jhelom
// ..
new CityInfo( "Haven", "Buckler's Hideaway", 3667, 2625, 0 )
if ( Core.AOS )
{
//CityInfo haven = new CityInfo( "Haven", "Uzeraan's Mansion", 3618, 2591, 0 );
CityInfo haven = new CityInfo( "Haven", "Uzeraan's Mansion", 3503, 2574, 14 );
StartingCities[StartingCities.Length - 1] = haven;
}
*/
if ( Core.AOS )
{
//CityInfo haven = new CityInfo( "Haven", "Uzeraan's Mansion", 3618, 2591, 0 );
CityInfo haven = new CityInfo( "Haven", "Uzeraan's Mansion", 3503, 2574, 14 );
StartingCities[StartingCities.Length - 1] = haven;
}
*/
private static bool PasswordCommandEnabled = false;
private static bool PasswordCommandEnabled = false;
private static Dictionary<IPAddress, int> m_IPTable;
public static void Initialize()
{
EventSink.DeleteRequest += EventSink_DeleteRequest;
EventSink.AccountLogin += EventSink_AccountLogin;
EventSink.GameLogin += EventSink_GameLogin;
private static readonly char[] m_ForbiddenChars =
{
'<', '>', ':', '"', '/', '\\', '|', '?', '*'
};
if ( PasswordCommandEnabled )
CommandSystem.Register( "Password", AccessLevel.Player, Password_OnCommand );
}
public static AccessLevel LockdownLevel{ get; set; }
[Usage( "Password <newPassword> <repeatPassword>" )]
[Description( "Changes the password of the commanding players account. Requires the same C-class IP address as the account's creator." )]
public static void Password_OnCommand( CommandEventArgs e )
{
Mobile from = e.Mobile;
public static Dictionary<IPAddress, int> IPTable
{
get
{
if (m_IPTable == null)
{
m_IPTable = new Dictionary<IPAddress, int>();
if ( !(from.Account is Account acct) )
return;
foreach (Account a in Accounts.GetAccounts())
if (a.LoginIPs.Length > 0)
{
IPAddress ip = a.LoginIPs[0];
IPAddress[] accessList = acct.LoginIPs;
if (m_IPTable.ContainsKey(ip))
m_IPTable[ip]++;
else
m_IPTable[ip] = 1;
}
}
if ( accessList.Length == 0 )
return;
return m_IPTable;
}
}
NetState ns = from.NetState;
public static void Initialize()
{
EventSink.DeleteRequest += EventSink_DeleteRequest;
EventSink.AccountLogin += EventSink_AccountLogin;
EventSink.GameLogin += EventSink_GameLogin;
if ( ns == null )
return;
if (PasswordCommandEnabled)
CommandSystem.Register("Password", AccessLevel.Player, Password_OnCommand);
}
if ( e.Length == 0 )
{
from.SendMessage( "You must specify the new password." );
return;
}
if ( e.Length == 1 )
{
from.SendMessage( "To prevent potential typing mistakes, you must type the password twice. Use the format:" );
from.SendMessage( "Password \"(newPassword)\" \"(repeated)\"" );
return;
}
[Usage("Password <newPassword> <repeatPassword>")]
[Description(
"Changes the password of the commanding players account. Requires the same C-class IP address as the account's creator.")]
public static void Password_OnCommand(CommandEventArgs e)
{
Mobile from = e.Mobile;
string pass = e.GetString( 0 );
string pass2 = e.GetString( 1 );
if (!(from.Account is Account acct))
return;
if ( pass != pass2 )
{
from.SendMessage( "The passwords do not match." );
return;
}
IPAddress[] accessList = acct.LoginIPs;
bool isSafe = true;
if (accessList.Length == 0)
return;
for ( int i = 0; isSafe && i < pass.Length; ++i )
isSafe = ( pass[i] >= 0x20 && pass[i] < 0x7F );
NetState ns = from.NetState;
if ( !isSafe )
{
from.SendMessage( "That is not a valid password." );
return;
}
if (ns == null)
return;
try
{
IPAddress ipAddress = ns.Address;
if (e.Length == 0)
{
from.SendMessage("You must specify the new password.");
return;
}
if ( Utility.IPMatchClassC( accessList[0], ipAddress ) )
{
acct.SetPassword( pass );
from.SendMessage( "The password to your account has changed." );
}
else
{
PageEntry entry = PageQueue.GetEntry( from );
if (e.Length == 1)
{
from.SendMessage("To prevent potential typing mistakes, you must type the password twice. Use the format:");
from.SendMessage("Password \"(newPassword)\" \"(repeated)\"");
return;
}
if ( entry != null )
{
if ( entry.Message.StartsWith( "[Automated: Change Password]" ) )
from.SendMessage( "You already have a password change request in the help system queue." );
else
from.SendMessage( "Your IP address does not match that which created this account." );
}
else if ( PageQueue.CheckAllowedToPage( from ) )
{
from.SendMessage( "Your IP address does not match that which created this account. A page has been entered into the help system on your behalf." );
string pass = e.GetString(0);
string pass2 = e.GetString(1);
from.SendLocalizedMessage( 501234, "", 0x35 ); /* The next available Counselor/Game Master will respond as soon as possible.
if (pass != pass2)
{
from.SendMessage("The passwords do not match.");
return;
}
bool isSafe = true;
for (int i = 0; isSafe && i < pass.Length; ++i)
isSafe = pass[i] >= 0x20 && pass[i] < 0x7F;
if (!isSafe)
{
from.SendMessage("That is not a valid password.");
return;
}
try
{
IPAddress ipAddress = ns.Address;
if (Utility.IPMatchClassC(accessList[0], ipAddress))
{
acct.SetPassword(pass);
from.SendMessage("The password to your account has changed.");
}
else
{
PageEntry entry = PageQueue.GetEntry(from);
if (entry != null)
{
if (entry.Message.StartsWith("[Automated: Change Password]"))
from.SendMessage("You already have a password change request in the help system queue.");
else
from.SendMessage("Your IP address does not match that which created this account.");
}
else if (PageQueue.CheckAllowedToPage(from))
{
from.SendMessage(
"Your IP address does not match that which created this account. A page has been entered into the help system on your behalf.");
from.SendLocalizedMessage(501234, "",
0x35); /* The next available Counselor/Game Master will respond as soon as possible.
* Please check your Journal for messages every few minutes.
*/
PageQueue.Enqueue( new PageEntry( from,
$"[Automated: Change Password]<br>Desired password: {pass}<br>Current IP address: {ipAddress}<br>Account IP address: {accessList[0]}", PageType.Account ) );
}
PageQueue.Enqueue(new PageEntry(from,
$"[Automated: Change Password]<br>Desired password: {pass}<br>Current IP address: {ipAddress}<br>Account IP address: {accessList[0]}",
PageType.Account));
}
}
}
catch
{
}
}
}
}
catch
{
}
}
private static void EventSink_DeleteRequest(DeleteRequestEventArgs e)
{
NetState state = e.State;
int index = e.Index;
private static void EventSink_DeleteRequest( DeleteRequestEventArgs e )
{
NetState state = e.State;
int index = e.Index;
if (!(state.Account is Account acct))
{
state.Dispose();
}
else if (index < 0 || index >= acct.Length)
{
state.Send(new DeleteResult(DeleteResultType.BadRequest));
state.Send(new CharacterListUpdate(acct));
}
else
{
Mobile m = acct[index];
if ( !(state.Account is Account acct) )
{
state.Dispose();
}
else if ( index < 0 || index >= acct.Length )
{
state.Send( new DeleteResult( DeleteResultType.BadRequest ) );
state.Send( new CharacterListUpdate( acct ) );
}
else
{
Mobile m = acct[index];
if (m == null)
{
state.Send(new DeleteResult(DeleteResultType.CharNotExist));
state.Send(new CharacterListUpdate(acct));
}
else if (m.NetState != null)
{
state.Send(new DeleteResult(DeleteResultType.CharBeingPlayed));
state.Send(new CharacterListUpdate(acct));
}
else if (RestrictDeletion && DateTime.UtcNow < m.CreationTime + DeleteDelay)
{
state.Send(new DeleteResult(DeleteResultType.CharTooYoung));
state.Send(new CharacterListUpdate(acct));
}
else if (m.AccessLevel == AccessLevel.Player &&
Region.Find(m.LogoutLocation, m.LogoutMap).GetRegion(typeof(Jail)) != null
) //Don't need to check current location, if netstate is null, they're logged out
{
state.Send(new DeleteResult(DeleteResultType.BadRequest));
state.Send(new CharacterListUpdate(acct));
}
else
{
Console.WriteLine("Client: {0}: Deleting character {1} (0x{2:X})", state, index, m.Serial.Value);
if ( m == null )
{
state.Send( new DeleteResult( DeleteResultType.CharNotExist ) );
state.Send( new CharacterListUpdate( acct ) );
}
else if ( m.NetState != null )
{
state.Send( new DeleteResult( DeleteResultType.CharBeingPlayed ) );
state.Send( new CharacterListUpdate( acct ) );
}
else if ( RestrictDeletion && DateTime.UtcNow < (m.CreationTime + DeleteDelay) )
{
state.Send( new DeleteResult( DeleteResultType.CharTooYoung ) );
state.Send( new CharacterListUpdate( acct ) );
}
else if ( m.AccessLevel == AccessLevel.Player && Region.Find( m.LogoutLocation, m.LogoutMap ).GetRegion( typeof( Jail ) ) != null ) //Don't need to check current location, if netstate is null, they're logged out
{
state.Send( new DeleteResult( DeleteResultType.BadRequest ) );
state.Send( new CharacterListUpdate( acct ) );
}
else
{
Console.WriteLine( "Client: {0}: Deleting character {1} (0x{2:X})", state, index, m.Serial.Value );
acct.Comments.Add(new AccountComment("System", $"Character #{index + 1} {m} deleted by {state}"));
acct.Comments.Add( new AccountComment( "System", $"Character #{index + 1} {m} deleted by {state}") );
m.Delete();
state.Send(new CharacterListUpdate(acct));
}
}
}
m.Delete();
state.Send( new CharacterListUpdate( acct ) );
}
}
}
public static bool CanCreate(IPAddress ip)
{
if (!IPTable.ContainsKey(ip))
return true;
public static bool CanCreate( IPAddress ip )
{
if ( !IPTable.ContainsKey( ip ) )
return true;
return IPTable[ip] < MaxAccountsPerIP;
}
return ( IPTable[ip] < MaxAccountsPerIP );
}
private static bool IsForbiddenChar(char c)
{
for (int i = 0; i < m_ForbiddenChars.Length; ++i)
if (c == m_ForbiddenChars[i])
return true;
private static Dictionary<IPAddress, int> m_IPTable;
return false;
}
public static Dictionary<IPAddress, int> IPTable
{
get
{
if ( m_IPTable == null )
{
m_IPTable = new Dictionary<IPAddress, int>();
private static Account CreateAccount(NetState state, string un, string pw)
{
if (un.Length == 0 || pw.Length == 0)
return null;
foreach ( Account a in Accounts.GetAccounts() )
if ( a.LoginIPs.Length > 0 )
{
IPAddress ip = a.LoginIPs[0];
bool isSafe = !(un.StartsWith(" ") || un.EndsWith(" ") || un.EndsWith("."));
if ( m_IPTable.ContainsKey( ip ) )
m_IPTable[ip]++;
else
m_IPTable[ip] = 1;
}
}
for (int i = 0; isSafe && i < un.Length; ++i)
isSafe = un[i] >= 0x20 && un[i] < 0x7F && !IsForbiddenChar(un[i]);
return m_IPTable;
}
}
for (int i = 0; isSafe && i < pw.Length; ++i)
isSafe = pw[i] >= 0x20 && pw[i] < 0x7F;
private static readonly char[] m_ForbiddenChars = {
'<', '>', ':', '"', '/', '\\', '|', '?', '*'
};
if (!isSafe)
return null;
private static bool IsForbiddenChar( char c )
{
for ( int i = 0; i < m_ForbiddenChars.Length; ++i )
if ( c == m_ForbiddenChars[i] )
return true;
if (!CanCreate(state.Address))
{
Console.WriteLine("Login: {0}: Account '{1}' not created, ip already has {2} account{3}.", state, un,
MaxAccountsPerIP, MaxAccountsPerIP == 1 ? "" : "s");
return null;
}
return false;
}
Console.WriteLine("Login: {0}: Creating new account '{1}'", state, un);
private static Account CreateAccount( NetState state, string un, string pw )
{
if ( un.Length == 0 || pw.Length == 0 )
return null;
Account a = new Account(un, pw);
bool isSafe = !( un.StartsWith( " " ) || un.EndsWith( " " ) || un.EndsWith( "." ) );
return a;
}
for ( int i = 0; isSafe && i < un.Length; ++i )
isSafe = ( un[i] >= 0x20 && un[i] < 0x7F && !IsForbiddenChar( un[i] ) );
public static void EventSink_AccountLogin(AccountLoginEventArgs e)
{
if (!IPLimiter.SocketBlock && !IPLimiter.Verify(e.State.Address))
{
e.Accepted = false;
e.RejectReason = ALRReason.InUse;
for ( int i = 0; isSafe && i < pw.Length; ++i )
isSafe = ( pw[i] >= 0x20 && pw[i] < 0x7F );
Console.WriteLine("Login: {0}: Past IP limit threshold", e.State);
if ( !isSafe )
return null;
using (StreamWriter op = new StreamWriter("ipLimits.log", true))
{
op.WriteLine("{0}\tPast IP limit threshold\t{1}", e.State, DateTime.UtcNow);
}
if ( !CanCreate( state.Address ) )
{
Console.WriteLine( "Login: {0}: Account '{1}' not created, ip already has {2} account{3}.", state, un, MaxAccountsPerIP, MaxAccountsPerIP == 1 ? "" : "s" );
return null;
}
return;
}
Console.WriteLine( "Login: {0}: Creating new account '{1}'", state, un );
string un = e.Username;
string pw = e.Password;
Account a = new Account( un, pw );
e.Accepted = false;
return a;
}
if (!(Accounts.GetAccount(un) is Account acct))
{
if (AutoAccountCreation && un.Trim().Length > 0
) // To prevent someone from making an account of just '' or a bunch of meaningless spaces
{
e.State.Account = acct = CreateAccount(e.State, un, pw);
e.Accepted = acct?.CheckAccess(e.State) ?? false;
public static void EventSink_AccountLogin( AccountLoginEventArgs e )
{
if ( !IPLimiter.SocketBlock && !IPLimiter.Verify( e.State.Address ) )
{
e.Accepted = false;
e.RejectReason = ALRReason.InUse;
if (!e.Accepted)
e.RejectReason = ALRReason.BadComm;
}
else
{
Console.WriteLine("Login: {0}: Invalid username '{1}'", e.State, un);
e.RejectReason = ALRReason.Invalid;
}
}
else if (!acct.HasAccess(e.State))
{
Console.WriteLine("Login: {0}: Access denied for '{1}'", e.State, un);
e.RejectReason = LockdownLevel > AccessLevel.Player ? ALRReason.BadComm : ALRReason.BadPass;
}
else if (!acct.CheckPassword(pw))
{
Console.WriteLine("Login: {0}: Invalid password for '{1}'", e.State, un);
e.RejectReason = ALRReason.BadPass;
}
else if (acct.Banned)
{
Console.WriteLine("Login: {0}: Banned account '{1}'", e.State, un);
e.RejectReason = ALRReason.Blocked;
}
else
{
Console.WriteLine("Login: {0}: Valid credentials for '{1}'", e.State, un);
e.State.Account = acct;
e.Accepted = true;
Console.WriteLine( "Login: {0}: Past IP limit threshold", e.State );
acct.LogAccess(e.State);
}
using ( StreamWriter op = new StreamWriter( "ipLimits.log", true ) )
op.WriteLine( "{0}\tPast IP limit threshold\t{1}", e.State, DateTime.UtcNow );
if (!e.Accepted)
AccountAttackLimiter.RegisterInvalidAccess(e.State);
}
return;
}
public static void EventSink_GameLogin(GameLoginEventArgs e)
{
if (!IPLimiter.SocketBlock && !IPLimiter.Verify(e.State.Address))
{
e.Accepted = false;
string un = e.Username;
string pw = e.Password;
Console.WriteLine("Login: {0}: Past IP limit threshold", e.State);
e.Accepted = false;
using (StreamWriter op = new StreamWriter("ipLimits.log", true))
{
op.WriteLine("{0}\tPast IP limit threshold\t{1}", e.State, DateTime.UtcNow);
}
if ( !(Accounts.GetAccount( un ) is Account acct) )
{
if ( AutoAccountCreation && un.Trim().Length > 0 ) // To prevent someone from making an account of just '' or a bunch of meaningless spaces
{
e.State.Account = acct = CreateAccount( e.State, un, pw );
e.Accepted = acct?.CheckAccess( e.State ) ?? false;
return;
}
if ( !e.Accepted )
e.RejectReason = ALRReason.BadComm;
}
else
{
Console.WriteLine( "Login: {0}: Invalid username '{1}'", e.State, un );
e.RejectReason = ALRReason.Invalid;
}
}
else if ( !acct.HasAccess( e.State ) )
{
Console.WriteLine( "Login: {0}: Access denied for '{1}'", e.State, un );
e.RejectReason = ( LockdownLevel > AccessLevel.Player ? ALRReason.BadComm : ALRReason.BadPass );
}
else if ( !acct.CheckPassword( pw ) )
{
Console.WriteLine( "Login: {0}: Invalid password for '{1}'", e.State, un );
e.RejectReason = ALRReason.BadPass;
}
else if ( acct.Banned )
{
Console.WriteLine( "Login: {0}: Banned account '{1}'", e.State, un );
e.RejectReason = ALRReason.Blocked;
}
else
{
Console.WriteLine( "Login: {0}: Valid credentials for '{1}'", e.State, un );
e.State.Account = acct;
e.Accepted = true;
string un = e.Username;
string pw = e.Password;
acct.LogAccess( e.State );
}
if (!(Accounts.GetAccount(un) is Account acct))
{
e.Accepted = false;
}
else if (!acct.HasAccess(e.State))
{
Console.WriteLine("Login: {0}: Access denied for '{1}'", e.State, un);
e.Accepted = false;
}
else if (!acct.CheckPassword(pw))
{
Console.WriteLine("Login: {0}: Invalid password for '{1}'", e.State, un);
e.Accepted = false;
}
else if (acct.Banned)
{
Console.WriteLine("Login: {0}: Banned account '{1}'", e.State, un);
e.Accepted = false;
}
else
{
acct.LogAccess(e.State);
if ( !e.Accepted )
AccountAttackLimiter.RegisterInvalidAccess( e.State );
}
Console.WriteLine("Login: {0}: Account '{1}' at character list", e.State, un);
e.State.Account = acct;
e.Accepted = true;
e.CityInfo = StartingCities;
}
public static void EventSink_GameLogin( GameLoginEventArgs e )
{
if ( !IPLimiter.SocketBlock && !IPLimiter.Verify( e.State.Address ) )
{
e.Accepted = false;
if (!e.Accepted)
AccountAttackLimiter.RegisterInvalidAccess(e.State);
}
Console.WriteLine( "Login: {0}: Past IP limit threshold", e.State );
public static bool CheckAccount(Mobile mobCheck, Mobile accCheck)
{
if (accCheck?.Account is Account a)
for (int i = 0; i < a.Length; ++i)
if (a[i] == mobCheck)
return true;
using ( StreamWriter op = new StreamWriter( "ipLimits.log", true ) )
op.WriteLine( "{0}\tPast IP limit threshold\t{1}", e.State, DateTime.UtcNow );
return;
}
string un = e.Username;
string pw = e.Password;
if ( !(Accounts.GetAccount( un ) is Account acct) )
{
e.Accepted = false;
}
else if ( !acct.HasAccess( e.State ) )
{
Console.WriteLine( "Login: {0}: Access denied for '{1}'", e.State, un );
e.Accepted = false;
}
else if ( !acct.CheckPassword( pw ) )
{
Console.WriteLine( "Login: {0}: Invalid password for '{1}'", e.State, un );
e.Accepted = false;
}
else if ( acct.Banned )
{
Console.WriteLine( "Login: {0}: Banned account '{1}'", e.State, un );
e.Accepted = false;
}
else
{
acct.LogAccess( e.State );
Console.WriteLine( "Login: {0}: Account '{1}' at character list", e.State, un );
e.State.Account = acct;
e.Accepted = true;
e.CityInfo = StartingCities;
}
if ( !e.Accepted )
AccountAttackLimiter.RegisterInvalidAccess( e.State );
}
public static bool CheckAccount( Mobile mobCheck, Mobile accCheck )
{
if ( accCheck?.Account is Account a )
{
for ( int i = 0; i < a.Length; ++i )
{
if ( a[i] == mobCheck )
return true;
}
}
return false;
}
}
}
return false;
}
}
}

View file

@ -2,49 +2,49 @@ using System.Xml;
namespace Server.Accounting
{
public class AccountTag
{
/// <summary>
/// Gets or sets the name of this tag.
/// </summary>
public string Name { get; set; }
public class AccountTag
{
/// <summary>
/// Constructs a new AccountTag instance with a specific name and value.
/// </summary>
/// <param name="name">Initial name.</param>
/// <param name="value">Initial value.</param>
public AccountTag(string name, string value)
{
Name = name;
Value = value;
}
/// <summary>
/// Gets or sets the value of this tag.
/// </summary>
public string Value { get; set; }
/// <summary>
/// Deserializes an AccountTag instance from an xml element.
/// </summary>
/// <param name="node">The XmlElement instance from which to deserialize.</param>
public AccountTag(XmlElement node)
{
Name = Utility.GetAttribute(node, "name", "empty");
Value = Utility.GetText(node, "");
}
/// <summary>
/// Constructs a new AccountTag instance with a specific name and value.
/// </summary>
/// <param name="name">Initial name.</param>
/// <param name="value">Initial value.</param>
public AccountTag( string name, string value )
{
Name = name;
Value = value;
}
/// <summary>
/// Gets or sets the name of this tag.
/// </summary>
public string Name{ get; set; }
/// <summary>
/// Deserializes an AccountTag instance from an xml element.
/// </summary>
/// <param name="node">The XmlElement instance from which to deserialize.</param>
public AccountTag( XmlElement node )
{
Name = Utility.GetAttribute( node, "name", "empty" );
Value = Utility.GetText( node, "" );
}
/// <summary>
/// Gets or sets the value of this tag.
/// </summary>
public string Value{ get; set; }
/// <summary>
/// Serializes this AccountTag instance to an XmlTextWriter.
/// </summary>
/// <param name="xml">The XmlTextWriter instance from which to serialize.</param>
public void Save( XmlTextWriter xml )
{
xml.WriteStartElement( "tag" );
xml.WriteAttributeString( "name", Name );
xml.WriteString( Value );
xml.WriteEndElement();
}
}
/// <summary>
/// Serializes this AccountTag instance to an XmlTextWriter.
/// </summary>
/// <param name="xml">The XmlTextWriter instance from which to serialize.</param>
public void Save(XmlTextWriter xml)
{
xml.WriteStartElement("tag");
xml.WriteAttributeString("name", Name);
xml.WriteString(Value);
xml.WriteEndElement();
}
}
}

View file

@ -5,99 +5,97 @@ using System.Xml;
namespace Server.Accounting
{
public class Accounts
{
private static Dictionary<string, IAccount> m_Accounts = new Dictionary<string, IAccount>();
public class Accounts
{
private static Dictionary<string, IAccount> m_Accounts = new Dictionary<string, IAccount>();
public static void Configure()
{
EventSink.WorldLoad += Load;
EventSink.WorldSave += Save;
}
static Accounts()
{
}
static Accounts()
{
}
public static int Count => m_Accounts.Count;
public static int Count => m_Accounts.Count;
public static void Configure()
{
EventSink.WorldLoad += Load;
EventSink.WorldSave += Save;
}
public static ICollection<IAccount> GetAccounts()
{
return m_Accounts.Values;
}
public static ICollection<IAccount> GetAccounts()
{
return m_Accounts.Values;
}
public static IAccount GetAccount( string username )
{
m_Accounts.TryGetValue( username, out IAccount a );
public static IAccount GetAccount(string username)
{
m_Accounts.TryGetValue(username, out IAccount a);
return a;
}
return a;
}
public static void Add( IAccount a )
{
m_Accounts[a.Username] = a;
}
public static void Add(IAccount a)
{
m_Accounts[a.Username] = a;
}
public static void Remove( string username )
{
m_Accounts.Remove( username );
}
public static void Remove(string username)
{
m_Accounts.Remove(username);
}
public static void Load()
{
m_Accounts = new Dictionary<string, IAccount>( 32, StringComparer.OrdinalIgnoreCase );
public static void Load()
{
m_Accounts = new Dictionary<string, IAccount>(32, StringComparer.OrdinalIgnoreCase);
string filePath = Path.Combine( "Saves/Accounts", "accounts.xml" );
string filePath = Path.Combine("Saves/Accounts", "accounts.xml");
if ( !File.Exists( filePath ) )
return;
if (!File.Exists(filePath))
return;
XmlDocument doc = new XmlDocument();
doc.Load( filePath );
XmlDocument doc = new XmlDocument();
doc.Load(filePath);
XmlElement root = doc["accounts"];
XmlElement root = doc["accounts"];
foreach ( XmlElement account in root.GetElementsByTagName( "account" ) )
{
try
{
Account acct = new Account( account );
}
catch
{
Console.WriteLine( "Warning: Account instance load failed" );
}
}
}
foreach (XmlElement account in root.GetElementsByTagName("account"))
try
{
Account acct = new Account(account);
}
catch
{
Console.WriteLine("Warning: Account instance load failed");
}
}
public static void Save( WorldSaveEventArgs e )
{
if ( !Directory.Exists( "Saves/Accounts" ) )
Directory.CreateDirectory( "Saves/Accounts" );
public static void Save(WorldSaveEventArgs e)
{
if (!Directory.Exists("Saves/Accounts"))
Directory.CreateDirectory("Saves/Accounts");
string filePath = Path.Combine( "Saves/Accounts", "accounts.xml" );
string filePath = Path.Combine("Saves/Accounts", "accounts.xml");
using ( StreamWriter op = new StreamWriter( filePath ) )
{
XmlTextWriter xml = new XmlTextWriter( op );
using (StreamWriter op = new StreamWriter(filePath))
{
XmlTextWriter xml = new XmlTextWriter(op);
xml.Formatting = Formatting.Indented;
xml.IndentChar = '\t';
xml.Indentation = 1;
xml.Formatting = Formatting.Indented;
xml.IndentChar = '\t';
xml.Indentation = 1;
xml.WriteStartDocument( true );
xml.WriteStartDocument(true);
xml.WriteStartElement( "accounts" );
xml.WriteStartElement("accounts");
xml.WriteAttributeString( "count", m_Accounts.Count.ToString() );
xml.WriteAttributeString("count", m_Accounts.Count.ToString());
foreach ( Account a in GetAccounts() )
a.Save( xml );
foreach (Account a in GetAccounts())
a.Save(xml);
xml.WriteEndElement();
xml.WriteEndElement();
xml.Close();
}
}
}
}
xml.Close();
}
}
}
}

View file

@ -1,303 +1,156 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
namespace Server
{
public class Firewall
{
#region Firewall Entries
public interface IFirewallEntry
{
bool IsBlocked( IPAddress address );
}
public class Firewall
{
static Firewall()
{
List = new List<IFirewallEntry>();
public class IPFirewallEntry : IFirewallEntry
{
IPAddress m_Address;
public IPFirewallEntry( IPAddress address )
{
m_Address = address;
}
string path = "firewall.cfg";
public bool IsBlocked( IPAddress address )
{
return m_Address.Equals( address );
}
if (File.Exists(path))
using (StreamReader ip = new StreamReader(path))
{
string line;
public override string ToString()
{
return m_Address.ToString();
}
while ((line = ip.ReadLine()) != null)
{
line = line.Trim();
public override bool Equals( object obj )
{
if ( obj is IPAddress )
{
return obj.Equals( m_Address );
}
if ( obj is string s )
{
if ( IPAddress.TryParse( s, out IPAddress otherAddress ) )
return otherAddress.Equals( m_Address );
}
else if ( obj is IPFirewallEntry entry )
{
return m_Address.Equals( entry.m_Address );
}
if (line.Length == 0)
continue;
return false;
}
List.Add(ToFirewallEntry(line));
public override int GetHashCode()
{
return m_Address.GetHashCode();
}
}
/*
object toAdd;
public class CIDRFirewallEntry : IFirewallEntry
{
IPAddress m_CIDRPrefix;
int m_CIDRLength;
IPAddress addr;
if ( IPAddress.TryParse( line, out addr ) )
toAdd = addr;
else
toAdd = line;
public CIDRFirewallEntry( IPAddress cidrPrefix, int cidrLength )
{
m_CIDRPrefix = cidrPrefix;
m_CIDRLength = cidrLength;
}
m_Blocked.Add( toAdd.ToString() );
* */
}
}
}
public bool IsBlocked( IPAddress address )
{
return Utility.IPMatchCIDR( m_CIDRPrefix, address, m_CIDRLength );
}
public static List<IFirewallEntry> List{ get; }
public override string ToString()
{
return $"{m_CIDRPrefix}/{m_CIDRLength}";
}
public static IFirewallEntry ToFirewallEntry(object entry)
{
if (entry is IFirewallEntry firewallEntry)
return firewallEntry;
if (entry is IPAddress address)
return new IPFirewallEntry(address);
if (entry is string s)
return ToFirewallEntry(s);
public override bool Equals( object obj )
{
if ( obj is string entry )
{
string[] str = entry.Split( '/' );
return null;
}
if ( str.Length == 2 )
{
if ( IPAddress.TryParse( str[0], out IPAddress cidrPrefix ) )
{
if ( int.TryParse( str[1], out int cidrLength ) )
return m_CIDRPrefix.Equals( cidrPrefix ) && m_CIDRLength.Equals( cidrLength );
}
}
}
else if ( obj is CIDRFirewallEntry cidrEntry )
{
return m_CIDRPrefix.Equals( cidrEntry.m_CIDRPrefix ) && m_CIDRLength.Equals( cidrEntry.m_CIDRLength );
}
public static IFirewallEntry ToFirewallEntry(string entry)
{
if (IPAddress.TryParse(entry, out IPAddress addr))
return new IPFirewallEntry(addr);
return false;
}
//Try CIDR parse
string[] str = entry.Split('/');
public override int GetHashCode()
{
return m_CIDRPrefix.GetHashCode() ^ m_CIDRLength.GetHashCode();
}
}
if (str.Length == 2)
if (IPAddress.TryParse(str[0], out IPAddress cidrPrefix))
if (int.TryParse(str[1], out int cidrLength))
return new CIDRFirewallEntry(cidrPrefix, cidrLength);
public class WildcardIPFirewallEntry : IFirewallEntry
{
string m_Entry;
return new WildcardIPFirewallEntry(entry);
}
bool m_Valid = true;
public static void RemoveAt(int index)
{
List.RemoveAt(index);
Save();
}
public WildcardIPFirewallEntry( string entry )
{
m_Entry = entry;
}
public static void Remove(object obj)
{
IFirewallEntry entry = ToFirewallEntry(obj);
public bool IsBlocked( IPAddress address )
{
if ( !m_Valid )
return false; //Why process if it's invalid? it'll return false anyway after processing it.
if (entry != null)
{
List.Remove(entry);
Save();
}
}
return Utility.IPMatch( m_Entry, address, ref m_Valid );
}
public static void Add(object obj)
{
if (obj is IPAddress address)
Add(address);
else if (obj is string s)
Add(s);
else if (obj is IFirewallEntry entry)
Add(entry);
}
public override string ToString()
{
return m_Entry;
}
public static void Add(IFirewallEntry entry)
{
if (!List.Contains(entry))
List.Add(entry);
public override bool Equals( object obj )
{
if ( obj is string )
return obj.Equals( m_Entry );
Save();
}
return obj is WildcardIPFirewallEntry entry && m_Entry.Equals( entry.m_Entry );
}
public static void Add(string pattern)
{
IFirewallEntry entry = ToFirewallEntry(pattern);
public override int GetHashCode()
{
return m_Entry.GetHashCode();
}
}
#endregion
if (!List.Contains(entry))
List.Add(entry);
static Firewall()
{
List = new List<IFirewallEntry>();
Save();
}
string path = "firewall.cfg";
public static void Add(IPAddress ip)
{
IFirewallEntry entry = new IPFirewallEntry(ip);
if ( File.Exists( path ) )
{
using ( StreamReader ip = new StreamReader( path ) )
{
string line;
if (!List.Contains(entry))
List.Add(entry);
while ( (line = ip.ReadLine()) != null )
{
line = line.Trim();
Save();
}
if ( line.Length == 0 )
continue;
public static void Save()
{
string path = "firewall.cfg";
List.Add( ToFirewallEntry( line ) );
using (StreamWriter op = new StreamWriter(path))
{
for (int i = 0; i < List.Count; ++i)
op.WriteLine(List[i]);
}
}
/*
object toAdd;
public static bool IsBlocked(IPAddress ip)
{
for (int i = 0; i < List.Count; i++)
if (List[i].IsBlocked(ip))
return true;
IPAddress addr;
if ( IPAddress.TryParse( line, out addr ) )
toAdd = addr;
else
toAdd = line;
return false;
/*
bool contains = false;
m_Blocked.Add( toAdd.ToString() );
* */
}
}
}
}
public static List<IFirewallEntry> List { get; }
public static IFirewallEntry ToFirewallEntry( object entry )
{
if ( entry is IFirewallEntry firewallEntry )
return firewallEntry;
if ( entry is IPAddress address )
return new IPFirewallEntry( address );
if ( entry is string s )
return ToFirewallEntry( s );
return null;
}
public static IFirewallEntry ToFirewallEntry( string entry )
{
if ( IPAddress.TryParse( entry, out IPAddress addr ) )
return new IPFirewallEntry( addr );
//Try CIDR parse
string[] str = entry.Split( '/' );
if ( str.Length == 2 )
{
if ( IPAddress.TryParse( str[0], out IPAddress cidrPrefix ) )
{
if ( int.TryParse( str[1], out int cidrLength ) )
return new CIDRFirewallEntry( cidrPrefix, cidrLength );
}
}
return new WildcardIPFirewallEntry( entry );
}
public static void RemoveAt( int index )
{
List.RemoveAt( index );
Save();
}
public static void Remove( object obj )
{
IFirewallEntry entry = ToFirewallEntry( obj );
if ( entry != null )
{
List.Remove( entry );
Save();
}
}
public static void Add( object obj )
{
if ( obj is IPAddress address )
Add( address );
else if ( obj is string s )
Add( s );
else if ( obj is IFirewallEntry entry )
Add( entry );
}
public static void Add( IFirewallEntry entry )
{
if ( !List.Contains( entry ) )
List.Add( entry );
Save();
}
public static void Add( string pattern )
{
IFirewallEntry entry = ToFirewallEntry( pattern );
if ( !List.Contains( entry ) )
List.Add( entry );
Save();
}
public static void Add( IPAddress ip )
{
IFirewallEntry entry = new IPFirewallEntry( ip );
if ( !List.Contains( entry ) )
List.Add( entry );
Save();
}
public static void Save()
{
string path = "firewall.cfg";
using ( StreamWriter op = new StreamWriter( path ) )
{
for ( int i = 0; i < List.Count; ++i )
op.WriteLine( List[i] );
}
}
public static bool IsBlocked( IPAddress ip )
{
for( int i = 0; i < List.Count; i++ )
{
if ( List[i].IsBlocked( ip ) )
return true;
}
return false;
/*
bool contains = false;
for ( int i = 0; !contains && i < m_Blocked.Count; ++i )
{
if ( m_Blocked[i] is IPAddress )
contains = ip.Equals( m_Blocked[i] );
for ( int i = 0; !contains && i < m_Blocked.Count; ++i )
{
if ( m_Blocked[i] is IPAddress )
contains = ip.Equals( m_Blocked[i] );
else if ( m_Blocked[i] is String )
{
string s = (string)m_Blocked[i];
@ -307,10 +160,144 @@ namespace Server
if ( !contains )
contains = Utility.IPMatch( s, ip );
}
}
}
return contains;
* */
}
}
}
return contains;
* */
}
#region Firewall Entries
public interface IFirewallEntry
{
bool IsBlocked(IPAddress address);
}
public class IPFirewallEntry : IFirewallEntry
{
private IPAddress m_Address;
public IPFirewallEntry(IPAddress address)
{
m_Address = address;
}
public bool IsBlocked(IPAddress address)
{
return m_Address.Equals(address);
}
public override string ToString()
{
return m_Address.ToString();
}
public override bool Equals(object obj)
{
if (obj is IPAddress) return obj.Equals(m_Address);
if (obj is string s)
{
if (IPAddress.TryParse(s, out IPAddress otherAddress))
return otherAddress.Equals(m_Address);
}
else if (obj is IPFirewallEntry entry)
{
return m_Address.Equals(entry.m_Address);
}
return false;
}
public override int GetHashCode()
{
return m_Address.GetHashCode();
}
}
public class CIDRFirewallEntry : IFirewallEntry
{
private int m_CIDRLength;
private IPAddress m_CIDRPrefix;
public CIDRFirewallEntry(IPAddress cidrPrefix, int cidrLength)
{
m_CIDRPrefix = cidrPrefix;
m_CIDRLength = cidrLength;
}
public bool IsBlocked(IPAddress address)
{
return Utility.IPMatchCIDR(m_CIDRPrefix, address, m_CIDRLength);
}
public override string ToString()
{
return $"{m_CIDRPrefix}/{m_CIDRLength}";
}
public override bool Equals(object obj)
{
if (obj is string entry)
{
string[] str = entry.Split('/');
if (str.Length == 2)
if (IPAddress.TryParse(str[0], out IPAddress cidrPrefix))
if (int.TryParse(str[1], out int cidrLength))
return m_CIDRPrefix.Equals(cidrPrefix) && m_CIDRLength.Equals(cidrLength);
}
else if (obj is CIDRFirewallEntry cidrEntry)
{
return m_CIDRPrefix.Equals(cidrEntry.m_CIDRPrefix) && m_CIDRLength.Equals(cidrEntry.m_CIDRLength);
}
return false;
}
public override int GetHashCode()
{
return m_CIDRPrefix.GetHashCode() ^ m_CIDRLength.GetHashCode();
}
}
public class WildcardIPFirewallEntry : IFirewallEntry
{
private string m_Entry;
private bool m_Valid = true;
public WildcardIPFirewallEntry(string entry)
{
m_Entry = entry;
}
public bool IsBlocked(IPAddress address)
{
if (!m_Valid)
return false; //Why process if it's invalid? it'll return false anyway after processing it.
return Utility.IPMatch(m_Entry, address, ref m_Valid);
}
public override string ToString()
{
return m_Entry;
}
public override bool Equals(object obj)
{
if (obj is string)
return obj.Equals(m_Entry);
return obj is WildcardIPFirewallEntry entry && m_Entry.Equals(entry.m_Entry);
}
public override int GetHashCode()
{
return m_Entry.GetHashCode();
}
}
#endregion
}
}

View file

@ -4,51 +4,50 @@ using Server.Network;
namespace Server.Misc
{
public class IPLimiter
{
public static bool Enabled = true;
public static bool SocketBlock = true; // true to block at connection, false to block at login request
public class IPLimiter
{
public static bool Enabled = true;
public static bool SocketBlock = true; // true to block at connection, false to block at login request
public static int MaxAddresses = 10;
public static IPAddress[] Exemptions = {
//IPAddress.Parse( "127.0.0.1" ),
};
public static int MaxAddresses = 10;
public static bool IsExempt( IPAddress ip )
{
for ( int i = 0; i < Exemptions.Length; i++ )
{
if ( ip.Equals( Exemptions[i] ) )
return true;
}
public static IPAddress[] Exemptions =
{
//IPAddress.Parse( "127.0.0.1" ),
};
return false;
}
public static bool IsExempt(IPAddress ip)
{
for (int i = 0; i < Exemptions.Length; i++)
if (ip.Equals(Exemptions[i]))
return true;
public static bool Verify( IPAddress ourAddress )
{
if ( !Enabled || IsExempt( ourAddress ) )
return true;
return false;
}
List<NetState> netStates = NetState.Instances;
public static bool Verify(IPAddress ourAddress)
{
if (!Enabled || IsExempt(ourAddress))
return true;
int count = 0;
List<NetState> netStates = NetState.Instances;
for ( int i = 0; i < netStates.Count; ++i )
{
NetState compState = netStates[i];
int count = 0;
if ( ourAddress.Equals( compState.Address ) )
{
++count;
for (int i = 0; i < netStates.Count; ++i)
{
NetState compState = netStates[i];
if ( count >= MaxAddresses )
return false;
}
}
if (ourAddress.Equals(compState.Address))
{
++count;
return true;
}
}
if (count >= MaxAddresses)
return false;
}
}
return true;
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -2,33 +2,33 @@ using System;
namespace Server
{
public class UsageAttribute : Attribute
{
public string Usage { get; }
public class UsageAttribute : Attribute
{
public UsageAttribute(string usage)
{
Usage = usage;
}
public UsageAttribute( string usage )
{
Usage = usage;
}
}
public string Usage{ get; }
}
public class DescriptionAttribute : Attribute
{
public string Description { get; }
public class DescriptionAttribute : Attribute
{
public DescriptionAttribute(string description)
{
Description = description;
}
public DescriptionAttribute( string description )
{
Description = description;
}
}
public string Description{ get; }
}
public class AliasesAttribute : Attribute
{
public string[] Aliases { get; }
public class AliasesAttribute : Attribute
{
public AliasesAttribute(params string[] aliases)
{
Aliases = aliases;
}
public AliasesAttribute( params string[] aliases )
{
Aliases = aliases;
}
}
public string[] Aliases{ get; }
}
}

View file

@ -1,423 +1,423 @@
using System;
using System.Reflection;
using System.Collections;
using System.Reflection;
using Server.Commands.Generic;
using Server.Gumps;
using Server.Network;
using Server.Commands.Generic;
namespace Server.Commands
{
public class Batch : BaseCommand
{
public BaseCommandImplementor Scope { get; set; }
public class Batch : BaseCommand
{
public Batch()
{
Commands = new[] { "Batch" };
ListOptimized = true;
public string Condition { get; set; }
BatchCommands = new ArrayList();
Condition = "";
}
public ArrayList BatchCommands { get; }
public BaseCommandImplementor Scope{ get; set; }
public Batch()
{
Commands = new[]{ "Batch" };
ListOptimized = true;
public string Condition{ get; set; }
BatchCommands = new ArrayList();
Condition = "";
}
public ArrayList BatchCommands{ get; }
public override void ExecuteList( CommandEventArgs e, ArrayList list )
{
if ( list.Count == 0 )
{
LogFailure( "Nothing was found to use this command on." );
return;
}
public override void ExecuteList(CommandEventArgs e, ArrayList list)
{
if (list.Count == 0)
{
LogFailure("Nothing was found to use this command on.");
return;
}
try
{
BaseCommand[] commands = new BaseCommand[BatchCommands.Count];
CommandEventArgs[] eventArgs = new CommandEventArgs[BatchCommands.Count];
try
{
BaseCommand[] commands = new BaseCommand[BatchCommands.Count];
CommandEventArgs[] eventArgs = new CommandEventArgs[BatchCommands.Count];
for ( int i = 0; i < BatchCommands.Count; ++i )
{
BatchCommand bc = (BatchCommand)BatchCommands[i];
bc.GetDetails( out string commandString, out string argString, out string[] args );
BaseCommand command = Scope.Commands[commandString];
commands[i] = command;
eventArgs[i] = new CommandEventArgs( e.Mobile, commandString, argString, args );
if ( command == null )
{
e.Mobile.SendMessage( "That is either an invalid command name or one that does not support this modifier: {0}.", commandString );
return;
}
if ( e.Mobile.AccessLevel < command.AccessLevel )
{
e.Mobile.SendMessage( "You do not have access to that command: {0}.", commandString );
return;
}
if ( !command.ValidateArgs( Scope, eventArgs[i] ) )
{
return;
}
}
for ( int i = 0; i < commands.Length; ++i )
{
BaseCommand command = commands[i];
BatchCommand bc = (BatchCommand)BatchCommands[i];
if ( list.Count > 20 )
CommandLogging.Enabled = false;
ArrayList usedList;
if ( Utility.InsensitiveCompare( bc.Object, "Current" ) == 0 )
{
usedList = list;
}
else
{
Hashtable propertyChains = new Hashtable();
usedList = new ArrayList( list.Count );
for ( int j = 0; j < list.Count; ++j )
{
object obj = list[j];
if ( obj == null )
continue;
Type type = obj.GetType();
PropertyInfo[] chain = (PropertyInfo[])propertyChains[type];
string failReason = "";
if ( chain == null && !propertyChains.Contains( type ) )
propertyChains[type] = chain = Properties.GetPropertyInfoChain( e.Mobile, type, bc.Object, PropertyAccess.Read, ref failReason );
if ( chain == null )
continue;
PropertyInfo endProp = Properties.GetPropertyInfo( ref obj, chain, ref failReason );
if ( endProp == null )
continue;
try
{
obj = endProp.GetValue( obj, null );
if ( obj != null )
usedList.Add( obj );
}
catch
{
}
}
}
command.ExecuteList( eventArgs[i], usedList );
if ( list.Count > 20 )
CommandLogging.Enabled = true;
command.Flush( e.Mobile, list.Count > 20 );
}
}
catch ( Exception ex )
{
e.Mobile.SendMessage( ex.Message );
}
}
public bool Run( Mobile from )
{
if ( Scope == null )
{
from.SendMessage( "You must select the batch command scope." );
return false;
}
if ( Condition.Length > 0 && !Scope.SupportsConditionals )
{
from.SendMessage( "This command scope does not support conditionals." );
return false;
}
if ( Condition.Length > 0 && !Utility.InsensitiveStartsWith( Condition, "where" ) )
{
from.SendMessage( "The condition field must start with \"where\"." );
return false;
}
string[] args = CommandSystem.Split( Condition );
Scope.Process( from, this, args );
return true;
}
public static void Initialize()
{
CommandSystem.Register( "Batch", AccessLevel.Counselor, Batch_OnCommand );
}
[Usage( "Batch" )]
[Description( "Allows multiple commands to be run at the same time." )]
public static void Batch_OnCommand( CommandEventArgs e )
{
e.Mobile.SendGump( new BatchGump( e.Mobile, new Batch() ) );
}
}
public class BatchCommand
{
public string Command { get; set; }
public string Object { get; set; }
public void GetDetails( out string command, out string argString, out string[] args )
{
int indexOf = Command.IndexOf( ' ' );
if ( indexOf >= 0 )
{
argString = Command.Substring( indexOf + 1 );
command = Command.Substring( 0, indexOf );
args = CommandSystem.Split( argString );
}
else
{
argString = "";
command = Command.ToLower();
args = new string[0];
}
}
public BatchCommand( string command, string obj )
{
Command = command;
Object = obj;
}
}
public class BatchGump : BaseGridGump
{
private Mobile m_From;
private Batch m_Batch;
public BatchGump( Mobile from, Batch batch ) : base( 30, 30 )
{
m_From = from;
m_Batch = batch;
Render();
}
public void Render()
{
AddNewPage();
/* Header */
AddEntryHeader( 20 );
AddEntryHtml( 180, Center( "Batch Commands" ) );
AddEntryHeader( 20 );
AddNewLine();
AddEntryHeader( 9 );
AddEntryLabel( 191, "Run Batch" );
AddEntryButton( 20, ArrowRightID1, ArrowRightID2, GetButtonID( 1, 0, 0 ), ArrowRightWidth, ArrowRightHeight );
AddNewLine();
AddBlankLine();
/* Scope */
AddEntryHeader( 20 );
AddEntryHtml( 180, Center( "Scope" ) );
AddEntryHeader( 20 );
AddNewLine();
AddEntryHeader( 9 );
AddEntryLabel( 191, m_Batch.Scope == null ? "Select Scope" : m_Batch.Scope.Accessors[0] );
AddEntryButton( 20, ArrowRightID1, ArrowRightID2, GetButtonID( 1, 0, 1 ), ArrowRightWidth, ArrowRightHeight );
AddNewLine();
AddBlankLine();
/* Condition */
AddEntryHeader( 20 );
AddEntryHtml( 180, Center( "Condition" ) );
AddEntryHeader( 20 );
AddNewLine();
AddEntryHeader( 9 );
AddEntryText( 202, 0, m_Batch.Condition );
AddEntryHeader( 9 );
AddNewLine();
AddBlankLine();
/* Commands */
AddEntryHeader( 20 );
AddEntryHtml( 180, Center( "Commands" ) );
AddEntryHeader( 20 );
for ( int i = 0; i < m_Batch.BatchCommands.Count; ++i )
{
BatchCommand bc = (BatchCommand)m_Batch.BatchCommands[i];
AddNewLine();
AddImageTiled( CurrentX, CurrentY, 9, 2, 0x24A8 );
AddImageTiled( CurrentX, CurrentY + 2, 2, EntryHeight + OffsetSize + EntryHeight - 4, 0x24A8 );
AddImageTiled( CurrentX, CurrentY + EntryHeight + OffsetSize + EntryHeight - 2, 9, 2, 0x24A8 );
AddImageTiled( CurrentX + 3, CurrentY + 3, 6, EntryHeight + EntryHeight - 4 - OffsetSize, HeaderGumpID );
IncreaseX( 9 );
AddEntryText( 202, 1+(i*2), bc.Command );
AddEntryHeader( 9, 2 );
AddNewLine();
IncreaseX( 9 );
AddEntryText( 202, 2+(i*2), bc.Object );
}
AddNewLine();
AddEntryHeader( 9 );
AddEntryLabel( 191, "Add New Command" );
AddEntryButton( 20, ArrowRightID1, ArrowRightID2, GetButtonID( 1, 0, 2 ), ArrowRightWidth, ArrowRightHeight );
FinishPage();
}
public override void OnResponse( NetState sender, RelayInfo info )
{
if ( !SplitButtonID( info.ButtonID, 1, out int type, out int index ) )
return;
TextRelay entry = info.GetTextEntry( 0 );
if ( entry != null )
m_Batch.Condition = entry.Text;
for ( int i = m_Batch.BatchCommands.Count - 1; i >= 0; --i )
{
BatchCommand sc = (BatchCommand)m_Batch.BatchCommands[i];
entry = info.GetTextEntry( 1 + (i * 2) );
if ( entry != null )
sc.Command = entry.Text;
entry = info.GetTextEntry( 2 + (i * 2) );
if ( entry != null )
sc.Object = entry.Text;
if ( sc.Command.Length == 0 && sc.Object.Length == 0 )
m_Batch.BatchCommands.RemoveAt( i );
}
switch ( type )
{
case 0: // main
{
switch ( index )
{
case 0: // run
{
m_Batch.Run( m_From );
break;
}
case 1: // set scope
{
m_From.SendGump( new BatchScopeGump( m_From, m_Batch ) );
return;
}
case 2: // add command
{
m_Batch.BatchCommands.Add( new BatchCommand( "", "" ) );
break;
}
}
break;
}
}
m_From.SendGump( new BatchGump( m_From, m_Batch ) );
}
}
public class BatchScopeGump : BaseGridGump
{
private Mobile m_From;
private Batch m_Batch;
public BatchScopeGump( Mobile from, Batch batch ) : base( 30, 30 )
{
m_From = from;
m_Batch = batch;
Render();
}
public void Render()
{
AddNewPage();
/* Header */
AddEntryHeader( 20 );
AddEntryHtml( 140, Center( "Change Scope" ) );
AddEntryHeader( 20 );
/* Options */
for ( int i = 0; i < BaseCommandImplementor.Implementors.Count; ++i )
{
BaseCommandImplementor impl = BaseCommandImplementor.Implementors[i];
if ( m_From.AccessLevel < impl.AccessLevel )
continue;
AddNewLine();
AddEntryLabel( 20 + OffsetSize + 140, impl.Accessors[0] );
AddEntryButton( 20, ArrowRightID1, ArrowRightID2, GetButtonID( 1, 0, i ), ArrowRightWidth, ArrowRightHeight );
}
FinishPage();
}
public override void OnResponse( NetState sender, RelayInfo info )
{
if ( SplitButtonID( info.ButtonID, 1, out int type, out int index ) )
{
switch ( type )
{
case 0:
{
if ( index < BaseCommandImplementor.Implementors.Count )
{
BaseCommandImplementor impl = BaseCommandImplementor.Implementors[index];
if ( m_From.AccessLevel >= impl.AccessLevel )
m_Batch.Scope = impl;
}
break;
}
}
}
m_From.SendGump( new BatchGump( m_From, m_Batch ) );
}
}
}
for (int i = 0; i < BatchCommands.Count; ++i)
{
BatchCommand bc = (BatchCommand)BatchCommands[i];
bc.GetDetails(out string commandString, out string argString, out string[] args);
BaseCommand command = Scope.Commands[commandString];
commands[i] = command;
eventArgs[i] = new CommandEventArgs(e.Mobile, commandString, argString, args);
if (command == null)
{
e.Mobile.SendMessage(
"That is either an invalid command name or one that does not support this modifier: {0}.",
commandString);
return;
}
if (e.Mobile.AccessLevel < command.AccessLevel)
{
e.Mobile.SendMessage("You do not have access to that command: {0}.", commandString);
return;
}
if (!command.ValidateArgs(Scope, eventArgs[i])) return;
}
for (int i = 0; i < commands.Length; ++i)
{
BaseCommand command = commands[i];
BatchCommand bc = (BatchCommand)BatchCommands[i];
if (list.Count > 20)
CommandLogging.Enabled = false;
ArrayList usedList;
if (Utility.InsensitiveCompare(bc.Object, "Current") == 0)
{
usedList = list;
}
else
{
Hashtable propertyChains = new Hashtable();
usedList = new ArrayList(list.Count);
for (int j = 0; j < list.Count; ++j)
{
object obj = list[j];
if (obj == null)
continue;
Type type = obj.GetType();
PropertyInfo[] chain = (PropertyInfo[])propertyChains[type];
string failReason = "";
if (chain == null && !propertyChains.Contains(type))
propertyChains[type] = chain = Properties.GetPropertyInfoChain(e.Mobile, type, bc.Object,
PropertyAccess.Read, ref failReason);
if (chain == null)
continue;
PropertyInfo endProp = Properties.GetPropertyInfo(ref obj, chain, ref failReason);
if (endProp == null)
continue;
try
{
obj = endProp.GetValue(obj, null);
if (obj != null)
usedList.Add(obj);
}
catch
{
}
}
}
command.ExecuteList(eventArgs[i], usedList);
if (list.Count > 20)
CommandLogging.Enabled = true;
command.Flush(e.Mobile, list.Count > 20);
}
}
catch (Exception ex)
{
e.Mobile.SendMessage(ex.Message);
}
}
public bool Run(Mobile from)
{
if (Scope == null)
{
from.SendMessage("You must select the batch command scope.");
return false;
}
if (Condition.Length > 0 && !Scope.SupportsConditionals)
{
from.SendMessage("This command scope does not support conditionals.");
return false;
}
if (Condition.Length > 0 && !Utility.InsensitiveStartsWith(Condition, "where"))
{
from.SendMessage("The condition field must start with \"where\".");
return false;
}
string[] args = CommandSystem.Split(Condition);
Scope.Process(from, this, args);
return true;
}
public static void Initialize()
{
CommandSystem.Register("Batch", AccessLevel.Counselor, Batch_OnCommand);
}
[Usage("Batch")]
[Description("Allows multiple commands to be run at the same time.")]
public static void Batch_OnCommand(CommandEventArgs e)
{
e.Mobile.SendGump(new BatchGump(e.Mobile, new Batch()));
}
}
public class BatchCommand
{
public BatchCommand(string command, string obj)
{
Command = command;
Object = obj;
}
public string Command{ get; set; }
public string Object{ get; set; }
public void GetDetails(out string command, out string argString, out string[] args)
{
int indexOf = Command.IndexOf(' ');
if (indexOf >= 0)
{
argString = Command.Substring(indexOf + 1);
command = Command.Substring(0, indexOf);
args = CommandSystem.Split(argString);
}
else
{
argString = "";
command = Command.ToLower();
args = new string[0];
}
}
}
public class BatchGump : BaseGridGump
{
private Batch m_Batch;
private Mobile m_From;
public BatchGump(Mobile from, Batch batch) : base(30, 30)
{
m_From = from;
m_Batch = batch;
Render();
}
public void Render()
{
AddNewPage();
/* Header */
AddEntryHeader(20);
AddEntryHtml(180, Center("Batch Commands"));
AddEntryHeader(20);
AddNewLine();
AddEntryHeader(9);
AddEntryLabel(191, "Run Batch");
AddEntryButton(20, ArrowRightID1, ArrowRightID2, GetButtonID(1, 0, 0), ArrowRightWidth, ArrowRightHeight);
AddNewLine();
AddBlankLine();
/* Scope */
AddEntryHeader(20);
AddEntryHtml(180, Center("Scope"));
AddEntryHeader(20);
AddNewLine();
AddEntryHeader(9);
AddEntryLabel(191, m_Batch.Scope == null ? "Select Scope" : m_Batch.Scope.Accessors[0]);
AddEntryButton(20, ArrowRightID1, ArrowRightID2, GetButtonID(1, 0, 1), ArrowRightWidth, ArrowRightHeight);
AddNewLine();
AddBlankLine();
/* Condition */
AddEntryHeader(20);
AddEntryHtml(180, Center("Condition"));
AddEntryHeader(20);
AddNewLine();
AddEntryHeader(9);
AddEntryText(202, 0, m_Batch.Condition);
AddEntryHeader(9);
AddNewLine();
AddBlankLine();
/* Commands */
AddEntryHeader(20);
AddEntryHtml(180, Center("Commands"));
AddEntryHeader(20);
for (int i = 0; i < m_Batch.BatchCommands.Count; ++i)
{
BatchCommand bc = (BatchCommand)m_Batch.BatchCommands[i];
AddNewLine();
AddImageTiled(CurrentX, CurrentY, 9, 2, 0x24A8);
AddImageTiled(CurrentX, CurrentY + 2, 2, EntryHeight + OffsetSize + EntryHeight - 4, 0x24A8);
AddImageTiled(CurrentX, CurrentY + EntryHeight + OffsetSize + EntryHeight - 2, 9, 2, 0x24A8);
AddImageTiled(CurrentX + 3, CurrentY + 3, 6, EntryHeight + EntryHeight - 4 - OffsetSize, HeaderGumpID);
IncreaseX(9);
AddEntryText(202, 1 + i * 2, bc.Command);
AddEntryHeader(9, 2);
AddNewLine();
IncreaseX(9);
AddEntryText(202, 2 + i * 2, bc.Object);
}
AddNewLine();
AddEntryHeader(9);
AddEntryLabel(191, "Add New Command");
AddEntryButton(20, ArrowRightID1, ArrowRightID2, GetButtonID(1, 0, 2), ArrowRightWidth, ArrowRightHeight);
FinishPage();
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (!SplitButtonID(info.ButtonID, 1, out int type, out int index))
return;
TextRelay entry = info.GetTextEntry(0);
if (entry != null)
m_Batch.Condition = entry.Text;
for (int i = m_Batch.BatchCommands.Count - 1; i >= 0; --i)
{
BatchCommand sc = (BatchCommand)m_Batch.BatchCommands[i];
entry = info.GetTextEntry(1 + i * 2);
if (entry != null)
sc.Command = entry.Text;
entry = info.GetTextEntry(2 + i * 2);
if (entry != null)
sc.Object = entry.Text;
if (sc.Command.Length == 0 && sc.Object.Length == 0)
m_Batch.BatchCommands.RemoveAt(i);
}
switch (type)
{
case 0: // main
{
switch (index)
{
case 0: // run
{
m_Batch.Run(m_From);
break;
}
case 1: // set scope
{
m_From.SendGump(new BatchScopeGump(m_From, m_Batch));
return;
}
case 2: // add command
{
m_Batch.BatchCommands.Add(new BatchCommand("", ""));
break;
}
}
break;
}
}
m_From.SendGump(new BatchGump(m_From, m_Batch));
}
}
public class BatchScopeGump : BaseGridGump
{
private Batch m_Batch;
private Mobile m_From;
public BatchScopeGump(Mobile from, Batch batch) : base(30, 30)
{
m_From = from;
m_Batch = batch;
Render();
}
public void Render()
{
AddNewPage();
/* Header */
AddEntryHeader(20);
AddEntryHtml(140, Center("Change Scope"));
AddEntryHeader(20);
/* Options */
for (int i = 0; i < BaseCommandImplementor.Implementors.Count; ++i)
{
BaseCommandImplementor impl = BaseCommandImplementor.Implementors[i];
if (m_From.AccessLevel < impl.AccessLevel)
continue;
AddNewLine();
AddEntryLabel(20 + OffsetSize + 140, impl.Accessors[0]);
AddEntryButton(20, ArrowRightID1, ArrowRightID2, GetButtonID(1, 0, i), ArrowRightWidth, ArrowRightHeight);
}
FinishPage();
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (SplitButtonID(info.ButtonID, 1, out int type, out int index))
switch (type)
{
case 0:
{
if (index < BaseCommandImplementor.Implementors.Count)
{
BaseCommandImplementor impl = BaseCommandImplementor.Implementors[index];
if (m_From.AccessLevel >= impl.AccessLevel)
m_Batch.Scope = impl;
}
break;
}
}
m_From.SendGump(new BatchGump(m_From, m_Batch));
}
}
}

View file

@ -2,64 +2,65 @@ using Server.Targeting;
namespace Server
{
public delegate void BoundingBoxCallback( Mobile from, Map map, Point3D start, Point3D end, object state );
public delegate void BoundingBoxCallback(Mobile from, Map map, Point3D start, Point3D end, object state);
public class BoundingBoxPicker
{
public static void Begin( Mobile from, BoundingBoxCallback callback, object state )
{
from.SendMessage( "Target the first location of the bounding box." );
from.Target = new PickTarget( callback, state );
}
public class BoundingBoxPicker
{
public static void Begin(Mobile from, BoundingBoxCallback callback, object state)
{
from.SendMessage("Target the first location of the bounding box.");
from.Target = new PickTarget(callback, state);
}
private class PickTarget : Target
{
private Point3D m_Store;
private bool m_First;
private Map m_Map;
private BoundingBoxCallback m_Callback;
private object m_State;
private class PickTarget : Target
{
private BoundingBoxCallback m_Callback;
private bool m_First;
private Map m_Map;
private object m_State;
private Point3D m_Store;
public PickTarget( BoundingBoxCallback callback, object state ) : this( Point3D.Zero, true, null, callback, state )
{
}
public PickTarget(BoundingBoxCallback callback, object state) : this(Point3D.Zero, true, null, callback, state)
{
}
public PickTarget( Point3D store, bool first, Map map, BoundingBoxCallback callback, object state ) : base( -1, true, TargetFlags.None )
{
m_Store = store;
m_First = first;
m_Map = map;
m_Callback = callback;
m_State = state;
}
public PickTarget(Point3D store, bool first, Map map, BoundingBoxCallback callback, object state) : base(-1,
true, TargetFlags.None)
{
m_Store = store;
m_First = first;
m_Map = map;
m_Callback = callback;
m_State = state;
}
protected override void OnTarget( Mobile from, object targeted )
{
if ( !(targeted is IPoint3D p) )
return;
protected override void OnTarget(Mobile from, object targeted)
{
if (!(targeted is IPoint3D p))
return;
if ( p is Item item )
p = item.GetWorldTop();
if (p is Item item)
p = item.GetWorldTop();
if ( m_First )
{
from.SendMessage( "Target another location to complete the bounding box." );
from.Target = new PickTarget( new Point3D( p ), false, from.Map, m_Callback, m_State );
}
else if ( from.Map != m_Map )
{
from.SendMessage( "Both locations must reside on the same map." );
}
else if ( m_Map != null && m_Map != Map.Internal && m_Callback != null )
{
Point3D start = m_Store;
Point3D end = new Point3D( p );
if (m_First)
{
from.SendMessage("Target another location to complete the bounding box.");
from.Target = new PickTarget(new Point3D(p), false, from.Map, m_Callback, m_State);
}
else if (from.Map != m_Map)
{
from.SendMessage("Both locations must reside on the same map.");
}
else if (m_Map != null && m_Map != Map.Internal && m_Callback != null)
{
Point3D start = m_Store;
Point3D end = new Point3D(p);
Utility.FixPoints( ref start, ref end );
Utility.FixPoints(ref start, ref end);
m_Callback( from, m_Map, start, end, m_State );
}
}
}
}
}
m_Callback(from, m_Map, start, end, m_State);
}
}
}
}
}

View file

@ -6,84 +6,82 @@ using Server.Network;
namespace Server.Commands
{
public class ConvertPlayers
{
public static void Initialize()
{
CommandSystem.Register( "ConvertPlayers", AccessLevel.Administrator, Convert_OnCommand );
}
public static void Convert_OnCommand( CommandEventArgs e )
{
e.Mobile.SendMessage( "Converting all players to PlayerMobile. You will be disconnected. Please Restart the server after the world has finished saving." );
List<Mobile> mobs = new List<Mobile>( World.Mobiles.Values );
int count = 0;
foreach ( Mobile m in mobs )
{
if ( m.Player && !(m is PlayerMobile ) )
{
count++;
m.NetState?.Dispose();
public class ConvertPlayers
{
public static void Initialize()
{
CommandSystem.Register("ConvertPlayers", AccessLevel.Administrator, Convert_OnCommand);
}
PlayerMobile pm = new PlayerMobile( m.Serial );
pm.DefaultMobileInit();
List<Item> copy = new List<Item>( m.Items );
for (int i=0;i<copy.Count;i++)
pm.AddItem( copy[i] );
CopyProps( pm, m );
for (int i=0;i<m.Skills.Length;i++)
{
pm.Skills[i].Base = m.Skills[i].Base;
pm.Skills[i].SetLockNoRelay( m.Skills[i].Lock );
}
World.Mobiles[m.Serial] = pm;
}
}
if ( count > 0 )
{
NetState.ProcessDisposedQueue();
World.Save();
Console.WriteLine( "{0} players have been converted to PlayerMobile. {1}.", count, Core.Service ? "The server is now restarting" : "Press any key to restart the server" );
if ( !Core.Service )
Console.ReadKey( true );
public static void Convert_OnCommand(CommandEventArgs e)
{
e.Mobile.SendMessage(
"Converting all players to PlayerMobile. You will be disconnected. Please Restart the server after the world has finished saving.");
List<Mobile> mobs = new List<Mobile>(World.Mobiles.Values);
int count = 0;
Core.Kill( true );
}
else
{
e.Mobile.SendMessage( "Couldn't find any Players to convert." );
}
}
private static void CopyProps( Mobile to, Mobile from )
{
Type type = typeof( Mobile );
PropertyInfo[] props = type.GetProperties( BindingFlags.Public | BindingFlags.Instance );
for (int p=0;p<props.Length;p++)
{
PropertyInfo prop = props[p];
if ( prop.CanRead && prop.CanWrite )
{
try
{
prop.SetValue( to, prop.GetValue( from, null ), null );
}
catch
{
}
}
}
}
}
}
foreach (Mobile m in mobs)
if (m.Player && !(m is PlayerMobile))
{
count++;
m.NetState?.Dispose();
PlayerMobile pm = new PlayerMobile(m.Serial);
pm.DefaultMobileInit();
List<Item> copy = new List<Item>(m.Items);
for (int i = 0; i < copy.Count; i++)
pm.AddItem(copy[i]);
CopyProps(pm, m);
for (int i = 0; i < m.Skills.Length; i++)
{
pm.Skills[i].Base = m.Skills[i].Base;
pm.Skills[i].SetLockNoRelay(m.Skills[i].Lock);
}
World.Mobiles[m.Serial] = pm;
}
if (count > 0)
{
NetState.ProcessDisposedQueue();
World.Save();
Console.WriteLine("{0} players have been converted to PlayerMobile. {1}.", count,
Core.Service ? "The server is now restarting" : "Press any key to restart the server");
if (!Core.Service)
Console.ReadKey(true);
Core.Kill(true);
}
else
{
e.Mobile.SendMessage("Couldn't find any Players to convert.");
}
}
private static void CopyProps(Mobile to, Mobile from)
{
Type type = typeof(Mobile);
PropertyInfo[] props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
for (int p = 0; p < props.Length; p++)
{
PropertyInfo prop = props[p];
if (prop.CanRead && prop.CanWrite)
try
{
prop.SetValue(to, prop.GetValue(from, null), null);
}
catch
{
}
}
}
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,26 +1,26 @@
namespace Server.Commands
{
public static class DragEffects
{
public static void Initialize()
{
CommandSystem.Register( "DragEffects", AccessLevel.Developer, DragEffects_OnCommand );
}
public static class DragEffects
{
public static void Initialize()
{
CommandSystem.Register("DragEffects", AccessLevel.Developer, DragEffects_OnCommand);
}
[Usage( "DragEffects [enable=false]" )]
[Description( "Enables or disables the item drag and drop effects." )]
public static void DragEffects_OnCommand( CommandEventArgs e )
{
if ( e.Length == 0 )
{
e.Mobile.SendMessage( "Drag effects are currently {0}.", Mobile.DragEffects ? "enabled" : "disabled" );
}
else
{
Mobile.DragEffects = e.GetBoolean( 0 );
[Usage("DragEffects [enable=false]")]
[Description("Enables or disables the item drag and drop effects.")]
public static void DragEffects_OnCommand(CommandEventArgs e)
{
if (e.Length == 0)
{
e.Mobile.SendMessage("Drag effects are currently {0}.", Mobile.DragEffects ? "enabled" : "disabled");
}
else
{
Mobile.DragEffects = e.GetBoolean(0);
e.Mobile.SendMessage( "Drag effects have been {0}.", Mobile.DragEffects ? "enabled" : "disabled" );
}
}
}
}
e.Mobile.SendMessage("Drag effects have been {0}.", Mobile.DragEffects ? "enabled" : "disabled");
}
}
}
}

View file

@ -5,138 +5,131 @@ using Server.Targeting;
namespace Server.Commands
{
public class Dupe
{
public static void Initialize()
{
CommandSystem.Register( "Dupe", AccessLevel.GameMaster, Dupe_OnCommand );
CommandSystem.Register( "DupeInBag", AccessLevel.GameMaster, DupeInBag_OnCommand );
}
public class Dupe
{
public static void Initialize()
{
CommandSystem.Register("Dupe", AccessLevel.GameMaster, Dupe_OnCommand);
CommandSystem.Register("DupeInBag", AccessLevel.GameMaster, DupeInBag_OnCommand);
}
[Usage( "Dupe [amount]" )]
[Description( "Dupes a targeted item." )]
private static void Dupe_OnCommand( CommandEventArgs e )
{
int amount = 1;
if ( e.Length >= 1 )
amount = e.GetInt32( 0 );
e.Mobile.Target = new DupeTarget( false, amount > 0 ? amount : 1 );
e.Mobile.SendMessage( "What do you wish to dupe?" );
}
[Usage("Dupe [amount]")]
[Description("Dupes a targeted item.")]
private static void Dupe_OnCommand(CommandEventArgs e)
{
int amount = 1;
if (e.Length >= 1)
amount = e.GetInt32(0);
e.Mobile.Target = new DupeTarget(false, amount > 0 ? amount : 1);
e.Mobile.SendMessage("What do you wish to dupe?");
}
[Usage( "DupeInBag <count>" )]
[Description( "Dupes an item at it's current location (count) number of times." )]
private static void DupeInBag_OnCommand( CommandEventArgs e )
{
int amount = 1;
if ( e.Length >= 1 )
amount = e.GetInt32( 0 );
[Usage("DupeInBag <count>")]
[Description("Dupes an item at it's current location (count) number of times.")]
private static void DupeInBag_OnCommand(CommandEventArgs e)
{
int amount = 1;
if (e.Length >= 1)
amount = e.GetInt32(0);
e.Mobile.Target = new DupeTarget( true, amount > 0 ? amount : 1 );
e.Mobile.SendMessage( "What do you wish to dupe?" );
}
e.Mobile.Target = new DupeTarget(true, amount > 0 ? amount : 1);
e.Mobile.SendMessage("What do you wish to dupe?");
}
private class DupeTarget : Target
{
private bool m_InBag;
private int m_Amount;
public static void CopyProperties(Item dest, Item src)
{
PropertyInfo[] props = src.GetType().GetProperties();
public DupeTarget( bool inbag, int amount )
: base( 15, false, TargetFlags.None )
{
m_InBag = inbag;
m_Amount = amount;
}
for (int i = 0; i < props.Length; i++)
try
{
if (props[i].CanRead && props[i].CanWrite) props[i].SetValue(dest, props[i].GetValue(src, null), null);
}
catch
{
//Console.WriteLine( "Denied" );
}
}
protected override void OnTarget( Mobile from, object targ )
{
bool done = false;
if ( !( targ is Item ) )
{
from.SendMessage( "You can only dupe items." );
return;
}
private class DupeTarget : Target
{
private int m_Amount;
private bool m_InBag;
CommandLogging.WriteLine( from, "{0} {1} duping {2} (inBag={3}; amount={4})", from.AccessLevel, CommandLogging.Format( from ), CommandLogging.Format( targ ), m_InBag, m_Amount );
public DupeTarget(bool inbag, int amount)
: base(15, false, TargetFlags.None)
{
m_InBag = inbag;
m_Amount = amount;
}
Item copy = (Item)targ;
Container pack = null;
protected override void OnTarget(Mobile from, object targ)
{
bool done = false;
if (!(targ is Item))
{
from.SendMessage("You can only dupe items.");
return;
}
if ( m_InBag )
{
if ( copy.Parent is Container cont )
pack = cont;
else if ( copy.Parent is Mobile m )
pack = m.Backpack;
}
else
pack = from.Backpack;
CommandLogging.WriteLine(from, "{0} {1} duping {2} (inBag={3}; amount={4})", from.AccessLevel,
CommandLogging.Format(from), CommandLogging.Format(targ), m_InBag, m_Amount);
Type t = copy.GetType();
Item copy = (Item)targ;
Container pack = null;
//ConstructorInfo[] info = t.GetConstructors();
if (m_InBag)
{
if (copy.Parent is Container cont)
pack = cont;
else if (copy.Parent is Mobile m)
pack = m.Backpack;
}
else
{
pack = from.Backpack;
}
ConstructorInfo c = t.GetConstructor( Type.EmptyTypes );
Type t = copy.GetType();
if ( c != null )
{
try
{
from.SendMessage( "Duping {0}...", m_Amount );
for ( int i = 0; i < m_Amount; i++ )
{
if ( c.Invoke( null ) is Item newItem )
{
CopyProperties( newItem, copy );//copy.Dupe( item, copy.Amount );
copy.OnAfterDuped( newItem );
newItem.Parent = null;
//ConstructorInfo[] info = t.GetConstructors();
if ( pack != null )
pack.DropItem( newItem );
else
newItem.MoveToWorld( from.Location, from.Map );
ConstructorInfo c = t.GetConstructor(Type.EmptyTypes);
newItem.InvalidateProperties();
if (c != null)
try
{
from.SendMessage("Duping {0}...", m_Amount);
for (int i = 0; i < m_Amount; i++)
if (c.Invoke(null) is Item newItem)
{
CopyProperties(newItem, copy); //copy.Dupe( item, copy.Amount );
copy.OnAfterDuped(newItem);
newItem.Parent = null;
CommandLogging.WriteLine( from, "{0} {1} duped {2} creating {3}", from.AccessLevel, CommandLogging.Format( from ), CommandLogging.Format( targ ), CommandLogging.Format( newItem ) );
}
}
from.SendMessage( "Done" );
done = true;
}
catch
{
from.SendMessage( "Error!" );
return;
}
}
if (pack != null)
pack.DropItem(newItem);
else
newItem.MoveToWorld(from.Location, from.Map);
if ( !done )
{
from.SendMessage( "Unable to dupe. Item must have a 0 parameter constructor." );
}
}
}
newItem.InvalidateProperties();
public static void CopyProperties( Item dest, Item src )
{
PropertyInfo[] props = src.GetType().GetProperties();
CommandLogging.WriteLine(from, "{0} {1} duped {2} creating {3}", from.AccessLevel,
CommandLogging.Format(from), CommandLogging.Format(targ),
CommandLogging.Format(newItem));
}
for ( int i = 0; i < props.Length; i++ )
{
try
{
if ( props[i].CanRead && props[i].CanWrite )
{
//Console.WriteLine( "Setting {0} = {1}", props[i].Name, props[i].GetValue( src, null ) );
props[i].SetValue( dest, props[i].GetValue( src, null ), null );
}
}
catch
{
//Console.WriteLine( "Denied" );
}
}
}
}
}
from.SendMessage("Done");
done = true;
}
catch
{
from.SendMessage("Error!");
return;
}
if (!done) from.SendMessage("Unable to dupe. Item must have a 0 parameter constructor.");
}
}
}
}

View file

@ -4,63 +4,61 @@ using Server.Items;
namespace Server.Commands
{
public class ExportCommand
{
private const string ExportFile = @"C:\Uo\WorldForge\items.wsc";
public class ExportCommand
{
private const string ExportFile = @"C:\Uo\WorldForge\items.wsc";
public static void Initialize()
{
CommandSystem.Register( "ExportWSC", AccessLevel.Administrator, Export_OnCommand );
}
public static void Initialize()
{
CommandSystem.Register("ExportWSC", AccessLevel.Administrator, Export_OnCommand);
}
public static void Export_OnCommand( CommandEventArgs e )
{
StreamWriter w = new StreamWriter( ExportFile );
ArrayList remove = new ArrayList();
int count = 0;
public static void Export_OnCommand(CommandEventArgs e)
{
StreamWriter w = new StreamWriter(ExportFile);
ArrayList remove = new ArrayList();
int count = 0;
e.Mobile.SendMessage( "Exporting all static items to \"{0}\"...", ExportFile );
e.Mobile.SendMessage( "This will delete all static items in the world. Please make a backup." );
e.Mobile.SendMessage("Exporting all static items to \"{0}\"...", ExportFile);
e.Mobile.SendMessage("This will delete all static items in the world. Please make a backup.");
foreach ( Item item in World.Items.Values )
{
if ( ( item is Static || item is BaseFloor || item is BaseWall )
&& item.RootParent == null )
{
w.WriteLine( "SECTION WORLDITEM {0}", count );
w.WriteLine( "{" );
w.WriteLine( "SERIAL {0}", item.Serial );
w.WriteLine( "NAME #" );
w.WriteLine( "NAME2 #" );
w.WriteLine( "ID {0}", item.ItemID );
w.WriteLine( "X {0}", item.X );
w.WriteLine( "Y {0}", item.Y );
w.WriteLine( "Z {0}", item.Z );
w.WriteLine( "COLOR {0}", item.Hue );
w.WriteLine( "CONT -1" );
w.WriteLine( "TYPE 0" );
w.WriteLine( "AMOUNT 1" );
w.WriteLine( "WEIGHT 255" );
w.WriteLine( "OWNER -1" );
w.WriteLine( "SPAWN -1" );
w.WriteLine( "VALUE 1" );
w.WriteLine( "}" );
w.WriteLine( "" );
foreach (Item item in World.Items.Values)
if ((item is Static || item is BaseFloor || item is BaseWall)
&& item.RootParent == null)
{
w.WriteLine("SECTION WORLDITEM {0}", count);
w.WriteLine("{");
w.WriteLine("SERIAL {0}", item.Serial);
w.WriteLine("NAME #");
w.WriteLine("NAME2 #");
w.WriteLine("ID {0}", item.ItemID);
w.WriteLine("X {0}", item.X);
w.WriteLine("Y {0}", item.Y);
w.WriteLine("Z {0}", item.Z);
w.WriteLine("COLOR {0}", item.Hue);
w.WriteLine("CONT -1");
w.WriteLine("TYPE 0");
w.WriteLine("AMOUNT 1");
w.WriteLine("WEIGHT 255");
w.WriteLine("OWNER -1");
w.WriteLine("SPAWN -1");
w.WriteLine("VALUE 1");
w.WriteLine("}");
w.WriteLine("");
count++;
remove.Add( item );
w.Flush();
}
}
count++;
remove.Add(item);
w.Flush();
}
w.Close();
w.Close();
foreach( Item item in remove )
item.Delete();
foreach (Item item in remove)
item.Delete();
e.Mobile.SendMessage( "Export complete. Exported {0} statics.", count );
}
}
e.Mobile.SendMessage("Export complete. Exported {0} statics.", count);
}
}
}
/*SECTION WORLDITEM 1
{
@ -78,4 +76,4 @@ WEIGHT 25500
OWNER -1
SPAWN -1
VALUE 1
}*/
}*/

View file

@ -1,413 +1,410 @@
using System;
using System.IO;
using System.Xml;
using System.Collections;
using System.IO;
using System.Reflection;
using System.Text;
using System.Xml;
using Server.Items;
namespace Server.Commands
{
public class Categorization
{
private static CategoryEntry m_RootItems, m_RootMobiles;
public class Categorization
{
private static CategoryEntry m_RootItems, m_RootMobiles;
public static CategoryEntry Items
{
get
{
if ( m_RootItems == null )
Load();
private static Type typeofItem = typeof(Item);
private static Type typeofMobile = typeof(Mobile);
private static Type typeofConstructible = typeof(ConstructibleAttribute);
return m_RootItems;
}
}
public static CategoryEntry Items
{
get
{
if (m_RootItems == null)
Load();
public static CategoryEntry Mobiles
{
get
{
if ( m_RootMobiles == null )
Load();
return m_RootItems;
}
}
return m_RootMobiles;
}
}
public static CategoryEntry Mobiles
{
get
{
if (m_RootMobiles == null)
Load();
public static void Initialize()
{
CommandSystem.Register( "RebuildCategorization", AccessLevel.Administrator, RebuildCategorization_OnCommand );
}
return m_RootMobiles;
}
}
[Usage( "RebuildCategorization" )]
[Description( "Rebuilds the categorization data file used by the Add command." )]
public static void RebuildCategorization_OnCommand( CommandEventArgs e )
{
CategoryEntry root = new CategoryEntry( null, "Add Menu", new[]{ Items, Mobiles } );
public static void Initialize()
{
CommandSystem.Register("RebuildCategorization", AccessLevel.Administrator, RebuildCategorization_OnCommand);
}
Export( root, "Data/objects.xml", "Objects" );
[Usage("RebuildCategorization")]
[Description("Rebuilds the categorization data file used by the Add command.")]
public static void RebuildCategorization_OnCommand(CommandEventArgs e)
{
CategoryEntry root = new CategoryEntry(null, "Add Menu", new[] { Items, Mobiles });
e.Mobile.SendMessage( "Categorization menu rebuilt." );
}
Export(root, "Data/objects.xml", "Objects");
public static void RecurseFindCategories( CategoryEntry ce, ArrayList list )
{
list.Add( ce );
e.Mobile.SendMessage("Categorization menu rebuilt.");
}
for ( int i = 0; i < ce.SubCategories.Length; ++i )
RecurseFindCategories( ce.SubCategories[i], list );
}
public static void RecurseFindCategories(CategoryEntry ce, ArrayList list)
{
list.Add(ce);
public static void Export( CategoryEntry ce, string fileName, string title )
{
XmlTextWriter xml = new XmlTextWriter( fileName, System.Text.Encoding.UTF8 );
for (int i = 0; i < ce.SubCategories.Length; ++i)
RecurseFindCategories(ce.SubCategories[i], list);
}
xml.Indentation = 1;
xml.IndentChar = '\t';
xml.Formatting = Formatting.Indented;
public static void Export(CategoryEntry ce, string fileName, string title)
{
XmlTextWriter xml = new XmlTextWriter(fileName, Encoding.UTF8);
xml.WriteStartDocument( true );
xml.Indentation = 1;
xml.IndentChar = '\t';
xml.Formatting = Formatting.Indented;
RecurseExport( xml, ce );
xml.WriteStartDocument(true);
xml.Flush();
xml.Close();
}
RecurseExport(xml, ce);
public static void RecurseExport( XmlTextWriter xml, CategoryEntry ce )
{
xml.WriteStartElement( "category" );
xml.Flush();
xml.Close();
}
xml.WriteAttributeString( "title", ce.Title );
public static void RecurseExport(XmlTextWriter xml, CategoryEntry ce)
{
xml.WriteStartElement("category");
ArrayList subCats = new ArrayList( ce.SubCategories );
xml.WriteAttributeString("title", ce.Title);
subCats.Sort( new CategorySorter() );
ArrayList subCats = new ArrayList(ce.SubCategories);
for ( int i = 0; i < subCats.Count; ++i )
RecurseExport( xml, (CategoryEntry)subCats[i] );
subCats.Sort(new CategorySorter());
ce.Matched.Sort( new CategorySorter() );
for (int i = 0; i < subCats.Count; ++i)
RecurseExport(xml, (CategoryEntry)subCats[i]);
for ( int i = 0; i < ce.Matched.Count; ++i )
{
CategoryTypeEntry cte = (CategoryTypeEntry)ce.Matched[i];
ce.Matched.Sort(new CategorySorter());
xml.WriteStartElement( "object" );
for (int i = 0; i < ce.Matched.Count; ++i)
{
CategoryTypeEntry cte = (CategoryTypeEntry)ce.Matched[i];
xml.WriteAttributeString( "type", cte.Type.ToString() );
xml.WriteStartElement("object");
if ( cte.Object is Item item )
{
int itemID = item.ItemID;
xml.WriteAttributeString("type", cte.Type.ToString());
if ( item is BaseAddon addon && addon.Components.Count == 1 )
itemID = addon.Components[0].ItemID;
if (cte.Object is Item item)
{
int itemID = item.ItemID;
if ( itemID > TileData.MaxItemValue )
itemID = 1;
if (item is BaseAddon addon && addon.Components.Count == 1)
itemID = addon.Components[0].ItemID;
xml.WriteAttributeString( "gfx", XmlConvert.ToString( itemID ) );
if (itemID > TileData.MaxItemValue)
itemID = 1;
int hue = item.Hue & 0x7FFF;
xml.WriteAttributeString("gfx", XmlConvert.ToString(itemID));
if ( (hue & 0x4000) != 0 )
hue = 0;
int hue = item.Hue & 0x7FFF;
if ( hue != 0 )
xml.WriteAttributeString( "hue", XmlConvert.ToString( hue ) );
if ((hue & 0x4000) != 0)
hue = 0;
item.Delete();
}
else if ( cte.Object is Mobile mob )
{
int itemID = ShrinkTable.Lookup( mob, 1 );
if (hue != 0)
xml.WriteAttributeString("hue", XmlConvert.ToString(hue));
xml.WriteAttributeString( "gfx", XmlConvert.ToString( itemID ) );
item.Delete();
}
else if (cte.Object is Mobile mob)
{
int itemID = ShrinkTable.Lookup(mob, 1);
int hue = mob.Hue & 0x7FFF;
xml.WriteAttributeString("gfx", XmlConvert.ToString(itemID));
if ( (hue & 0x4000) != 0 )
hue = 0;
int hue = mob.Hue & 0x7FFF;
if ( hue != 0 )
xml.WriteAttributeString( "hue", XmlConvert.ToString( hue ) );
if ((hue & 0x4000) != 0)
hue = 0;
mob.Delete();
}
if (hue != 0)
xml.WriteAttributeString("hue", XmlConvert.ToString(hue));
xml.WriteEndElement();
}
mob.Delete();
}
xml.WriteEndElement();
}
xml.WriteEndElement();
}
public static void Load()
{
ArrayList types = new ArrayList();
xml.WriteEndElement();
}
AddTypes( Core.Assembly, types );
public static void Load()
{
ArrayList types = new ArrayList();
for ( int i = 0; i < ScriptCompiler.Assemblies.Length; ++i )
AddTypes( ScriptCompiler.Assemblies[i], types );
AddTypes(Core.Assembly, types);
m_RootItems = Load( types, "Data/items.cfg" );
m_RootMobiles = Load( types, "Data/mobiles.cfg" );
}
for (int i = 0; i < ScriptCompiler.Assemblies.Length; ++i)
AddTypes(ScriptCompiler.Assemblies[i], types);
private static CategoryEntry Load( ArrayList types, string config )
{
CategoryLine[] lines = CategoryLine.Load( config );
m_RootItems = Load(types, "Data/items.cfg");
m_RootMobiles = Load(types, "Data/mobiles.cfg");
}
if ( lines.Length > 0 )
{
int index = 0;
CategoryEntry root = new CategoryEntry( null, lines, ref index );
private static CategoryEntry Load(ArrayList types, string config)
{
CategoryLine[] lines = CategoryLine.Load(config);
Fill( root, types );
if (lines.Length > 0)
{
int index = 0;
CategoryEntry root = new CategoryEntry(null, lines, ref index);
return root;
}
Fill(root, types);
return new CategoryEntry();
}
return root;
}
private static Type typeofItem = typeof( Item );
private static Type typeofMobile = typeof( Mobile );
private static Type typeofConstructible = typeof( ConstructibleAttribute );
return new CategoryEntry();
}
private static bool IsConstructible( Type type )
{
if ( !type.IsSubclassOf( typeofItem ) && !type.IsSubclassOf( typeofMobile ) )
return false;
private static bool IsConstructible(Type type)
{
if (!type.IsSubclassOf(typeofItem) && !type.IsSubclassOf(typeofMobile))
return false;
ConstructorInfo ctor = type.GetConstructor( Type.EmptyTypes );
ConstructorInfo ctor = type.GetConstructor(Type.EmptyTypes);
return ( ctor != null && ctor.IsDefined( typeofConstructible, false ) );
}
return ctor != null && ctor.IsDefined(typeofConstructible, false);
}
private static void AddTypes( Assembly asm, ArrayList types )
{
Type[] allTypes = asm.GetTypes();
private static void AddTypes(Assembly asm, ArrayList types)
{
Type[] allTypes = asm.GetTypes();
for ( int i = 0; i < allTypes.Length; ++i )
{
Type type = allTypes[i];
for (int i = 0; i < allTypes.Length; ++i)
{
Type type = allTypes[i];
if ( type.IsAbstract )
continue;
if (type.IsAbstract)
continue;
if ( IsConstructible( type ) )
types.Add( type );
}
}
if (IsConstructible(type))
types.Add(type);
}
}
private static void Fill( CategoryEntry root, ArrayList list )
{
for ( int i = 0; i < list.Count; ++i )
{
Type type = (Type)list[i];
CategoryEntry match = GetDeepestMatch( root, type );
private static void Fill(CategoryEntry root, ArrayList list)
{
for (int i = 0; i < list.Count; ++i)
{
Type type = (Type)list[i];
CategoryEntry match = GetDeepestMatch(root, type);
if ( match == null )
continue;
if (match == null)
continue;
try
{
match.Matched.Add( new CategoryTypeEntry( type ) );
}
catch
{
}
}
}
try
{
match.Matched.Add(new CategoryTypeEntry(type));
}
catch
{
}
}
}
private static CategoryEntry GetDeepestMatch( CategoryEntry root, Type type )
{
if ( !root.IsMatch( type ) )
return null;
private static CategoryEntry GetDeepestMatch(CategoryEntry root, Type type)
{
if (!root.IsMatch(type))
return null;
for ( int i = 0; i < root.SubCategories.Length; ++i )
{
CategoryEntry check = GetDeepestMatch( root.SubCategories[i], type );
for (int i = 0; i < root.SubCategories.Length; ++i)
{
CategoryEntry check = GetDeepestMatch(root.SubCategories[i], type);
if ( check != null )
return check;
}
if (check != null)
return check;
}
return root;
}
}
return root;
}
}
public class CategorySorter : IComparer
{
public int Compare( object x, object y )
{
string a = null, b = null;
public class CategorySorter : IComparer
{
public int Compare(object x, object y)
{
string a = null, b = null;
if ( x is CategoryEntry entry )
a = entry.Title;
else if ( x is CategoryTypeEntry xTypeEntry )
a = xTypeEntry.Type.Name;
if (x is CategoryEntry entry)
a = entry.Title;
else if (x is CategoryTypeEntry xTypeEntry)
a = xTypeEntry.Type.Name;
if ( y is CategoryEntry categoryEntry )
b = categoryEntry.Title;
else if ( y is CategoryTypeEntry yTypeEntry )
b = yTypeEntry.Type.Name;
if (y is CategoryEntry categoryEntry)
b = categoryEntry.Title;
else if (y is CategoryTypeEntry yTypeEntry)
b = yTypeEntry.Type.Name;
if ( a == null && b == null )
return 0;
if (a == null && b == null)
return 0;
if ( a == null )
return 1;
if (a == null)
return 1;
if ( b == null )
return -1;
if (b == null)
return -1;
return a.CompareTo( b );
}
}
return a.CompareTo(b);
}
}
public class CategoryTypeEntry
{
public Type Type { get; }
public class CategoryTypeEntry
{
public CategoryTypeEntry(Type type)
{
Type = type;
Object = Activator.CreateInstance(type);
}
public object Object { get; }
public Type Type{ get; }
public CategoryTypeEntry( Type type )
{
Type = type;
Object = Activator.CreateInstance( type );
}
}
public object Object{ get; }
}
public class CategoryEntry
{
public string Title { get; }
public class CategoryEntry
{
public CategoryEntry()
{
Title = "(empty)";
Matches = new Type[0];
SubCategories = new CategoryEntry[0];
Matched = new ArrayList();
}
public Type[] Matches { get; }
public CategoryEntry(CategoryEntry parent, string title, CategoryEntry[] subCats)
{
Parent = parent;
Title = title;
SubCategories = subCats;
Matches = new Type[0];
Matched = new ArrayList();
}
public CategoryEntry Parent { get; }
public CategoryEntry(CategoryEntry parent, CategoryLine[] lines, ref int index)
{
Parent = parent;
public CategoryEntry[] SubCategories { get; }
string text = lines[index].Text;
public ArrayList Matched { get; }
int start = text.IndexOf('(');
public CategoryEntry()
{
Title = "(empty)";
Matches = new Type[0];
SubCategories = new CategoryEntry[0];
Matched = new ArrayList();
}
if (start < 0)
throw new FormatException($"Input string not correctly formatted ('{text}')");
public CategoryEntry( CategoryEntry parent, string title, CategoryEntry[] subCats )
{
Parent = parent;
Title = title;
SubCategories = subCats;
Matches = new Type[0];
Matched = new ArrayList();
}
Title = text.Substring(0, start).Trim();
public bool IsMatch( Type type )
{
bool isMatch = false;
int end = text.IndexOf(')', ++start);
for ( int i = 0; !isMatch && i < Matches.Length; ++i )
isMatch = ( type == Matches[i] || type.IsSubclassOf( Matches[i] ) );
if (end < start)
throw new FormatException($"Input string not correctly formatted ('{text}')");
return isMatch;
}
text = text.Substring(start, end - start);
string[] split = text.Split(';');
public CategoryEntry( CategoryEntry parent, CategoryLine[] lines, ref int index )
{
Parent = parent;
ArrayList list = new ArrayList();
string text = lines[index].Text;
for (int i = 0; i < split.Length; ++i)
{
Type type = ScriptCompiler.FindTypeByName(split[i].Trim());
int start = text.IndexOf( '(' );
if (type == null)
Console.WriteLine("Match type not found ('{0}')", split[i].Trim());
else
list.Add(type);
}
if ( start < 0 )
throw new FormatException($"Input string not correctly formatted ('{text}')");
Matches = (Type[])list.ToArray(typeof(Type));
list.Clear();
Title = text.Substring( 0, start ).Trim();
int ourIndentation = lines[index].Indentation;
int end = text.IndexOf( ')', ++start );
++index;
if ( end < start )
throw new FormatException($"Input string not correctly formatted ('{text}')");
while (index < lines.Length && lines[index].Indentation > ourIndentation)
list.Add(new CategoryEntry(this, lines, ref index));
text = text.Substring( start, end-start );
string[] split = text.Split( ';' );
SubCategories = (CategoryEntry[])list.ToArray(typeof(CategoryEntry));
list.Clear();
ArrayList list = new ArrayList();
Matched = list;
}
for ( int i = 0; i < split.Length; ++i )
{
Type type = ScriptCompiler.FindTypeByName( split[i].Trim() );
public string Title{ get; }
if ( type == null )
Console.WriteLine( "Match type not found ('{0}')", split[i].Trim() );
else
list.Add( type );
}
public Type[] Matches{ get; }
Matches = (Type[])list.ToArray( typeof( Type ) );
list.Clear();
public CategoryEntry Parent{ get; }
int ourIndentation = lines[index].Indentation;
public CategoryEntry[] SubCategories{ get; }
++index;
public ArrayList Matched{ get; }
while ( index < lines.Length && lines[index].Indentation > ourIndentation )
list.Add( new CategoryEntry( this, lines, ref index ) );
public bool IsMatch(Type type)
{
bool isMatch = false;
SubCategories = (CategoryEntry[])list.ToArray( typeof( CategoryEntry ) );
list.Clear();
for (int i = 0; !isMatch && i < Matches.Length; ++i)
isMatch = type == Matches[i] || type.IsSubclassOf(Matches[i]);
Matched = list;
}
}
return isMatch;
}
}
public class CategoryLine
{
public int Indentation { get; }
public class CategoryLine
{
public CategoryLine(string input)
{
int index;
public string Text { get; }
for (index = 0; index < input.Length; ++index)
if (char.IsLetter(input, index))
break;
public CategoryLine( string input )
{
int index;
if (index >= input.Length)
throw new FormatException($"Input string not correctly formatted ('{input}')");
for ( index = 0; index < input.Length; ++index )
{
if ( char.IsLetter( input, index ) )
break;
}
Indentation = index;
Text = input.Substring(index);
}
if ( index >= input.Length )
throw new FormatException($"Input string not correctly formatted ('{input}')");
public int Indentation{ get; }
Indentation = index;
Text = input.Substring( index );
}
public string Text{ get; }
public static CategoryLine[] Load( string path )
{
ArrayList list = new ArrayList();
public static CategoryLine[] Load(string path)
{
ArrayList list = new ArrayList();
if ( File.Exists( path ) )
{
using ( StreamReader ip = new StreamReader( path ) )
{
string line;
if (File.Exists(path))
using (StreamReader ip = new StreamReader(path))
{
string line;
while ( (line = ip.ReadLine()) != null )
list.Add( new CategoryLine( line ) );
}
}
while ((line = ip.ReadLine()) != null)
list.Add(new CategoryLine(line));
}
return (CategoryLine[])list.ToArray( typeof( CategoryLine ) );
}
}
}
return (CategoryLine[])list.ToArray(typeof(CategoryLine));
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,163 +1,158 @@
using System;
using System.Collections;
using Server.Gumps;
namespace Server.Commands.Generic
{
public enum ObjectTypes
{
Both,
Items,
Mobiles,
All
}
public enum ObjectTypes
{
Both,
Items,
Mobiles,
All
}
public abstract class BaseCommand
{
public bool ListOptimized { get; set; }
public abstract class BaseCommand
{
private ArrayList m_Responses, m_Failures;
public string[] Commands { get; set; }
public BaseCommand()
{
m_Responses = new ArrayList();
m_Failures = new ArrayList();
}
public string Usage { get; set; }
public bool ListOptimized{ get; set; }
public string Description { get; set; }
public string[] Commands{ get; set; }
public AccessLevel AccessLevel { get; set; }
public string Usage{ get; set; }
public ObjectTypes ObjectTypes { get; set; }
public string Description{ get; set; }
public CommandSupport Supports { get; set; }
public AccessLevel AccessLevel{ get; set; }
public BaseCommand()
{
m_Responses = new ArrayList();
m_Failures = new ArrayList();
}
public ObjectTypes ObjectTypes{ get; set; }
public static bool IsAccessible( Mobile from, object obj )
{
if ( from.AccessLevel >= AccessLevel.Administrator || obj == null )
return true;
public CommandSupport Supports{ get; set; }
Mobile mob = null;
public static bool IsAccessible(Mobile from, object obj)
{
if (from.AccessLevel >= AccessLevel.Administrator || obj == null)
return true;
if ( obj is Mobile m )
mob = m;
else if ( obj is Item item )
mob = item.RootParent as Mobile;
Mobile mob = null;
return mob == null || mob == from || from.AccessLevel > mob.AccessLevel;
}
if (obj is Mobile m)
mob = m;
else if (obj is Item item)
mob = item.RootParent as Mobile;
public virtual void ExecuteList( CommandEventArgs e, ArrayList list )
{
for ( int i = 0; i < list.Count; ++i )
Execute( e, list[i] );
}
return mob == null || mob == from || from.AccessLevel > mob.AccessLevel;
}
public virtual void Execute( CommandEventArgs e, object obj )
{
}
public virtual void ExecuteList(CommandEventArgs e, ArrayList list)
{
for (int i = 0; i < list.Count; ++i)
Execute(e, list[i]);
}
public virtual bool ValidateArgs( BaseCommandImplementor impl, CommandEventArgs e )
{
return true;
}
public virtual void Execute(CommandEventArgs e, object obj)
{
}
private ArrayList m_Responses, m_Failures;
public virtual bool ValidateArgs(BaseCommandImplementor impl, CommandEventArgs e)
{
return true;
}
private class MessageEntry
{
public string m_Message;
public int m_Count;
public void AddResponse(string message)
{
for (int i = 0; i < m_Responses.Count; ++i)
{
MessageEntry entry = (MessageEntry)m_Responses[i];
public MessageEntry( string message )
{
m_Message = message;
m_Count = 1;
}
if (entry.m_Message == message)
{
++entry.m_Count;
return;
}
}
public override string ToString()
{
if ( m_Count > 1 )
return $"{m_Message} ({m_Count})";
if (m_Responses.Count == 10)
return;
return m_Message;
}
}
m_Responses.Add(new MessageEntry(message));
}
public void AddResponse( string message )
{
for ( int i = 0; i < m_Responses.Count; ++i )
{
MessageEntry entry = (MessageEntry)m_Responses[i];
public void AddResponse(Gump gump)
{
m_Responses.Add(gump);
}
if ( entry.m_Message == message )
{
++entry.m_Count;
return;
}
}
public void LogFailure(string message)
{
for (int i = 0; i < m_Failures.Count; ++i)
{
MessageEntry entry = (MessageEntry)m_Failures[i];
if ( m_Responses.Count == 10 )
return;
if (entry.m_Message == message)
{
++entry.m_Count;
return;
}
}
m_Responses.Add( new MessageEntry( message ) );
}
if (m_Failures.Count == 10)
return;
public void AddResponse( Gump gump )
{
m_Responses.Add( gump );
}
m_Failures.Add(new MessageEntry(message));
}
public void LogFailure( string message )
{
for ( int i = 0; i < m_Failures.Count; ++i )
{
MessageEntry entry = (MessageEntry)m_Failures[i];
public void Flush(Mobile from, bool flushToLog)
{
if (m_Responses.Count > 0)
for (int i = 0; i < m_Responses.Count; ++i)
{
object obj = m_Responses[i];
if ( entry.m_Message == message )
{
++entry.m_Count;
return;
}
}
if (obj is MessageEntry entry)
{
from.SendMessage(entry.ToString());
if ( m_Failures.Count == 10 )
return;
if (flushToLog)
CommandLogging.WriteLine(from, entry.ToString());
}
else if (obj is Gump gump)
{
from.SendGump(gump);
}
}
else
for (int i = 0; i < m_Failures.Count; ++i)
from.SendMessage(((MessageEntry)m_Failures[i]).ToString());
m_Failures.Add( new MessageEntry( message ) );
}
m_Responses.Clear();
m_Failures.Clear();
}
public void Flush( Mobile from, bool flushToLog )
{
if ( m_Responses.Count > 0 )
{
for ( int i = 0; i < m_Responses.Count; ++i )
{
object obj = m_Responses[i];
private class MessageEntry
{
public int m_Count;
public string m_Message;
if ( obj is MessageEntry entry )
{
from.SendMessage( entry.ToString() );
public MessageEntry(string message)
{
m_Message = message;
m_Count = 1;
}
if ( flushToLog )
CommandLogging.WriteLine( from, entry.ToString() );
}
else if ( obj is Gump gump )
{
from.SendGump( gump );
}
}
}
else
{
for ( int i = 0; i < m_Failures.Count; ++i )
from.SendMessage( ((MessageEntry)m_Failures[i]).ToString() );
}
public override string ToString()
{
if (m_Count > 1)
return $"{m_Message} ({m_Count})";
m_Responses.Clear();
m_Failures.Clear();
}
}
}
return m_Message;
}
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,3 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Server.Gumps;
@ -8,198 +7,204 @@ using Server.Targeting;
namespace Server.Commands.Generic
{
public class DesignInsertCommand : BaseCommand
{
public static void Initialize()
{
TargetCommands.Register( new DesignInsertCommand() );
}
public class DesignInsertCommand : BaseCommand
{
public enum DesignInsertResult
{
Valid,
InvalidItem,
NotInHouse,
OutsideHouseBounds
}
public DesignInsertCommand()
{
AccessLevel = AccessLevel.GameMaster;
Supports = CommandSupport.Single | CommandSupport.Area;
Commands = new[] { "DesignInsert" };
ObjectTypes = ObjectTypes.Items;
Usage = "DesignInsert [allItems=false]";
Description = "Inserts multiple targeted items into a customizable house's design.";
}
public DesignInsertCommand()
{
AccessLevel = AccessLevel.GameMaster;
Supports = CommandSupport.Single | CommandSupport.Area;
Commands = new[] { "DesignInsert" };
ObjectTypes = ObjectTypes.Items;
Usage = "DesignInsert [allItems=false]";
Description = "Inserts multiple targeted items into a customizable house's design.";
}
#region Single targeting mode
public override void Execute( CommandEventArgs e, object obj )
{
Target t = new DesignInsertTarget( new List<HouseFoundation>(), ( e.Length < 1 || !e.GetBoolean( 0 ) ) );
t.Invoke( e.Mobile, obj );
}
public static void Initialize()
{
TargetCommands.Register(new DesignInsertCommand());
}
private class DesignInsertTarget : Target
{
private List<HouseFoundation> m_Foundations;
private bool m_StaticsOnly;
public static DesignInsertResult ProcessInsert(Item item, bool staticsOnly, out HouseFoundation house)
{
house = null;
public DesignInsertTarget( List<HouseFoundation> foundations, bool staticsOnly )
: base( -1, false, TargetFlags.None )
{
m_Foundations = foundations;
m_StaticsOnly = staticsOnly;
}
if (item == null || item is BaseMulti || item is HouseSign || staticsOnly && !(item is Static))
return DesignInsertResult.InvalidItem;
protected override void OnTargetCancel( Mobile from, TargetCancelType cancelType )
{
if ( m_Foundations.Count != 0 )
{
from.SendMessage( "Your changes have been committed. Updating..." );
house = BaseHouse.FindHouseAt(item) as HouseFoundation;
foreach ( HouseFoundation house in m_Foundations )
house.Delta( ItemDelta.Update );
}
}
if (house == null)
return DesignInsertResult.NotInHouse;
protected override void OnTarget( Mobile from, object obj )
{
HouseFoundation house;
DesignInsertResult result = ProcessInsert( obj as Item, m_StaticsOnly, out house );
int x = item.X - house.X;
int y = item.Y - house.Y;
int z = item.Z - house.Z;
switch ( result )
{
case DesignInsertResult.Valid:
{
if ( m_Foundations.Count == 0 )
from.SendMessage( "The item has been inserted into the house design. Press ESC when you are finished." );
else
from.SendMessage( "The item has been inserted into the house design." );
if (!TryInsertIntoState(house.CurrentState, item.ItemID, x, y, z))
return DesignInsertResult.OutsideHouseBounds;
if ( !m_Foundations.Contains( house ) )
m_Foundations.Add( house );
TryInsertIntoState(house.DesignState, item.ItemID, x, y, z);
item.Delete();
break;
}
case DesignInsertResult.InvalidItem:
{
from.SendMessage( "That cannot be inserted. Try again." );
break;
}
case DesignInsertResult.NotInHouse:
case DesignInsertResult.OutsideHouseBounds:
{
from.SendMessage( "That item is not inside a customizable house. Try again." );
break;
}
}
return DesignInsertResult.Valid;
}
from.Target = new DesignInsertTarget( m_Foundations, m_StaticsOnly );
}
}
#endregion
private static bool TryInsertIntoState(DesignState state, int itemID, int x, int y, int z)
{
MultiComponentList mcl = state.Components;
#region Area targeting mode
public override void ExecuteList( CommandEventArgs e, ArrayList list )
{
e.Mobile.SendGump( new WarningGump( 1060637, 30720,
$"You are about to insert {list.Count} objects. This cannot be undone without a full server revert.<br><br>Continue?", 0xFFC000, 420, 280, OnConfirmCallback, new object[] { e, list, ( e.Length < 1 || !e.GetBoolean( 0 ) ) } ) );
AddResponse( "Awaiting confirmation..." );
}
if (x < mcl.Min.X || y < mcl.Min.Y || x > mcl.Max.X || y > mcl.Max.Y)
return false;
private void OnConfirmCallback( Mobile from, bool okay, object state )
{
object[] states = (object[])state;
CommandEventArgs e = (CommandEventArgs)states[0];
ArrayList list = (ArrayList)states[1];
bool staticsOnly = (bool)states[2];
mcl.Add(itemID, x, y, z);
state.OnRevised();
bool flushToLog = false;
return true;
}
if ( okay )
{
List<HouseFoundation> foundations = new List<HouseFoundation>();
flushToLog = ( list.Count > 20 );
#region Single targeting mode
for ( int i = 0; i < list.Count; ++i )
{
HouseFoundation house;
DesignInsertResult result = ProcessInsert( list[i] as Item, staticsOnly, out house );
public override void Execute(CommandEventArgs e, object obj)
{
Target t = new DesignInsertTarget(new List<HouseFoundation>(), e.Length < 1 || !e.GetBoolean(0));
t.Invoke(e.Mobile, obj);
}
switch ( result )
{
case DesignInsertResult.Valid:
{
AddResponse( "The item has been inserted into the house design." );
private class DesignInsertTarget : Target
{
private List<HouseFoundation> m_Foundations;
private bool m_StaticsOnly;
if ( !foundations.Contains( house ) )
foundations.Add( house );
public DesignInsertTarget(List<HouseFoundation> foundations, bool staticsOnly)
: base(-1, false, TargetFlags.None)
{
m_Foundations = foundations;
m_StaticsOnly = staticsOnly;
}
break;
}
case DesignInsertResult.InvalidItem:
{
LogFailure( "That cannot be inserted." );
break;
}
case DesignInsertResult.NotInHouse:
case DesignInsertResult.OutsideHouseBounds:
{
LogFailure( "That item is not inside a customizable house." );
break;
}
}
}
protected override void OnTargetCancel(Mobile from, TargetCancelType cancelType)
{
if (m_Foundations.Count != 0)
{
from.SendMessage("Your changes have been committed. Updating...");
foreach ( HouseFoundation house in foundations )
house.Delta( ItemDelta.Update );
}
else
{
AddResponse( "Command aborted." );
}
foreach (HouseFoundation house in m_Foundations)
house.Delta(ItemDelta.Update);
}
}
Flush( from, flushToLog );
}
#endregion
protected override void OnTarget(Mobile from, object obj)
{
HouseFoundation house;
DesignInsertResult result = ProcessInsert(obj as Item, m_StaticsOnly, out house);
public enum DesignInsertResult
{
Valid,
InvalidItem,
NotInHouse,
OutsideHouseBounds
}
switch (result)
{
case DesignInsertResult.Valid:
{
if (m_Foundations.Count == 0)
from.SendMessage(
"The item has been inserted into the house design. Press ESC when you are finished.");
else
from.SendMessage("The item has been inserted into the house design.");
public static DesignInsertResult ProcessInsert( Item item, bool staticsOnly, out HouseFoundation house )
{
house = null;
if (!m_Foundations.Contains(house))
m_Foundations.Add(house);
if ( item == null || item is BaseMulti || item is HouseSign || ( staticsOnly && !( item is Static ) ) )
return DesignInsertResult.InvalidItem;
break;
}
case DesignInsertResult.InvalidItem:
{
from.SendMessage("That cannot be inserted. Try again.");
break;
}
case DesignInsertResult.NotInHouse:
case DesignInsertResult.OutsideHouseBounds:
{
from.SendMessage("That item is not inside a customizable house. Try again.");
break;
}
}
house = BaseHouse.FindHouseAt( item ) as HouseFoundation;
from.Target = new DesignInsertTarget(m_Foundations, m_StaticsOnly);
}
}
if ( house == null )
return DesignInsertResult.NotInHouse;
#endregion
int x = item.X - house.X;
int y = item.Y - house.Y;
int z = item.Z - house.Z;
#region Area targeting mode
if ( !TryInsertIntoState( house.CurrentState, item.ItemID, x, y, z ) )
return DesignInsertResult.OutsideHouseBounds;
public override void ExecuteList(CommandEventArgs e, ArrayList list)
{
e.Mobile.SendGump(new WarningGump(1060637, 30720,
$"You are about to insert {list.Count} objects. This cannot be undone without a full server revert.<br><br>Continue?",
0xFFC000, 420, 280, OnConfirmCallback, new object[] { e, list, e.Length < 1 || !e.GetBoolean(0) }));
AddResponse("Awaiting confirmation...");
}
TryInsertIntoState( house.DesignState, item.ItemID, x, y, z );
item.Delete();
private void OnConfirmCallback(Mobile from, bool okay, object state)
{
object[] states = (object[])state;
CommandEventArgs e = (CommandEventArgs)states[0];
ArrayList list = (ArrayList)states[1];
bool staticsOnly = (bool)states[2];
return DesignInsertResult.Valid;
}
bool flushToLog = false;
private static bool TryInsertIntoState( DesignState state, int itemID, int x, int y, int z )
{
MultiComponentList mcl = state.Components;
if (okay)
{
List<HouseFoundation> foundations = new List<HouseFoundation>();
flushToLog = list.Count > 20;
if ( x < mcl.Min.X || y < mcl.Min.Y || x > mcl.Max.X || y > mcl.Max.Y )
return false;
for (int i = 0; i < list.Count; ++i)
{
HouseFoundation house;
DesignInsertResult result = ProcessInsert(list[i] as Item, staticsOnly, out house);
mcl.Add( itemID, x, y, z );
state.OnRevised();
switch (result)
{
case DesignInsertResult.Valid:
{
AddResponse("The item has been inserted into the house design.");
return true;
}
}
}
if (!foundations.Contains(house))
foundations.Add(house);
break;
}
case DesignInsertResult.InvalidItem:
{
LogFailure("That cannot be inserted.");
break;
}
case DesignInsertResult.NotInHouse:
case DesignInsertResult.OutsideHouseBounds:
{
LogFailure("That item is not inside a customizable house.");
break;
}
}
}
foreach (HouseFoundation house in foundations)
house.Delta(ItemDelta.Update);
}
else
{
AddResponse("Command aborted.");
}
Flush(from, flushToLog);
}
#endregion
}
}

File diff suppressed because it is too large Load diff

View file

@ -4,139 +4,131 @@ using System.Collections.Generic;
namespace Server.Commands.Generic
{
public delegate BaseExtension ExtensionConstructor();
public delegate BaseExtension ExtensionConstructor();
public sealed class ExtensionInfo
{
public static Dictionary<string, ExtensionInfo> Table { get; } = new Dictionary<string, ExtensionInfo>( StringComparer.InvariantCultureIgnoreCase );
public sealed class ExtensionInfo
{
public ExtensionInfo(int order, string name, int size, ExtensionConstructor constructor)
{
Name = name;
Size = size;
public static void Register( ExtensionInfo ext )
{
Table[ext.Name] = ext;
}
Order = order;
public int Order { get; }
Constructor = constructor;
}
public string Name { get; }
public static Dictionary<string, ExtensionInfo> Table{ get; } =
new Dictionary<string, ExtensionInfo>(StringComparer.InvariantCultureIgnoreCase);
public int Size { get; }
public int Order{ get; }
public bool IsFixedSize => ( Size >= 0 );
public string Name{ get; }
public ExtensionConstructor Constructor { get; }
public int Size{ get; }
public ExtensionInfo( int order, string name, int size, ExtensionConstructor constructor )
{
Name = name;
Size = size;
public bool IsFixedSize => Size >= 0;
Order = order;
public ExtensionConstructor Constructor{ get; }
Constructor = constructor;
}
}
public static void Register(ExtensionInfo ext)
{
Table[ext.Name] = ext;
}
}
public sealed class Extensions : List<BaseExtension>
{
public Extensions()
{
}
public sealed class Extensions : List<BaseExtension>
{
public bool IsValid(object obj)
{
for (int i = 0; i < Count; ++i)
if (!this[i].IsValid(obj))
return false;
public bool IsValid( object obj )
{
for ( int i = 0; i < Count; ++i )
{
if ( !this[i].IsValid( obj ) )
return false;
}
return true;
}
return true;
}
public void Filter(ArrayList list)
{
for (int i = 0; i < Count; ++i)
this[i].Filter(list);
}
public void Filter( ArrayList list )
{
for ( int i = 0; i < Count; ++i )
this[i].Filter( list );
}
public static Extensions Parse(Mobile from, ref string[] args)
{
Extensions parsed = new Extensions();
public static Extensions Parse( Mobile from, ref string[] args )
{
Extensions parsed = new Extensions();
int size = args.Length;
int size = args.Length;
Type baseType = null;
Type baseType = null;
for (int i = args.Length - 1; i >= 0; --i)
{
if (!ExtensionInfo.Table.TryGetValue(args[i], out ExtensionInfo extInfo))
continue;
for ( int i = args.Length - 1; i >= 0; --i )
{
if ( !ExtensionInfo.Table.TryGetValue( args[i], out ExtensionInfo extInfo ) )
continue;
if (extInfo.IsFixedSize && i != size - extInfo.Size - 1)
throw new Exception("Invalid extended argument count.");
if ( extInfo.IsFixedSize && i != ( size - extInfo.Size - 1 ) )
throw new Exception( "Invalid extended argument count." );
BaseExtension ext = extInfo.Constructor();
BaseExtension ext = extInfo.Constructor();
ext.Parse(from, args, i + 1, size - i - 1);
ext.Parse( from, args, i + 1, size - i - 1 );
if (ext is WhereExtension extension)
baseType = extension.Conditional.Type;
if ( ext is WhereExtension extension )
baseType = extension.Conditional.Type;
parsed.Add(ext);
parsed.Add( ext );
size = i;
}
size = i;
}
parsed.Sort(delegate(BaseExtension a, BaseExtension b) { return a.Order - b.Order; });
parsed.Sort( delegate( BaseExtension a, BaseExtension b )
{
return ( a.Order - b.Order );
} );
AssemblyEmitter emitter = null;
AssemblyEmitter emitter = null;
foreach (BaseExtension update in parsed)
update.Optimize(from, baseType, ref emitter);
foreach ( BaseExtension update in parsed )
update.Optimize( from, baseType, ref emitter );
if (size != args.Length)
{
string[] old = args;
args = new string[size];
if ( size != args.Length )
{
string[] old = args;
args = new string[size];
for (int i = 0; i < args.Length; ++i)
args[i] = old[i];
}
for ( int i = 0; i < args.Length; ++i )
args[i] = old[i];
}
return parsed;
}
}
return parsed;
}
}
public abstract class BaseExtension
{
public abstract ExtensionInfo Info{ get; }
public abstract class BaseExtension
{
public abstract ExtensionInfo Info { get; }
public string Name => Info.Name;
public string Name => Info.Name;
public int Size => Info.Size;
public int Size => Info.Size;
public bool IsFixedSize => Info.IsFixedSize;
public bool IsFixedSize => Info.IsFixedSize;
public int Order => Info.Order;
public int Order => Info.Order;
public virtual void Optimize(Mobile from, Type baseType, ref AssemblyEmitter assembly)
{
}
public virtual void Optimize( Mobile from, Type baseType, ref AssemblyEmitter assembly )
{
}
public virtual void Parse(Mobile from, string[] arguments, int offset, int size)
{
}
public virtual void Parse( Mobile from, string[] arguments, int offset, int size )
{
}
public virtual bool IsValid(object obj)
{
return true;
}
public virtual bool IsValid( object obj )
{
return true;
}
public virtual void Filter( ArrayList list )
{
}
}
}
public virtual void Filter(ArrayList list)
{
}
}
}

View file

@ -6,242 +6,254 @@ using System.Reflection.Emit;
namespace Server.Commands.Generic
{
public static class DistinctCompiler
{
public static IComparer Compile( AssemblyEmitter assembly, Type objectType, Property[] props )
{
TypeBuilder typeBuilder = assembly.DefineType(
"__distinct",
TypeAttributes.Public,
typeof( object )
);
public static class DistinctCompiler
{
public static IComparer Compile(AssemblyEmitter assembly, Type objectType, Property[] props)
{
TypeBuilder typeBuilder = assembly.DefineType(
"__distinct",
TypeAttributes.Public,
typeof(object)
);
#region Constructor
{
ConstructorBuilder ctor = typeBuilder.DefineConstructor(
MethodAttributes.Public,
CallingConventions.Standard,
Type.EmptyTypes
);
#region Constructor
ILGenerator il = ctor.GetILGenerator();
{
ConstructorBuilder ctor = typeBuilder.DefineConstructor(
MethodAttributes.Public,
CallingConventions.Standard,
Type.EmptyTypes
);
// : base()
il.Emit( OpCodes.Ldarg_0 );
il.Emit( OpCodes.Call, typeof( object ).GetConstructor( Type.EmptyTypes ) );
ILGenerator il = ctor.GetILGenerator();
// return;
il.Emit( OpCodes.Ret );
}
#endregion
// : base()
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));
#region IComparer
typeBuilder.AddInterfaceImplementation( typeof( IComparer ) );
// return;
il.Emit(OpCodes.Ret);
}
MethodBuilder compareMethod;
#endregion
#region Compare
{
MethodEmitter emitter = new MethodEmitter( typeBuilder );
#region IComparer
emitter.Define(
/* name */ "Compare",
/* attr */ MethodAttributes.Public | MethodAttributes.Virtual,
/* return */ typeof( int ),
/* params */ new[] { typeof( object ), typeof( object ) } );
typeBuilder.AddInterfaceImplementation(typeof(IComparer));
LocalBuilder a = emitter.CreateLocal( objectType );
LocalBuilder b = emitter.CreateLocal( objectType );
MethodBuilder compareMethod;
LocalBuilder v = emitter.CreateLocal( typeof( int ) );
#region Compare
emitter.LoadArgument( 1 );
emitter.CastAs( objectType );
emitter.StoreLocal( a );
{
MethodEmitter emitter = new MethodEmitter(typeBuilder);
emitter.LoadArgument( 2 );
emitter.CastAs( objectType );
emitter.StoreLocal( b );
emitter.Define(
/* name */ "Compare",
/* attr */ MethodAttributes.Public | MethodAttributes.Virtual,
/* return */ typeof(int),
/* params */ new[] { typeof(object), typeof(object) });
emitter.Load( 0 );
emitter.StoreLocal( v );
LocalBuilder a = emitter.CreateLocal(objectType);
LocalBuilder b = emitter.CreateLocal(objectType);
Label end = emitter.CreateLabel();
LocalBuilder v = emitter.CreateLocal(typeof(int));
for ( int i = 0; i < props.Length; ++i )
{
if ( i > 0 )
{
emitter.LoadLocal( v );
emitter.BranchIfTrue( end ); // if ( v != 0 ) return v;
}
emitter.LoadArgument(1);
emitter.CastAs(objectType);
emitter.StoreLocal(a);
Property prop = props[i];
emitter.LoadArgument(2);
emitter.CastAs(objectType);
emitter.StoreLocal(b);
emitter.LoadLocal( a );
emitter.Chain( prop );
emitter.Load(0);
emitter.StoreLocal(v);
bool couldCompare =
emitter.CompareTo( 1, delegate
{
emitter.LoadLocal( b );
emitter.Chain( prop );
} );
Label end = emitter.CreateLabel();
if ( !couldCompare )
throw new InvalidOperationException( "Property is not comparable." );
for (int i = 0; i < props.Length; ++i)
{
if (i > 0)
{
emitter.LoadLocal(v);
emitter.BranchIfTrue(end); // if ( v != 0 ) return v;
}
emitter.StoreLocal( v );
}
Property prop = props[i];
emitter.MarkLabel( end );
emitter.LoadLocal(a);
emitter.Chain(prop);
emitter.LoadLocal( v );
emitter.Return();
bool couldCompare =
emitter.CompareTo(1, delegate
{
emitter.LoadLocal(b);
emitter.Chain(prop);
});
typeBuilder.DefineMethodOverride(
emitter.Method,
typeof( IComparer ).GetMethod(
"Compare",
new[]
{
typeof( object ),
typeof( object )
}
)
);
if (!couldCompare)
throw new InvalidOperationException("Property is not comparable.");
compareMethod = emitter.Method;
}
#endregion
#endregion
emitter.StoreLocal(v);
}
#region IEqualityComparer
typeBuilder.AddInterfaceImplementation( typeof( IEqualityComparer<object> ) );
emitter.MarkLabel(end);
#region Equals
{
MethodEmitter emitter = new MethodEmitter( typeBuilder );
emitter.LoadLocal(v);
emitter.Return();
emitter.Define(
/* name */ "Equals",
/* attr */ MethodAttributes.Public | MethodAttributes.Virtual,
/* return */ typeof( bool ),
/* params */ new[] { typeof( object ), typeof( object ) } );
typeBuilder.DefineMethodOverride(
emitter.Method,
typeof(IComparer).GetMethod(
"Compare",
new[]
{
typeof(object),
typeof(object)
}
)
);
emitter.Generator.Emit( OpCodes.Ldarg_0 );
emitter.Generator.Emit( OpCodes.Ldarg_1 );
emitter.Generator.Emit( OpCodes.Ldarg_2 );
compareMethod = emitter.Method;
}
emitter.Generator.Emit( OpCodes.Call, compareMethod );
#endregion
emitter.Generator.Emit( OpCodes.Ldc_I4_0 );
#endregion
emitter.Generator.Emit( OpCodes.Ceq );
#region IEqualityComparer
emitter.Generator.Emit( OpCodes.Ret );
typeBuilder.AddInterfaceImplementation(typeof(IEqualityComparer<object>));
typeBuilder.DefineMethodOverride(
emitter.Method,
typeof( IEqualityComparer<object> ).GetMethod(
"Equals",
new[]
{
typeof( object ),
typeof( object )
}
)
);
}
#endregion
#region Equals
#region GetHashCode
{
MethodEmitter emitter = new MethodEmitter( typeBuilder );
{
MethodEmitter emitter = new MethodEmitter(typeBuilder);
emitter.Define(
/* name */ "GetHashCode",
/* attr */ MethodAttributes.Public | MethodAttributes.Virtual,
/* return */ typeof( int ),
/* params */ new[] { typeof( object ) } );
emitter.Define(
/* name */ "Equals",
/* attr */ MethodAttributes.Public | MethodAttributes.Virtual,
/* return */ typeof(bool),
/* params */ new[] { typeof(object), typeof(object) });
LocalBuilder obj = emitter.CreateLocal( objectType );
emitter.Generator.Emit(OpCodes.Ldarg_0);
emitter.Generator.Emit(OpCodes.Ldarg_1);
emitter.Generator.Emit(OpCodes.Ldarg_2);
emitter.LoadArgument( 1 );
emitter.CastAs( objectType );
emitter.StoreLocal( obj );
emitter.Generator.Emit(OpCodes.Call, compareMethod);
for ( int i = 0; i < props.Length; ++i )
{
Property prop = props[i];
emitter.Generator.Emit(OpCodes.Ldc_I4_0);
emitter.LoadLocal( obj );
emitter.Chain( prop );
emitter.Generator.Emit(OpCodes.Ceq);
Type active = emitter.Active;
emitter.Generator.Emit(OpCodes.Ret);
MethodInfo getHashCode = active.GetMethod( "GetHashCode", Type.EmptyTypes );
typeBuilder.DefineMethodOverride(
emitter.Method,
typeof(IEqualityComparer<object>).GetMethod(
"Equals",
new[]
{
typeof(object),
typeof(object)
}
)
);
}
if ( getHashCode == null )
getHashCode = typeof( object ).GetMethod( "GetHashCode", Type.EmptyTypes );
#endregion
if ( active != typeof( int ) )
{
if ( !active.IsValueType )
{
LocalBuilder value = emitter.AcquireTemp( active );
#region GetHashCode
Label valueNotNull = emitter.CreateLabel();
Label done = emitter.CreateLabel();
{
MethodEmitter emitter = new MethodEmitter(typeBuilder);
emitter.StoreLocal( value );
emitter.LoadLocal( value );
emitter.Define(
/* name */ "GetHashCode",
/* attr */ MethodAttributes.Public | MethodAttributes.Virtual,
/* return */ typeof(int),
/* params */ new[] { typeof(object) });
emitter.BranchIfTrue( valueNotNull );
LocalBuilder obj = emitter.CreateLocal(objectType);
emitter.Load( 0 );
emitter.Pop( typeof( int ) );
emitter.LoadArgument(1);
emitter.CastAs(objectType);
emitter.StoreLocal(obj);
emitter.Branch( done );
for (int i = 0; i < props.Length; ++i)
{
Property prop = props[i];
emitter.MarkLabel( valueNotNull );
emitter.LoadLocal(obj);
emitter.Chain(prop);
emitter.LoadLocal( value );
emitter.Call( getHashCode );
Type active = emitter.Active;
emitter.ReleaseTemp( value );
MethodInfo getHashCode = active.GetMethod("GetHashCode", Type.EmptyTypes);
emitter.MarkLabel( done );
}
else
{
emitter.Call( getHashCode );
}
}
if (getHashCode == null)
getHashCode = typeof(object).GetMethod("GetHashCode", Type.EmptyTypes);
if ( i > 0 )
emitter.Xor();
}
if (active != typeof(int))
{
if (!active.IsValueType)
{
LocalBuilder value = emitter.AcquireTemp(active);
emitter.Return();
Label valueNotNull = emitter.CreateLabel();
Label done = emitter.CreateLabel();
typeBuilder.DefineMethodOverride(
emitter.Method,
typeof( IEqualityComparer<object> ).GetMethod(
"GetHashCode",
new[]
{
typeof( object )
}
)
);
}
#endregion
#endregion
emitter.StoreLocal(value);
emitter.LoadLocal(value);
Type comparerType = typeBuilder.CreateType();
emitter.BranchIfTrue(valueNotNull);
return (IComparer) Activator.CreateInstance( comparerType );
}
}
}
emitter.Load(0);
emitter.Pop(typeof(int));
emitter.Branch(done);
emitter.MarkLabel(valueNotNull);
emitter.LoadLocal(value);
emitter.Call(getHashCode);
emitter.ReleaseTemp(value);
emitter.MarkLabel(done);
}
else
{
emitter.Call(getHashCode);
}
}
if (i > 0)
emitter.Xor();
}
emitter.Return();
typeBuilder.DefineMethodOverride(
emitter.Method,
typeof(IEqualityComparer<object>).GetMethod(
"GetHashCode",
new[]
{
typeof(object)
}
)
);
}
#endregion
#endregion
Type comparerType = typeBuilder.CreateType();
return (IComparer)Activator.CreateInstance(comparerType);
}
}
}

View file

@ -5,160 +5,166 @@ using System.Reflection.Emit;
namespace Server.Commands.Generic
{
public sealed class OrderInfo
{
private int m_Order;
public sealed class OrderInfo
{
private int m_Order;
public Property Property { get; set; }
public OrderInfo(Property property, bool isAscending)
{
Property = property;
public bool IsAscending
{
get => ( m_Order > 0 );
set => m_Order = ( value ? +1 : -1 );
}
IsAscending = isAscending;
}
public bool IsDescending
{
get => ( m_Order < 0 );
set => m_Order = ( value ? -1 : +1 );
}
public Property Property{ get; set; }
public int Sign
{
get => Math.Sign( m_Order );
set
{
m_Order = Math.Sign( value );
public bool IsAscending
{
get => m_Order > 0;
set => m_Order = value ? +1 : -1;
}
if ( m_Order == 0 )
throw new InvalidOperationException( "Sign cannot be zero." );
}
}
public bool IsDescending
{
get => m_Order < 0;
set => m_Order = value ? -1 : +1;
}
public OrderInfo( Property property, bool isAscending )
{
Property = property;
public int Sign
{
get => Math.Sign(m_Order);
set
{
m_Order = Math.Sign(value);
IsAscending = isAscending;
}
}
if (m_Order == 0)
throw new InvalidOperationException("Sign cannot be zero.");
}
}
}
public static class SortCompiler
{
public static IComparer Compile( AssemblyEmitter assembly, Type objectType, OrderInfo[] orders )
{
TypeBuilder typeBuilder = assembly.DefineType(
"__sort",
TypeAttributes.Public,
typeof( object )
);
public static class SortCompiler
{
public static IComparer Compile(AssemblyEmitter assembly, Type objectType, OrderInfo[] orders)
{
TypeBuilder typeBuilder = assembly.DefineType(
"__sort",
TypeAttributes.Public,
typeof(object)
);
#region Constructor
{
ConstructorBuilder ctor = typeBuilder.DefineConstructor(
MethodAttributes.Public,
CallingConventions.Standard,
Type.EmptyTypes
);
#region Constructor
ILGenerator il = ctor.GetILGenerator();
{
ConstructorBuilder ctor = typeBuilder.DefineConstructor(
MethodAttributes.Public,
CallingConventions.Standard,
Type.EmptyTypes
);
// : base()
il.Emit( OpCodes.Ldarg_0 );
il.Emit( OpCodes.Call, typeof( object ).GetConstructor( Type.EmptyTypes ) );
ILGenerator il = ctor.GetILGenerator();
// return;
il.Emit( OpCodes.Ret );
}
#endregion
// : base()
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));
#region IComparer
typeBuilder.AddInterfaceImplementation( typeof( IComparer ) );
// return;
il.Emit(OpCodes.Ret);
}
MethodBuilder compareMethod;
#endregion
#region Compare
{
MethodEmitter emitter = new MethodEmitter( typeBuilder );
#region IComparer
emitter.Define(
/* name */ "Compare",
/* attr */ MethodAttributes.Public | MethodAttributes.Virtual,
/* return */ typeof( int ),
/* params */ new[] { typeof( object ), typeof( object ) } );
typeBuilder.AddInterfaceImplementation(typeof(IComparer));
LocalBuilder a = emitter.CreateLocal( objectType );
LocalBuilder b = emitter.CreateLocal( objectType );
MethodBuilder compareMethod;
LocalBuilder v = emitter.CreateLocal( typeof( int ) );
#region Compare
emitter.LoadArgument( 1 );
emitter.CastAs( objectType );
emitter.StoreLocal( a );
{
MethodEmitter emitter = new MethodEmitter(typeBuilder);
emitter.LoadArgument( 2 );
emitter.CastAs( objectType );
emitter.StoreLocal( b );
emitter.Define(
/* name */ "Compare",
/* attr */ MethodAttributes.Public | MethodAttributes.Virtual,
/* return */ typeof(int),
/* params */ new[] { typeof(object), typeof(object) });
emitter.Load( 0 );
emitter.StoreLocal( v );
LocalBuilder a = emitter.CreateLocal(objectType);
LocalBuilder b = emitter.CreateLocal(objectType);
Label end = emitter.CreateLabel();
LocalBuilder v = emitter.CreateLocal(typeof(int));
for ( int i = 0; i < orders.Length; ++i )
{
if ( i > 0 )
{
emitter.LoadLocal( v );
emitter.BranchIfTrue( end ); // if ( v != 0 ) return v;
}
emitter.LoadArgument(1);
emitter.CastAs(objectType);
emitter.StoreLocal(a);
OrderInfo orderInfo = orders[i];
emitter.LoadArgument(2);
emitter.CastAs(objectType);
emitter.StoreLocal(b);
Property prop = orderInfo.Property;
int sign = orderInfo.Sign;
emitter.Load(0);
emitter.StoreLocal(v);
emitter.LoadLocal( a );
emitter.Chain( prop );
Label end = emitter.CreateLabel();
bool couldCompare =
emitter.CompareTo( sign, delegate
{
emitter.LoadLocal( b );
emitter.Chain( prop );
} );
for (int i = 0; i < orders.Length; ++i)
{
if (i > 0)
{
emitter.LoadLocal(v);
emitter.BranchIfTrue(end); // if ( v != 0 ) return v;
}
if ( !couldCompare )
throw new InvalidOperationException( "Property is not comparable." );
OrderInfo orderInfo = orders[i];
emitter.StoreLocal( v );
}
Property prop = orderInfo.Property;
int sign = orderInfo.Sign;
emitter.MarkLabel( end );
emitter.LoadLocal(a);
emitter.Chain(prop);
emitter.LoadLocal( v );
emitter.Return();
bool couldCompare =
emitter.CompareTo(sign, delegate
{
emitter.LoadLocal(b);
emitter.Chain(prop);
});
typeBuilder.DefineMethodOverride(
emitter.Method,
typeof( IComparer ).GetMethod(
"Compare",
new[]
{
typeof( object ),
typeof( object )
}
)
);
if (!couldCompare)
throw new InvalidOperationException("Property is not comparable.");
compareMethod = emitter.Method;
}
#endregion
#endregion
emitter.StoreLocal(v);
}
Type comparerType = typeBuilder.CreateType();
emitter.MarkLabel(end);
return (IComparer) Activator.CreateInstance( comparerType );
}
}
}
emitter.LoadLocal(v);
emitter.Return();
typeBuilder.DefineMethodOverride(
emitter.Method,
typeof(IComparer).GetMethod(
"Compare",
new[]
{
typeof(object),
typeof(object)
}
)
);
compareMethod = emitter.Method;
}
#endregion
#endregion
Type comparerType = typeBuilder.CreateType();
return (IComparer)Activator.CreateInstance(comparerType);
}
}
}

View file

@ -4,81 +4,82 @@ using System.Collections.Generic;
namespace Server.Commands.Generic
{
public sealed class DistinctExtension : BaseExtension
{
public static ExtensionInfo ExtInfo = new ExtensionInfo( 30, "Distinct", -1, delegate { return new DistinctExtension(); } );
public sealed class DistinctExtension : BaseExtension
{
public static ExtensionInfo ExtInfo =
new ExtensionInfo(30, "Distinct", -1, delegate { return new DistinctExtension(); });
public static void Initialize()
{
ExtensionInfo.Register( ExtInfo );
}
private IComparer m_Comparer;
public override ExtensionInfo Info => ExtInfo;
private List<Property> m_Properties;
private List<Property> m_Properties;
public DistinctExtension()
{
m_Properties = new List<Property>();
}
private IComparer m_Comparer;
public override ExtensionInfo Info => ExtInfo;
public DistinctExtension()
{
m_Properties = new List<Property>();
}
public static void Initialize()
{
ExtensionInfo.Register(ExtInfo);
}
public override void Optimize( Mobile from, Type baseType, ref AssemblyEmitter assembly )
{
if ( baseType == null )
throw new Exception( "Distinct extension may only be used in combination with an object conditional." );
public override void Optimize(Mobile from, Type baseType, ref AssemblyEmitter assembly)
{
if (baseType == null)
throw new Exception("Distinct extension may only be used in combination with an object conditional.");
foreach ( Property prop in m_Properties )
{
prop.BindTo( baseType, PropertyAccess.Read );
prop.CheckAccess( from );
}
foreach (Property prop in m_Properties)
{
prop.BindTo(baseType, PropertyAccess.Read);
prop.CheckAccess(from);
}
if ( assembly == null )
assembly = new AssemblyEmitter( "__dynamic", false );
if (assembly == null)
assembly = new AssemblyEmitter("__dynamic", false);
m_Comparer = DistinctCompiler.Compile( assembly, baseType, m_Properties.ToArray() );
}
m_Comparer = DistinctCompiler.Compile(assembly, baseType, m_Properties.ToArray());
}
public override void Parse( Mobile from, string[] arguments, int offset, int size )
{
if ( size < 1 )
throw new Exception( "Invalid distinction syntax." );
public override void Parse(Mobile from, string[] arguments, int offset, int size)
{
if (size < 1)
throw new Exception("Invalid distinction syntax.");
int end = offset + size;
int end = offset + size;
while ( offset < end )
{
string binding = arguments[offset++];
while (offset < end)
{
string binding = arguments[offset++];
m_Properties.Add( new Property( binding ) );
}
}
m_Properties.Add(new Property(binding));
}
}
public override void Filter( ArrayList list )
{
if ( m_Comparer == null )
throw new InvalidOperationException( "The extension must first be optimized." );
public override void Filter(ArrayList list)
{
if (m_Comparer == null)
throw new InvalidOperationException("The extension must first be optimized.");
ArrayList copy = new ArrayList( list );
ArrayList copy = new ArrayList(list);
copy.Sort( m_Comparer );
copy.Sort(m_Comparer);
list.Clear();
list.Clear();
object last = null;
object last = null;
for ( int i = 0; i < copy.Count; ++i )
{
object obj = copy[i];
for (int i = 0; i < copy.Count; ++i)
{
object obj = copy[i];
if ( last == null || m_Comparer.Compare( obj, last ) != 0 )
{
list.Add( obj );
last = obj;
}
}
}
}
}
if (last == null || m_Comparer.Compare(obj, last) != 0)
{
list.Add(obj);
last = obj;
}
}
}
}
}

View file

@ -3,35 +3,31 @@ using System.Collections;
namespace Server.Commands.Generic
{
public sealed class LimitExtension : BaseExtension
{
public static ExtensionInfo ExtInfo = new ExtensionInfo( 80, "Limit", 1, delegate { return new LimitExtension(); } );
public sealed class LimitExtension : BaseExtension
{
public static ExtensionInfo ExtInfo = new ExtensionInfo(80, "Limit", 1, delegate { return new LimitExtension(); });
public static void Initialize()
{
ExtensionInfo.Register( ExtInfo );
}
public override ExtensionInfo Info => ExtInfo;
public override ExtensionInfo Info => ExtInfo;
public int Limit{ get; private set; }
public int Limit { get; private set; }
public static void Initialize()
{
ExtensionInfo.Register(ExtInfo);
}
public LimitExtension()
{
}
public override void Parse(Mobile from, string[] arguments, int offset, int size)
{
Limit = Utility.ToInt32(arguments[offset]);
public override void Parse( Mobile from, string[] arguments, int offset, int size )
{
Limit = Utility.ToInt32( arguments[offset] );
if (Limit < 0)
throw new Exception("Limit cannot be less than zero.");
}
if ( Limit < 0 )
throw new Exception( "Limit cannot be less than zero." );
}
public override void Filter( ArrayList list )
{
if ( list.Count > Limit )
list.RemoveRange( Limit, list.Count - Limit );
}
}
}
public override void Filter(ArrayList list)
{
if (list.Count > Limit)
list.RemoveRange(Limit, list.Count - Limit);
}
}
}

View file

@ -4,101 +4,101 @@ using System.Collections.Generic;
namespace Server.Commands.Generic
{
public sealed class SortExtension : BaseExtension
{
public static ExtensionInfo ExtInfo = new ExtensionInfo( 40, "Order", -1, delegate { return new SortExtension(); } );
public sealed class SortExtension : BaseExtension
{
public static ExtensionInfo ExtInfo = new ExtensionInfo(40, "Order", -1, delegate { return new SortExtension(); });
public static void Initialize()
{
ExtensionInfo.Register( ExtInfo );
}
private IComparer m_Comparer;
public override ExtensionInfo Info => ExtInfo;
private List<OrderInfo> m_Orders;
private List<OrderInfo> m_Orders;
public SortExtension()
{
m_Orders = new List<OrderInfo>();
}
private IComparer m_Comparer;
public override ExtensionInfo Info => ExtInfo;
public SortExtension()
{
m_Orders = new List<OrderInfo>();
}
public static void Initialize()
{
ExtensionInfo.Register(ExtInfo);
}
public override void Optimize( Mobile from, Type baseType, ref AssemblyEmitter assembly )
{
if ( baseType == null )
throw new Exception( "The ordering extension may only be used in combination with an object conditional." );
public override void Optimize(Mobile from, Type baseType, ref AssemblyEmitter assembly)
{
if (baseType == null)
throw new Exception("The ordering extension may only be used in combination with an object conditional.");
foreach ( OrderInfo order in m_Orders )
{
order.Property.BindTo( baseType, PropertyAccess.Read );
order.Property.CheckAccess( from );
}
foreach (OrderInfo order in m_Orders)
{
order.Property.BindTo(baseType, PropertyAccess.Read);
order.Property.CheckAccess(from);
}
if ( assembly == null )
assembly = new AssemblyEmitter( "__dynamic", false );
if (assembly == null)
assembly = new AssemblyEmitter("__dynamic", false);
m_Comparer = SortCompiler.Compile( assembly, baseType, m_Orders.ToArray() );
}
m_Comparer = SortCompiler.Compile(assembly, baseType, m_Orders.ToArray());
}
public override void Parse( Mobile from, string[] arguments, int offset, int size )
{
if ( size < 1 )
throw new Exception( "Invalid ordering syntax." );
public override void Parse(Mobile from, string[] arguments, int offset, int size)
{
if (size < 1)
throw new Exception("Invalid ordering syntax.");
if ( Insensitive.Equals( arguments[offset], "by" ) )
{
++offset;
--size;
if (Insensitive.Equals(arguments[offset], "by"))
{
++offset;
--size;
if ( size < 1 )
throw new Exception( "Invalid ordering syntax." );
}
if (size < 1)
throw new Exception("Invalid ordering syntax.");
}
int end = offset + size;
int end = offset + size;
while ( offset < end )
{
string binding = arguments[offset++];
while (offset < end)
{
string binding = arguments[offset++];
bool isAscending = true;
bool isAscending = true;
if ( offset < end )
{
string next = arguments[offset];
if (offset < end)
{
string next = arguments[offset];
switch ( next.ToLower() )
{
case "+":
case "up":
case "asc":
case "ascending":
isAscending = true;
++offset;
break;
switch (next.ToLower())
{
case "+":
case "up":
case "asc":
case "ascending":
isAscending = true;
++offset;
break;
case "-":
case "down":
case "desc":
case "descending":
isAscending = false;
++offset;
break;
}
}
case "-":
case "down":
case "desc":
case "descending":
isAscending = false;
++offset;
break;
}
}
Property property = new Property( binding );
Property property = new Property(binding);
m_Orders.Add( new OrderInfo( property, isAscending ) );
}
}
m_Orders.Add(new OrderInfo(property, isAscending));
}
}
public override void Filter( ArrayList list )
{
if ( m_Comparer == null )
throw new InvalidOperationException( "The extension must first be optimized." );
public override void Filter(ArrayList list)
{
if (m_Comparer == null)
throw new InvalidOperationException("The extension must first be optimized.");
list.Sort( m_Comparer );
}
}
}
list.Sort(m_Comparer);
}
}
}

View file

@ -2,42 +2,38 @@ using System;
namespace Server.Commands.Generic
{
public sealed class WhereExtension : BaseExtension
{
public static ExtensionInfo ExtInfo = new ExtensionInfo( 20, "Where", -1, delegate { return new WhereExtension(); } );
public sealed class WhereExtension : BaseExtension
{
public static ExtensionInfo ExtInfo = new ExtensionInfo(20, "Where", -1, delegate { return new WhereExtension(); });
public static void Initialize()
{
ExtensionInfo.Register( ExtInfo );
}
public override ExtensionInfo Info => ExtInfo;
public override ExtensionInfo Info => ExtInfo;
public ObjectConditional Conditional{ get; private set; }
public ObjectConditional Conditional { get; private set; }
public static void Initialize()
{
ExtensionInfo.Register(ExtInfo);
}
public WhereExtension()
{
}
public override void Optimize(Mobile from, Type baseType, ref AssemblyEmitter assembly)
{
if (baseType == null)
throw new InvalidOperationException("Insanity.");
public override void Optimize( Mobile from, Type baseType, ref AssemblyEmitter assembly )
{
if ( baseType == null )
throw new InvalidOperationException( "Insanity." );
Conditional.Compile(ref assembly);
}
Conditional.Compile( ref assembly );
}
public override void Parse(Mobile from, string[] arguments, int offset, int size)
{
if (size < 1)
throw new Exception("Invalid condition syntax.");
public override void Parse( Mobile from, string[] arguments, int offset, int size )
{
if ( size < 1 )
throw new Exception( "Invalid condition syntax." );
Conditional = ObjectConditional.ParseDirect(from, arguments, offset, size);
}
Conditional = ObjectConditional.ParseDirect( from, arguments, offset, size );
}
public override bool IsValid( object obj )
{
return Conditional.CheckCondition( obj );
}
}
}
public override bool IsValid(object obj)
{
return Conditional.CheckCondition(obj);
}
}
}

View file

@ -3,72 +3,73 @@ using System.Collections;
namespace Server.Commands.Generic
{
public class AreaCommandImplementor : BaseCommandImplementor
{
public static AreaCommandImplementor Instance { get; private set; }
public class AreaCommandImplementor : BaseCommandImplementor
{
public AreaCommandImplementor()
{
Accessors = new[] { "Area", "Group" };
SupportRequirement = CommandSupport.Area;
SupportsConditionals = true;
AccessLevel = AccessLevel.GameMaster;
Usage = "Area <command> [condition]";
Description =
"Invokes the command on all appropriate objects in a targeted area. Optional condition arguments can further restrict the set of objects.";
public AreaCommandImplementor()
{
Accessors = new[]{ "Area", "Group" };
SupportRequirement = CommandSupport.Area;
SupportsConditionals = true;
AccessLevel = AccessLevel.GameMaster;
Usage = "Area <command> [condition]";
Description = "Invokes the command on all appropriate objects in a targeted area. Optional condition arguments can further restrict the set of objects.";
Instance = this;
}
Instance = this;
}
public static AreaCommandImplementor Instance{ get; private set; }
public override void Process( Mobile from, BaseCommand command, string[] args )
{
BoundingBoxPicker.Begin( from, OnTarget, new object[]{ command, args } );
}
public override void Process(Mobile from, BaseCommand command, string[] args)
{
BoundingBoxPicker.Begin(from, OnTarget, new object[] { command, args });
}
public void OnTarget( Mobile from, Map map, Point3D start, Point3D end, object state )
{
try
{
object[] states = (object[])state;
BaseCommand command = (BaseCommand)states[0];
string[] args = (string[])states[1];
public void OnTarget(Mobile from, Map map, Point3D start, Point3D end, object state)
{
try
{
object[] states = (object[])state;
BaseCommand command = (BaseCommand)states[0];
string[] args = (string[])states[1];
Rectangle2D rect = new Rectangle2D( start.X, start.Y, end.X - start.X + 1, end.Y - start.Y + 1 );
Rectangle2D rect = new Rectangle2D(start.X, start.Y, end.X - start.X + 1, end.Y - start.Y + 1);
Extensions ext = Extensions.Parse( from, ref args );
Extensions ext = Extensions.Parse(from, ref args);
bool items, mobiles;
bool items, mobiles;
if ( !CheckObjectTypes( from, command, ext, out items, out mobiles ) )
return;
if (!CheckObjectTypes(from, command, ext, out items, out mobiles))
return;
IPooledEnumerable<IEntity> eable;
IPooledEnumerable<IEntity> eable;
if (items || mobiles)
eable = map.GetObjectsInBounds(rect, items, mobiles);
else
return;
if (items || mobiles)
eable = map.GetObjectsInBounds(rect, items, mobiles);
else
return;
ArrayList objs = new ArrayList();
ArrayList objs = new ArrayList();
foreach ( IEntity obj in eable )
{
if ( mobiles && obj is Mobile && !BaseCommand.IsAccessible( from, obj ) )
continue;
foreach (IEntity obj in eable)
{
if (mobiles && obj is Mobile && !BaseCommand.IsAccessible(from, obj))
continue;
if ( ext.IsValid( obj ) )
objs.Add( obj );
}
if (ext.IsValid(obj))
objs.Add(obj);
}
eable.Free();
eable.Free();
ext.Filter( objs );
ext.Filter(objs);
RunCommand( from, objs, command, args );
}
catch ( Exception ex )
{
from.SendMessage( ex.Message );
}
}
}
}
RunCommand(from, objs, command, args);
}
catch (Exception ex)
{
from.SendMessage(ex.Message);
}
}
}
}

View file

@ -5,299 +5,294 @@ using System.Text;
namespace Server.Commands.Generic
{
[Flags]
public enum CommandSupport
{
Single = 0x0001,
Global = 0x0002,
Online = 0x0004,
Multi = 0x0008,
Area = 0x0010,
Self = 0x0020,
Region = 0x0040,
Contained = 0x0080,
IPAddress = 0x0100,
[Flags]
public enum CommandSupport
{
Single = 0x0001,
Global = 0x0002,
Online = 0x0004,
Multi = 0x0008,
Area = 0x0010,
Self = 0x0020,
Region = 0x0040,
Contained = 0x0080,
IPAddress = 0x0100,
All = Single | Global | Online | Multi | Area | Self | Region | Contained | IPAddress,
AllMobiles = All & ~Contained,
AllNPCs = All & ~(IPAddress | Online | Self | Contained),
AllItems = All & ~(IPAddress | Online | Self | Region),
All = Single | Global | Online | Multi | Area | Self | Region | Contained | IPAddress,
AllMobiles = All & ~Contained,
AllNPCs = All & ~(IPAddress | Online | Self | Contained),
AllItems = All & ~(IPAddress | Online | Self | Region),
Simple = Single | Multi,
Complex = Global | Online | Area | Region | Contained | IPAddress
}
Simple = Single | Multi,
Complex = Global | Online | Area | Region | Contained | IPAddress
}
public abstract class BaseCommandImplementor
{
public static void RegisterImplementors()
{
Register( new RegionCommandImplementor() );
Register( new GlobalCommandImplementor() );
Register( new OnlineCommandImplementor() );
Register( new SingleCommandImplementor() );
Register( new SerialCommandImplementor() );
Register( new MultiCommandImplementor() );
Register( new AreaCommandImplementor() );
Register( new SelfCommandImplementor() );
Register( new ContainedCommandImplementor() );
Register( new IPAddressCommandImplementor() );
public abstract class BaseCommandImplementor
{
private static List<BaseCommandImplementor> m_Implementors;
Register( new RangeCommandImplementor() );
Register( new ScreenCommandImplementor() );
Register( new FacetCommandImplementor() );
}
public BaseCommandImplementor()
{
Commands = new Dictionary<string, BaseCommand>(StringComparer.OrdinalIgnoreCase);
}
public bool SupportsConditionals { get; set; }
public bool SupportsConditionals{ get; set; }
public string[] Accessors { get; set; }
public string[] Accessors{ get; set; }
public string Usage { get; set; }
public string Usage{ get; set; }
public string Description { get; set; }
public string Description{ get; set; }
public AccessLevel AccessLevel { get; set; }
public AccessLevel AccessLevel{ get; set; }
public CommandSupport SupportRequirement { get; set; }
public CommandSupport SupportRequirement{ get; set; }
public Dictionary<string, BaseCommand> Commands { get; }
public Dictionary<string, BaseCommand> Commands{ get; }
public BaseCommandImplementor()
{
Commands = new Dictionary<string, BaseCommand>( StringComparer.OrdinalIgnoreCase );
}
public static List<BaseCommandImplementor> Implementors
{
get
{
if (m_Implementors == null)
{
m_Implementors = new List<BaseCommandImplementor>();
RegisterImplementors();
}
public virtual void Compile( Mobile from, BaseCommand command, ref string[] args, ref object obj )
{
obj = null;
}
return m_Implementors;
}
}
public virtual void Register( BaseCommand command )
{
for ( int i = 0; i < command.Commands.Length; ++i )
Commands[command.Commands[i]] = command;
}
public static void RegisterImplementors()
{
Register(new RegionCommandImplementor());
Register(new GlobalCommandImplementor());
Register(new OnlineCommandImplementor());
Register(new SingleCommandImplementor());
Register(new SerialCommandImplementor());
Register(new MultiCommandImplementor());
Register(new AreaCommandImplementor());
Register(new SelfCommandImplementor());
Register(new ContainedCommandImplementor());
Register(new IPAddressCommandImplementor());
public bool CheckObjectTypes( Mobile from, BaseCommand command, Extensions ext, out bool items, out bool mobiles )
{
items = mobiles = false;
Register(new RangeCommandImplementor());
Register(new ScreenCommandImplementor());
Register(new FacetCommandImplementor());
}
ObjectConditional cond = ObjectConditional.Empty;
public virtual void Compile(Mobile from, BaseCommand command, ref string[] args, ref object obj)
{
obj = null;
}
foreach ( BaseExtension check in ext )
{
if ( check is WhereExtension extension )
{
cond = extension.Conditional;
public virtual void Register(BaseCommand command)
{
for (int i = 0; i < command.Commands.Length; ++i)
Commands[command.Commands[i]] = command;
}
break;
}
}
public bool CheckObjectTypes(Mobile from, BaseCommand command, Extensions ext, out bool items, out bool mobiles)
{
items = mobiles = false;
bool condIsItem = cond.IsItem;
bool condIsMobile = cond.IsMobile;
ObjectConditional cond = ObjectConditional.Empty;
switch ( command.ObjectTypes )
{
case ObjectTypes.All:
case ObjectTypes.Both:
{
if ( condIsItem )
items = true;
foreach (BaseExtension check in ext)
if (check is WhereExtension extension)
{
cond = extension.Conditional;
if ( condIsMobile )
mobiles = true;
break;
}
break;
}
case ObjectTypes.Items:
{
if ( condIsItem )
{
items = true;
}
else if ( condIsMobile )
{
from.SendMessage( "You may not use a mobile type condition for this command." );
return false;
}
bool condIsItem = cond.IsItem;
bool condIsMobile = cond.IsMobile;
break;
}
case ObjectTypes.Mobiles:
{
if ( condIsMobile )
{
mobiles = true;
}
else if ( condIsItem )
{
from.SendMessage( "You may not use an item type condition for this command." );
return false;
}
switch (command.ObjectTypes)
{
case ObjectTypes.All:
case ObjectTypes.Both:
{
if (condIsItem)
items = true;
break;
}
}
if (condIsMobile)
mobiles = true;
return true;
}
break;
}
case ObjectTypes.Items:
{
if (condIsItem)
{
items = true;
}
else if (condIsMobile)
{
from.SendMessage("You may not use a mobile type condition for this command.");
return false;
}
public void RunCommand( Mobile from, BaseCommand command, string[] args )
{
try
{
object obj = null;
break;
}
case ObjectTypes.Mobiles:
{
if (condIsMobile)
{
mobiles = true;
}
else if (condIsItem)
{
from.SendMessage("You may not use an item type condition for this command.");
return false;
}
Compile( from, command, ref args, ref obj );
break;
}
}
RunCommand( from, obj, command, args );
}
catch ( Exception ex )
{
from.SendMessage( ex.Message );
}
}
return true;
}
public string GenerateArgString( string[] args )
{
if ( args.Length == 0 )
return "";
public void RunCommand(Mobile from, BaseCommand command, string[] args)
{
try
{
object obj = null;
// NOTE: this does not preserve the case where quotation marks are used on a single word
Compile(from, command, ref args, ref obj);
StringBuilder sb = new StringBuilder();
RunCommand(from, obj, command, args);
}
catch (Exception ex)
{
from.SendMessage(ex.Message);
}
}
for ( int i = 0; i < args.Length; ++i )
{
if ( i > 0 )
sb.Append( ' ' );
public string GenerateArgString(string[] args)
{
if (args.Length == 0)
return "";
if ( args[i].IndexOf( ' ' ) >= 0 )
{
sb.Append( '"' );
sb.Append( args[i] );
sb.Append( '"' );
}
else
{
sb.Append( args[i] );
}
}
// NOTE: this does not preserve the case where quotation marks are used on a single word
return sb.ToString();
}
StringBuilder sb = new StringBuilder();
public void RunCommand( Mobile from, object obj, BaseCommand command, string[] args )
{
// try
// {
CommandEventArgs e = new CommandEventArgs( from, command.Commands[0], GenerateArgString( args ), args );
for (int i = 0; i < args.Length; ++i)
{
if (i > 0)
sb.Append(' ');
if ( !command.ValidateArgs( this, e ) )
return;
if (args[i].IndexOf(' ') >= 0)
{
sb.Append('"');
sb.Append(args[i]);
sb.Append('"');
}
else
{
sb.Append(args[i]);
}
}
bool flushToLog = false;
return sb.ToString();
}
if ( obj is ArrayList list )
{
if ( list.Count > 20 )
CommandLogging.Enabled = false;
else if ( list.Count == 0 )
command.LogFailure( "Nothing was found to use this command on." );
public void RunCommand(Mobile from, object obj, BaseCommand command, string[] args)
{
// try
// {
CommandEventArgs e = new CommandEventArgs(from, command.Commands[0], GenerateArgString(args), args);
command.ExecuteList( e, list );
if (!command.ValidateArgs(this, e))
return;
if ( list.Count > 20 )
{
flushToLog = true;
CommandLogging.Enabled = true;
}
}
else if ( obj != null )
{
if ( command.ListOptimized )
{
command.ExecuteList( e, new ArrayList{ obj } );
}
else
{
command.Execute( e, obj );
}
}
bool flushToLog = false;
command.Flush( from, flushToLog );
// }
// catch ( Exception ex )
// {
// from.SendMessage( ex.Message );
// }
}
if (obj is ArrayList list)
{
if (list.Count > 20)
CommandLogging.Enabled = false;
else if (list.Count == 0)
command.LogFailure("Nothing was found to use this command on.");
public virtual void Process( Mobile from, BaseCommand command, string[] args )
{
RunCommand( from, command, args );
}
command.ExecuteList(e, list);
public virtual void Execute( CommandEventArgs e )
{
if ( e.Length >= 1 )
{
Commands.TryGetValue( e.GetString( 0 ), out BaseCommand command );
if (list.Count > 20)
{
flushToLog = true;
CommandLogging.Enabled = true;
}
}
else if (obj != null)
{
if (command.ListOptimized)
command.ExecuteList(e, new ArrayList { obj });
else
command.Execute(e, obj);
}
if ( command == null )
{
e.Mobile.SendMessage( "That is either an invalid command name or one that does not support this modifier." );
}
else if ( e.Mobile.AccessLevel < command.AccessLevel )
{
e.Mobile.SendMessage( "You do not have access to that command." );
}
else
{
string[] oldArgs = e.Arguments;
string[] args = new string[oldArgs.Length - 1];
command.Flush(from, flushToLog);
// }
// catch ( Exception ex )
// {
// from.SendMessage( ex.Message );
// }
}
for ( int i = 0; i < args.Length; ++i )
args[i] = oldArgs[i + 1];
public virtual void Process(Mobile from, BaseCommand command, string[] args)
{
RunCommand(from, command, args);
}
Process( e.Mobile, command, args );
}
}
else
{
e.Mobile.SendMessage( "You must supply a command name." );
}
}
public virtual void Execute(CommandEventArgs e)
{
if (e.Length >= 1)
{
Commands.TryGetValue(e.GetString(0), out BaseCommand command);
public void Register()
{
if ( Accessors == null )
return;
if (command == null)
{
e.Mobile.SendMessage(
"That is either an invalid command name or one that does not support this modifier.");
}
else if (e.Mobile.AccessLevel < command.AccessLevel)
{
e.Mobile.SendMessage("You do not have access to that command.");
}
else
{
string[] oldArgs = e.Arguments;
string[] args = new string[oldArgs.Length - 1];
for ( int i = 0; i < Accessors.Length; ++i )
CommandSystem.Register( Accessors[i], AccessLevel, Execute );
}
for (int i = 0; i < args.Length; ++i)
args[i] = oldArgs[i + 1];
public static void Register( BaseCommandImplementor impl )
{
m_Implementors.Add( impl );
impl.Register();
}
Process(e.Mobile, command, args);
}
}
else
{
e.Mobile.SendMessage("You must supply a command name.");
}
}
private static List<BaseCommandImplementor> m_Implementors;
public void Register()
{
if (Accessors == null)
return;
public static List<BaseCommandImplementor> Implementors
{
get
{
if ( m_Implementors == null )
{
m_Implementors = new List<BaseCommandImplementor>();
RegisterImplementors();
}
for (int i = 0; i < Accessors.Length; ++i)
CommandSystem.Register(Accessors[i], AccessLevel, Execute);
}
return m_Implementors;
}
}
}
}
public static void Register(BaseCommandImplementor impl)
{
m_Implementors.Add(impl);
impl.Register();
}
}
}

View file

@ -5,80 +5,76 @@ using Server.Targeting;
namespace Server.Commands.Generic
{
public class ContainedCommandImplementor : BaseCommandImplementor
{
public ContainedCommandImplementor()
{
Accessors = new[]{ "Contained" };
SupportRequirement = CommandSupport.Contained;
AccessLevel = AccessLevel.GameMaster;
Usage = "Contained <command> [condition]";
Description = "Invokes the command on all child items in a targeted container. Optional condition arguments can further restrict the set of objects.";
}
public class ContainedCommandImplementor : BaseCommandImplementor
{
public ContainedCommandImplementor()
{
Accessors = new[] { "Contained" };
SupportRequirement = CommandSupport.Contained;
AccessLevel = AccessLevel.GameMaster;
Usage = "Contained <command> [condition]";
Description =
"Invokes the command on all child items in a targeted container. Optional condition arguments can further restrict the set of objects.";
}
public override void Process( Mobile from, BaseCommand command, string[] args )
{
if ( command.ValidateArgs( this, new CommandEventArgs( from, command.Commands[0], GenerateArgString( args ), args ) ) )
from.BeginTarget( -1, command.ObjectTypes == ObjectTypes.All, TargetFlags.None, new TargetStateCallback( OnTarget ), new object[]{ command, args } );
}
public override void Process(Mobile from, BaseCommand command, string[] args)
{
if (command.ValidateArgs(this, new CommandEventArgs(from, command.Commands[0], GenerateArgString(args), args)))
from.BeginTarget(-1, command.ObjectTypes == ObjectTypes.All, TargetFlags.None,
new TargetStateCallback(OnTarget), new object[] { command, args });
}
public void OnTarget( Mobile from, object targeted, object state )
{
if ( !BaseCommand.IsAccessible( from, targeted ) )
{
from.SendMessage( "That is not accessible." );
return;
}
public void OnTarget(Mobile from, object targeted, object state)
{
if (!BaseCommand.IsAccessible(from, targeted))
{
from.SendMessage("That is not accessible.");
return;
}
object[] states = (object[])state;
BaseCommand command = (BaseCommand)states[0];
string[] args = (string[])states[1];
object[] states = (object[])state;
BaseCommand command = (BaseCommand)states[0];
string[] args = (string[])states[1];
if ( command.ObjectTypes == ObjectTypes.Mobiles )
return; // sanity check
if (command.ObjectTypes == ObjectTypes.Mobiles)
return; // sanity check
if ( !(targeted is Container) )
{
from.SendMessage( "That is not a container." );
}
else
{
try
{
Extensions ext = Extensions.Parse( from, ref args );
if (!(targeted is Container))
from.SendMessage("That is not a container.");
else
try
{
Extensions ext = Extensions.Parse(from, ref args);
bool items, mobiles;
bool items, mobiles;
if ( !CheckObjectTypes( from, command, ext, out items, out mobiles ) )
return;
if (!CheckObjectTypes(from, command, ext, out items, out mobiles))
return;
if ( !items )
{
from.SendMessage( "This command only works on items." );
return;
}
if (!items)
{
from.SendMessage("This command only works on items.");
return;
}
Container cont = (Container)targeted;
Container cont = (Container)targeted;
Item[] found = cont.FindItemsByType( typeof( Item ), true );
Item[] found = cont.FindItemsByType(typeof(Item), true);
ArrayList list = new ArrayList();
ArrayList list = new ArrayList();
for ( int i = 0; i < found.Length; ++i )
{
if ( ext.IsValid( found[i] ) )
list.Add( found[i] );
}
for (int i = 0; i < found.Length; ++i)
if (ext.IsValid(found[i]))
list.Add(found[i]);
ext.Filter( list );
ext.Filter(list);
RunCommand( from, list, command, args );
}
catch ( Exception e )
{
from.SendMessage( e.Message );
}
}
}
}
RunCommand(from, list, command, args);
}
catch (Exception e)
{
from.SendMessage(e.Message);
}
}
}
}

View file

@ -1,30 +1,32 @@
namespace Server.Commands.Generic
{
public class FacetCommandImplementor : BaseCommandImplementor
{
public FacetCommandImplementor()
{
Accessors = new[]{ "Facet" };
SupportRequirement = CommandSupport.Area;
SupportsConditionals = true;
AccessLevel = AccessLevel.GameMaster;
Usage = "Facet <command> [condition]";
Description = "Invokes the command on all appropriate objects within your facet's map bounds. Optional condition arguments can further restrict the set of objects.";
}
public class FacetCommandImplementor : BaseCommandImplementor
{
public FacetCommandImplementor()
{
Accessors = new[] { "Facet" };
SupportRequirement = CommandSupport.Area;
SupportsConditionals = true;
AccessLevel = AccessLevel.GameMaster;
Usage = "Facet <command> [condition]";
Description =
"Invokes the command on all appropriate objects within your facet's map bounds. Optional condition arguments can further restrict the set of objects.";
}
public override void Process( Mobile from, BaseCommand command, string[] args )
{
AreaCommandImplementor impl = AreaCommandImplementor.Instance;
public override void Process(Mobile from, BaseCommand command, string[] args)
{
AreaCommandImplementor impl = AreaCommandImplementor.Instance;
if ( impl == null )
return;
if (impl == null)
return;
Map map = from.Map;
Map map = from.Map;
if ( map == null || map == Map.Internal )
return;
if (map == null || map == Map.Internal)
return;
impl.OnTarget( from, map, Point3D.Zero, new Point3D( map.Width - 1, map.Height - 1, 0 ), new object[] { command, args } );
}
}
}
impl.OnTarget(from, map, Point3D.Zero, new Point3D(map.Width - 1, map.Height - 1, 0),
new object[] { command, args });
}
}
}

View file

@ -3,57 +3,50 @@ using System.Collections;
namespace Server.Commands.Generic
{
public class GlobalCommandImplementor : BaseCommandImplementor
{
public GlobalCommandImplementor()
{
Accessors = new[]{ "Global" };
SupportRequirement = CommandSupport.Global;
SupportsConditionals = true;
AccessLevel = AccessLevel.Administrator;
Usage = "Global <command> [condition]";
Description = "Invokes the command on all appropriate objects in the world. Optional condition arguments can further restrict the set of objects.";
}
public class GlobalCommandImplementor : BaseCommandImplementor
{
public GlobalCommandImplementor()
{
Accessors = new[] { "Global" };
SupportRequirement = CommandSupport.Global;
SupportsConditionals = true;
AccessLevel = AccessLevel.Administrator;
Usage = "Global <command> [condition]";
Description =
"Invokes the command on all appropriate objects in the world. Optional condition arguments can further restrict the set of objects.";
}
public override void Compile( Mobile from, BaseCommand command, ref string[] args, ref object obj )
{
try
{
Extensions ext = Extensions.Parse( from, ref args );
public override void Compile(Mobile from, BaseCommand command, ref string[] args, ref object obj)
{
try
{
Extensions ext = Extensions.Parse(from, ref args);
bool items, mobiles;
bool items, mobiles;
if ( !CheckObjectTypes( from, command, ext, out items, out mobiles ) )
return;
if (!CheckObjectTypes(from, command, ext, out items, out mobiles))
return;
ArrayList list = new ArrayList();
ArrayList list = new ArrayList();
if ( items )
{
foreach ( Item item in World.Items.Values )
{
if ( ext.IsValid( item ) )
list.Add( item );
}
}
if (items)
foreach (Item item in World.Items.Values)
if (ext.IsValid(item))
list.Add(item);
if ( mobiles )
{
foreach ( Mobile mob in World.Mobiles.Values )
{
if ( ext.IsValid( mob ) )
list.Add( mob );
}
}
if (mobiles)
foreach (Mobile mob in World.Mobiles.Values)
if (ext.IsValid(mob))
list.Add(mob);
ext.Filter( list );
ext.Filter(list);
obj = list;
}
catch ( Exception ex )
{
from.SendMessage( ex.Message );
}
}
}
obj = list;
}
catch (Exception ex)
{
from.SendMessage(ex.Message);
}
}
}
}

View file

@ -1,63 +1,65 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Server.Network;
namespace Server.Commands.Generic
{
public class IPAddressCommandImplementor : BaseCommandImplementor
{
public IPAddressCommandImplementor()
{
Accessors = new[]{ "IPAddress" };
SupportRequirement = CommandSupport.IPAddress;
SupportsConditionals = true;
AccessLevel = AccessLevel.Administrator;
Usage = "IPAddress <command> [condition]";
Description = "Invokes the command on one mobile from each IP address that is logged in. Optional condition arguments can further restrict the set of objects.";
}
public class IPAddressCommandImplementor : BaseCommandImplementor
{
public IPAddressCommandImplementor()
{
Accessors = new[] { "IPAddress" };
SupportRequirement = CommandSupport.IPAddress;
SupportsConditionals = true;
AccessLevel = AccessLevel.Administrator;
Usage = "IPAddress <command> [condition]";
Description =
"Invokes the command on one mobile from each IP address that is logged in. Optional condition arguments can further restrict the set of objects.";
}
public override void Compile( Mobile from, BaseCommand command, ref string[] args, ref object obj )
{
try
{
Extensions ext = Extensions.Parse( from, ref args );
public override void Compile(Mobile from, BaseCommand command, ref string[] args, ref object obj)
{
try
{
Extensions ext = Extensions.Parse(from, ref args);
bool items, mobiles;
bool items, mobiles;
if ( !CheckObjectTypes( from, command, ext, out items, out mobiles ) )
return;
if (!CheckObjectTypes(from, command, ext, out items, out mobiles))
return;
if ( !mobiles ) // sanity check
{
command.LogFailure( "This command does not support items." );
return;
}
if (!mobiles) // sanity check
{
command.LogFailure("This command does not support items.");
return;
}
ArrayList list = new ArrayList();
ArrayList addresses = new ArrayList();
ArrayList list = new ArrayList();
ArrayList addresses = new ArrayList();
System.Collections.Generic.List<NetState> states = NetState.Instances;
List<NetState> states = NetState.Instances;
for ( int i = 0; i < states.Count; ++i )
{
NetState ns = (NetState)states[i];
Mobile mob = ns.Mobile;
for (int i = 0; i < states.Count; ++i)
{
NetState ns = states[i];
Mobile mob = ns.Mobile;
if ( mob != null && !addresses.Contains( ns.Address ) && ext.IsValid( mob ) )
{
list.Add( mob );
addresses.Add( ns.Address );
}
}
if (mob != null && !addresses.Contains(ns.Address) && ext.IsValid(mob))
{
list.Add(mob);
addresses.Add(ns.Address);
}
}
ext.Filter( list );
ext.Filter(list);
obj = list;
}
catch ( Exception ex )
{
from.SendMessage( ex.Message );
}
}
}
obj = list;
}
catch (Exception ex)
{
from.SendMessage(ex.Message);
}
}
}
}

View file

@ -2,73 +2,76 @@ using Server.Targeting;
namespace Server.Commands.Generic
{
public class MultiCommandImplementor : BaseCommandImplementor
{
public MultiCommandImplementor()
{
Accessors = new[]{ "Multi", "m" };
SupportRequirement = CommandSupport.Multi;
AccessLevel = AccessLevel.Counselor;
Usage = "Multi <command>";
Description = "Invokes the command on multiple targeted objects.";
}
public class MultiCommandImplementor : BaseCommandImplementor
{
public MultiCommandImplementor()
{
Accessors = new[] { "Multi", "m" };
SupportRequirement = CommandSupport.Multi;
AccessLevel = AccessLevel.Counselor;
Usage = "Multi <command>";
Description = "Invokes the command on multiple targeted objects.";
}
public override void Process( Mobile from, BaseCommand command, string[] args )
{
if ( command.ValidateArgs( this, new CommandEventArgs( from, command.Commands[0], GenerateArgString( args ), args ) ) )
from.BeginTarget( -1, command.ObjectTypes == ObjectTypes.All, TargetFlags.None, new TargetStateCallback( OnTarget ), new object[]{ command, args } );
}
public override void Process(Mobile from, BaseCommand command, string[] args)
{
if (command.ValidateArgs(this, new CommandEventArgs(from, command.Commands[0], GenerateArgString(args), args)))
from.BeginTarget(-1, command.ObjectTypes == ObjectTypes.All, TargetFlags.None,
new TargetStateCallback(OnTarget), new object[] { command, args });
}
public void OnTarget( Mobile from, object targeted, object state )
{
object[] states = (object[])state;
BaseCommand command = (BaseCommand)states[0];
string[] args = (string[])states[1];
public void OnTarget(Mobile from, object targeted, object state)
{
object[] states = (object[])state;
BaseCommand command = (BaseCommand)states[0];
string[] args = (string[])states[1];
if ( !BaseCommand.IsAccessible( from, targeted ) )
{
from.SendMessage( "That is not accessible." );
from.BeginTarget( -1, command.ObjectTypes == ObjectTypes.All, TargetFlags.None, new TargetStateCallback( OnTarget ), new object[]{ command, args } );
return;
}
if (!BaseCommand.IsAccessible(from, targeted))
{
from.SendMessage("That is not accessible.");
from.BeginTarget(-1, command.ObjectTypes == ObjectTypes.All, TargetFlags.None,
new TargetStateCallback(OnTarget), new object[] { command, args });
return;
}
switch ( command.ObjectTypes )
{
case ObjectTypes.Both:
{
if ( !(targeted is Item) && !(targeted is Mobile) )
{
from.SendMessage( "This command does not work on that." );
return;
}
switch (command.ObjectTypes)
{
case ObjectTypes.Both:
{
if (!(targeted is Item) && !(targeted is Mobile))
{
from.SendMessage("This command does not work on that.");
return;
}
break;
}
case ObjectTypes.Items:
{
if ( !(targeted is Item) )
{
from.SendMessage( "This command only works on items." );
return;
}
break;
}
case ObjectTypes.Items:
{
if (!(targeted is Item))
{
from.SendMessage("This command only works on items.");
return;
}
break;
}
case ObjectTypes.Mobiles:
{
if ( !(targeted is Mobile) )
{
from.SendMessage( "This command only works on mobiles." );
return;
}
break;
}
case ObjectTypes.Mobiles:
{
if (!(targeted is Mobile))
{
from.SendMessage("This command only works on mobiles.");
return;
}
break;
}
}
break;
}
}
RunCommand( from, targeted, command, args );
RunCommand(from, targeted, command, args);
from.BeginTarget( -1, command.ObjectTypes == ObjectTypes.All, TargetFlags.None, new TargetStateCallback( OnTarget ), new object[]{ command, args } );
}
}
from.BeginTarget(-1, command.ObjectTypes == ObjectTypes.All, TargetFlags.None, new TargetStateCallback(OnTarget),
new object[] { command, args });
}
}
}

View file

@ -4,245 +4,247 @@ using CPA = Server.CommandPropertyAttribute;
namespace Server.Commands.Generic
{
public sealed class ObjectConditional
{
private static readonly Type typeofItem = typeof( Item );
private static readonly Type typeofMobile = typeof( Mobile );
public sealed class ObjectConditional
{
private static readonly Type typeofItem = typeof(Item);
private static readonly Type typeofMobile = typeof(Mobile);
private ICondition[][] m_Conditions;
public static readonly ObjectConditional Empty = new ObjectConditional(null, null);
private IConditional[] m_Conditionals;
private IConditional[] m_Conditionals;
public Type Type { get; }
private ICondition[][] m_Conditions;
public bool IsItem => ( Type == null || Type == typeofItem || Type.IsSubclassOf( typeofItem ) );
public ObjectConditional(Type objectType, ICondition[][] conditions)
{
Type = objectType;
m_Conditions = conditions;
}
public bool IsMobile => ( Type == null || Type == typeofMobile || Type.IsSubclassOf( typeofMobile ) );
public Type Type{ get; }
public static readonly ObjectConditional Empty = new ObjectConditional( null, null );
public bool IsItem => Type == null || Type == typeofItem || Type.IsSubclassOf(typeofItem);
public bool HasCompiled => ( m_Conditionals != null );
public bool IsMobile => Type == null || Type == typeofMobile || Type.IsSubclassOf(typeofMobile);
public void Compile( ref AssemblyEmitter emitter )
{
if ( emitter == null )
emitter = new AssemblyEmitter( "__dynamic", false );
public bool HasCompiled => m_Conditionals != null;
m_Conditionals = new IConditional[m_Conditions.Length];
public void Compile(ref AssemblyEmitter emitter)
{
if (emitter == null)
emitter = new AssemblyEmitter("__dynamic", false);
for ( int i = 0; i < m_Conditionals.Length; ++i )
m_Conditionals[i] = ConditionalCompiler.Compile( emitter, Type, m_Conditions[i], i );
}
m_Conditionals = new IConditional[m_Conditions.Length];
public bool CheckCondition( object obj )
{
if ( Type == null )
return true; // null type means no condition
for (int i = 0; i < m_Conditionals.Length; ++i)
m_Conditionals[i] = ConditionalCompiler.Compile(emitter, Type, m_Conditions[i], i);
}
if ( !HasCompiled )
{
AssemblyEmitter emitter = null;
public bool CheckCondition(object obj)
{
if (Type == null)
return true; // null type means no condition
Compile( ref emitter );
}
if (!HasCompiled)
{
AssemblyEmitter emitter = null;
for ( int i = 0; i < m_Conditionals.Length; ++i )
{
if ( m_Conditionals[i].Verify( obj ) )
return true;
}
Compile(ref emitter);
}
return false; // all conditions false
}
for (int i = 0; i < m_Conditionals.Length; ++i)
if (m_Conditionals[i].Verify(obj))
return true;
public static ObjectConditional Parse( Mobile from, ref string[] args )
{
string[] conditionArgs = null;
return false; // all conditions false
}
for ( int i = 0; i < args.Length; ++i )
{
if ( Insensitive.Equals( args[i], "where" ) )
{
string[] origArgs = args;
public static ObjectConditional Parse(Mobile from, ref string[] args)
{
string[] conditionArgs = null;
args = new string[i];
for (int i = 0; i < args.Length; ++i)
if (Insensitive.Equals(args[i], "where"))
{
string[] origArgs = args;
for ( int j = 0; j < args.Length; ++j )
args[j] = origArgs[j];
args = new string[i];
conditionArgs = new string[origArgs.Length - i - 1];
for (int j = 0; j < args.Length; ++j)
args[j] = origArgs[j];
for ( int j = 0; j < conditionArgs.Length; ++j )
conditionArgs[j] = origArgs[i + j + 1];
conditionArgs = new string[origArgs.Length - i - 1];
break;
}
}
for (int j = 0; j < conditionArgs.Length; ++j)
conditionArgs[j] = origArgs[i + j + 1];
return ParseDirect( from, conditionArgs, 0, conditionArgs.Length );
}
break;
}
public static ObjectConditional ParseDirect( Mobile from, string[] args, int offset, int size )
{
if ( args == null || size == 0 )
return Empty;
return ParseDirect(from, conditionArgs, 0, conditionArgs.Length);
}
int index = 0;
public static ObjectConditional ParseDirect(Mobile from, string[] args, int offset, int size)
{
if (args == null || size == 0)
return Empty;
Type objectType = ScriptCompiler.FindTypeByName( args[offset + index], true );
int index = 0;
if ( objectType == null )
throw new Exception($"No type with that name ({args[offset + index]}) was found.");
Type objectType = ScriptCompiler.FindTypeByName(args[offset + index], true);
++index;
if (objectType == null)
throw new Exception($"No type with that name ({args[offset + index]}) was found.");
List<ICondition[]> conditions = new List<ICondition[]>();
List<ICondition> current = new List<ICondition>();
++index;
current.Add( TypeCondition.Default );
List<ICondition[]> conditions = new List<ICondition[]>();
List<ICondition> current = new List<ICondition>();
while ( index < size )
{
string cur = args[offset + index];
current.Add(TypeCondition.Default);
bool inverse = false;
while (index < size)
{
string cur = args[offset + index];
if ( Insensitive.Equals( cur, "not" ) || cur == "!" )
{
inverse = true;
++index;
bool inverse = false;
if ( index >= size )
throw new Exception( "Improperly formatted object conditional." );
}
else if ( Insensitive.Equals( cur, "or" ) || cur == "||" )
{
if ( current.Count > 1 )
{
conditions.Add( current.ToArray() );
if (Insensitive.Equals(cur, "not") || cur == "!")
{
inverse = true;
++index;
current.Clear();
current.Add( TypeCondition.Default );
}
if (index >= size)
throw new Exception("Improperly formatted object conditional.");
}
else if (Insensitive.Equals(cur, "or") || cur == "||")
{
if (current.Count > 1)
{
conditions.Add(current.ToArray());
++index;
current.Clear();
current.Add(TypeCondition.Default);
}
continue;
}
++index;
string binding = args[offset + index];
index++;
continue;
}
if ( index >= size )
throw new Exception( "Improperly formatted object conditional." );
string binding = args[offset + index];
index++;
string oper = args[offset + index];
index++;
if (index >= size)
throw new Exception("Improperly formatted object conditional.");
if ( index >= size )
throw new Exception( "Improperly formatted object conditional." );
string oper = args[offset + index];
index++;
string val = args[offset + index];
index++;
if (index >= size)
throw new Exception("Improperly formatted object conditional.");
Property prop = new Property( binding );
string val = args[offset + index];
index++;
prop.BindTo( objectType, PropertyAccess.Read );
prop.CheckAccess( from );
Property prop = new Property(binding);
ICondition condition = null;
prop.BindTo(objectType, PropertyAccess.Read);
prop.CheckAccess(from);
switch ( oper )
{
#region Equality
case "=":
case "==":
case "is":
condition = new ComparisonCondition( prop, inverse, ComparisonOperator.Equal, val );
break;
ICondition condition = null;
case "!=":
condition = new ComparisonCondition( prop, inverse, ComparisonOperator.NotEqual, val );
break;
#endregion
switch (oper)
{
#region Equality
#region Relational
case ">":
condition = new ComparisonCondition( prop, inverse, ComparisonOperator.Greater, val );
break;
case "=":
case "==":
case "is":
condition = new ComparisonCondition(prop, inverse, ComparisonOperator.Equal, val);
break;
case "<":
condition = new ComparisonCondition( prop, inverse, ComparisonOperator.Lesser, val );
break;
case "!=":
condition = new ComparisonCondition(prop, inverse, ComparisonOperator.NotEqual, val);
break;
case ">=":
condition = new ComparisonCondition( prop, inverse, ComparisonOperator.GreaterEqual, val );
break;
#endregion
case "<=":
condition = new ComparisonCondition( prop, inverse, ComparisonOperator.LesserEqual, val );
break;
#endregion
#region Relational
#region Strings
case "==~":
case "~==":
case "=~":
case "~=":
case "is~":
case "~is":
condition = new StringCondition( prop, inverse, StringOperator.Equal, val, true );
break;
case ">":
condition = new ComparisonCondition(prop, inverse, ComparisonOperator.Greater, val);
break;
case "!=~":
case "~!=":
condition = new StringCondition( prop, inverse, StringOperator.NotEqual, val, true );
break;
case "<":
condition = new ComparisonCondition(prop, inverse, ComparisonOperator.Lesser, val);
break;
case "starts":
condition = new StringCondition( prop, inverse, StringOperator.StartsWith, val, false );
break;
case ">=":
condition = new ComparisonCondition(prop, inverse, ComparisonOperator.GreaterEqual, val);
break;
case "starts~":
case "~starts":
condition = new StringCondition( prop, inverse, StringOperator.StartsWith, val, true );
break;
case "<=":
condition = new ComparisonCondition(prop, inverse, ComparisonOperator.LesserEqual, val);
break;
case "ends":
condition = new StringCondition( prop, inverse, StringOperator.EndsWith, val, false );
break;
#endregion
case "ends~":
case "~ends":
condition = new StringCondition( prop, inverse, StringOperator.EndsWith, val, true );
break;
#region Strings
case "contains":
condition = new StringCondition( prop, inverse, StringOperator.Contains, val, false );
break;
case "==~":
case "~==":
case "=~":
case "~=":
case "is~":
case "~is":
condition = new StringCondition(prop, inverse, StringOperator.Equal, val, true);
break;
case "contains~":
case "~contains":
condition = new StringCondition( prop, inverse, StringOperator.Contains, val, true );
break;
#endregion
}
case "!=~":
case "~!=":
condition = new StringCondition(prop, inverse, StringOperator.NotEqual, val, true);
break;
if ( condition == null )
throw new InvalidOperationException($"Unrecognized operator (\"{oper}\").");
case "starts":
condition = new StringCondition(prop, inverse, StringOperator.StartsWith, val, false);
break;
current.Add( condition );
}
case "starts~":
case "~starts":
condition = new StringCondition(prop, inverse, StringOperator.StartsWith, val, true);
break;
conditions.Add( current.ToArray() );
case "ends":
condition = new StringCondition(prop, inverse, StringOperator.EndsWith, val, false);
break;
return new ObjectConditional( objectType, conditions.ToArray() );
}
case "ends~":
case "~ends":
condition = new StringCondition(prop, inverse, StringOperator.EndsWith, val, true);
break;
public ObjectConditional( Type objectType, ICondition[][] conditions )
{
Type = objectType;
m_Conditions = conditions;
}
}
case "contains":
condition = new StringCondition(prop, inverse, StringOperator.Contains, val, false);
break;
case "contains~":
case "~contains":
condition = new StringCondition(prop, inverse, StringOperator.Contains, val, true);
break;
#endregion
}
if (condition == null)
throw new InvalidOperationException($"Unrecognized operator (\"{oper}\").");
current.Add(condition);
}
conditions.Add(current.ToArray());
return new ObjectConditional(objectType, conditions.ToArray());
}
}
}

View file

@ -5,62 +5,63 @@ using Server.Network;
namespace Server.Commands.Generic
{
public class OnlineCommandImplementor : BaseCommandImplementor
{
public OnlineCommandImplementor()
{
Accessors = new[]{ "Online" };
SupportRequirement = CommandSupport.Online;
SupportsConditionals = true;
AccessLevel = AccessLevel.GameMaster;
Usage = "Online <command> [condition]";
Description = "Invokes the command on all mobiles that are currently logged in. Optional condition arguments can further restrict the set of objects.";
}
public class OnlineCommandImplementor : BaseCommandImplementor
{
public OnlineCommandImplementor()
{
Accessors = new[] { "Online" };
SupportRequirement = CommandSupport.Online;
SupportsConditionals = true;
AccessLevel = AccessLevel.GameMaster;
Usage = "Online <command> [condition]";
Description =
"Invokes the command on all mobiles that are currently logged in. Optional condition arguments can further restrict the set of objects.";
}
public override void Compile( Mobile from, BaseCommand command, ref string[] args, ref object obj )
{
try
{
Extensions ext = Extensions.Parse( from, ref args );
public override void Compile(Mobile from, BaseCommand command, ref string[] args, ref object obj)
{
try
{
Extensions ext = Extensions.Parse(from, ref args);
bool items, mobiles;
bool items, mobiles;
if ( !CheckObjectTypes( from, command, ext, out items, out mobiles ) )
return;
if (!CheckObjectTypes(from, command, ext, out items, out mobiles))
return;
if ( !mobiles ) // sanity check
{
command.LogFailure( "This command does not support items." );
return;
}
if (!mobiles) // sanity check
{
command.LogFailure("This command does not support items.");
return;
}
ArrayList list = new ArrayList();
ArrayList list = new ArrayList();
List<NetState> states = NetState.Instances;
List<NetState> states = NetState.Instances;
for ( int i = 0; i < states.Count; ++i )
{
NetState ns = states[i];
Mobile mob = ns.Mobile;
for (int i = 0; i < states.Count; ++i)
{
NetState ns = states[i];
Mobile mob = ns.Mobile;
if ( mob == null )
continue;
if (mob == null)
continue;
if ( !BaseCommand.IsAccessible( from, mob ) )
continue;
if (!BaseCommand.IsAccessible(from, mob))
continue;
if ( ext.IsValid( mob ) )
list.Add( mob );
}
if (ext.IsValid(mob))
list.Add(mob);
}
ext.Filter( list );
ext.Filter(list);
obj = list;
}
catch ( Exception ex )
{
from.SendMessage( ex.Message );
}
}
}
}
obj = list;
}
catch (Exception ex)
{
from.SendMessage(ex.Message);
}
}
}
}

View file

@ -1,77 +1,79 @@
namespace Server.Commands.Generic
{
public class RangeCommandImplementor : BaseCommandImplementor
{
public static RangeCommandImplementor Instance { get; private set; }
public class RangeCommandImplementor : BaseCommandImplementor
{
public RangeCommandImplementor()
{
Accessors = new[] { "Range" };
SupportRequirement = CommandSupport.Area;
SupportsConditionals = true;
AccessLevel = AccessLevel.GameMaster;
Usage = "Range <range> <command> [condition]";
Description =
"Invokes the command on all appropriate objects within a specified range of you. Optional condition arguments can further restrict the set of objects.";
public RangeCommandImplementor()
{
Accessors = new[]{ "Range" };
SupportRequirement = CommandSupport.Area;
SupportsConditionals = true;
AccessLevel = AccessLevel.GameMaster;
Usage = "Range <range> <command> [condition]";
Description = "Invokes the command on all appropriate objects within a specified range of you. Optional condition arguments can further restrict the set of objects.";
Instance = this;
}
Instance = this;
}
public static RangeCommandImplementor Instance{ get; private set; }
public override void Execute( CommandEventArgs e )
{
if ( e.Length >= 2 )
{
int range = e.GetInt32( 0 );
public override void Execute(CommandEventArgs e)
{
if (e.Length >= 2)
{
int range = e.GetInt32(0);
if ( range < 0 )
{
e.Mobile.SendMessage( "The range must not be negative." );
}
else
{
Commands.TryGetValue( e.GetString( 1 ), out BaseCommand command );
if (range < 0)
{
e.Mobile.SendMessage("The range must not be negative.");
}
else
{
Commands.TryGetValue(e.GetString(1), out BaseCommand command);
if ( command == null )
{
e.Mobile.SendMessage( "That is either an invalid command name or one that does not support this modifier." );
}
else if ( e.Mobile.AccessLevel < command.AccessLevel )
{
e.Mobile.SendMessage( "You do not have access to that command." );
}
else
{
string[] oldArgs = e.Arguments;
string[] args = new string[oldArgs.Length - 2];
if (command == null)
{
e.Mobile.SendMessage(
"That is either an invalid command name or one that does not support this modifier.");
}
else if (e.Mobile.AccessLevel < command.AccessLevel)
{
e.Mobile.SendMessage("You do not have access to that command.");
}
else
{
string[] oldArgs = e.Arguments;
string[] args = new string[oldArgs.Length - 2];
for ( int i = 0; i < args.Length; ++i )
args[i] = oldArgs[i + 2];
for (int i = 0; i < args.Length; ++i)
args[i] = oldArgs[i + 2];
Process( range, e.Mobile, command, args );
}
}
}
else
{
e.Mobile.SendMessage( "You must supply a range and a command name." );
}
}
Process(range, e.Mobile, command, args);
}
}
}
else
{
e.Mobile.SendMessage("You must supply a range and a command name.");
}
}
public void Process( int range, Mobile from, BaseCommand command, string[] args )
{
AreaCommandImplementor impl = AreaCommandImplementor.Instance;
public void Process(int range, Mobile from, BaseCommand command, string[] args)
{
AreaCommandImplementor impl = AreaCommandImplementor.Instance;
if ( impl == null )
return;
if (impl == null)
return;
Map map = from.Map;
Map map = from.Map;
if ( map == null || map == Map.Internal )
return;
if (map == null || map == Map.Internal)
return;
Point3D start = new Point3D( from.X - range, from.Y - range, from.Z );
Point3D end = new Point3D( from.X + range, from.Y + range, from.Z );
Point3D start = new Point3D(from.X - range, from.Y - range, from.Z);
Point3D end = new Point3D(from.X + range, from.Y + range, from.Z);
impl.OnTarget( from, map, start, end, new object[] { command, args } );
}
}
}
impl.OnTarget(from, map, start, end, new object[] { command, args });
}
}
}

View file

@ -3,58 +3,59 @@ using System.Collections;
namespace Server.Commands.Generic
{
public class RegionCommandImplementor : BaseCommandImplementor
{
public RegionCommandImplementor()
{
Accessors = new[]{ "Region" };
SupportRequirement = CommandSupport.Region;
SupportsConditionals = true;
AccessLevel = AccessLevel.GameMaster;
Usage = "Region <command> [condition]";
Description = "Invokes the command on all appropriate mobiles in your current region. Optional condition arguments can further restrict the set of objects.";
}
public class RegionCommandImplementor : BaseCommandImplementor
{
public RegionCommandImplementor()
{
Accessors = new[] { "Region" };
SupportRequirement = CommandSupport.Region;
SupportsConditionals = true;
AccessLevel = AccessLevel.GameMaster;
Usage = "Region <command> [condition]";
Description =
"Invokes the command on all appropriate mobiles in your current region. Optional condition arguments can further restrict the set of objects.";
}
public override void Compile( Mobile from, BaseCommand command, ref string[] args, ref object obj )
{
try
{
Extensions ext = Extensions.Parse( from, ref args );
public override void Compile(Mobile from, BaseCommand command, ref string[] args, ref object obj)
{
try
{
Extensions ext = Extensions.Parse(from, ref args);
bool items, mobiles;
bool items, mobiles;
if ( !CheckObjectTypes( from, command, ext, out items, out mobiles ) )
return;
if (!CheckObjectTypes(from, command, ext, out items, out mobiles))
return;
Region reg = from.Region;
Region reg = from.Region;
ArrayList list = new ArrayList();
ArrayList list = new ArrayList();
if ( mobiles )
{
foreach ( Mobile mob in reg.GetMobiles() )
{
if ( !BaseCommand.IsAccessible( from, mob ) )
continue;
if (mobiles)
{
foreach (Mobile mob in reg.GetMobiles())
{
if (!BaseCommand.IsAccessible(from, mob))
continue;
if ( ext.IsValid( mob ) )
list.Add( mob );
}
}
else
{
command.LogFailure( "This command does not support items." );
return;
}
if (ext.IsValid(mob))
list.Add(mob);
}
}
else
{
command.LogFailure("This command does not support items.");
return;
}
ext.Filter( list );
ext.Filter(list);
obj = list;
}
catch ( Exception ex )
{
from.SendMessage( ex.Message );
}
}
}
}
obj = list;
}
catch (Exception ex)
{
from.SendMessage(ex.Message);
}
}
}
}

View file

@ -1,22 +1,23 @@
namespace Server.Commands.Generic
{
public class ScreenCommandImplementor : BaseCommandImplementor
{
public ScreenCommandImplementor()
{
Accessors = new[]{ "Screen" };
SupportRequirement = CommandSupport.Area;
SupportsConditionals = true;
AccessLevel = AccessLevel.GameMaster;
Usage = "Screen <command> [condition]";
Description = "Invokes the command on all appropriate objects in your screen. Optional condition arguments can further restrict the set of objects.";
}
public class ScreenCommandImplementor : BaseCommandImplementor
{
public ScreenCommandImplementor()
{
Accessors = new[] { "Screen" };
SupportRequirement = CommandSupport.Area;
SupportsConditionals = true;
AccessLevel = AccessLevel.GameMaster;
Usage = "Screen <command> [condition]";
Description =
"Invokes the command on all appropriate objects in your screen. Optional condition arguments can further restrict the set of objects.";
}
public override void Process( Mobile from, BaseCommand command, string[] args )
{
RangeCommandImplementor impl = RangeCommandImplementor.Instance;
public override void Process(Mobile from, BaseCommand command, string[] args)
{
RangeCommandImplementor impl = RangeCommandImplementor.Instance;
impl?.Process( 18, from, command, args );
}
}
}
impl?.Process(18, from, command, args);
}
}
}

View file

@ -1,22 +1,22 @@
namespace Server.Commands.Generic
{
public class SelfCommandImplementor : BaseCommandImplementor
{
public SelfCommandImplementor()
{
Accessors = new[]{ "Self" };
SupportRequirement = CommandSupport.Self;
AccessLevel = AccessLevel.Counselor;
Usage = "Self <command>";
Description = "Invokes the command on the commanding player.";
}
public class SelfCommandImplementor : BaseCommandImplementor
{
public SelfCommandImplementor()
{
Accessors = new[] { "Self" };
SupportRequirement = CommandSupport.Self;
AccessLevel = AccessLevel.Counselor;
Usage = "Self <command>";
Description = "Invokes the command on the commanding player.";
}
public override void Compile( Mobile from, BaseCommand command, ref string[] args, ref object obj )
{
if ( command.ObjectTypes == ObjectTypes.Items )
return; // sanity check
public override void Compile(Mobile from, BaseCommand command, ref string[] args, ref object obj)
{
if (command.ObjectTypes == ObjectTypes.Items)
return; // sanity check
obj = from;
}
}
obj = from;
}
}
}

View file

@ -1,95 +1,96 @@
namespace Server.Commands.Generic
{
public class SerialCommandImplementor : BaseCommandImplementor
{
public SerialCommandImplementor()
{
Accessors = new[]{ "Serial" };
SupportRequirement = CommandSupport.Single;
AccessLevel = AccessLevel.Counselor;
Usage = "Serial <serial> <command>";
Description = "Invokes the command on a single object by serial.";
}
public class SerialCommandImplementor : BaseCommandImplementor
{
public SerialCommandImplementor()
{
Accessors = new[] { "Serial" };
SupportRequirement = CommandSupport.Single;
AccessLevel = AccessLevel.Counselor;
Usage = "Serial <serial> <command>";
Description = "Invokes the command on a single object by serial.";
}
public override void Execute( CommandEventArgs e )
{
if ( e.Length >= 2 )
{
Serial serial = e.GetInt32( 0 );
public override void Execute(CommandEventArgs e)
{
if (e.Length >= 2)
{
Serial serial = e.GetInt32(0);
object obj = null;
object obj = null;
if ( serial.IsItem )
obj = World.FindItem( serial );
else if ( serial.IsMobile )
obj = World.FindMobile( serial );
if (serial.IsItem)
obj = World.FindItem(serial);
else if (serial.IsMobile)
obj = World.FindMobile(serial);
if ( obj == null )
{
e.Mobile.SendMessage( "That is not a valid serial." );
}
else
{
Commands.TryGetValue( e.GetString( 1 ), out BaseCommand command );
if (obj == null)
{
e.Mobile.SendMessage("That is not a valid serial.");
}
else
{
Commands.TryGetValue(e.GetString(1), out BaseCommand command);
if ( command == null )
{
e.Mobile.SendMessage( "That is either an invalid command name or one that does not support this modifier." );
}
else if ( e.Mobile.AccessLevel < command.AccessLevel )
{
e.Mobile.SendMessage( "You do not have access to that command." );
}
else
{
switch ( command.ObjectTypes )
{
case ObjectTypes.Both:
{
if ( !(obj is Item) && !(obj is Mobile) )
{
e.Mobile.SendMessage( "This command does not work on that." );
return;
}
if (command == null)
{
e.Mobile.SendMessage(
"That is either an invalid command name or one that does not support this modifier.");
}
else if (e.Mobile.AccessLevel < command.AccessLevel)
{
e.Mobile.SendMessage("You do not have access to that command.");
}
else
{
switch (command.ObjectTypes)
{
// case ObjectTypes.Both:
// {
// if (!(obj is Item) && !(obj is Mobile))
// {
// e.Mobile.SendMessage("This command does not work on that.");
// return;
// }
//
// break;
// }
case ObjectTypes.Items:
{
if (!(obj is Item))
{
e.Mobile.SendMessage("This command only works on items.");
return;
}
break;
}
case ObjectTypes.Items:
{
if ( !(obj is Item) )
{
e.Mobile.SendMessage( "This command only works on items." );
return;
}
break;
}
case ObjectTypes.Mobiles:
{
if (!(obj is Mobile))
{
e.Mobile.SendMessage("This command only works on mobiles.");
return;
}
break;
}
case ObjectTypes.Mobiles:
{
if ( !(obj is Mobile) )
{
e.Mobile.SendMessage( "This command only works on mobiles." );
return;
}
break;
}
}
break;
}
}
string[] oldArgs = e.Arguments;
string[] args = new string[oldArgs.Length - 2];
string[] oldArgs = e.Arguments;
string[] args = new string[oldArgs.Length - 2];
for (int i = 0; i < args.Length; ++i)
args[i] = oldArgs[i + 2];
for ( int i = 0; i < args.Length; ++i )
args[i] = oldArgs[i + 2];
RunCommand( e.Mobile, obj, command, args );
}
}
}
else
{
e.Mobile.SendMessage( "You must supply an object serial and a command name." );
}
}
}
}
RunCommand(e.Mobile, obj, command, args);
}
}
}
else
{
e.Mobile.SendMessage("You must supply an object serial and a command name.");
}
}
}
}

View file

@ -2,90 +2,92 @@ using Server.Targeting;
namespace Server.Commands.Generic
{
public class SingleCommandImplementor : BaseCommandImplementor
{
public SingleCommandImplementor()
{
Accessors = new[]{ "Single" };
SupportRequirement = CommandSupport.Single;
AccessLevel = AccessLevel.Counselor;
Usage = "Single <command>";
Description = "Invokes the command on a single targeted object. This is the same as just invoking the command directly.";
}
public class SingleCommandImplementor : BaseCommandImplementor
{
public SingleCommandImplementor()
{
Accessors = new[] { "Single" };
SupportRequirement = CommandSupport.Single;
AccessLevel = AccessLevel.Counselor;
Usage = "Single <command>";
Description =
"Invokes the command on a single targeted object. This is the same as just invoking the command directly.";
}
public override void Register( BaseCommand command )
{
base.Register( command );
public override void Register(BaseCommand command)
{
base.Register(command);
for ( int i = 0; i < command.Commands.Length; ++i )
CommandSystem.Register( command.Commands[i], command.AccessLevel, Redirect );
}
for (int i = 0; i < command.Commands.Length; ++i)
CommandSystem.Register(command.Commands[i], command.AccessLevel, Redirect);
}
public void Redirect( CommandEventArgs e )
{
Commands.TryGetValue( e.Command, out BaseCommand command );
public void Redirect(CommandEventArgs e)
{
Commands.TryGetValue(e.Command, out BaseCommand command);
if ( command == null )
e.Mobile.SendMessage( "That is either an invalid command name or one that does not support this modifier." );
else if ( e.Mobile.AccessLevel < command.AccessLevel )
e.Mobile.SendMessage( "You do not have access to that command." );
else if ( command.ValidateArgs( this, e ) )
Process( e.Mobile, command, e.Arguments );
}
if (command == null)
e.Mobile.SendMessage("That is either an invalid command name or one that does not support this modifier.");
else if (e.Mobile.AccessLevel < command.AccessLevel)
e.Mobile.SendMessage("You do not have access to that command.");
else if (command.ValidateArgs(this, e))
Process(e.Mobile, command, e.Arguments);
}
public override void Process( Mobile from, BaseCommand command, string[] args )
{
if ( command.ValidateArgs( this, new CommandEventArgs( from, command.Commands[0], GenerateArgString( args ), args ) ) )
from.BeginTarget( -1, command.ObjectTypes == ObjectTypes.All, TargetFlags.None, new TargetStateCallback( OnTarget ), new object[]{ command, args } );
}
public override void Process(Mobile from, BaseCommand command, string[] args)
{
if (command.ValidateArgs(this, new CommandEventArgs(from, command.Commands[0], GenerateArgString(args), args)))
from.BeginTarget(-1, command.ObjectTypes == ObjectTypes.All, TargetFlags.None,
new TargetStateCallback(OnTarget), new object[] { command, args });
}
public void OnTarget( Mobile from, object targeted, object state )
{
if ( !BaseCommand.IsAccessible( from, targeted ) )
{
from.SendMessage( "That is not accessible." );
return;
}
public void OnTarget(Mobile from, object targeted, object state)
{
if (!BaseCommand.IsAccessible(from, targeted))
{
from.SendMessage("That is not accessible.");
return;
}
object[] states = (object[])state;
BaseCommand command = (BaseCommand)states[0];
string[] args = (string[])states[1];
object[] states = (object[])state;
BaseCommand command = (BaseCommand)states[0];
string[] args = (string[])states[1];
switch ( command.ObjectTypes )
{
case ObjectTypes.Both:
{
if ( !(targeted is Item) && !(targeted is Mobile) )
{
from.SendMessage( "This command does not work on that." );
return;
}
switch (command.ObjectTypes)
{
case ObjectTypes.Both:
{
if (!(targeted is Item) && !(targeted is Mobile))
{
from.SendMessage("This command does not work on that.");
return;
}
break;
}
case ObjectTypes.Items:
{
if ( !(targeted is Item) )
{
from.SendMessage( "This command only works on items." );
return;
}
break;
}
case ObjectTypes.Items:
{
if (!(targeted is Item))
{
from.SendMessage("This command only works on items.");
return;
}
break;
}
case ObjectTypes.Mobiles:
{
if ( !(targeted is Mobile) )
{
from.SendMessage( "This command only works on mobiles." );
return;
}
break;
}
case ObjectTypes.Mobiles:
{
if (!(targeted is Mobile))
{
from.SendMessage("This command only works on mobiles.");
return;
}
break;
}
}
break;
}
}
RunCommand( from, targeted, command, args );
}
}
}
RunCommand(from, targeted, command, args);
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,413 +1,411 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Text;
using Server.Commands.Generic;
using Server.Gumps;
using Server.Network;
using Server.Commands.Generic;
using CommandInfo=Server.Commands.Docs.DocCommandEntry;
using CommandInfoSorter=Server.Commands.Docs.CommandEntrySorter;
using CommandInfo = Server.Commands.Docs.DocCommandEntry;
using CommandInfoSorter = Server.Commands.Docs.CommandEntrySorter;
namespace Server.Commands
{
public class HelpInfo
{
public static Dictionary<string, CommandInfo> HelpInfos { get; } = new Dictionary<string, CommandInfo>();
public class HelpInfo
{
public static Dictionary<string, CommandInfo> HelpInfos{ get; } = new Dictionary<string, CommandInfo>();
public static List<CommandInfo> SortedHelpInfo { get; private set; } = new List<CommandInfo>();
public static List<CommandInfo> SortedHelpInfo{ get; private set; } = new List<CommandInfo>();
[CallPriority( 100 )]
public static void Initialize()
{
CommandSystem.Register( "HelpInfo", AccessLevel.Player, HelpInfo_OnCommand );
[CallPriority(100)]
public static void Initialize()
{
CommandSystem.Register("HelpInfo", AccessLevel.Player, HelpInfo_OnCommand);
FillTable();
}
FillTable();
}
[Usage( "HelpInfo [<command>]" )]
[Description( "Gives information on a specified command, or when no argument specified, displays a gump containing all commands" )]
private static void HelpInfo_OnCommand( CommandEventArgs e )
{
if ( e.Length > 0 )
{
string arg = e.GetString( 0 ).ToLower();
if (HelpInfos.TryGetValue( arg, out CommandInfo c ))
{
Mobile m = e.Mobile;
[Usage("HelpInfo [<command>]")]
[Description(
"Gives information on a specified command, or when no argument specified, displays a gump containing all commands")]
private static void HelpInfo_OnCommand(CommandEventArgs e)
{
if (e.Length > 0)
{
string arg = e.GetString(0).ToLower();
if (HelpInfos.TryGetValue(arg, out CommandInfo c))
{
Mobile m = e.Mobile;
if ( m.AccessLevel >= c.AccessLevel )
m.SendGump( new CommandInfoGump( c ) );
else
m.SendMessage( "You don't have access to that command." );
if (m.AccessLevel >= c.AccessLevel)
m.SendGump(new CommandInfoGump(c));
else
m.SendMessage("You don't have access to that command.");
return;
}
return;
}
e.Mobile.SendMessage($"Command '{arg}' not found!");
}
e.Mobile.SendMessage($"Command '{arg}' not found!");
}
e.Mobile.SendGump( new CommandListGump( 0, e.Mobile, null ) );
e.Mobile.SendGump(new CommandListGump(0, e.Mobile, null));
}
}
public static void FillTable()
{
List<CommandEntry> commands = new List<CommandEntry>(CommandSystem.Entries.Values);
List<CommandInfo> list = new List<CommandInfo>();
public static void FillTable()
{
List<CommandEntry> commands = new List<CommandEntry>( CommandSystem.Entries.Values );
List<CommandInfo> list = new List<CommandInfo>();
commands.Sort();
commands.Reverse();
Docs.Clean(commands);
commands.Sort();
commands.Reverse();
Docs.Clean( commands );
for (int i = 0; i < commands.Count; ++i)
{
CommandEntry e = commands[i];
for( int i = 0; i < commands.Count; ++i )
{
CommandEntry e =commands[i];
MethodInfo mi = e.Handler.Method;
MethodInfo mi = e.Handler.Method;
object[] attrs = mi.GetCustomAttributes(typeof(UsageAttribute), false);
object[] attrs = mi.GetCustomAttributes( typeof( UsageAttribute ), false );
if (attrs.Length == 0)
continue;
if ( attrs.Length == 0 )
continue;
UsageAttribute usage = attrs[0] as UsageAttribute;
UsageAttribute usage = attrs[0] as UsageAttribute;
attrs = mi.GetCustomAttributes(typeof(DescriptionAttribute), false);
attrs = mi.GetCustomAttributes( typeof( DescriptionAttribute ), false );
if (attrs.Length == 0)
continue;
if ( attrs.Length == 0 )
continue;
if (usage == null || !(attrs[0] is DescriptionAttribute desc))
continue;
if ( usage == null || !(attrs[0] is DescriptionAttribute desc) )
continue;
attrs = mi.GetCustomAttributes(typeof(AliasesAttribute), false);
attrs = mi.GetCustomAttributes( typeof( AliasesAttribute ), false );
AliasesAttribute aliases = attrs.Length == 0 ? null : attrs[0] as AliasesAttribute;
AliasesAttribute aliases = (attrs.Length == 0 ? null : attrs[0] as AliasesAttribute);
string descString = desc.Description.Replace("<", "(").Replace(">", ")");
string descString = desc.Description.Replace( "<", "(" ).Replace( ">", ")" );
if (aliases == null)
{
list.Add(new CommandInfo(e.AccessLevel, e.Command, null, usage.Usage, descString));
}
else
{
list.Add(new CommandInfo(e.AccessLevel, e.Command, aliases.Aliases, usage.Usage, descString));
if ( aliases == null )
list.Add( new CommandInfo( e.AccessLevel, e.Command, null, usage.Usage, descString ) );
else
{
list.Add( new CommandInfo( e.AccessLevel, e.Command, aliases.Aliases, usage.Usage, descString ) );
for (int j = 0; j < aliases.Aliases.Length; j++)
{
string[] newAliases = new string[aliases.Aliases.Length];
for( int j = 0; j < aliases.Aliases.Length; j++ )
{
string[] newAliases = new string[aliases.Aliases.Length];
aliases.Aliases.CopyTo(newAliases, 0);
aliases.Aliases.CopyTo( newAliases, 0 );
newAliases[j] = e.Command;
newAliases[j] = e.Command;
list.Add(new CommandInfo(e.AccessLevel, aliases.Aliases[j], newAliases, usage.Usage, descString));
}
}
}
list.Add( new CommandInfo( e.AccessLevel, aliases.Aliases[j], newAliases, usage.Usage, descString ) );
}
}
}
for (int i = 0; i < TargetCommands.AllCommands.Count; ++i)
{
BaseCommand command = TargetCommands.AllCommands[i];
for( int i = 0; i < TargetCommands.AllCommands.Count; ++i )
{
BaseCommand command = TargetCommands.AllCommands[i];
string usage = command.Usage;
string desc = command.Description;
string usage = command.Usage;
string desc = command.Description;
if (usage == null || desc == null)
continue;
if ( usage == null || desc == null )
continue;
string[] cmds = command.Commands;
string cmd = cmds[0];
string[] aliases = new string[cmds.Length - 1];
string[] cmds = command.Commands;
string cmd = cmds[0];
string[] aliases = new string[cmds.Length - 1];
for (int j = 0; j < aliases.Length; ++j)
aliases[j] = cmds[j + 1];
for( int j = 0; j < aliases.Length; ++j )
aliases[j] = cmds[j + 1];
desc = desc.Replace("<", "(").Replace(">", ")");
desc = desc.Replace( "<", "(" ).Replace( ">", ")" );
if (command.Supports != CommandSupport.Single)
{
StringBuilder sb = new StringBuilder(50 + desc.Length);
if ( command.Supports != CommandSupport.Single )
{
StringBuilder sb = new StringBuilder( 50 + desc.Length );
sb.Append("Modifiers: ");
sb.Append( "Modifiers: " );
if ((command.Supports & CommandSupport.Global) != 0)
sb.Append("<i>Global</i>, ");
if ( (command.Supports & CommandSupport.Global) != 0 )
sb.Append( "<i>Global</i>, " );
if ((command.Supports & CommandSupport.Online) != 0)
sb.Append("<i>Online</i>, ");
if ( (command.Supports & CommandSupport.Online) != 0 )
sb.Append( "<i>Online</i>, " );
if ((command.Supports & CommandSupport.Region) != 0)
sb.Append("<i>Region</i>, ");
if ( (command.Supports & CommandSupport.Region) != 0 )
sb.Append( "<i>Region</i>, " );
if ((command.Supports & CommandSupport.Contained) != 0)
sb.Append("<i>Contained</i>, ");
if ( (command.Supports & CommandSupport.Contained) != 0 )
sb.Append( "<i>Contained</i>, " );
if ((command.Supports & CommandSupport.Multi) != 0)
sb.Append("<i>Multi</i>, ");
if ( (command.Supports & CommandSupport.Multi) != 0 )
sb.Append( "<i>Multi</i>, " );
if ((command.Supports & CommandSupport.Area) != 0)
sb.Append("<i>Area</i>, ");
if ( (command.Supports & CommandSupport.Area) != 0 )
sb.Append( "<i>Area</i>, " );
if ((command.Supports & CommandSupport.Self) != 0)
sb.Append("<i>Self</i>, ");
if ( (command.Supports & CommandSupport.Self) != 0 )
sb.Append( "<i>Self</i>, " );
sb.Remove(sb.Length - 2, 2);
sb.Append("<br>");
sb.Append(desc);
sb.Remove( sb.Length - 2, 2 );
sb.Append( "<br>" );
sb.Append( desc );
desc = sb.ToString();
}
desc = sb.ToString();
}
list.Add(new CommandInfo(command.AccessLevel, cmd, aliases, usage, desc));
list.Add( new CommandInfo( command.AccessLevel, cmd, aliases, usage, desc ) );
for (int j = 0; j < aliases.Length; j++)
{
string[] newAliases = new string[aliases.Length];
for( int j = 0; j < aliases.Length; j++ )
{
string[] newAliases = new string[aliases.Length];
aliases.CopyTo(newAliases, 0);
aliases.CopyTo( newAliases, 0 );
newAliases[j] = cmd;
newAliases[j] = cmd;
list.Add(new CommandInfo(command.AccessLevel, aliases[j], newAliases, usage, desc));
}
}
list.Add( new CommandInfo( command.AccessLevel, aliases[j], newAliases, usage, desc ) );
}
}
List<BaseCommandImplementor> commandImpls = BaseCommandImplementor.Implementors;
List<BaseCommandImplementor> commandImpls = BaseCommandImplementor.Implementors;
for (int i = 0; i < commandImpls.Count; ++i)
{
BaseCommandImplementor command = commandImpls[i];
for( int i = 0; i < commandImpls.Count; ++i )
{
BaseCommandImplementor command = commandImpls[i];
string usage = command.Usage;
string desc = command.Description;
string usage = command.Usage;
string desc = command.Description;
if (usage == null || desc == null)
continue;
if ( usage == null || desc == null )
continue;
string[] cmds = command.Accessors;
string cmd = cmds[0];
string[] aliases = new string[cmds.Length - 1];
string[] cmds = command.Accessors;
string cmd = cmds[0];
string[] aliases = new string[cmds.Length - 1];
for (int j = 0; j < aliases.Length; ++j)
aliases[j] = cmds[j + 1];
for( int j = 0; j < aliases.Length; ++j )
aliases[j] = cmds[j + 1];
desc = desc.Replace("<", ")").Replace(">", ")");
desc = desc.Replace( "<", ")" ).Replace( ">", ")" );
list.Add(new CommandInfo(command.AccessLevel, cmd, aliases, usage, desc));
list.Add( new CommandInfo( command.AccessLevel, cmd, aliases, usage, desc ) );
for (int j = 0; j < aliases.Length; j++)
{
string[] newAliases = new string[aliases.Length];
for( int j = 0; j < aliases.Length; j++ )
{
string[] newAliases = new string[aliases.Length];
aliases.CopyTo(newAliases, 0);
aliases.CopyTo( newAliases, 0 );
newAliases[j] = cmd;
newAliases[j] = cmd;
list.Add(new CommandInfo(command.AccessLevel, aliases[j], newAliases, usage, desc));
}
}
list.Add( new CommandInfo( command.AccessLevel, aliases[j], newAliases, usage, desc ) );
}
}
list.Sort(new CommandInfoSorter());
list.Sort( new CommandInfoSorter() );
SortedHelpInfo = list;
SortedHelpInfo = list;
foreach (CommandInfo c in SortedHelpInfo)
if (!HelpInfos.ContainsKey(c.Name.ToLower()))
HelpInfos.Add(c.Name.ToLower(), c);
}
foreach( CommandInfo c in SortedHelpInfo )
{
if ( !HelpInfos.ContainsKey( c.Name.ToLower() ) )
HelpInfos.Add( c.Name.ToLower(), c );
}
}
public class CommandListGump : BaseGridGump
{
private const int EntriesPerPage = 15;
private List<CommandInfo> m_List;
public class CommandListGump : BaseGridGump
{
private const int EntriesPerPage = 15;
private int m_Page;
int m_Page;
List<CommandInfo> m_List;
public CommandListGump(int page, Mobile from, List<CommandInfo> list)
: base(30, 30)
{
m_Page = page;
public CommandListGump( int page, Mobile from, List<CommandInfo> list )
: base( 30, 30 )
{
m_Page = page;
if (list == null)
{
m_List = new List<CommandInfo>();
if ( list == null )
{
m_List = new List<CommandInfo>();
foreach (CommandInfo c in SortedHelpInfo)
if (from.AccessLevel >= c.AccessLevel)
m_List.Add(c);
}
else
{
m_List = list;
}
foreach( CommandInfo c in SortedHelpInfo )
{
if ( from.AccessLevel >= c.AccessLevel )
m_List.Add( c );
}
}
else
m_List = list;
AddNewPage();
AddNewPage();
if (m_Page > 0)
AddEntryButton(20, ArrowLeftID1, ArrowLeftID2, 1, ArrowLeftWidth, ArrowLeftHeight);
else
AddEntryHeader(20);
if ( m_Page > 0 )
AddEntryButton( 20, ArrowLeftID1, ArrowLeftID2, 1, ArrowLeftWidth, ArrowLeftHeight );
else
AddEntryHeader( 20 );
AddEntryHtml(160, Center(
$"Page {m_Page + 1} of {(m_List.Count + EntriesPerPage - 1) / EntriesPerPage}"));
AddEntryHtml( 160, Center(
$"Page {m_Page + 1} of {(m_List.Count + EntriesPerPage - 1) / EntriesPerPage}") );
if ( (m_Page + 1) * EntriesPerPage < m_List.Count )
AddEntryButton( 20, ArrowRightID1, ArrowRightID2, 2, ArrowRightWidth, ArrowRightHeight );
else
AddEntryHeader( 20 );
int last = (int)AccessLevel.Player - 1;
for( int i = m_Page * EntriesPerPage, line = 0; line < EntriesPerPage && i < m_List.Count; ++i, ++line )
{
CommandInfo c = m_List[i];
if ( from.AccessLevel >= c.AccessLevel )
{
if ( (int)c.AccessLevel != last )
{
AddNewLine();
AddEntryHtml( 20 + OffsetSize + 160, Color( c.AccessLevel.ToString(), 0xFF0000 ) );
AddEntryHeader( 20 );
line++;
}
last = (int)c.AccessLevel;
AddNewLine();
AddEntryHtml( 20 + OffsetSize + 160, c.Name );
AddEntryButton( 20, ArrowRightID1, ArrowRightID2, 3 + i, ArrowRightWidth, ArrowRightHeight );
}
}
FinishPage();
}
public override void OnResponse( NetState sender, RelayInfo info )
{
Mobile m = sender.Mobile;
switch( info.ButtonID )
{
case 0:
{
m.CloseGump( typeof( CommandInfoGump ) );
break;
}
case 1:
{
if ( m_Page > 0 )
m.SendGump( new CommandListGump( m_Page - 1, m, m_List ) );
break;
}
case 2:
{
if ( (m_Page + 1) * EntriesPerPage < SortedHelpInfo.Count )
m.SendGump( new CommandListGump( m_Page + 1, m, m_List ) );
break;
}
default:
{
int v = info.ButtonID - 3;
if ( v >= 0 && v < m_List.Count )
{
CommandInfo c = m_List[v];
if ( m.AccessLevel >= c.AccessLevel )
{
m.SendGump( new CommandInfoGump( c ) );
m.SendGump( new CommandListGump( m_Page, m, m_List ) );
}
else
{
m.SendMessage( "You no longer have access to that command." );
m.SendGump( new CommandListGump( m_Page, m, null ) );
}
}
break;
}
}
}
}
public class CommandInfoGump : Gump
{
public string Color( string text, int color )
{
return $"<BASEFONT COLOR=#{color:X6}>{text}</BASEFONT>";
}
public string Center( string text )
{
return $"<CENTER>{text}</CENTER>";
}
public CommandInfoGump( CommandInfo info )
: this( info, 320, 200 )
{
}
public CommandInfoGump( CommandInfo info, int width, int height )
: base( 300, 50 )
{
AddPage( 0 );
AddBackground( 0, 0, width, height, 5054 );
//AddImageTiled( 10, 10, width - 20, 20, 2624 );
//AddAlphaRegion( 10, 10, width - 20, 20 );
//AddHtmlLocalized( 10, 10, width - 20, 20, header, headerColor, false, false );
AddHtml( 10, 10, width - 20, 20, Color( Center( info.Name ), 0xFF0000 ), false, false );
//AddImageTiled( 10, 40, width - 20, height - 80, 2624 );
//AddAlphaRegion( 10, 40, width - 20, height - 80 );
StringBuilder sb = new StringBuilder();
sb.Append( "Usage: " );
sb.Append( info.Usage.Replace( "<", "(" ).Replace( ">", ")" ) );
sb.Append( "<BR>" );
string[] aliases = info.Aliases;
if ( aliases != null && aliases.Length != 0 )
{
sb.Append($"Alias{(aliases.Length == 1 ? "" : "es")}: ");
for( int i = 0; i < aliases.Length; ++i )
{
if ( i != 0 )
sb.Append( ", " );
sb.Append( aliases[i] );
}
sb.Append( "<BR>" );
}
sb.Append( "AccessLevel: " );
sb.Append( info.AccessLevel.ToString() );
sb.Append( "<BR>" );
sb.Append( "<BR>" );
sb.Append( info.Description );
AddHtml( 10, 40, width - 20, height - 80, sb.ToString(), false, true );
//AddImageTiled( 10, height - 30, width - 20, 20, 2624 );
//AddAlphaRegion( 10, height - 30, width - 20, 20 );
}
}
}
}
if ((m_Page + 1) * EntriesPerPage < m_List.Count)
AddEntryButton(20, ArrowRightID1, ArrowRightID2, 2, ArrowRightWidth, ArrowRightHeight);
else
AddEntryHeader(20);
int last = (int)AccessLevel.Player - 1;
for (int i = m_Page * EntriesPerPage, line = 0; line < EntriesPerPage && i < m_List.Count; ++i, ++line)
{
CommandInfo c = m_List[i];
if (from.AccessLevel >= c.AccessLevel)
{
if ((int)c.AccessLevel != last)
{
AddNewLine();
AddEntryHtml(20 + OffsetSize + 160, Color(c.AccessLevel.ToString(), 0xFF0000));
AddEntryHeader(20);
line++;
}
last = (int)c.AccessLevel;
AddNewLine();
AddEntryHtml(20 + OffsetSize + 160, c.Name);
AddEntryButton(20, ArrowRightID1, ArrowRightID2, 3 + i, ArrowRightWidth, ArrowRightHeight);
}
}
FinishPage();
}
public override void OnResponse(NetState sender, RelayInfo info)
{
Mobile m = sender.Mobile;
switch (info.ButtonID)
{
case 0:
{
m.CloseGump(typeof(CommandInfoGump));
break;
}
case 1:
{
if (m_Page > 0)
m.SendGump(new CommandListGump(m_Page - 1, m, m_List));
break;
}
case 2:
{
if ((m_Page + 1) * EntriesPerPage < SortedHelpInfo.Count)
m.SendGump(new CommandListGump(m_Page + 1, m, m_List));
break;
}
default:
{
int v = info.ButtonID - 3;
if (v >= 0 && v < m_List.Count)
{
CommandInfo c = m_List[v];
if (m.AccessLevel >= c.AccessLevel)
{
m.SendGump(new CommandInfoGump(c));
m.SendGump(new CommandListGump(m_Page, m, m_List));
}
else
{
m.SendMessage("You no longer have access to that command.");
m.SendGump(new CommandListGump(m_Page, m, null));
}
}
break;
}
}
}
}
public class CommandInfoGump : Gump
{
public CommandInfoGump(CommandInfo info)
: this(info, 320, 200)
{
}
public CommandInfoGump(CommandInfo info, int width, int height)
: base(300, 50)
{
AddPage(0);
AddBackground(0, 0, width, height, 5054);
//AddImageTiled( 10, 10, width - 20, 20, 2624 );
//AddAlphaRegion( 10, 10, width - 20, 20 );
//AddHtmlLocalized( 10, 10, width - 20, 20, header, headerColor, false, false );
AddHtml(10, 10, width - 20, 20, Color(Center(info.Name), 0xFF0000), false, false);
//AddImageTiled( 10, 40, width - 20, height - 80, 2624 );
//AddAlphaRegion( 10, 40, width - 20, height - 80 );
StringBuilder sb = new StringBuilder();
sb.Append("Usage: ");
sb.Append(info.Usage.Replace("<", "(").Replace(">", ")"));
sb.Append("<BR>");
string[] aliases = info.Aliases;
if (aliases != null && aliases.Length != 0)
{
sb.Append($"Alias{(aliases.Length == 1 ? "" : "es")}: ");
for (int i = 0; i < aliases.Length; ++i)
{
if (i != 0)
sb.Append(", ");
sb.Append(aliases[i]);
}
sb.Append("<BR>");
}
sb.Append("AccessLevel: ");
sb.Append(info.AccessLevel.ToString());
sb.Append("<BR>");
sb.Append("<BR>");
sb.Append(info.Description);
AddHtml(10, 40, width - 20, height - 80, sb.ToString(), false, true);
//AddImageTiled( 10, height - 30, width - 20, 20, 2624 );
//AddAlphaRegion( 10, height - 30, width - 20, 20 );
}
public string Color(string text, int color)
{
return $"<BASEFONT COLOR=#{color:X6}>{text}</BASEFONT>";
}
public string Center(string text)
{
return $"<CENTER>{text}</CENTER>";
}
}
}
}

View file

@ -1,137 +1,139 @@
using System;
using System.IO;
using System.Text;
using Server.Accounting;
namespace Server.Commands
{
public class CommandLogging
{
public static bool Enabled { get; set; } = true;
public class CommandLogging
{
private static char[] m_NotSafe = { '\\', '/', ':', '*', '?', '"', '<', '>', '|' };
public static bool Enabled{ get; set; } = true;
public static StreamWriter Output { get; private set; }
public static StreamWriter Output{ get; private set; }
public static void Initialize()
{
EventSink.Command += EventSink_Command;
public static void Initialize()
{
EventSink.Command += EventSink_Command;
if ( !Directory.Exists( "Logs" ) )
Directory.CreateDirectory( "Logs" );
if (!Directory.Exists("Logs"))
Directory.CreateDirectory("Logs");
string directory = "Logs/Commands";
string directory = "Logs/Commands";
if ( !Directory.Exists( directory ) )
Directory.CreateDirectory( directory );
if (!Directory.Exists(directory))
Directory.CreateDirectory(directory);
try
{
Output = new StreamWriter( Path.Combine( directory, $"{DateTime.UtcNow.ToLongDateString()}.log"), true );
try
{
Output = new StreamWriter(Path.Combine(directory, $"{DateTime.UtcNow.ToLongDateString()}.log"), true);
Output.AutoFlush = true;
Output.AutoFlush = true;
Output.WriteLine( "##############################" );
Output.WriteLine( "Log started on {0}", DateTime.UtcNow );
Output.WriteLine();
}
catch
{
}
}
Output.WriteLine("##############################");
Output.WriteLine("Log started on {0}", DateTime.UtcNow);
Output.WriteLine();
}
catch
{
}
}
public static object Format( object o )
{
if ( o is Mobile m )
{
if ( m.Account == null )
return $"{m} (no account)";
public static object Format(object o)
{
if (o is Mobile m)
{
if (m.Account == null)
return $"{m} (no account)";
return $"{m} ('{m.Account.Username}')";
}
if ( o is Item item )
{
return $"0x{item.Serial.Value:X} ({item.GetType().Name})";
}
return $"{m} ('{m.Account.Username}')";
}
return o;
}
if (o is Item item) return $"0x{item.Serial.Value:X} ({item.GetType().Name})";
public static void WriteLine( Mobile from, string format, params object[] args )
{
if ( !Enabled )
return;
return o;
}
WriteLine( from, string.Format( format, args ) );
}
public static void WriteLine(Mobile from, string format, params object[] args)
{
if (!Enabled)
return;
public static void WriteLine( Mobile from, string text )
{
if ( !Enabled )
return;
WriteLine(from, string.Format(format, args));
}
try
{
Output.WriteLine( "{0}: {1}: {2}", DateTime.UtcNow, from.NetState, text );
public static void WriteLine(Mobile from, string text)
{
if (!Enabled)
return;
string path = Core.BaseDirectory;
try
{
Output.WriteLine("{0}: {1}: {2}", DateTime.UtcNow, from.NetState, text);
string name = ( !(from.Account is Account acct) ? from.Name : acct.Username );
string path = Core.BaseDirectory;
AppendPath( ref path, "Logs" );
AppendPath( ref path, "Commands" );
AppendPath( ref path, from.AccessLevel.ToString() );
path = Path.Combine( path, $"{name}.log");
string name = !(from.Account is Account acct) ? from.Name : acct.Username;
using ( StreamWriter sw = new StreamWriter( path, true ) )
sw.WriteLine( "{0}: {1}: {2}", DateTime.UtcNow, from.NetState, text );
}
catch
{
}
}
AppendPath(ref path, "Logs");
AppendPath(ref path, "Commands");
AppendPath(ref path, from.AccessLevel.ToString());
path = Path.Combine(path, $"{name}.log");
private static char[] m_NotSafe = { '\\', '/', ':', '*', '?', '"', '<', '>', '|' };
using (StreamWriter sw = new StreamWriter(path, true))
{
sw.WriteLine("{0}: {1}: {2}", DateTime.UtcNow, from.NetState, text);
}
}
catch
{
}
}
public static void AppendPath( ref string path, string toAppend )
{
path = Path.Combine( path, toAppend );
public static void AppendPath(ref string path, string toAppend)
{
path = Path.Combine(path, toAppend);
if ( !Directory.Exists( path ) )
Directory.CreateDirectory( path );
}
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
}
public static string Safe( string ip )
{
if ( ip == null )
return "null";
public static string Safe(string ip)
{
if (ip == null)
return "null";
ip = ip.Trim();
ip = ip.Trim();
if ( ip.Length == 0 )
return "empty";
if (ip.Length == 0)
return "empty";
bool isSafe = true;
bool isSafe = true;
for ( int i = 0; isSafe && i < m_NotSafe.Length; ++i )
isSafe = ( ip.IndexOf( m_NotSafe[i] ) == -1 );
for (int i = 0; isSafe && i < m_NotSafe.Length; ++i)
isSafe = ip.IndexOf(m_NotSafe[i]) == -1;
if ( isSafe )
return ip;
if (isSafe)
return ip;
System.Text.StringBuilder sb = new System.Text.StringBuilder( ip );
StringBuilder sb = new StringBuilder(ip);
for ( int i = 0; i < m_NotSafe.Length; ++i )
sb.Replace( m_NotSafe[i], '_' );
for (int i = 0; i < m_NotSafe.Length; ++i)
sb.Replace(m_NotSafe[i], '_');
return sb.ToString();
}
return sb.ToString();
}
public static void EventSink_Command( CommandEventArgs e )
{
WriteLine( e.Mobile, "{0} {1} used command '{2} {3}'", e.Mobile.AccessLevel, Format( e.Mobile ), e.Command, e.ArgString );
}
public static void EventSink_Command(CommandEventArgs e)
{
WriteLine(e.Mobile, "{0} {1} used command '{2} {3}'", e.Mobile.AccessLevel, Format(e.Mobile), e.Command,
e.ArgString);
}
public static void LogChangeProperty( Mobile from, object o, string name, string value )
{
WriteLine( from, "{0} {1} set property '{2}' of {3} to '{4}'", from.AccessLevel, Format( from ), name, Format( o ), value );
}
}
}
public static void LogChangeProperty(Mobile from, object o, string name, string value)
{
WriteLine(from, "{0} {1} set property '{2}' of {3} to '{4}'", from.AccessLevel, Format(from), name, Format(o),
value);
}
}
}

View file

@ -1,396 +1,399 @@
using System;
using System.IO;
using System.Collections;
using System.IO;
using Server.Diagnostics;
namespace Server.Commands
{
public class Profiling
{
public static void Initialize()
{
CommandSystem.Register( "DumpTimers", AccessLevel.Administrator, DumpTimers_OnCommand );
CommandSystem.Register( "CountObjects", AccessLevel.Administrator, CountObjects_OnCommand );
CommandSystem.Register( "ProfileWorld", AccessLevel.Administrator, ProfileWorld_OnCommand );
CommandSystem.Register( "TraceInternal", AccessLevel.Administrator, TraceInternal_OnCommand );
CommandSystem.Register( "TraceExpanded", AccessLevel.Administrator, TraceExpanded_OnCommand );
CommandSystem.Register( "WriteProfiles", AccessLevel.Administrator, WriteProfiles_OnCommand );
CommandSystem.Register( "SetProfiles", AccessLevel.Administrator, SetProfiles_OnCommand );
}
[Usage( "WriteProfiles" )]
[Description( "Generates a log files containing performance diagnostic information." )]
public static void WriteProfiles_OnCommand( CommandEventArgs e )
{
try
{
using ( StreamWriter sw = new StreamWriter( "profiles.log", true ) )
{
sw.WriteLine( "# Dump on {0:f}", DateTime.UtcNow );
sw.WriteLine( "# Core profiling for " + Core.ProfileTime );
sw.WriteLine( "# Packet send" );
BaseProfile.WriteAll( sw, PacketSendProfile.Profiles );
sw.WriteLine();
sw.WriteLine( "# Packet receive" );
BaseProfile.WriteAll( sw, PacketReceiveProfile.Profiles );
sw.WriteLine();
sw.WriteLine( "# Timer" );
BaseProfile.WriteAll( sw, TimerProfile.Profiles );
sw.WriteLine();
sw.WriteLine( "# Gump response" );
BaseProfile.WriteAll( sw, GumpProfile.Profiles );
sw.WriteLine();
sw.WriteLine( "# Target response" );
BaseProfile.WriteAll( sw, TargetProfile.Profiles );
sw.WriteLine();
}
}
catch
{
}
}
[Usage( "SetProfiles [true | false]" )]
[Description( "Enables, disables, or toggles the state of core packet and timer profiling." )]
public static void SetProfiles_OnCommand( CommandEventArgs e )
{
if ( e.Length == 1 )
Core.Profiling = e.GetBoolean( 0 );
else
Core.Profiling = !Core.Profiling;
e.Mobile.SendMessage( "Profiling has been {0}.", Core.Profiling ? "enabled" : "disabled" );
}
[Usage( "DumpTimers" )]
[Description( "Generates a log file of all currently executing timers. Used for tracing timer leaks." )]
public static void DumpTimers_OnCommand( CommandEventArgs e )
{
try
{
using ( StreamWriter sw = new StreamWriter( "timerdump.log", true ) )
Timer.DumpInfo( sw );
}
catch
{
}
}
private class CountSorter : IComparer
{
public int Compare( object x, object y )
{
DictionaryEntry a = (DictionaryEntry)x;
DictionaryEntry b = (DictionaryEntry)y;
int aCount = GetCount( a.Value );
int bCount = GetCount( b.Value );
int v = -aCount.CompareTo( bCount );
if ( v == 0 )
{
Type aType = (Type)a.Key;
Type bType = (Type)b.Key;
v = aType.FullName.CompareTo( bType.FullName );
}
return v;
}
private int GetCount( object obj )
{
if ( obj is int intObj )
return intObj;
if ( obj is int[] list )
{
int total = 0;
for ( int i = 0; i < list.Length; ++i )
total += list[i];
return total;
}
return 0;
}
}
[Usage( "CountObjects" )]
[Description( "Generates a log file detailing all item and mobile types in the world." )]
public static void CountObjects_OnCommand( CommandEventArgs e )
{
using ( StreamWriter op = new StreamWriter( "objects.log" ) )
{
Hashtable table = new Hashtable();
public class Profiling
{
public static void Initialize()
{
CommandSystem.Register("DumpTimers", AccessLevel.Administrator, DumpTimers_OnCommand);
CommandSystem.Register("CountObjects", AccessLevel.Administrator, CountObjects_OnCommand);
CommandSystem.Register("ProfileWorld", AccessLevel.Administrator, ProfileWorld_OnCommand);
CommandSystem.Register("TraceInternal", AccessLevel.Administrator, TraceInternal_OnCommand);
CommandSystem.Register("TraceExpanded", AccessLevel.Administrator, TraceExpanded_OnCommand);
CommandSystem.Register("WriteProfiles", AccessLevel.Administrator, WriteProfiles_OnCommand);
CommandSystem.Register("SetProfiles", AccessLevel.Administrator, SetProfiles_OnCommand);
}
[Usage("WriteProfiles")]
[Description("Generates a log files containing performance diagnostic information.")]
public static void WriteProfiles_OnCommand(CommandEventArgs e)
{
try
{
using (StreamWriter sw = new StreamWriter("profiles.log", true))
{
sw.WriteLine("# Dump on {0:f}", DateTime.UtcNow);
sw.WriteLine("# Core profiling for " + Core.ProfileTime);
sw.WriteLine("# Packet send");
BaseProfile.WriteAll(sw, PacketSendProfile.Profiles);
sw.WriteLine();
sw.WriteLine("# Packet receive");
BaseProfile.WriteAll(sw, PacketReceiveProfile.Profiles);
sw.WriteLine();
sw.WriteLine("# Timer");
BaseProfile.WriteAll(sw, TimerProfile.Profiles);
sw.WriteLine();
sw.WriteLine("# Gump response");
BaseProfile.WriteAll(sw, GumpProfile.Profiles);
sw.WriteLine();
sw.WriteLine("# Target response");
BaseProfile.WriteAll(sw, TargetProfile.Profiles);
sw.WriteLine();
}
}
catch
{
}
}
[Usage("SetProfiles [true | false]")]
[Description("Enables, disables, or toggles the state of core packet and timer profiling.")]
public static void SetProfiles_OnCommand(CommandEventArgs e)
{
if (e.Length == 1)
Core.Profiling = e.GetBoolean(0);
else
Core.Profiling = !Core.Profiling;
e.Mobile.SendMessage("Profiling has been {0}.", Core.Profiling ? "enabled" : "disabled");
}
[Usage("DumpTimers")]
[Description("Generates a log file of all currently executing timers. Used for tracing timer leaks.")]
public static void DumpTimers_OnCommand(CommandEventArgs e)
{
try
{
using (StreamWriter sw = new StreamWriter("timerdump.log", true))
{
Timer.DumpInfo(sw);
}
}
catch
{
}
}
[Usage("CountObjects")]
[Description("Generates a log file detailing all item and mobile types in the world.")]
public static void CountObjects_OnCommand(CommandEventArgs e)
{
using (StreamWriter op = new StreamWriter("objects.log"))
{
Hashtable table = new Hashtable();
foreach (Item item in World.Items.Values)
{
Type type = item.GetType();
object o = table[type];
if (o == null)
table[type] = 1;
else
table[type] = 1 + (int)o;
}
ArrayList items = new ArrayList(table);
table.Clear();
foreach (Mobile m in World.Mobiles.Values)
{
Type type = m.GetType();
object o = table[type];
if (o == null)
table[type] = 1;
else
table[type] = 1 + (int)o;
}
ArrayList mobiles = new ArrayList(table);
items.Sort(new CountSorter());
mobiles.Sort(new CountSorter());
op.WriteLine("# Object count table generated on {0}", DateTime.UtcNow);
op.WriteLine();
op.WriteLine();
op.WriteLine("# Items:");
foreach (DictionaryEntry de in items)
op.WriteLine("{0}\t{1:F2}%\t{2}", de.Value, 100 * (int)de.Value / (double)World.Items.Count, de.Key);
op.WriteLine();
op.WriteLine();
op.WriteLine("#Mobiles:");
foreach (DictionaryEntry de in mobiles)
op.WriteLine("{0}\t{1:F2}%\t{2}", de.Value, 100 * (int)de.Value / (double)World.Mobiles.Count, de.Key);
}
e.Mobile.SendMessage("Object table has been generated. See the file : <runuo root>/objects.log");
}
[Usage("TraceExpanded")]
[Description("Generates a log file describing all items using expanded memory.")]
public static void TraceExpanded_OnCommand(CommandEventArgs e)
{
Hashtable typeTable = new Hashtable();
foreach (Item item in World.Items.Values)
{
ExpandFlag flags = item.GetExpandFlags();
if ((flags & ~(ExpandFlag.TempFlag | ExpandFlag.SaveFlag)) == 0)
continue;
Type itemType = item.GetType();
do
{
if (!(typeTable[itemType] is int[] countTable))
typeTable[itemType] = countTable = new int[9];
if ((flags & ExpandFlag.Name) != 0)
++countTable[0];
if ((flags & ExpandFlag.Items) != 0)
++countTable[1];
if ((flags & ExpandFlag.Bounce) != 0)
++countTable[2];
if ((flags & ExpandFlag.Holder) != 0)
++countTable[3];
if ((flags & ExpandFlag.Blessed) != 0)
++countTable[4];
foreach ( Item item in World.Items.Values )
{
Type type = item.GetType();
/*if ( ( flags & ExpandFlag.TempFlag ) != 0 )
++countTable[5];
object o = (object)table[type];
if ( ( flags & ExpandFlag.SaveFlag ) != 0 )
++countTable[6];*/
if ((flags & ExpandFlag.Weight) != 0)
++countTable[7];
if ( o == null )
table[type] = 1;
else
table[type] = 1 + (int)o;
}
ArrayList items = new ArrayList( table );
table.Clear();
foreach ( Mobile m in World.Mobiles.Values )
{
Type type = m.GetType();
object o = (object)table[type];
if ( o == null )
table[type] = 1;
else
table[type] = 1 + (int)o;
}
ArrayList mobiles = new ArrayList( table );
items.Sort( new CountSorter() );
mobiles.Sort( new CountSorter() );
op.WriteLine( "# Object count table generated on {0}", DateTime.UtcNow );
op.WriteLine();
op.WriteLine();
op.WriteLine( "# Items:" );
foreach ( DictionaryEntry de in items )
op.WriteLine( "{0}\t{1:F2}%\t{2}", de.Value, (100 * (int)de.Value) / (double)World.Items.Count, de.Key );
op.WriteLine();
op.WriteLine();
op.WriteLine( "#Mobiles:" );
foreach ( DictionaryEntry de in mobiles )
op.WriteLine( "{0}\t{1:F2}%\t{2}", de.Value, (100 * (int)de.Value) / (double)World.Mobiles.Count, de.Key );
}
e.Mobile.SendMessage( "Object table has been generated. See the file : <runuo root>/objects.log" );
}
[Usage( "TraceExpanded" )]
[Description( "Generates a log file describing all items using expanded memory." )]
public static void TraceExpanded_OnCommand( CommandEventArgs e )
{
Hashtable typeTable = new Hashtable();
foreach ( Item item in World.Items.Values )
{
ExpandFlag flags = item.GetExpandFlags();
if ( ( flags & ~(ExpandFlag.TempFlag | ExpandFlag.SaveFlag) ) == 0 )
continue;
Type itemType = item.GetType();
do
{
if ( !(typeTable[itemType] is int[] countTable) )
typeTable[itemType] = countTable = new int[9];
if ( ( flags & ExpandFlag.Name ) != 0 )
++countTable[0];
if ( ( flags & ExpandFlag.Items ) != 0 )
++countTable[1];
if ( ( flags & ExpandFlag.Bounce ) != 0 )
++countTable[2];
if ( ( flags & ExpandFlag.Holder ) != 0 )
++countTable[3];
if ( ( flags & ExpandFlag.Blessed ) != 0 )
++countTable[4];
/*if ( ( flags & ExpandFlag.TempFlag ) != 0 )
++countTable[5];
if ( ( flags & ExpandFlag.SaveFlag ) != 0 )
++countTable[6];*/
if ( ( flags & ExpandFlag.Weight ) != 0 )
++countTable[7];
if ((flags & ExpandFlag.Spawner) != 0)
++countTable[8];
itemType = itemType.BaseType;
} while ( itemType != typeof( object ) );
}
try
{
using ( StreamWriter op = new StreamWriter( "expandedItems.log", true ) )
{
string[] names = {
"Name",
"Items",
"Bounce",
"Holder",
"Blessed",
"TempFlag",
"SaveFlag",
"Weight",
"Spawner"
};
ArrayList list = new ArrayList( typeTable );
list.Sort( new CountSorter() );
foreach ( DictionaryEntry de in list )
{
Type itemType = de.Key as Type;
int[] countTable = de.Value as int[];
op.WriteLine( "# {0}", itemType.FullName );
for ( int i = 0; i < countTable.Length; ++i )
{
if ( countTable[i] > 0 )
op.WriteLine( "{0}\t{1:N0}", names[i], countTable[i] );
}
op.WriteLine();
}
}
}
catch
{
}
}
[Usage( "TraceInternal" )]
[Description( "Generates a log file describing all items in the 'internal' map." )]
public static void TraceInternal_OnCommand( CommandEventArgs e )
{
int totalCount = 0;
Hashtable table = new Hashtable();
foreach ( Item item in World.Items.Values )
{
if ( item.Parent != null || item.Map != Map.Internal )
continue;
++totalCount;
Type type = item.GetType();
int[] parms = (int[])table[type];
if ( parms == null )
table[type] = parms = new[]{ 0, 0 };
parms[0]++;
parms[1] += item.Amount;
}
using ( StreamWriter op = new StreamWriter( "internal.log" ) )
{
op.WriteLine( "# {0} items found", totalCount );
op.WriteLine( "# {0} different types", table.Count );
op.WriteLine();
op.WriteLine();
op.WriteLine( "Type\t\tCount\t\tAmount\t\tAvg. Amount" );
foreach ( DictionaryEntry de in table )
{
Type type = (Type)de.Key;
int[] parms = (int[])de.Value;
op.WriteLine( "{0}\t\t{1}\t\t{2}\t\t{3:F2}", type.Name, parms[0], parms[1], (double)parms[1] / parms[0] );
}
}
}
[Usage( "ProfileWorld" )]
[Description( "Prints the amount of data serialized for every object type in your world file." )]
public static void ProfileWorld_OnCommand( CommandEventArgs e )
{
ProfileWorld( "items", "worldprofile_items.log" );
ProfileWorld( "mobiles", "worldprofile_mobiles.log" );
}
public static void ProfileWorld( string type, string opFile )
{
try
{
ArrayList types = new ArrayList();
using ( BinaryReader bin = new BinaryReader( new FileStream( string.Format( "Saves/{0}/{0}.tdb", type ), FileMode.Open, FileAccess.Read, FileShare.Read ) ) )
{
int count = bin.ReadInt32();
for ( int i = 0; i < count; ++i )
types.Add( ScriptCompiler.FindTypeByFullName( bin.ReadString() ) );
}
long total = 0;
Hashtable table = new Hashtable();
using ( BinaryReader bin = new BinaryReader( new FileStream( string.Format( "Saves/{0}/{0}.idx", type ), FileMode.Open, FileAccess.Read, FileShare.Read ) ) )
{
int count = bin.ReadInt32();
for ( int i = 0; i < count; ++i )
{
int typeID = bin.ReadInt32();
int serial = bin.ReadInt32();
long pos = bin.ReadInt64();
int length = bin.ReadInt32();
Type objType = (Type)types[typeID];
while ( objType != null && objType != typeof( object ) )
{
object obj = table[objType];
if ( obj == null )
table[objType] = length;
else
table[objType] = length + (int)obj;
objType = objType.BaseType;
total += length;
}
}
}
ArrayList list = new ArrayList( table );
list.Sort( new CountSorter() );
using ( StreamWriter op = new StreamWriter( opFile ) )
{
op.WriteLine( "# Profile of world {0}", type );
op.WriteLine( "# Generated on {0}", DateTime.UtcNow );
op.WriteLine();
op.WriteLine();
foreach ( DictionaryEntry de in list )
op.WriteLine( "{0}\t{1:F2}%\t{2}", de.Value, (100 * (int)de.Value) / (double)total, de.Key );
}
}
catch
{
}
}
}
}
if ((flags & ExpandFlag.Spawner) != 0)
++countTable[8];
itemType = itemType.BaseType;
} while (itemType != typeof(object));
}
try
{
using (StreamWriter op = new StreamWriter("expandedItems.log", true))
{
string[] names =
{
"Name",
"Items",
"Bounce",
"Holder",
"Blessed",
"TempFlag",
"SaveFlag",
"Weight",
"Spawner"
};
ArrayList list = new ArrayList(typeTable);
list.Sort(new CountSorter());
foreach (DictionaryEntry de in list)
{
Type itemType = de.Key as Type;
int[] countTable = de.Value as int[];
op.WriteLine("# {0}", itemType.FullName);
for (int i = 0; i < countTable.Length; ++i)
if (countTable[i] > 0)
op.WriteLine("{0}\t{1:N0}", names[i], countTable[i]);
op.WriteLine();
}
}
}
catch
{
}
}
[Usage("TraceInternal")]
[Description("Generates a log file describing all items in the 'internal' map.")]
public static void TraceInternal_OnCommand(CommandEventArgs e)
{
int totalCount = 0;
Hashtable table = new Hashtable();
foreach (Item item in World.Items.Values)
{
if (item.Parent != null || item.Map != Map.Internal)
continue;
++totalCount;
Type type = item.GetType();
int[] parms = (int[])table[type];
if (parms == null)
table[type] = parms = new[] { 0, 0 };
parms[0]++;
parms[1] += item.Amount;
}
using (StreamWriter op = new StreamWriter("internal.log"))
{
op.WriteLine("# {0} items found", totalCount);
op.WriteLine("# {0} different types", table.Count);
op.WriteLine();
op.WriteLine();
op.WriteLine("Type\t\tCount\t\tAmount\t\tAvg. Amount");
foreach (DictionaryEntry de in table)
{
Type type = (Type)de.Key;
int[] parms = (int[])de.Value;
op.WriteLine("{0}\t\t{1}\t\t{2}\t\t{3:F2}", type.Name, parms[0], parms[1], (double)parms[1] / parms[0]);
}
}
}
[Usage("ProfileWorld")]
[Description("Prints the amount of data serialized for every object type in your world file.")]
public static void ProfileWorld_OnCommand(CommandEventArgs e)
{
ProfileWorld("items", "worldprofile_items.log");
ProfileWorld("mobiles", "worldprofile_mobiles.log");
}
public static void ProfileWorld(string type, string opFile)
{
try
{
ArrayList types = new ArrayList();
using (BinaryReader bin = new BinaryReader(new FileStream(string.Format("Saves/{0}/{0}.tdb", type),
FileMode.Open, FileAccess.Read, FileShare.Read)))
{
int count = bin.ReadInt32();
for (int i = 0; i < count; ++i)
types.Add(ScriptCompiler.FindTypeByFullName(bin.ReadString()));
}
long total = 0;
Hashtable table = new Hashtable();
using (BinaryReader bin = new BinaryReader(new FileStream(string.Format("Saves/{0}/{0}.idx", type),
FileMode.Open, FileAccess.Read, FileShare.Read)))
{
int count = bin.ReadInt32();
for (int i = 0; i < count; ++i)
{
int typeID = bin.ReadInt32();
int serial = bin.ReadInt32();
long pos = bin.ReadInt64();
int length = bin.ReadInt32();
Type objType = (Type)types[typeID];
while (objType != null && objType != typeof(object))
{
object obj = table[objType];
if (obj == null)
table[objType] = length;
else
table[objType] = length + (int)obj;
objType = objType.BaseType;
total += length;
}
}
}
ArrayList list = new ArrayList(table);
list.Sort(new CountSorter());
using (StreamWriter op = new StreamWriter(opFile))
{
op.WriteLine("# Profile of world {0}", type);
op.WriteLine("# Generated on {0}", DateTime.UtcNow);
op.WriteLine();
op.WriteLine();
foreach (DictionaryEntry de in list)
op.WriteLine("{0}\t{1:F2}%\t{2}", de.Value, 100 * (int)de.Value / (double)total, de.Key);
}
}
catch
{
}
}
private class CountSorter : IComparer
{
public int Compare(object x, object y)
{
DictionaryEntry a = (DictionaryEntry)x;
DictionaryEntry b = (DictionaryEntry)y;
int aCount = GetCount(a.Value);
int bCount = GetCount(b.Value);
int v = -aCount.CompareTo(bCount);
if (v == 0)
{
Type aType = (Type)a.Key;
Type bType = (Type)b.Key;
v = aType.FullName.CompareTo(bType.FullName);
}
return v;
}
private int GetCount(object obj)
{
if (obj is int intObj)
return intObj;
if (obj is int[] list)
{
int total = 0;
for (int i = 0; i < list.Length; ++i)
total += list[i];
return total;
}
return 0;
}
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -2,18 +2,18 @@
namespace Server.Commands
{
public class ShardTime
{
public static void Initialize()
{
CommandSystem.Register( "Time", AccessLevel.Player, Time_OnCommand );
}
public class ShardTime
{
public static void Initialize()
{
CommandSystem.Register("Time", AccessLevel.Player, Time_OnCommand);
}
[Usage( "Time" )]
[Description( "Returns the server's local time." )]
private static void Time_OnCommand( CommandEventArgs e )
{
e.Mobile.SendMessage( DateTime.UtcNow.ToString() );
}
}
[Usage("Time")]
[Description("Returns the server's local time.")]
private static void Time_OnCommand(CommandEventArgs e)
{
e.Mobile.SendMessage(DateTime.UtcNow.ToString());
}
}
}

View file

@ -4,134 +4,145 @@ using Server.Items;
namespace Server.Commands
{
public class SignParser
{
private class SignEntry
{
public string m_Text;
public Point3D m_Location;
public int m_ItemID;
public int m_Map;
public class SignParser
{
private static Queue<Item> m_ToDelete = new Queue<Item>();
public SignEntry( string text, Point3D pt, int itemID, int mapLoc )
{
m_Text = text;
m_Location = pt;
m_ItemID = itemID;
m_Map = mapLoc;
}
}
public static void Initialize()
{
CommandSystem.Register("SignGen", AccessLevel.Administrator, SignGen_OnCommand);
}
public static void Initialize()
{
CommandSystem.Register( "SignGen", AccessLevel.Administrator, SignGen_OnCommand );
}
[Usage("SignGen")]
[Description("Generates world/shop signs on all facets.")]
public static void SignGen_OnCommand(CommandEventArgs c)
{
Parse(c.Mobile);
}
[Usage( "SignGen" )]
[Description( "Generates world/shop signs on all facets." )]
public static void SignGen_OnCommand( CommandEventArgs c )
{
Parse( c.Mobile );
}
public static void Parse(Mobile from)
{
string cfg = Path.Combine(Core.BaseDirectory, "Data/signs.cfg");
public static void Parse( Mobile from )
{
string cfg = Path.Combine( Core.BaseDirectory, "Data/signs.cfg" );
if (File.Exists(cfg))
{
List<SignEntry> list = new List<SignEntry>();
from.SendMessage("Generating signs, please wait.");
if ( File.Exists( cfg ) )
{
List<SignEntry> list = new List<SignEntry>();
from.SendMessage( "Generating signs, please wait." );
using (StreamReader ip = new StreamReader(cfg))
{
string line;
using ( StreamReader ip = new StreamReader( cfg ) )
{
string line;
while ((line = ip.ReadLine()) != null)
{
string[] split = line.Split(' ');
while ( (line = ip.ReadLine()) != null )
{
string[] split = line.Split( ' ' );
SignEntry e = new SignEntry(
line.Substring(split[0].Length + 1 + split[1].Length + 1 + split[2].Length + 1 +
split[3].Length + 1 + split[4].Length + 1),
new Point3D(Utility.ToInt32(split[2]), Utility.ToInt32(split[3]), Utility.ToInt32(split[4])),
Utility.ToInt32(split[1]), Utility.ToInt32(split[0]));
SignEntry e = new SignEntry(
line.Substring( split[0].Length + 1 + split[1].Length + 1 + split[2].Length + 1 + split[3].Length + 1 + split[4].Length + 1 ),
new Point3D( Utility.ToInt32( split[2] ), Utility.ToInt32( split[3] ), Utility.ToInt32( split[4] ) ),
Utility.ToInt32( split[1] ), Utility.ToInt32( split[0] ) );
list.Add(e);
}
}
list.Add( e );
}
}
Map[] brit = { Map.Felucca, Map.Trammel };
Map[] fel = { Map.Felucca };
Map[] tram = { Map.Trammel };
Map[] ilsh = { Map.Ilshenar };
Map[] malas = { Map.Malas };
Map[] tokuno = { Map.Tokuno };
Map[] brit = { Map.Felucca, Map.Trammel };
Map[] fel = { Map.Felucca };
Map[] tram = { Map.Trammel };
Map[] ilsh = { Map.Ilshenar };
Map[] malas = { Map.Malas };
Map[] tokuno = { Map.Tokuno };
for (int i = 0; i < list.Count; ++i)
{
SignEntry e = list[i];
Map[] maps = null;
for ( int i = 0; i < list.Count; ++i )
{
SignEntry e = list[i];
Map[] maps = null;
switch (e.m_Map)
{
case 0:
maps = brit;
break; // Trammel and Felucca
case 1:
maps = fel;
break; // Felucca
case 2:
maps = tram;
break; // Trammel
case 3:
maps = ilsh;
break; // Ilshenar
case 4:
maps = malas;
break; // Malas
case 5:
maps = tokuno;
break; // Tokuno Islands
}
switch ( e.m_Map )
{
case 0: maps = brit; break; // Trammel and Felucca
case 1: maps = fel; break; // Felucca
case 2: maps = tram; break; // Trammel
case 3: maps = ilsh; break; // Ilshenar
case 4: maps = malas; break; // Malas
case 5: maps = tokuno; break; // Tokuno Islands
}
for (int j = 0; maps != null && j < maps.Length; ++j)
Add_Static(e.m_ItemID, e.m_Location, maps[j], e.m_Text);
}
for ( int j = 0; maps != null && j < maps.Length; ++j )
Add_Static( e.m_ItemID, e.m_Location, maps[j], e.m_Text );
}
from.SendMessage("Sign generating complete.");
}
else
{
from.SendMessage("{0} not found!", cfg);
}
}
from.SendMessage( "Sign generating complete." );
}
else
{
from.SendMessage( "{0} not found!", cfg );
}
}
public static void Add_Static(int itemID, Point3D location, Map map, string name)
{
IPooledEnumerable<Item> eable = map.GetItemsInRange(location, 0);
private static Queue<Item> m_ToDelete = new Queue<Item>();
foreach (Item item in eable)
if (item is Sign && item.Z == location.Z && item.ItemID == itemID)
m_ToDelete.Enqueue(item);
public static void Add_Static( int itemID, Point3D location, Map map, string name )
{
IPooledEnumerable<Item> eable = map.GetItemsInRange( location, 0 );
eable.Free();
foreach ( Item item in eable )
{
if ( item is Sign && item.Z == location.Z && item.ItemID == itemID )
m_ToDelete.Enqueue( item );
}
while (m_ToDelete.Count > 0)
m_ToDelete.Dequeue().Delete();
eable.Free();
Item sign;
while ( m_ToDelete.Count > 0 )
m_ToDelete.Dequeue().Delete();
if (name.StartsWith("#"))
{
sign = new LocalizedSign(itemID, Utility.ToInt32(name.Substring(1)));
}
else
{
sign = new Sign(itemID);
sign.Name = name;
}
Item sign;
if (map == Map.Malas)
{
if (location.X >= 965 && location.Y >= 502 && location.X <= 1012 && location.Y <= 537)
sign.Hue = 0x47E;
else if (location.X >= 1960 && location.Y >= 1278 && location.X < 2106 && location.Y < 1413)
sign.Hue = 0x44E;
}
if ( name.StartsWith( "#" ) )
{
sign = new LocalizedSign( itemID, Utility.ToInt32( name.Substring( 1 ) ) );
}
else
{
sign = new Sign( itemID );
sign.Name = name;
}
sign.MoveToWorld(location, map);
}
if ( map == Map.Malas )
{
if ( location.X >= 965 && location.Y >= 502 && location.X <= 1012 && location.Y <= 537 )
sign.Hue = 0x47E;
else if ( location.X >= 1960 && location.Y >= 1278 && location.X < 2106 && location.Y < 1413 )
sign.Hue = 0x44E;
}
private class SignEntry
{
public int m_ItemID;
public Point3D m_Location;
public int m_Map;
public string m_Text;
sign.MoveToWorld( location, map );
}
}
}
public SignEntry(string text, Point3D pt, int itemID, int mapLoc)
{
m_Text = text;
m_Location = pt;
m_ItemID = itemID;
m_Map = mapLoc;
}
}
}
}

View file

@ -3,141 +3,129 @@ using Server.Targeting;
namespace Server.Commands
{
public class SkillsCommand
{
public static void Initialize()
{
CommandSystem.Register( "SetSkill", AccessLevel.GameMaster, SetSkill_OnCommand );
CommandSystem.Register( "GetSkill", AccessLevel.GameMaster, GetSkill_OnCommand );
CommandSystem.Register( "SetAllSkills", AccessLevel.GameMaster, SetAllSkills_OnCommand );
}
public class SkillsCommand
{
public static void Initialize()
{
CommandSystem.Register("SetSkill", AccessLevel.GameMaster, SetSkill_OnCommand);
CommandSystem.Register("GetSkill", AccessLevel.GameMaster, GetSkill_OnCommand);
CommandSystem.Register("SetAllSkills", AccessLevel.GameMaster, SetAllSkills_OnCommand);
}
[Usage( "SetSkill <name> <value>" )]
[Description( "Sets a skill value by name of a targeted mobile." )]
public static void SetSkill_OnCommand( CommandEventArgs arg )
{
if ( arg.Length != 2 )
{
arg.Mobile.SendMessage( "SetSkill <skill name> <value>" );
}
else
{
SkillName skill;
if ( Enum.TryParse( arg.GetString( 0 ), true, out skill ) )
{
arg.Mobile.Target = new SkillTarget( skill, arg.GetDouble( 1 ) );
}
else
{
arg.Mobile.SendLocalizedMessage( 1005631 ); // You have specified an invalid skill to set.
}
}
}
[Usage("SetSkill <name> <value>")]
[Description("Sets a skill value by name of a targeted mobile.")]
public static void SetSkill_OnCommand(CommandEventArgs arg)
{
if (arg.Length != 2)
{
arg.Mobile.SendMessage("SetSkill <skill name> <value>");
}
else
{
SkillName skill;
if (Enum.TryParse(arg.GetString(0), true, out skill))
arg.Mobile.Target = new SkillTarget(skill, arg.GetDouble(1));
else
arg.Mobile.SendLocalizedMessage(1005631); // You have specified an invalid skill to set.
}
}
[Usage( "SetAllSkills <name> <value>" )]
[Description( "Sets all skill values of a targeted mobile." )]
public static void SetAllSkills_OnCommand( CommandEventArgs arg )
{
if ( arg.Length != 1 )
{
arg.Mobile.SendMessage( "SetAllSkills <value>" );
}
else
{
arg.Mobile.Target = new AllSkillsTarget( arg.GetDouble( 0 ) );
}
}
[Usage("SetAllSkills <name> <value>")]
[Description("Sets all skill values of a targeted mobile.")]
public static void SetAllSkills_OnCommand(CommandEventArgs arg)
{
if (arg.Length != 1)
arg.Mobile.SendMessage("SetAllSkills <value>");
else
arg.Mobile.Target = new AllSkillsTarget(arg.GetDouble(0));
}
[Usage( "GetSkill <name>" )]
[Description( "Gets a skill value by name of a targeted mobile." )]
public static void GetSkill_OnCommand( CommandEventArgs arg )
{
if ( arg.Length != 1 )
{
arg.Mobile.SendMessage( "GetSkill <skill name>" );
}
else
{
SkillName skill;
if ( Enum.TryParse( arg.GetString( 0 ), true, out skill ) )
{
arg.Mobile.Target = new SkillTarget( skill );
}
else
{
arg.Mobile.SendMessage( "You have specified an invalid skill to get." );
}
}
}
[Usage("GetSkill <name>")]
[Description("Gets a skill value by name of a targeted mobile.")]
public static void GetSkill_OnCommand(CommandEventArgs arg)
{
if (arg.Length != 1)
{
arg.Mobile.SendMessage("GetSkill <skill name>");
}
else
{
SkillName skill;
if (Enum.TryParse(arg.GetString(0), true, out skill))
arg.Mobile.Target = new SkillTarget(skill);
else
arg.Mobile.SendMessage("You have specified an invalid skill to get.");
}
}
public class AllSkillsTarget : Target
{
private double m_Value;
public class AllSkillsTarget : Target
{
private double m_Value;
public AllSkillsTarget( double value ) : base( -1, false, TargetFlags.None )
{
m_Value = value;
}
public AllSkillsTarget(double value) : base(-1, false, TargetFlags.None)
{
m_Value = value;
}
protected override void OnTarget( Mobile from, object targeted )
{
if ( targeted is Mobile targ )
{
Server.Skills skills = targ.Skills;
protected override void OnTarget(Mobile from, object targeted)
{
if (targeted is Mobile targ)
{
Server.Skills skills = targ.Skills;
for ( int i = 0; i < skills.Length; ++i )
skills[i].Base = m_Value;
for (int i = 0; i < skills.Length; ++i)
skills[i].Base = m_Value;
CommandLogging.LogChangeProperty( from, targ, "EverySkill.Base", m_Value.ToString() );
}
else
{
from.SendMessage( "That does not have skills!" );
}
}
}
CommandLogging.LogChangeProperty(from, targ, "EverySkill.Base", m_Value.ToString());
}
else
{
from.SendMessage("That does not have skills!");
}
}
}
public class SkillTarget : Target
{
private bool m_Set;
private SkillName m_Skill;
private double m_Value;
public class SkillTarget : Target
{
private bool m_Set;
private SkillName m_Skill;
private double m_Value;
public SkillTarget( SkillName skill, double value ) : base( -1, false, TargetFlags.None )
{
m_Set = true;
m_Skill = skill;
m_Value = value;
}
public SkillTarget(SkillName skill, double value) : base(-1, false, TargetFlags.None)
{
m_Set = true;
m_Skill = skill;
m_Value = value;
}
public SkillTarget( SkillName skill ) : base( -1, false, TargetFlags.None )
{
m_Set = false;
m_Skill = skill;
}
public SkillTarget(SkillName skill) : base(-1, false, TargetFlags.None)
{
m_Set = false;
m_Skill = skill;
}
protected override void OnTarget( Mobile from, object targeted )
{
if ( targeted is Mobile targ )
{
Skill skill = targ.Skills[m_Skill];
protected override void OnTarget(Mobile from, object targeted)
{
if (targeted is Mobile targ)
{
Skill skill = targ.Skills[m_Skill];
if ( skill == null )
return;
if (skill == null)
return;
if ( m_Set )
{
skill.Base = m_Value;
CommandLogging.LogChangeProperty( from, targ, $"{m_Skill}.Base", m_Value.ToString() );
}
if (m_Set)
{
skill.Base = m_Value;
CommandLogging.LogChangeProperty(from, targ, $"{m_Skill}.Base", m_Value.ToString());
}
from.SendMessage( "{0} : {1} (Base: {2})", m_Skill, skill.Value, skill.Base );
}
else
{
from.SendMessage( "That does not have skills!" );
}
}
}
}
}
from.SendMessage("{0} : {1} (Base: {2})", m_Skill, skill.Value, skill.Base);
}
else
{
from.SendMessage("That does not have skills!");
}
}
}
}
}

View file

@ -1,38 +1,38 @@
using Server.Targeting;
using Server.Gumps;
using Server.Targeting;
namespace Server.Commands
{
public class Skills
{
public static void Initialize()
{
Register();
}
public class Skills
{
public static void Initialize()
{
Register();
}
public static void Register()
{
CommandSystem.Register( "Skills", AccessLevel.Counselor, Skills_OnCommand );
}
public static void Register()
{
CommandSystem.Register("Skills", AccessLevel.Counselor, Skills_OnCommand);
}
private class SkillsTarget : Target
{
public SkillsTarget( ) : base( -1, true, TargetFlags.None )
{
}
[Usage("Skills")]
[Description("Opens a menu where you can view or edit skills of a targeted mobile.")]
private static void Skills_OnCommand(CommandEventArgs e)
{
e.Mobile.Target = new SkillsTarget();
}
protected override void OnTarget( Mobile from, object o )
{
if ( o is Mobile mobile )
from.SendGump( new SkillsGump( from, mobile ) );
}
}
private class SkillsTarget : Target
{
public SkillsTarget() : base(-1, true, TargetFlags.None)
{
}
[Usage( "Skills" )]
[Description( "Opens a menu where you can view or edit skills of a targeted mobile." )]
private static void Skills_OnCommand( CommandEventArgs e )
{
e.Mobile.Target = new SkillsTarget();
}
}
}
protected override void OnTarget(Mobile from, object o)
{
if (o is Mobile mobile)
from.SendGump(new SkillsGump(from, mobile));
}
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,142 +1,141 @@
using Server.Mobiles;
using Server.Targeting;
using Server.Network;
using System.Collections.Generic;
using Server.Mobiles;
using Server.Network;
using Server.Targeting;
namespace Server.Commands
{
public class VisibilityList
{
public static void Initialize()
{
EventSink.Login += OnLogin;
public class VisibilityList
{
public static void Initialize()
{
EventSink.Login += OnLogin;
CommandSystem.Register( "Vis", AccessLevel.Counselor, Vis_OnCommand );
CommandSystem.Register( "VisList", AccessLevel.Counselor, VisList_OnCommand );
CommandSystem.Register( "VisClear", AccessLevel.Counselor, VisClear_OnCommand );
}
CommandSystem.Register("Vis", AccessLevel.Counselor, Vis_OnCommand);
CommandSystem.Register("VisList", AccessLevel.Counselor, VisList_OnCommand);
CommandSystem.Register("VisClear", AccessLevel.Counselor, VisClear_OnCommand);
}
public static void OnLogin( LoginEventArgs e )
{
if ( e.Mobile is PlayerMobile pm )
{
pm.VisibilityList.Clear();
}
}
public static void OnLogin(LoginEventArgs e)
{
if (e.Mobile is PlayerMobile pm) pm.VisibilityList.Clear();
}
[Usage( "Vis" )]
[Description( "Adds or removes a targeted player from your visibility list. Anyone on your visibility list will be able to see you at all times, even when you're hidden." )]
public static void Vis_OnCommand( CommandEventArgs e )
{
if ( e.Mobile is PlayerMobile )
{
e.Mobile.Target = new VisTarget();
e.Mobile.SendMessage( "Select person to add or remove from your visibility list." );
}
}
[Usage("Vis")]
[Description(
"Adds or removes a targeted player from your visibility list. Anyone on your visibility list will be able to see you at all times, even when you're hidden.")]
public static void Vis_OnCommand(CommandEventArgs e)
{
if (e.Mobile is PlayerMobile)
{
e.Mobile.Target = new VisTarget();
e.Mobile.SendMessage("Select person to add or remove from your visibility list.");
}
}
[Usage( "VisList" )]
[Description( "Shows the names of everyone in your visibility list." )]
public static void VisList_OnCommand( CommandEventArgs e )
{
if ( e.Mobile is PlayerMobile pm )
{
List<Mobile> list = pm.VisibilityList;
[Usage("VisList")]
[Description("Shows the names of everyone in your visibility list.")]
public static void VisList_OnCommand(CommandEventArgs e)
{
if (e.Mobile is PlayerMobile pm)
{
List<Mobile> list = pm.VisibilityList;
if ( list.Count > 0 )
{
pm.SendMessage( "You are visible to {0} mobile{1}:", list.Count, list.Count == 1 ? "" : "s" );
if (list.Count > 0)
{
pm.SendMessage("You are visible to {0} mobile{1}:", list.Count, list.Count == 1 ? "" : "s");
for ( int i = 0; i < list.Count; ++i )
pm.SendMessage( "#{0}: {1}", i+1, list[i].Name );
}
else
{
pm.SendMessage( "Your visibility list is empty." );
}
}
}
for (int i = 0; i < list.Count; ++i)
pm.SendMessage("#{0}: {1}", i + 1, list[i].Name);
}
else
{
pm.SendMessage("Your visibility list is empty.");
}
}
}
[Usage( "VisClear" )]
[Description( "Removes everyone from your visibility list." )]
public static void VisClear_OnCommand( CommandEventArgs e )
{
if ( e.Mobile is PlayerMobile pm )
{
List<Mobile> list = new List<Mobile>( pm.VisibilityList );
[Usage("VisClear")]
[Description("Removes everyone from your visibility list.")]
public static void VisClear_OnCommand(CommandEventArgs e)
{
if (e.Mobile is PlayerMobile pm)
{
List<Mobile> list = new List<Mobile>(pm.VisibilityList);
pm.VisibilityList.Clear();
pm.SendMessage( "Your visibility list has been cleared." );
pm.VisibilityList.Clear();
pm.SendMessage("Your visibility list has been cleared.");
for ( int i = 0; i < list.Count; ++i )
{
Mobile m = list[i];
for (int i = 0; i < list.Count; ++i)
{
Mobile m = list[i];
if ( !m.CanSee( pm ) && Utility.InUpdateRange( m, pm ) )
m.Send( pm.RemovePacket );
}
}
}
if (!m.CanSee(pm) && Utility.InUpdateRange(m, pm))
m.Send(pm.RemovePacket);
}
}
}
private class VisTarget : Target
{
public VisTarget() : base( -1, false, TargetFlags.None )
{
}
private class VisTarget : Target
{
public VisTarget() : base(-1, false, TargetFlags.None)
{
}
protected override void OnTarget( Mobile from, object targeted )
{
if ( from is PlayerMobile pm && targeted is Mobile targ )
{
if ( targ.AccessLevel <= pm.AccessLevel )
{
List<Mobile> list = pm.VisibilityList;
protected override void OnTarget(Mobile from, object targeted)
{
if (from is PlayerMobile pm && targeted is Mobile targ)
{
if (targ.AccessLevel <= pm.AccessLevel)
{
List<Mobile> list = pm.VisibilityList;
if ( list.Contains( targ ) )
{
list.Remove( targ );
pm.SendMessage( "{0} has been removed from your visibility list.", targ.Name );
}
else
{
list.Add( targ );
pm.SendMessage( "{0} has been added to your visibility list.", targ.Name );
}
if (list.Contains(targ))
{
list.Remove(targ);
pm.SendMessage("{0} has been removed from your visibility list.", targ.Name);
}
else
{
list.Add(targ);
pm.SendMessage("{0} has been added to your visibility list.", targ.Name);
}
if ( Utility.InUpdateRange( targ, from ) )
{
NetState ns = targ.NetState;
if (Utility.InUpdateRange(targ, from))
{
NetState ns = targ.NetState;
if ( ns != null ) {
if ( targ.CanSee( pm ) )
{
ns.Send(MobileIncoming.Create(ns, targ, pm));
if (ns != null)
{
if (targ.CanSee(pm))
{
ns.Send(MobileIncoming.Create(ns, targ, pm));
if ( ObjectPropertyList.Enabled )
{
ns.Send( pm.OPLPacket );
if (ObjectPropertyList.Enabled)
{
ns.Send(pm.OPLPacket);
foreach ( Item item in pm.Items )
ns.Send( item.OPLPacket );
}
}
else
{
ns.Send( pm.RemovePacket );
}
}
}
}
else
{
pm.SendMessage( "They can already see you!" );
}
}
else
{
from.SendMessage( "Add only mobiles to your visibility list." );
}
}
}
}
}
foreach (Item item in pm.Items)
ns.Send(item.OPLPacket);
}
}
else
{
ns.Send(pm.RemovePacket);
}
}
}
}
else
{
pm.SendMessage("They can already see you!");
}
}
else
{
from.SendMessage("Add only mobiles to your visibility list.");
}
}
}
}
}

View file

@ -5,96 +5,95 @@ using Server.Multis;
namespace Server.Commands
{
public class Wipe
{
[Flags]
public enum WipeType
{
Items = 0x01,
Mobiles = 0x02,
Multis = 0x04,
All = Items | Mobiles | Multis
}
public class Wipe
{
[Flags]
public enum WipeType
{
Items = 0x01,
Mobiles = 0x02,
Multis = 0x04,
All = Items | Mobiles | Multis
}
public static void Initialize()
{
CommandSystem.Register( "Wipe", AccessLevel.GameMaster, WipeAll_OnCommand );
CommandSystem.Register( "WipeItems", AccessLevel.GameMaster, WipeItems_OnCommand );
CommandSystem.Register( "WipeNPCs", AccessLevel.GameMaster, WipeNPCs_OnCommand );
CommandSystem.Register( "WipeMultis", AccessLevel.GameMaster, WipeMultis_OnCommand );
}
public static void Initialize()
{
CommandSystem.Register("Wipe", AccessLevel.GameMaster, WipeAll_OnCommand);
CommandSystem.Register("WipeItems", AccessLevel.GameMaster, WipeItems_OnCommand);
CommandSystem.Register("WipeNPCs", AccessLevel.GameMaster, WipeNPCs_OnCommand);
CommandSystem.Register("WipeMultis", AccessLevel.GameMaster, WipeMultis_OnCommand);
}
[Usage( "Wipe" )]
[Description( "Wipes all items and npcs in a targeted bounding box." )]
private static void WipeAll_OnCommand( CommandEventArgs e )
{
BeginWipe( e.Mobile, WipeType.Items | WipeType.Mobiles );
}
[Usage("Wipe")]
[Description("Wipes all items and npcs in a targeted bounding box.")]
private static void WipeAll_OnCommand(CommandEventArgs e)
{
BeginWipe(e.Mobile, WipeType.Items | WipeType.Mobiles);
}
[Usage( "WipeItems" )]
[Description( "Wipes all items in a targeted bounding box." )]
private static void WipeItems_OnCommand( CommandEventArgs e )
{
BeginWipe( e.Mobile, WipeType.Items );
}
[Usage("WipeItems")]
[Description("Wipes all items in a targeted bounding box.")]
private static void WipeItems_OnCommand(CommandEventArgs e)
{
BeginWipe(e.Mobile, WipeType.Items);
}
[Usage( "WipeNPCs" )]
[Description( "Wipes all npcs in a targeted bounding box." )]
private static void WipeNPCs_OnCommand( CommandEventArgs e )
{
BeginWipe( e.Mobile, WipeType.Mobiles );
}
[Usage("WipeNPCs")]
[Description("Wipes all npcs in a targeted bounding box.")]
private static void WipeNPCs_OnCommand(CommandEventArgs e)
{
BeginWipe(e.Mobile, WipeType.Mobiles);
}
[Usage( "WipeMultis" )]
[Description( "Wipes all multis in a targeted bounding box." )]
private static void WipeMultis_OnCommand( CommandEventArgs e )
{
BeginWipe( e.Mobile, WipeType.Multis );
}
[Usage("WipeMultis")]
[Description("Wipes all multis in a targeted bounding box.")]
private static void WipeMultis_OnCommand(CommandEventArgs e)
{
BeginWipe(e.Mobile, WipeType.Multis);
}
public static void BeginWipe( Mobile from, WipeType type )
{
BoundingBoxPicker.Begin( from, WipeBox_Callback, type );
}
public static void BeginWipe(Mobile from, WipeType type)
{
BoundingBoxPicker.Begin(from, WipeBox_Callback, type);
}
private static void WipeBox_Callback( Mobile from, Map map, Point3D start, Point3D end, object state )
{
DoWipe( from, map, start, end, (WipeType)state );
}
private static void WipeBox_Callback(Mobile from, Map map, Point3D start, Point3D end, object state)
{
DoWipe(from, map, start, end, (WipeType)state);
}
public static void DoWipe( Mobile from, Map map, Point3D start, Point3D end, WipeType type )
{
CommandLogging.WriteLine( from, "{0} {1} wiping from {2} to {3} in {5} ({4})", from.AccessLevel, CommandLogging.Format( from ), start, end, type, map );
public static void DoWipe(Mobile from, Map map, Point3D start, Point3D end, WipeType type)
{
CommandLogging.WriteLine(from, "{0} {1} wiping from {2} to {3} in {5} ({4})", from.AccessLevel,
CommandLogging.Format(from), start, end, type, map);
bool mobiles = ( (type & WipeType.Mobiles) != 0 );
bool multis = ( (type & WipeType.Multis) != 0 );
bool items = ( (type & WipeType.Items) != 0 );
bool mobiles = (type & WipeType.Mobiles) != 0;
bool multis = (type & WipeType.Multis) != 0;
bool items = (type & WipeType.Items) != 0;
List<IEntity> toDelete = new List<IEntity>();
List<IEntity> toDelete = new List<IEntity>();
Rectangle2D rect = new Rectangle2D( start.X, start.Y, end.X - start.X + 1, end.Y - start.Y + 1 );
Rectangle2D rect = new Rectangle2D(start.X, start.Y, end.X - start.X + 1, end.Y - start.Y + 1);
IPooledEnumerable<IEntity> eable;
IPooledEnumerable<IEntity> eable;
if ( (items || multis) && mobiles )
eable = map.GetObjectsInBounds( rect, items || multis, mobiles );
else
return;
if ((items || multis) && mobiles)
eable = map.GetObjectsInBounds(rect, items || multis, mobiles);
else
return;
foreach ( IEntity obj in eable )
{
if ( items && (obj is Item) && !((obj is BaseMulti) || (obj is HouseSign)) )
toDelete.Add( obj );
else if ( multis && (obj is BaseMulti) )
toDelete.Add( obj );
else if ( mobiles && (obj is Mobile mobile) && !mobile.Player )
toDelete.Add( mobile );
}
foreach (IEntity obj in eable)
if (items && obj is Item && !(obj is BaseMulti || obj is HouseSign))
toDelete.Add(obj);
else if (multis && obj is BaseMulti)
toDelete.Add(obj);
else if (mobiles && obj is Mobile mobile && !mobile.Player)
toDelete.Add(mobile);
eable.Free();
eable.Free();
for ( int i = 0; i < toDelete.Count; ++i )
toDelete[i].Delete();
}
}
}
for (int i = 0; i < toDelete.Count; ++i)
toDelete[i].Delete();
}
}
}

View file

@ -2,36 +2,36 @@ using Server.Engines.PartySystem;
namespace Server.ContextMenus
{
public class AddToPartyEntry : ContextMenuEntry
{
private Mobile m_From;
private Mobile m_Target;
public AddToPartyEntry( Mobile from, Mobile target ) : base( 0197, 12 )
{
m_From = from;
m_Target = target;
}
public class AddToPartyEntry : ContextMenuEntry
{
private Mobile m_From;
private Mobile m_Target;
public override void OnClick()
{
Party p = Party.Get( m_From );
Party mp = Party.Get( m_Target );
public AddToPartyEntry(Mobile from, Mobile target) : base(0197, 12)
{
m_From = from;
m_Target = target;
}
if ( m_From == m_Target )
m_From.SendLocalizedMessage( 1005439 ); // You cannot add yourself to a party.
else if ( p != null && p.Leader != m_From )
m_From.SendLocalizedMessage( 1005453 ); // You may only add members to the party if you are the leader.
else if ( p != null && (p.Members.Count + p.Candidates.Count) >= Party.Capacity )
m_From.SendLocalizedMessage( 1008095 ); // You may only have 10 in your party (this includes candidates).
else if ( !m_Target.Player )
m_From.SendLocalizedMessage( 1005444 ); // The creature ignores your offer.
else if ( mp != null && mp == p )
m_From.SendLocalizedMessage( 1005440 ); // This person is already in your party!
else if ( mp != null )
m_From.SendLocalizedMessage( 1005441 ); // This person is already in a party!
else
Party.Invite( m_From, m_Target );
}
}
}
public override void OnClick()
{
Party p = Party.Get(m_From);
Party mp = Party.Get(m_Target);
if (m_From == m_Target)
m_From.SendLocalizedMessage(1005439); // You cannot add yourself to a party.
else if (p != null && p.Leader != m_From)
m_From.SendLocalizedMessage(1005453); // You may only add members to the party if you are the leader.
else if (p != null && p.Members.Count + p.Candidates.Count >= Party.Capacity)
m_From.SendLocalizedMessage(1008095); // You may only have 10 in your party (this includes candidates).
else if (!m_Target.Player)
m_From.SendLocalizedMessage(1005444); // The creature ignores your offer.
else if (mp != null && mp == p)
m_From.SendLocalizedMessage(1005440); // This person is already in your party!
else if (mp != null)
m_From.SendLocalizedMessage(1005441); // This person is already in a party!
else
Party.Invite(m_From, m_Target);
}
}
}

View file

@ -1,60 +1,60 @@
using Server.Items;
using Server.Network;
using Server.Targeting;
namespace Server.ContextMenus
{
public class AddToSpellbookEntry : ContextMenuEntry
{
public AddToSpellbookEntry() : base( 6144, 3 )
{
}
public class AddToSpellbookEntry : ContextMenuEntry
{
public AddToSpellbookEntry() : base(6144, 3)
{
}
public override void OnClick()
{
if ( Owner.From.CheckAlive() && Owner.Target is SpellScroll scroll )
Owner.From.Target = new InternalTarget( scroll );
}
public override void OnClick()
{
if (Owner.From.CheckAlive() && Owner.Target is SpellScroll scroll)
Owner.From.Target = new InternalTarget(scroll);
}
private class InternalTarget : Target
{
private SpellScroll m_Scroll;
private class InternalTarget : Target
{
private SpellScroll m_Scroll;
public InternalTarget( SpellScroll scroll ) : base( 3, false, TargetFlags.None )
{
m_Scroll = scroll;
}
public InternalTarget(SpellScroll scroll) : base(3, false, TargetFlags.None)
{
m_Scroll = scroll;
}
protected override void OnTarget( Mobile from, object targeted )
{
if ( targeted is Spellbook book )
{
if ( from.CheckAlive() && !m_Scroll.Deleted && m_Scroll.Movable && m_Scroll.Amount >= 1 && m_Scroll.CheckItemUse( from ) )
{
SpellbookType type = Spellbook.GetTypeForSpell( m_Scroll.SpellID );
protected override void OnTarget(Mobile from, object targeted)
{
if (targeted is Spellbook book)
if (from.CheckAlive() && !m_Scroll.Deleted && m_Scroll.Movable && m_Scroll.Amount >= 1 &&
m_Scroll.CheckItemUse(from))
{
SpellbookType type = Spellbook.GetTypeForSpell(m_Scroll.SpellID);
if ( type != book.SpellbookType )
{
}
else if ( book.HasSpell( m_Scroll.SpellID ) )
{
from.SendLocalizedMessage( 500179 ); // That spell is already present in that spellbook.
}
else
{
int val = m_Scroll.SpellID - book.BookOffset;
if (type != book.SpellbookType)
{
}
else if (book.HasSpell(m_Scroll.SpellID))
{
from.SendLocalizedMessage(500179); // That spell is already present in that spellbook.
}
else
{
int val = m_Scroll.SpellID - book.BookOffset;
if ( val >= 0 && val < book.BookCount )
{
book.Content |= (ulong)1 << val;
if (val >= 0 && val < book.BookCount)
{
book.Content |= (ulong)1 << val;
m_Scroll.Consume();
m_Scroll.Consume();
from.Send( new Network.PlaySound( 0x249, book.GetWorldLocation() ) );
}
}
}
}
}
}
}
}
from.Send(new PlaySound(0x249, book.GetWorldLocation()));
}
}
}
}
}
}
}

View file

@ -2,23 +2,23 @@ using Server.Items;
namespace Server.ContextMenus
{
public class EatEntry : ContextMenuEntry
{
private Mobile m_From;
private Food m_Food;
public class EatEntry : ContextMenuEntry
{
private Food m_Food;
private Mobile m_From;
public EatEntry( Mobile from, Food food ) : base( 6135, 1 )
{
m_From = from;
m_Food = food;
}
public EatEntry(Mobile from, Food food) : base(6135, 1)
{
m_From = from;
m_Food = food;
}
public override void OnClick()
{
if ( m_Food.Deleted || !m_Food.Movable || !m_From.CheckAlive() || !m_Food.CheckItemUse( m_From ) )
return;
public override void OnClick()
{
if (m_Food.Deleted || !m_Food.Movable || !m_From.CheckAlive() || !m_Food.CheckItemUse(m_From))
return;
m_Food.Eat( m_From );
}
}
m_Food.Eat(m_From);
}
}
}

View file

@ -2,26 +2,26 @@ using Server.Multis;
namespace Server.ContextMenus
{
public class EjectPlayerEntry : ContextMenuEntry
{
private Mobile m_From;
private Mobile m_Target;
private BaseHouse m_TargetHouse;
public class EjectPlayerEntry : ContextMenuEntry
{
private Mobile m_From;
private Mobile m_Target;
private BaseHouse m_TargetHouse;
public EjectPlayerEntry( Mobile from, Mobile target ) : base( 6206, 12 )
{
m_From = from;
m_Target = target;
m_TargetHouse = BaseHouse.FindHouseAt( m_Target );
}
public EjectPlayerEntry(Mobile from, Mobile target) : base(6206, 12)
{
m_From = from;
m_Target = target;
m_TargetHouse = BaseHouse.FindHouseAt(m_Target);
}
public override void OnClick()
{
if ( !m_From.Alive || m_TargetHouse.Deleted || !m_TargetHouse.IsFriend( m_From ) )
return;
public override void OnClick()
{
if (!m_From.Alive || m_TargetHouse.Deleted || !m_TargetHouse.IsFriend(m_From))
return;
if ( m_Target is Mobile mobile )
m_TargetHouse.Kick( m_From, mobile );
}
}
}
if (m_Target is Mobile mobile)
m_TargetHouse.Kick(m_From, mobile);
}
}
}

View file

@ -1,27 +1,23 @@
namespace Server.ContextMenus
{
public class OpenBankEntry : ContextMenuEntry
{
private Mobile m_Banker;
public class OpenBankEntry : ContextMenuEntry
{
private Mobile m_Banker;
public OpenBankEntry( Mobile from, Mobile banker ) : base( 6105, 12 )
{
m_Banker = banker;
}
public OpenBankEntry(Mobile from, Mobile banker) : base(6105, 12)
{
m_Banker = banker;
}
public override void OnClick()
{
if ( !Owner.From.CheckAlive() )
return;
public override void OnClick()
{
if (!Owner.From.CheckAlive())
return;
if ( Owner.From.Criminal )
{
m_Banker.Say( 500378 ); // Thou art a criminal and cannot access thy bank box.
}
else
{
Owner.From.BankBox.Open();
}
}
}
if (Owner.From.Criminal)
m_Banker.Say(500378); // Thou art a criminal and cannot access thy bank box.
else
Owner.From.BankBox.Open();
}
}
}

View file

@ -1,29 +1,30 @@
using Server.Mobiles;
using Server.Network;
namespace Server.ContextMenus
{
public class TeachEntry : ContextMenuEntry
{
private SkillName m_Skill;
private BaseCreature m_Mobile;
private Mobile m_From;
public class TeachEntry : ContextMenuEntry
{
private Mobile m_From;
private BaseCreature m_Mobile;
private SkillName m_Skill;
public TeachEntry( SkillName skill, BaseCreature m, Mobile from, bool enabled ) : base( 6000 + (int)skill )
{
m_Skill = skill;
m_Mobile = m;
m_From = from;
public TeachEntry(SkillName skill, BaseCreature m, Mobile from, bool enabled) : base(6000 + (int)skill)
{
m_Skill = skill;
m_Mobile = m;
m_From = from;
if ( !enabled )
Flags |= Network.CMEFlags.Disabled;
}
if (!enabled)
Flags |= CMEFlags.Disabled;
}
public override void OnClick()
{
if ( !m_From.CheckAlive() )
return;
public override void OnClick()
{
if (!m_From.CheckAlive())
return;
m_Mobile.Teach( m_Skill, m_From, 0, false );
}
}
m_Mobile.Teach(m_Skill, m_From, 0, false);
}
}
}

View file

@ -1,62 +1,62 @@
namespace Server.Engines.BulkOrders
{
public class BOBFilter
{
public bool IsDefault => ( Type == 0 && Quality == 0 && Material == 0 && Quantity == 0 );
public class BOBFilter
{
public BOBFilter()
{
}
public void Clear()
{
Type = 0;
Quality = 0;
Material = 0;
Quantity = 0;
}
public BOBFilter(GenericReader reader)
{
int version = reader.ReadEncodedInt();
public int Type { get; set; }
switch (version)
{
case 1:
{
Type = reader.ReadEncodedInt();
Quality = reader.ReadEncodedInt();
Material = reader.ReadEncodedInt();
Quantity = reader.ReadEncodedInt();
public int Quality { get; set; }
break;
}
}
}
public int Material { get; set; }
public bool IsDefault => Type == 0 && Quality == 0 && Material == 0 && Quantity == 0;
public int Quantity { get; set; }
public int Type{ get; set; }
public BOBFilter()
{
}
public int Quality{ get; set; }
public BOBFilter( GenericReader reader )
{
int version = reader.ReadEncodedInt();
public int Material{ get; set; }
switch ( version )
{
case 1:
{
Type = reader.ReadEncodedInt();
Quality = reader.ReadEncodedInt();
Material = reader.ReadEncodedInt();
Quantity = reader.ReadEncodedInt();
public int Quantity{ get; set; }
break;
}
}
}
public void Clear()
{
Type = 0;
Quality = 0;
Material = 0;
Quantity = 0;
}
public void Serialize( GenericWriter writer )
{
if ( IsDefault )
{
writer.WriteEncodedInt( 0 ); // version
}
else
{
writer.WriteEncodedInt( 1 ); // version
public void Serialize(GenericWriter writer)
{
if (IsDefault)
{
writer.WriteEncodedInt(0); // version
}
else
{
writer.WriteEncodedInt(1); // version
writer.WriteEncodedInt( Type );
writer.WriteEncodedInt( Quality );
writer.WriteEncodedInt( Material );
writer.WriteEncodedInt( Quantity );
}
}
}
writer.WriteEncodedInt(Type);
writer.WriteEncodedInt(Quality);
writer.WriteEncodedInt(Material);
writer.WriteEncodedInt(Quantity);
}
}
}
}

View file

@ -1,206 +1,224 @@
using Server.Gumps;
using Server.Mobiles;
using Server.Network;
namespace Server.Engines.BulkOrders
{
public class BOBFilterGump : Gump
{
private PlayerMobile m_From;
private BulkOrderBook m_Book;
public class BOBFilterGump : Gump
{
private const int LabelColor = 0x7FFF;
private const int LabelColor = 0x7FFF;
private static int[,] m_MaterialFilters =
{
{ 1044067, 1 }, // Blacksmithy
{ 1062226, 3 }, // Iron
{ 1018332, 4 }, // Dull Copper
{ 1018333, 5 }, // Shadow Iron
{ 1018334, 6 }, // Copper
{ 1018335, 7 }, // Bronze
private static int[,] m_MaterialFilters = {
{ 1044067, 1 }, // Blacksmithy
{ 1062226, 3 }, // Iron
{ 1018332, 4 }, // Dull Copper
{ 1018333, 5 }, // Shadow Iron
{ 1018334, 6 }, // Copper
{ 1018335, 7 }, // Bronze
{ 0, 0 }, // --Blank--
{ 1018336, 8 }, // Golden
{ 1018337, 9 }, // Agapite
{ 1018338, 10 }, // Verite
{ 1018339, 11 }, // Valorite
{ 0, 0 }, // --Blank--
{ 0, 0 }, // --Blank--
{ 1018336, 8 }, // Golden
{ 1018337, 9 }, // Agapite
{ 1018338, 10 }, // Verite
{ 1018339, 11 }, // Valorite
{ 0, 0 }, // --Blank--
{ 1044094, 2 }, // Tailoring
{ 1044286, 12 }, // Cloth
{ 1062235, 13 }, // Leather
{ 1062236, 14 }, // Spined
{ 1062237, 15 }, // Horned
{ 1062238, 16 } // Barbed
};
{ 1044094, 2 }, // Tailoring
{ 1044286, 12 }, // Cloth
{ 1062235, 13 }, // Leather
{ 1062236, 14 }, // Spined
{ 1062237, 15 }, // Horned
{ 1062238, 16 } // Barbed
};
private static int[,] m_TypeFilters =
{
{ 1062229, 0 }, // All
{ 1062224, 1 }, // Small
{ 1062225, 2 } // Large
};
private static int[,] m_TypeFilters = {
{ 1062229, 0 }, // All
{ 1062224, 1 }, // Small
{ 1062225, 2 } // Large
};
private static int[,] m_QualityFilters =
{
{ 1062229, 0 }, // All
{ 1011542, 1 }, // Normal
{ 1060636, 2 } // Exceptional
};
private static int[,] m_QualityFilters = {
{ 1062229, 0 }, // All
{ 1011542, 1 }, // Normal
{ 1060636, 2 } // Exceptional
};
private static int[,] m_AmountFilters =
{
{ 1062229, 0 }, // All
{ 1049706, 1 }, // 10
{ 1016007, 2 }, // 15
{ 1062239, 3 } // 20
};
private static int[,] m_AmountFilters = {
{ 1062229, 0 }, // All
{ 1049706, 1 }, // 10
{ 1016007, 2 }, // 15
{ 1062239, 3 } // 20
};
private static int[][,] m_Filters =
{
m_TypeFilters,
m_QualityFilters,
m_MaterialFilters,
m_AmountFilters
};
private static int[][,] m_Filters = {
m_TypeFilters,
m_QualityFilters,
m_MaterialFilters,
m_AmountFilters
};
private static int[] m_XOffsets_Type = { 0, 75, 170 };
private static int[] m_XOffsets_Quality = { 0, 75, 170 };
private static int[] m_XOffsets_Amount = { 0, 75, 180, 275 };
private static int[] m_XOffsets_Material = { 0, 105, 210, 305, 390, 485 };
private static int[] m_XOffsets_Type = { 0, 75, 170 };
private static int[] m_XOffsets_Quality = { 0, 75, 170 };
private static int[] m_XOffsets_Amount = { 0, 75, 180, 275 };
private static int[] m_XOffsets_Material = { 0, 105, 210, 305, 390, 485 };
private static int[] m_XWidths_Small = { 50, 50, 70, 50 };
private static int[] m_XWidths_Large = { 80, 50, 50, 50, 50, 50 };
private BulkOrderBook m_Book;
private PlayerMobile m_From;
private static int[] m_XWidths_Small = { 50, 50, 70, 50 };
private static int[] m_XWidths_Large = { 80, 50, 50, 50, 50, 50 };
public BOBFilterGump(PlayerMobile from, BulkOrderBook book) : base(12, 24)
{
from.CloseGump(typeof(BOBGump));
from.CloseGump(typeof(BOBFilterGump));
private void AddFilterList( int x, int y, int[] xOffsets, int yOffset, int[,] filters, int[] xWidths, int filterValue, int filterIndex )
{
for ( int i = 0; i < filters.GetLength( 0 ); ++i )
{
int number = filters[i, 0];
m_From = from;
m_Book = book;
if ( number == 0 )
continue;
BOBFilter f = from.UseOwnFilter ? from.BOBFilter : book.Filter;
bool isSelected = ( filters[i, 1] == filterValue );
AddPage(0);
if ( !isSelected && (i % xOffsets.Length) == 0 )
isSelected = ( filterValue == 0 );
AddBackground(10, 10, 600, 439, 5054);
AddHtmlLocalized( x + 35 + xOffsets[i % xOffsets.Length], y + ((i / xOffsets.Length) * yOffset), xWidths[i % xOffsets.Length], 32, number, isSelected ? 16927 : LabelColor, false, false );
AddButton( x + xOffsets[i % xOffsets.Length], y + ((i / xOffsets.Length) * yOffset), 4005, 4007, 4 + filterIndex + (i * 4), GumpButtonType.Reply, 0 );
}
}
AddImageTiled(18, 20, 583, 420, 2624);
AddAlphaRegion(18, 20, 583, 420);
public override void OnResponse( Network.NetState sender, RelayInfo info )
{
BOBFilter f = ( m_From.UseOwnFilter ? m_From.BOBFilter : m_Book.Filter );
AddImage(5, 5, 10460);
AddImage(585, 5, 10460);
AddImage(5, 424, 10460);
AddImage(585, 424, 10460);
int index = info.ButtonID;
AddHtmlLocalized(270, 32, 200, 32, 1062223, LabelColor, false, false); // Filter Preference
switch ( index )
{
case 0: // Apply
{
m_From.SendGump( new BOBGump( m_From, m_Book ) );
AddHtmlLocalized(26, 64, 120, 32, 1062228, LabelColor, false, false); // Bulk Order Type
AddFilterList(25, 96, m_XOffsets_Type, 40, m_TypeFilters, m_XWidths_Small, f.Type, 0);
break;
}
case 1: // Set Book Filter
{
m_From.UseOwnFilter = false;
m_From.SendGump( new BOBFilterGump( m_From, m_Book ) );
AddHtmlLocalized(320, 64, 50, 32, 1062215, LabelColor, false, false); // Quality
AddFilterList(320, 96, m_XOffsets_Quality, 40, m_QualityFilters, m_XWidths_Small, f.Quality, 1);
break;
}
case 2: // Set Your Filter
{
m_From.UseOwnFilter = true;
m_From.SendGump( new BOBFilterGump( m_From, m_Book ) );
AddHtmlLocalized(26, 160, 120, 32, 1062232, LabelColor, false, false); // Material Type
AddFilterList(25, 192, m_XOffsets_Material, 40, m_MaterialFilters, m_XWidths_Large, f.Material, 2);
break;
}
case 3: // Clear Filter
{
f.Clear();
m_From.SendGump( new BOBFilterGump( m_From, m_Book ) );
AddHtmlLocalized(26, 320, 120, 32, 1062217, LabelColor, false, false); // Amount
AddFilterList(25, 352, m_XOffsets_Amount, 40, m_AmountFilters, m_XWidths_Small, f.Quantity, 3);
break;
}
default:
{
index -= 4;
AddHtmlLocalized(75, 416, 120, 32, 1062477, from.UseOwnFilter ? LabelColor : 16927, false,
false); // Set Book Filter
AddButton(40, 416, 4005, 4007, 1, GumpButtonType.Reply, 0);
int type = index % 4;
index /= 4;
AddHtmlLocalized(235, 416, 120, 32, 1062478, from.UseOwnFilter ? 16927 : LabelColor, false,
false); // Set Your Filter
AddButton(200, 416, 4005, 4007, 2, GumpButtonType.Reply, 0);
if ( type >= 0 && type < m_Filters.Length )
{
int[,] filters = m_Filters[type];
AddHtmlLocalized(405, 416, 120, 32, 1062231, LabelColor, false, false); // Clear Filter
AddButton(370, 416, 4005, 4007, 3, GumpButtonType.Reply, 0);
if ( index >= 0 && index < filters.GetLength( 0 ) )
{
if ( filters[index, 0] == 0 )
break;
AddHtmlLocalized(540, 416, 50, 32, 1011046, LabelColor, false, false); // APPLY
AddButton(505, 416, 4017, 4018, 0, GumpButtonType.Reply, 0);
}
switch ( type )
{
case 0: f.Type = filters[index, 1]; break;
case 1: f.Quality = filters[index, 1]; break;
case 2: f.Material = filters[index, 1]; break;
case 3: f.Quantity = filters[index, 1]; break;
}
private void AddFilterList(int x, int y, int[] xOffsets, int yOffset, int[,] filters, int[] xWidths, int filterValue,
int filterIndex)
{
for (int i = 0; i < filters.GetLength(0); ++i)
{
int number = filters[i, 0];
m_From.SendGump( new BOBFilterGump( m_From, m_Book ) );
}
}
if (number == 0)
continue;
break;
}
}
}
bool isSelected = filters[i, 1] == filterValue;
public BOBFilterGump( PlayerMobile from, BulkOrderBook book ) : base( 12, 24 )
{
from.CloseGump( typeof( BOBGump ) );
from.CloseGump( typeof( BOBFilterGump ) );
if (!isSelected && i % xOffsets.Length == 0)
isSelected = filterValue == 0;
m_From = from;
m_Book = book;
AddHtmlLocalized(x + 35 + xOffsets[i % xOffsets.Length], y + i / xOffsets.Length * yOffset,
xWidths[i % xOffsets.Length], 32, number, isSelected ? 16927 : LabelColor, false, false);
AddButton(x + xOffsets[i % xOffsets.Length], y + i / xOffsets.Length * yOffset, 4005, 4007,
4 + filterIndex + i * 4, GumpButtonType.Reply, 0);
}
}
BOBFilter f = ( from.UseOwnFilter ? from.BOBFilter : book.Filter );
public override void OnResponse(NetState sender, RelayInfo info)
{
BOBFilter f = m_From.UseOwnFilter ? m_From.BOBFilter : m_Book.Filter;
AddPage( 0 );
int index = info.ButtonID;
AddBackground( 10, 10, 600, 439, 5054 );
switch (index)
{
case 0: // Apply
{
m_From.SendGump(new BOBGump(m_From, m_Book));
AddImageTiled( 18, 20, 583, 420, 2624 );
AddAlphaRegion( 18, 20, 583, 420 );
break;
}
case 1: // Set Book Filter
{
m_From.UseOwnFilter = false;
m_From.SendGump(new BOBFilterGump(m_From, m_Book));
AddImage( 5, 5, 10460 );
AddImage( 585, 5, 10460 );
AddImage( 5, 424, 10460 );
AddImage( 585, 424, 10460 );
break;
}
case 2: // Set Your Filter
{
m_From.UseOwnFilter = true;
m_From.SendGump(new BOBFilterGump(m_From, m_Book));
AddHtmlLocalized( 270, 32, 200, 32, 1062223, LabelColor, false, false ); // Filter Preference
break;
}
case 3: // Clear Filter
{
f.Clear();
m_From.SendGump(new BOBFilterGump(m_From, m_Book));
AddHtmlLocalized( 26, 64, 120, 32, 1062228, LabelColor, false, false ); // Bulk Order Type
AddFilterList( 25, 96, m_XOffsets_Type, 40, m_TypeFilters, m_XWidths_Small, f.Type, 0 );
break;
}
default:
{
index -= 4;
AddHtmlLocalized( 320, 64, 50, 32, 1062215, LabelColor, false, false ); // Quality
AddFilterList( 320, 96, m_XOffsets_Quality, 40, m_QualityFilters, m_XWidths_Small, f.Quality, 1 );
int type = index % 4;
index /= 4;
AddHtmlLocalized( 26, 160, 120, 32, 1062232, LabelColor, false, false ); // Material Type
AddFilterList( 25, 192, m_XOffsets_Material, 40, m_MaterialFilters, m_XWidths_Large, f.Material, 2 );
if (type >= 0 && type < m_Filters.Length)
{
int[,] filters = m_Filters[type];
AddHtmlLocalized( 26, 320, 120, 32, 1062217, LabelColor, false, false ); // Amount
AddFilterList( 25, 352, m_XOffsets_Amount, 40, m_AmountFilters, m_XWidths_Small, f.Quantity, 3 );
if (index >= 0 && index < filters.GetLength(0))
{
if (filters[index, 0] == 0)
break;
AddHtmlLocalized( 75, 416, 120, 32, 1062477, ( from.UseOwnFilter ? LabelColor : 16927 ), false, false ); // Set Book Filter
AddButton( 40, 416, 4005, 4007, 1, GumpButtonType.Reply, 0 );
switch (type)
{
case 0:
f.Type = filters[index, 1];
break;
case 1:
f.Quality = filters[index, 1];
break;
case 2:
f.Material = filters[index, 1];
break;
case 3:
f.Quantity = filters[index, 1];
break;
}
AddHtmlLocalized( 235, 416, 120, 32, 1062478, ( from.UseOwnFilter ? 16927 : LabelColor ), false, false ); // Set Your Filter
AddButton( 200, 416, 4005, 4007, 2, GumpButtonType.Reply, 0 );
m_From.SendGump(new BOBFilterGump(m_From, m_Book));
}
}
AddHtmlLocalized( 405, 416, 120, 32, 1062231, LabelColor, false, false ); // Clear Filter
AddButton( 370, 416, 4005, 4007, 3, GumpButtonType.Reply, 0 );
AddHtmlLocalized( 540, 416, 50, 32, 1011046, LabelColor, false, false ); // APPLY
AddButton( 505, 416, 4017, 4018, 0, GumpButtonType.Reply, 0 );
}
}
break;
}
}
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,106 +1,107 @@
namespace Server.Engines.BulkOrders
{
public class BOBLargeEntry
{
public bool RequireExceptional { get; }
public class BOBLargeEntry
{
public BOBLargeEntry(LargeBOD bod)
{
RequireExceptional = bod.RequireExceptional;
public BODType DeedType { get; }
if (bod is LargeTailorBOD)
DeedType = BODType.Tailor;
else if (bod is LargeSmithBOD)
DeedType = BODType.Smith;
public BulkMaterialType Material { get; }
Material = bod.Material;
AmountMax = bod.AmountMax;
public int AmountMax { get; }
Entries = new BOBLargeSubEntry[bod.Entries.Length];
public int Price { get; set; }
for (int i = 0; i < Entries.Length; ++i)
Entries[i] = new BOBLargeSubEntry(bod.Entries[i]);
}
public BOBLargeSubEntry[] Entries { get; }
public BOBLargeEntry(GenericReader reader)
{
int version = reader.ReadEncodedInt();
public Item Reconstruct()
{
LargeBOD bod = null;
switch (version)
{
case 0:
{
RequireExceptional = reader.ReadBool();
if ( DeedType == BODType.Smith )
bod = new LargeSmithBOD( AmountMax, RequireExceptional, Material, ReconstructEntries() );
else if ( DeedType == BODType.Tailor )
bod = new LargeTailorBOD( AmountMax, RequireExceptional, Material, ReconstructEntries() );
DeedType = (BODType)reader.ReadEncodedInt();
for ( int i = 0; bod != null && i < bod.Entries.Length; ++i )
bod.Entries[i].Owner = bod;
Material = (BulkMaterialType)reader.ReadEncodedInt();
AmountMax = reader.ReadEncodedInt();
Price = reader.ReadEncodedInt();
return bod;
}
Entries = new BOBLargeSubEntry[reader.ReadEncodedInt()];
private LargeBulkEntry[] ReconstructEntries()
{
LargeBulkEntry[] entries = new LargeBulkEntry[Entries.Length];
for (int i = 0; i < Entries.Length; ++i)
Entries[i] = new BOBLargeSubEntry(reader);
for ( int i = 0; i < Entries.Length; ++i )
{
entries[i] = new LargeBulkEntry( null, new SmallBulkEntry( Entries[i].ItemType, Entries[i].Number, Entries[i].Graphic ) );
entries[i].Amount = Entries[i].AmountCur;
}
break;
}
}
}
return entries;
}
public bool RequireExceptional{ get; }
public BOBLargeEntry( LargeBOD bod )
{
RequireExceptional = bod.RequireExceptional;
public BODType DeedType{ get; }
if ( bod is LargeTailorBOD )
DeedType = BODType.Tailor;
else if ( bod is LargeSmithBOD )
DeedType = BODType.Smith;
public BulkMaterialType Material{ get; }
Material = bod.Material;
AmountMax = bod.AmountMax;
public int AmountMax{ get; }
Entries = new BOBLargeSubEntry[bod.Entries.Length];
public int Price{ get; set; }
for ( int i = 0; i < Entries.Length; ++i )
Entries[i] = new BOBLargeSubEntry( bod.Entries[i] );
}
public BOBLargeSubEntry[] Entries{ get; }
public BOBLargeEntry( GenericReader reader )
{
int version = reader.ReadEncodedInt();
public Item Reconstruct()
{
LargeBOD bod = null;
switch ( version )
{
case 0:
{
RequireExceptional = reader.ReadBool();
if (DeedType == BODType.Smith)
bod = new LargeSmithBOD(AmountMax, RequireExceptional, Material, ReconstructEntries());
else if (DeedType == BODType.Tailor)
bod = new LargeTailorBOD(AmountMax, RequireExceptional, Material, ReconstructEntries());
DeedType = (BODType)reader.ReadEncodedInt();
for (int i = 0; bod != null && i < bod.Entries.Length; ++i)
bod.Entries[i].Owner = bod;
Material = (BulkMaterialType)reader.ReadEncodedInt();
AmountMax = reader.ReadEncodedInt();
Price = reader.ReadEncodedInt();
return bod;
}
Entries = new BOBLargeSubEntry[reader.ReadEncodedInt()];
private LargeBulkEntry[] ReconstructEntries()
{
LargeBulkEntry[] entries = new LargeBulkEntry[Entries.Length];
for ( int i = 0; i < Entries.Length; ++i )
Entries[i] = new BOBLargeSubEntry( reader );
for (int i = 0; i < Entries.Length; ++i)
{
entries[i] = new LargeBulkEntry(null,
new SmallBulkEntry(Entries[i].ItemType, Entries[i].Number, Entries[i].Graphic));
entries[i].Amount = Entries[i].AmountCur;
}
break;
}
}
}
return entries;
}
public void Serialize( GenericWriter writer )
{
writer.WriteEncodedInt( 0 ); // version
public void Serialize(GenericWriter writer)
{
writer.WriteEncodedInt(0); // version
writer.Write( (bool) RequireExceptional );
writer.Write(RequireExceptional);
writer.WriteEncodedInt( (int) DeedType );
writer.WriteEncodedInt( (int) Material );
writer.WriteEncodedInt( (int) AmountMax );
writer.WriteEncodedInt( (int) Price );
writer.WriteEncodedInt((int)DeedType);
writer.WriteEncodedInt((int)Material);
writer.WriteEncodedInt(AmountMax);
writer.WriteEncodedInt(Price);
writer.WriteEncodedInt( (int) Entries.Length );
writer.WriteEncodedInt(Entries.Length);
for ( int i = 0; i < Entries.Length; ++i )
Entries[i].Serialize( writer );
}
}
for (int i = 0; i < Entries.Length; ++i)
Entries[i].Serialize(writer);
}
}
}

View file

@ -2,55 +2,55 @@ using System;
namespace Server.Engines.BulkOrders
{
public class BOBLargeSubEntry
{
public Type ItemType { get; }
public class BOBLargeSubEntry
{
public BOBLargeSubEntry(LargeBulkEntry lbe)
{
ItemType = lbe.Details.Type;
AmountCur = lbe.Amount;
Number = lbe.Details.Number;
Graphic = lbe.Details.Graphic;
}
public int AmountCur { get; }
public BOBLargeSubEntry(GenericReader reader)
{
int version = reader.ReadEncodedInt();
public int Number { get; }
switch (version)
{
case 0:
{
string type = reader.ReadString();
public int Graphic { get; }
if (type != null)
ItemType = ScriptCompiler.FindTypeByFullName(type);
public BOBLargeSubEntry( LargeBulkEntry lbe )
{
ItemType = lbe.Details.Type;
AmountCur = lbe.Amount;
Number = lbe.Details.Number;
Graphic = lbe.Details.Graphic;
}
AmountCur = reader.ReadEncodedInt();
Number = reader.ReadEncodedInt();
Graphic = reader.ReadEncodedInt();
public BOBLargeSubEntry( GenericReader reader )
{
int version = reader.ReadEncodedInt();
break;
}
}
}
switch ( version )
{
case 0:
{
string type = reader.ReadString();
public Type ItemType{ get; }
if ( type != null )
ItemType = ScriptCompiler.FindTypeByFullName( type );
public int AmountCur{ get; }
AmountCur = reader.ReadEncodedInt();
Number = reader.ReadEncodedInt();
Graphic = reader.ReadEncodedInt();
public int Number{ get; }
break;
}
}
}
public int Graphic{ get; }
public void Serialize( GenericWriter writer )
{
writer.WriteEncodedInt( 0 ); // version
public void Serialize(GenericWriter writer)
{
writer.WriteEncodedInt(0); // version
writer.Write( ItemType == null ? null : ItemType.FullName );
writer.Write(ItemType == null ? null : ItemType.FullName);
writer.WriteEncodedInt( (int) AmountCur );
writer.WriteEncodedInt( (int) Number );
writer.WriteEncodedInt( (int) Graphic );
}
}
writer.WriteEncodedInt(AmountCur);
writer.WriteEncodedInt(Number);
writer.WriteEncodedInt(Graphic);
}
}
}

View file

@ -2,99 +2,99 @@ using System;
namespace Server.Engines.BulkOrders
{
public class BOBSmallEntry
{
public Type ItemType { get; }
public class BOBSmallEntry
{
public BOBSmallEntry(SmallBOD bod)
{
ItemType = bod.Type;
RequireExceptional = bod.RequireExceptional;
public bool RequireExceptional { get; }
if (bod is SmallTailorBOD)
DeedType = BODType.Tailor;
else if (bod is SmallSmithBOD)
DeedType = BODType.Smith;
public BODType DeedType { get; }
Material = bod.Material;
AmountCur = bod.AmountCur;
AmountMax = bod.AmountMax;
Number = bod.Number;
Graphic = bod.Graphic;
}
public BulkMaterialType Material { get; }
public BOBSmallEntry(GenericReader reader)
{
int version = reader.ReadEncodedInt();
public int AmountCur { get; }
switch (version)
{
case 0:
{
string type = reader.ReadString();
public int AmountMax { get; }
if (type != null)
ItemType = ScriptCompiler.FindTypeByFullName(type);
public int Number { get; }
RequireExceptional = reader.ReadBool();
public int Graphic { get; }
DeedType = (BODType)reader.ReadEncodedInt();
public int Price { get; set; }
Material = (BulkMaterialType)reader.ReadEncodedInt();
AmountCur = reader.ReadEncodedInt();
AmountMax = reader.ReadEncodedInt();
Number = reader.ReadEncodedInt();
Graphic = reader.ReadEncodedInt();
Price = reader.ReadEncodedInt();
public Item Reconstruct()
{
SmallBOD bod = null;
break;
}
}
}
if ( DeedType == BODType.Smith )
bod = new SmallSmithBOD( AmountCur, AmountMax, ItemType, Number, Graphic, RequireExceptional, Material );
else if ( DeedType == BODType.Tailor )
bod = new SmallTailorBOD( AmountCur, AmountMax, ItemType, Number, Graphic, RequireExceptional, Material );
public Type ItemType{ get; }
return bod;
}
public bool RequireExceptional{ get; }
public BOBSmallEntry( SmallBOD bod )
{
ItemType = bod.Type;
RequireExceptional = bod.RequireExceptional;
public BODType DeedType{ get; }
if ( bod is SmallTailorBOD )
DeedType = BODType.Tailor;
else if ( bod is SmallSmithBOD )
DeedType = BODType.Smith;
public BulkMaterialType Material{ get; }
Material = bod.Material;
AmountCur = bod.AmountCur;
AmountMax = bod.AmountMax;
Number = bod.Number;
Graphic = bod.Graphic;
}
public int AmountCur{ get; }
public BOBSmallEntry( GenericReader reader )
{
int version = reader.ReadEncodedInt();
public int AmountMax{ get; }
switch ( version )
{
case 0:
{
string type = reader.ReadString();
public int Number{ get; }
if ( type != null )
ItemType = ScriptCompiler.FindTypeByFullName( type );
public int Graphic{ get; }
RequireExceptional = reader.ReadBool();
public int Price{ get; set; }
DeedType = (BODType)reader.ReadEncodedInt();
public Item Reconstruct()
{
SmallBOD bod = null;
Material = (BulkMaterialType)reader.ReadEncodedInt();
AmountCur = reader.ReadEncodedInt();
AmountMax = reader.ReadEncodedInt();
Number = reader.ReadEncodedInt();
Graphic = reader.ReadEncodedInt();
Price = reader.ReadEncodedInt();
if (DeedType == BODType.Smith)
bod = new SmallSmithBOD(AmountCur, AmountMax, ItemType, Number, Graphic, RequireExceptional, Material);
else if (DeedType == BODType.Tailor)
bod = new SmallTailorBOD(AmountCur, AmountMax, ItemType, Number, Graphic, RequireExceptional, Material);
break;
}
}
}
return bod;
}
public void Serialize( GenericWriter writer )
{
writer.WriteEncodedInt( 0 ); // version
public void Serialize(GenericWriter writer)
{
writer.WriteEncodedInt(0); // version
writer.Write( ItemType == null ? null : ItemType.FullName );
writer.Write(ItemType == null ? null : ItemType.FullName);
writer.Write( (bool) RequireExceptional );
writer.Write(RequireExceptional);
writer.WriteEncodedInt( (int) DeedType );
writer.WriteEncodedInt( (int) Material );
writer.WriteEncodedInt( (int) AmountCur );
writer.WriteEncodedInt( (int) AmountMax );
writer.WriteEncodedInt( (int) Number );
writer.WriteEncodedInt( (int) Graphic );
writer.WriteEncodedInt( (int) Price );
}
}
writer.WriteEncodedInt((int)DeedType);
writer.WriteEncodedInt((int)Material);
writer.WriteEncodedInt(AmountCur);
writer.WriteEncodedInt(AmountMax);
writer.WriteEncodedInt(Number);
writer.WriteEncodedInt(Graphic);
writer.WriteEncodedInt(Price);
}
}
}

View file

@ -1,136 +1,140 @@
using Server.Items;
using Server.Gumps;
using Server.Items;
using Server.Mobiles;
using Server.Network;
namespace Server.Engines.BulkOrders
{
public class BODBuyGump : Gump
{
private PlayerMobile m_From;
private BulkOrderBook m_Book;
private object m_Object;
private int m_Price;
private int m_Page;
public class BODBuyGump : Gump
{
private BulkOrderBook m_Book;
private PlayerMobile m_From;
private object m_Object;
private int m_Page;
private int m_Price;
public override void OnResponse( Network.NetState sender, RelayInfo info )
{
if ( info.ButtonID == 2 )
{
PlayerVendor pv = m_Book.RootParent as PlayerVendor;
public BODBuyGump(PlayerMobile from, BulkOrderBook book, object obj, int page, int price) : base(100, 200)
{
m_From = from;
m_Book = book;
m_Object = obj;
m_Price = price;
m_Page = page;
if ( m_Book.Entries.Contains( m_Object ) && pv != null )
{
int price = 0;
AddPage(0);
VendorItem vi = pv.GetVendorItem( m_Book );
AddBackground(100, 10, 300, 150, 5054);
if ( vi != null && !vi.IsForSale )
{
if ( m_Object is BOBLargeEntry entry )
price = entry.Price;
else
price = ((BOBSmallEntry)m_Object).Price;
}
AddHtmlLocalized(125, 20, 250, 24, 1019070, false, false); // You have agreed to purchase:
AddHtmlLocalized(125, 45, 250, 24, 1045151, false, false); // a bulk order deed
if ( price != m_Price )
{
pv.SayTo( m_From, "The price has been been changed. If you like, you may offer to purchase the item again." );
}
else if ( price == 0 )
{
pv.SayTo( m_From, 1062382 ); // The deed selected is not available.
}
else
{
Item item = null;
AddHtmlLocalized(125, 70, 250, 24, 1019071, false, false); // for the amount of:
AddLabel(125, 95, 0, price.ToString());
if ( m_Object is BOBLargeEntry entry )
item = entry.Reconstruct();
else
item = ((BOBSmallEntry)m_Object).Reconstruct();
AddButton(250, 130, 4005, 4007, 1, GumpButtonType.Reply, 0);
AddHtmlLocalized(282, 130, 100, 24, 1011012, false, false); // CANCEL
if ( item == null )
{
m_From.SendMessage( "Internal error. The bulk order deed could not be reconstructed." );
}
else
{
pv.Say( m_From.Name );
AddButton(120, 130, 4005, 4007, 2, GumpButtonType.Reply, 0);
AddHtmlLocalized(152, 130, 100, 24, 1011036, false, false); // OKAY
}
Container pack = m_From.Backpack;
public override void OnResponse(NetState sender, RelayInfo info)
{
if (info.ButtonID == 2)
{
PlayerVendor pv = m_Book.RootParent as PlayerVendor;
if ( (pack == null) || ((pack != null) && (!pack.CheckHold(m_From, item, true, true, 0, item.PileWeight + item.TotalWeight)) ) )
{
pv.SayTo(m_From, 503204); // You do not have room in your backpack for this
m_From.SendGump(new BOBGump(m_From, m_Book, m_Page, null));
}
else
{
if ((pack != null && pack.ConsumeTotal( typeof( Gold ), price )) || Banker.Withdraw( m_From, price ) )
{
m_Book.Entries.Remove( m_Object );
m_Book.InvalidateProperties();
pv.HoldGold += price;
m_From.AddToBackpack( item );
m_From.SendLocalizedMessage( 1045152 ); // The bulk order deed has been placed in your backpack.
if (m_Book.Entries.Contains(m_Object) && pv != null)
{
int price = 0;
if ( m_Book.Entries.Count / 5 < m_Book.ItemCount )
{
m_Book.ItemCount--;
m_Book.InvalidateItems();
}
VendorItem vi = pv.GetVendorItem(m_Book);
if ( m_Book.Entries.Count > 0 )
m_From.SendGump( new BOBGump( m_From, m_Book, m_Page, null ) );
else
m_From.SendLocalizedMessage( 1062381 ); // The book is empty.
}
else
{
pv.SayTo( m_From, 503205 ); // You cannot afford this item.
item.Delete();
}
}
}
}
}
else
{
if ( pv == null )
m_From.SendLocalizedMessage( 1062382 ); // The deed selected is not available.
else
pv.SayTo( m_From, 1062382 ); // The deed selected is not available.
}
}
else
{
m_From.SendLocalizedMessage( 503207 ); // Cancelled purchase.
}
}
if (vi != null && !vi.IsForSale)
{
if (m_Object is BOBLargeEntry entry)
price = entry.Price;
else
price = ((BOBSmallEntry)m_Object).Price;
}
public BODBuyGump( PlayerMobile from, BulkOrderBook book, object obj, int page, int price ) : base( 100, 200 )
{
m_From = from;
m_Book = book;
m_Object = obj;
m_Price = price;
m_Page = page;
if (price != m_Price)
{
pv.SayTo(m_From,
"The price has been been changed. If you like, you may offer to purchase the item again.");
}
else if (price == 0)
{
pv.SayTo(m_From, 1062382); // The deed selected is not available.
}
else
{
Item item = null;
AddPage( 0 );
if (m_Object is BOBLargeEntry entry)
item = entry.Reconstruct();
else
item = ((BOBSmallEntry)m_Object).Reconstruct();
AddBackground( 100, 10, 300, 150, 5054 );
if (item == null)
{
m_From.SendMessage("Internal error. The bulk order deed could not be reconstructed.");
}
else
{
pv.Say(m_From.Name);
AddHtmlLocalized( 125, 20, 250, 24, 1019070, false, false ); // You have agreed to purchase:
AddHtmlLocalized( 125, 45, 250, 24, 1045151, false, false ); // a bulk order deed
Container pack = m_From.Backpack;
AddHtmlLocalized( 125, 70, 250, 24, 1019071, false, false ); // for the amount of:
AddLabel( 125, 95, 0, price.ToString() );
if (pack == null || pack != null && !pack.CheckHold(m_From, item, true, true, 0,
item.PileWeight + item.TotalWeight))
{
pv.SayTo(m_From, 503204); // You do not have room in your backpack for this
m_From.SendGump(new BOBGump(m_From, m_Book, m_Page, null));
}
else
{
if (pack != null && pack.ConsumeTotal(typeof(Gold), price) || Banker.Withdraw(m_From, price))
{
m_Book.Entries.Remove(m_Object);
m_Book.InvalidateProperties();
pv.HoldGold += price;
m_From.AddToBackpack(item);
m_From.SendLocalizedMessage(
1045152); // The bulk order deed has been placed in your backpack.
AddButton( 250, 130, 4005, 4007, 1, GumpButtonType.Reply, 0 );
AddHtmlLocalized( 282, 130, 100, 24, 1011012, false, false ); // CANCEL
if (m_Book.Entries.Count / 5 < m_Book.ItemCount)
{
m_Book.ItemCount--;
m_Book.InvalidateItems();
}
AddButton( 120, 130, 4005, 4007, 2, GumpButtonType.Reply, 0 );
AddHtmlLocalized( 152, 130, 100, 24, 1011036, false, false ); // OKAY
}
}
}
if (m_Book.Entries.Count > 0)
m_From.SendGump(new BOBGump(m_From, m_Book, m_Page, null));
else
m_From.SendLocalizedMessage(1062381); // The book is empty.
}
else
{
pv.SayTo(m_From, 503205); // You cannot afford this item.
item.Delete();
}
}
}
}
}
else
{
if (pv == null)
m_From.SendLocalizedMessage(1062382); // The deed selected is not available.
else
pv.SayTo(m_From, 1062382); // The deed selected is not available.
}
}
else
{
m_From.SendLocalizedMessage(503207); // Cancelled purchase.
}
}
}
}

View file

@ -1,8 +1,8 @@
namespace Server.Engines.BulkOrders
{
public enum BODType
{
Smith,
Tailor
}
public enum BODType
{
Smith,
Tailor
}
}

View file

@ -3,42 +3,42 @@ using Server.Items;
namespace Server.Engines.BulkOrders
{
public enum BulkMaterialType
{
None,
DullCopper,
ShadowIron,
Copper,
Bronze,
Gold,
Agapite,
Verite,
Valorite,
Spined,
Horned,
Barbed
}
public enum BulkMaterialType
{
None,
DullCopper,
ShadowIron,
Copper,
Bronze,
Gold,
Agapite,
Verite,
Valorite,
Spined,
Horned,
Barbed
}
public enum BulkGenericType
{
Iron,
Cloth,
Leather
}
public enum BulkGenericType
{
Iron,
Cloth,
Leather
}
public class BGTClassifier
{
public static BulkGenericType Classify( BODType deedType, Type itemType )
{
if ( deedType == BODType.Tailor )
{
if ( itemType == null || itemType.IsSubclassOf( typeof( BaseArmor ) ) || itemType.IsSubclassOf( typeof( BaseShoes ) ) )
return BulkGenericType.Leather;
public class BGTClassifier
{
public static BulkGenericType Classify(BODType deedType, Type itemType)
{
if (deedType == BODType.Tailor)
{
if (itemType == null || itemType.IsSubclassOf(typeof(BaseArmor)) || itemType.IsSubclassOf(typeof(BaseShoes)))
return BulkGenericType.Leather;
return BulkGenericType.Cloth;
}
return BulkGenericType.Cloth;
}
return BulkGenericType.Iron;
}
}
return BulkGenericType.Iron;
}
}
}

View file

@ -3,102 +3,105 @@ using Server.Network;
namespace Server.Engines.BulkOrders
{
public class LargeBODAcceptGump : Gump
{
private LargeBOD m_Deed;
private Mobile m_From;
public class LargeBODAcceptGump : Gump
{
private LargeBOD m_Deed;
private Mobile m_From;
public LargeBODAcceptGump( Mobile from, LargeBOD deed ) : base( 50, 50 )
{
m_From = from;
m_Deed = deed;
public LargeBODAcceptGump(Mobile from, LargeBOD deed) : base(50, 50)
{
m_From = from;
m_Deed = deed;
m_From.CloseGump( typeof( LargeBODAcceptGump ) );
m_From.CloseGump( typeof( SmallBODAcceptGump ) );
m_From.CloseGump(typeof(LargeBODAcceptGump));
m_From.CloseGump(typeof(SmallBODAcceptGump));
LargeBulkEntry[] entries = deed.Entries;
LargeBulkEntry[] entries = deed.Entries;
AddPage( 0 );
AddPage(0);
AddBackground( 25, 10, 430, 240 + (entries.Length * 24), 5054 );
AddBackground(25, 10, 430, 240 + entries.Length * 24, 5054);
AddImageTiled( 33, 20, 413, 221 + (entries.Length * 24), 2624 );
AddAlphaRegion( 33, 20, 413, 221 + (entries.Length * 24) );
AddImageTiled(33, 20, 413, 221 + entries.Length * 24, 2624);
AddAlphaRegion(33, 20, 413, 221 + entries.Length * 24);
AddImage( 20, 5, 10460 );
AddImage( 430, 5, 10460 );
AddImage( 20, 225 + (entries.Length * 24), 10460 );
AddImage( 430, 225 + (entries.Length * 24), 10460 );
AddImage(20, 5, 10460);
AddImage(430, 5, 10460);
AddImage(20, 225 + entries.Length * 24, 10460);
AddImage(430, 225 + entries.Length * 24, 10460);
AddHtmlLocalized( 180, 25, 120, 20, 1045134, 0x7FFF, false, false ); // A large bulk order
AddHtmlLocalized(180, 25, 120, 20, 1045134, 0x7FFF, false, false); // A large bulk order
AddHtmlLocalized( 40, 48, 350, 20, 1045135, 0x7FFF, false, false ); // Ah! Thanks for the goods! Would you help me out?
AddHtmlLocalized(40, 48, 350, 20, 1045135, 0x7FFF, false,
false); // Ah! Thanks for the goods! Would you help me out?
AddHtmlLocalized( 40, 72, 210, 20, 1045138, 0x7FFF, false, false ); // Amount to make:
AddLabel( 250, 72, 1152, deed.AmountMax.ToString() );
AddHtmlLocalized(40, 72, 210, 20, 1045138, 0x7FFF, false, false); // Amount to make:
AddLabel(250, 72, 1152, deed.AmountMax.ToString());
AddHtmlLocalized( 40, 96, 120, 20, 1045137, 0x7FFF, false, false ); // Items requested:
AddHtmlLocalized(40, 96, 120, 20, 1045137, 0x7FFF, false, false); // Items requested:
int y = 120;
int y = 120;
for ( int i = 0; i < entries.Length; ++i, y += 24 )
AddHtmlLocalized( 40, y, 210, 20, entries[i].Details.Number, 0x7FFF, false, false );
for (int i = 0; i < entries.Length; ++i, y += 24)
AddHtmlLocalized(40, y, 210, 20, entries[i].Details.Number, 0x7FFF, false, false);
if ( deed.RequireExceptional || deed.Material != BulkMaterialType.None )
{
AddHtmlLocalized( 40, y, 210, 20, 1045140, 0x7FFF, false, false ); // Special requirements to meet:
y += 24;
if (deed.RequireExceptional || deed.Material != BulkMaterialType.None)
{
AddHtmlLocalized(40, y, 210, 20, 1045140, 0x7FFF, false, false); // Special requirements to meet:
y += 24;
if ( deed.RequireExceptional )
{
AddHtmlLocalized( 40, y, 350, 20, 1045141, 0x7FFF, false, false ); // All items must be exceptional.
y += 24;
}
if (deed.RequireExceptional)
{
AddHtmlLocalized(40, y, 350, 20, 1045141, 0x7FFF, false, false); // All items must be exceptional.
y += 24;
}
if ( deed.Material != BulkMaterialType.None )
{
AddHtmlLocalized( 40, y, 350, 20, GetMaterialNumberFor( deed.Material ), 0x7FFF, false, false ); // All items must be made with x material.
y += 24;
}
}
if (deed.Material != BulkMaterialType.None)
{
AddHtmlLocalized(40, y, 350, 20, GetMaterialNumberFor(deed.Material), 0x7FFF, false,
false); // All items must be made with x material.
y += 24;
}
}
AddHtmlLocalized( 40, 192 + (entries.Length * 24), 350, 20, 1045139, 0x7FFF, false, false ); // Do you want to accept this order?
AddHtmlLocalized(40, 192 + entries.Length * 24, 350, 20, 1045139, 0x7FFF, false,
false); // Do you want to accept this order?
AddButton( 100, 216 + (entries.Length * 24), 4005, 4007, 1, GumpButtonType.Reply, 0 );
AddHtmlLocalized( 135, 216 + (entries.Length * 24), 120, 20, 1006044, 0x7FFF, false, false ); // Ok
AddButton(100, 216 + entries.Length * 24, 4005, 4007, 1, GumpButtonType.Reply, 0);
AddHtmlLocalized(135, 216 + entries.Length * 24, 120, 20, 1006044, 0x7FFF, false, false); // Ok
AddButton( 275, 216 + (entries.Length * 24), 4005, 4007, 0, GumpButtonType.Reply, 0 );
AddHtmlLocalized( 310, 216 + (entries.Length * 24), 120, 20, 1011012, 0x7FFF, false, false ); // CANCEL
}
AddButton(275, 216 + entries.Length * 24, 4005, 4007, 0, GumpButtonType.Reply, 0);
AddHtmlLocalized(310, 216 + entries.Length * 24, 120, 20, 1011012, 0x7FFF, false, false); // CANCEL
}
public override void OnResponse( NetState sender, RelayInfo info )
{
if ( info.ButtonID == 1 ) // Ok
{
if ( m_From.PlaceInBackpack( m_Deed ) )
{
m_From.SendLocalizedMessage( 1045152 ); // The bulk order deed has been placed in your backpack.
}
else
{
m_From.SendLocalizedMessage( 1045150 ); // There is not enough room in your backpack for the deed.
m_Deed.Delete();
}
}
else
{
m_Deed.Delete();
}
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (info.ButtonID == 1) // Ok
{
if (m_From.PlaceInBackpack(m_Deed))
{
m_From.SendLocalizedMessage(1045152); // The bulk order deed has been placed in your backpack.
}
else
{
m_From.SendLocalizedMessage(1045150); // There is not enough room in your backpack for the deed.
m_Deed.Delete();
}
}
else
{
m_Deed.Delete();
}
}
public static int GetMaterialNumberFor( BulkMaterialType material )
{
if ( material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Valorite )
return 1045142 + (int)(material - BulkMaterialType.DullCopper);
if ( material >= BulkMaterialType.Spined && material <= BulkMaterialType.Barbed )
return 1049348 + (int)(material - BulkMaterialType.Spined);
public static int GetMaterialNumberFor(BulkMaterialType material)
{
if (material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Valorite)
return 1045142 + (material - BulkMaterialType.DullCopper);
if (material >= BulkMaterialType.Spined && material <= BulkMaterialType.Barbed)
return 1049348 + (material - BulkMaterialType.Spined);
return 0;
}
}
return 0;
}
}
}

View file

@ -3,96 +3,98 @@ using Server.Network;
namespace Server.Engines.BulkOrders
{
public class LargeBODGump : Gump
{
private LargeBOD m_Deed;
private Mobile m_From;
public class LargeBODGump : Gump
{
private LargeBOD m_Deed;
private Mobile m_From;
public LargeBODGump( Mobile from, LargeBOD deed ) : base( 25, 25 )
{
m_From = from;
m_Deed = deed;
public LargeBODGump(Mobile from, LargeBOD deed) : base(25, 25)
{
m_From = from;
m_Deed = deed;
m_From.CloseGump( typeof( LargeBODGump ) );
m_From.CloseGump( typeof( SmallBODGump ) );
m_From.CloseGump(typeof(LargeBODGump));
m_From.CloseGump(typeof(SmallBODGump));
LargeBulkEntry[] entries = deed.Entries;
LargeBulkEntry[] entries = deed.Entries;
AddPage( 0 );
AddPage(0);
AddBackground( 50, 10, 455, 236 + (entries.Length * 24), 5054 );
AddBackground(50, 10, 455, 236 + entries.Length * 24, 5054);
AddImageTiled( 58, 20, 438, 217 + (entries.Length * 24), 2624 );
AddAlphaRegion( 58, 20, 438, 217 + (entries.Length * 24) );
AddImageTiled(58, 20, 438, 217 + entries.Length * 24, 2624);
AddAlphaRegion(58, 20, 438, 217 + entries.Length * 24);
AddImage( 45, 5, 10460 );
AddImage( 480, 5, 10460 );
AddImage( 45, 221 + (entries.Length * 24), 10460 );
AddImage( 480, 221 + (entries.Length * 24), 10460 );
AddImage(45, 5, 10460);
AddImage(480, 5, 10460);
AddImage(45, 221 + entries.Length * 24, 10460);
AddImage(480, 221 + entries.Length * 24, 10460);
AddHtmlLocalized( 225, 25, 120, 20, 1045134, 0x7FFF, false, false ); // A large bulk order
AddHtmlLocalized(225, 25, 120, 20, 1045134, 0x7FFF, false, false); // A large bulk order
AddHtmlLocalized( 75, 48, 250, 20, 1045138, 0x7FFF, false, false ); // Amount to make:
AddLabel( 275, 48, 1152, deed.AmountMax.ToString() );
AddHtmlLocalized(75, 48, 250, 20, 1045138, 0x7FFF, false, false); // Amount to make:
AddLabel(275, 48, 1152, deed.AmountMax.ToString());
AddHtmlLocalized( 75, 72, 120, 20, 1045137, 0x7FFF, false, false ); // Items requested:
AddHtmlLocalized( 275, 76, 200, 20, 1045153, 0x7FFF, false, false ); // Amount finished:
AddHtmlLocalized(75, 72, 120, 20, 1045137, 0x7FFF, false, false); // Items requested:
AddHtmlLocalized(275, 76, 200, 20, 1045153, 0x7FFF, false, false); // Amount finished:
int y = 96;
int y = 96;
for ( int i = 0; i < entries.Length; ++i )
{
LargeBulkEntry entry = entries[i];
SmallBulkEntry details = entry.Details;
for (int i = 0; i < entries.Length; ++i)
{
LargeBulkEntry entry = entries[i];
SmallBulkEntry details = entry.Details;
AddHtmlLocalized( 75, y, 210, 20, details.Number, 0x7FFF, false, false );
AddLabel( 275, y, 0x480, entry.Amount.ToString() );
AddHtmlLocalized(75, y, 210, 20, details.Number, 0x7FFF, false, false);
AddLabel(275, y, 0x480, entry.Amount.ToString());
y += 24;
}
y += 24;
}
if ( deed.RequireExceptional || deed.Material != BulkMaterialType.None )
{
AddHtmlLocalized( 75, y, 200, 20, 1045140, 0x7FFF, false, false ); // Special requirements to meet:
y += 24;
}
if (deed.RequireExceptional || deed.Material != BulkMaterialType.None)
{
AddHtmlLocalized(75, y, 200, 20, 1045140, 0x7FFF, false, false); // Special requirements to meet:
y += 24;
}
if ( deed.RequireExceptional )
{
AddHtmlLocalized( 75, y, 300, 20, 1045141, 0x7FFF, false, false ); // All items must be exceptional.
y += 24;
}
if (deed.RequireExceptional)
{
AddHtmlLocalized(75, y, 300, 20, 1045141, 0x7FFF, false, false); // All items must be exceptional.
y += 24;
}
if ( deed.Material != BulkMaterialType.None )
AddHtmlLocalized( 75, y, 300, 20, GetMaterialNumberFor( deed.Material ), 0x7FFF, false, false ); // All items must be made with x material.
if (deed.Material != BulkMaterialType.None)
AddHtmlLocalized(75, y, 300, 20, GetMaterialNumberFor(deed.Material), 0x7FFF, false,
false); // All items must be made with x material.
AddButton( 125, 168 + (entries.Length * 24), 4005, 4007, 2, GumpButtonType.Reply, 0 );
AddHtmlLocalized( 160, 168 + (entries.Length * 24), 300, 20, 1045155, 0x7FFF, false, false ); // Combine this deed with another deed.
AddButton(125, 168 + entries.Length * 24, 4005, 4007, 2, GumpButtonType.Reply, 0);
AddHtmlLocalized(160, 168 + entries.Length * 24, 300, 20, 1045155, 0x7FFF, false,
false); // Combine this deed with another deed.
AddButton( 125, 192 + (entries.Length * 24), 4005, 4007, 1, GumpButtonType.Reply, 0 );
AddHtmlLocalized( 160, 192 + (entries.Length * 24), 120, 20, 1011441, 0x7FFF, false, false ); // EXIT
}
AddButton(125, 192 + entries.Length * 24, 4005, 4007, 1, GumpButtonType.Reply, 0);
AddHtmlLocalized(160, 192 + entries.Length * 24, 120, 20, 1011441, 0x7FFF, false, false); // EXIT
}
public override void OnResponse( NetState sender, RelayInfo info )
{
if ( m_Deed.Deleted || !m_Deed.IsChildOf( m_From.Backpack ) )
return;
public override void OnResponse(NetState sender, RelayInfo info)
{
if (m_Deed.Deleted || !m_Deed.IsChildOf(m_From.Backpack))
return;
if ( info.ButtonID == 2 ) // Combine
{
m_From.SendGump( new LargeBODGump( m_From, m_Deed ) );
m_Deed.BeginCombine( m_From );
}
}
if (info.ButtonID == 2) // Combine
{
m_From.SendGump(new LargeBODGump(m_From, m_Deed));
m_Deed.BeginCombine(m_From);
}
}
public static int GetMaterialNumberFor( BulkMaterialType material )
{
if ( material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Valorite )
return 1045142 + (int)(material - BulkMaterialType.DullCopper);
if ( material >= BulkMaterialType.Spined && material <= BulkMaterialType.Barbed )
return 1049348 + (int)(material - BulkMaterialType.Spined);
public static int GetMaterialNumberFor(BulkMaterialType material)
{
if (material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Valorite)
return 1045142 + (material - BulkMaterialType.DullCopper);
if (material >= BulkMaterialType.Spined && material <= BulkMaterialType.Barbed)
return 1049348 + (material - BulkMaterialType.Spined);
return 0;
}
}
return 0;
}
}
}

View file

@ -2,21 +2,21 @@ using Server.Targeting;
namespace Server.Engines.BulkOrders
{
public class LargeBODTarget : Target
{
private LargeBOD m_Deed;
public class LargeBODTarget : Target
{
private LargeBOD m_Deed;
public LargeBODTarget( LargeBOD deed ) : base( 18, false, TargetFlags.None )
{
m_Deed = deed;
}
public LargeBODTarget(LargeBOD deed) : base(18, false, TargetFlags.None)
{
m_Deed = deed;
}
protected override void OnTarget( Mobile from, object targeted )
{
if ( m_Deed.Deleted || !m_Deed.IsChildOf( from.Backpack ) )
return;
protected override void OnTarget(Mobile from, object targeted)
{
if (m_Deed.Deleted || !m_Deed.IsChildOf(from.Backpack))
return;
m_Deed.EndCombine( from, targeted );
}
}
m_Deed.EndCombine(from, targeted);
}
}
}

View file

@ -1,132 +1,150 @@
using Mat = Server.Engines.BulkOrders.BulkMaterialType;
using System.Collections.Generic;
using Mat = Server.Engines.BulkOrders.BulkMaterialType;
namespace Server.Engines.BulkOrders
{
[TypeAlias( "Scripts.Engines.BulkOrders.LargeSmithBOD" )]
public class LargeSmithBOD : LargeBOD
{
public static double[] m_BlacksmithMaterialChances = {
0.501953125, // None
0.250000000, // Dull Copper
0.125000000, // Shadow Iron
0.062500000, // Copper
0.031250000, // Bronze
0.015625000, // Gold
0.007812500, // Agapite
0.003906250, // Verite
0.001953125 // Valorite
};
[TypeAlias("Scripts.Engines.BulkOrders.LargeSmithBOD")]
public class LargeSmithBOD : LargeBOD
{
public static double[] m_BlacksmithMaterialChances =
{
0.501953125, // None
0.250000000, // Dull Copper
0.125000000, // Shadow Iron
0.062500000, // Copper
0.031250000, // Bronze
0.015625000, // Gold
0.007812500, // Agapite
0.003906250, // Verite
0.001953125 // Valorite
};
public override int ComputeFame()
{
return SmithRewardCalculator.Instance.ComputeFame( this );
}
[Constructible]
public LargeSmithBOD()
{
LargeBulkEntry[] entries;
bool useMaterials = true;
public override int ComputeGold()
{
return SmithRewardCalculator.Instance.ComputeGold( this );
}
int rand = Utility.Random(8);
[Constructible]
public LargeSmithBOD()
{
LargeBulkEntry[] entries;
bool useMaterials = true;
switch (rand)
{
default:
case 0:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargeRing);
break;
case 1:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargePlate);
break;
case 2:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargeChain);
break;
case 3:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargeAxes);
break;
case 4:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargeFencing);
break;
case 5:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargeMaces);
break;
case 6:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargePolearms);
break;
case 7:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargeSwords);
break;
}
int rand = Utility.Random( 8 );
if (rand > 2 && rand < 8)
useMaterials = false;
switch ( rand )
{
default:
case 0: entries = LargeBulkEntry.ConvertEntries( this, LargeBulkEntry.LargeRing ); break;
case 1: entries = LargeBulkEntry.ConvertEntries( this, LargeBulkEntry.LargePlate ); break;
case 2: entries = LargeBulkEntry.ConvertEntries( this, LargeBulkEntry.LargeChain ); break;
case 3: entries = LargeBulkEntry.ConvertEntries( this, LargeBulkEntry.LargeAxes ); break;
case 4: entries = LargeBulkEntry.ConvertEntries( this, LargeBulkEntry.LargeFencing ); break;
case 5: entries = LargeBulkEntry.ConvertEntries( this, LargeBulkEntry.LargeMaces ); break;
case 6: entries = LargeBulkEntry.ConvertEntries( this, LargeBulkEntry.LargePolearms ); break;
case 7: entries = LargeBulkEntry.ConvertEntries( this, LargeBulkEntry.LargeSwords ); break;
}
int hue = 0x44E;
int amountMax = Utility.RandomList(10, 15, 20, 20);
bool reqExceptional = 0.825 > Utility.RandomDouble();
if ( rand > 2 && rand < 8 )
useMaterials = false;
BulkMaterialType material;
int hue = 0x44E;
int amountMax = Utility.RandomList( 10, 15, 20, 20 );
bool reqExceptional = ( 0.825 > Utility.RandomDouble() );
if (useMaterials)
material = GetRandomMaterial(BulkMaterialType.DullCopper, m_BlacksmithMaterialChances);
else
material = BulkMaterialType.None;
BulkMaterialType material;
Hue = hue;
AmountMax = amountMax;
Entries = entries;
RequireExceptional = reqExceptional;
Material = material;
}
if ( useMaterials )
material = GetRandomMaterial( BulkMaterialType.DullCopper, m_BlacksmithMaterialChances );
else
material = BulkMaterialType.None;
public LargeSmithBOD(int amountMax, bool reqExceptional, BulkMaterialType mat, LargeBulkEntry[] entries)
{
Hue = 0x44E;
AmountMax = amountMax;
Entries = entries;
RequireExceptional = reqExceptional;
Material = mat;
}
Hue = hue;
AmountMax = amountMax;
Entries = entries;
RequireExceptional = reqExceptional;
Material = material;
}
public LargeSmithBOD(Serial serial) : base(serial)
{
}
public LargeSmithBOD( int amountMax, bool reqExceptional, BulkMaterialType mat, LargeBulkEntry[] entries )
{
Hue = 0x44E;
AmountMax = amountMax;
Entries = entries;
RequireExceptional = reqExceptional;
Material = mat;
}
public override int ComputeFame()
{
return SmithRewardCalculator.Instance.ComputeFame(this);
}
public override List<Item> ComputeRewards( bool full )
{
List<Item> list = new List<Item>();
public override int ComputeGold()
{
return SmithRewardCalculator.Instance.ComputeGold(this);
}
RewardGroup rewardGroup = SmithRewardCalculator.Instance.LookupRewards( SmithRewardCalculator.Instance.ComputePoints( this ) );
public override List<Item> ComputeRewards(bool full)
{
List<Item> list = new List<Item>();
if ( rewardGroup != null )
{
if ( full )
{
for ( int i = 0; i < rewardGroup.Items.Length; ++i )
{
Item item = rewardGroup.Items[i].Construct();
RewardGroup rewardGroup =
SmithRewardCalculator.Instance.LookupRewards(SmithRewardCalculator.Instance.ComputePoints(this));
if ( item != null )
list.Add( item );
}
}
else
{
RewardItem rewardItem = rewardGroup.AcquireItem();
if (rewardGroup != null)
{
if (full)
{
for (int i = 0; i < rewardGroup.Items.Length; ++i)
{
Item item = rewardGroup.Items[i].Construct();
Item item = rewardItem?.Construct();
if (item != null)
list.Add(item);
}
}
else
{
RewardItem rewardItem = rewardGroup.AcquireItem();
if ( item != null )
list.Add( item );
}
}
Item item = rewardItem?.Construct();
return list;
}
if (item != null)
list.Add(item);
}
}
public LargeSmithBOD( Serial serial ) : base( serial )
{
}
return list;
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write( (int) 0 ); // version
}
writer.Write(0); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}
int version = reader.ReadInt();
}
}
}

View file

@ -1,127 +1,162 @@
using Mat = Server.Engines.BulkOrders.BulkMaterialType;
using System.Collections.Generic;
using Mat = Server.Engines.BulkOrders.BulkMaterialType;
namespace Server.Engines.BulkOrders
{
public class LargeTailorBOD : LargeBOD
{
public static double[] m_TailoringMaterialChances = {
0.857421875, // None
0.125000000, // Spined
0.015625000, // Horned
0.001953125 // Barbed
};
public class LargeTailorBOD : LargeBOD
{
public static double[] m_TailoringMaterialChances =
{
0.857421875, // None
0.125000000, // Spined
0.015625000, // Horned
0.001953125 // Barbed
};
public override int ComputeFame()
{
return TailorRewardCalculator.Instance.ComputeFame( this );
}
[Constructible]
public LargeTailorBOD()
{
LargeBulkEntry[] entries;
bool useMaterials = false;
public override int ComputeGold()
{
return TailorRewardCalculator.Instance.ComputeGold( this );
}
switch (Utility.Random(14))
{
default:
case 0:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.Farmer);
break;
case 1:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.FemaleLeatherSet);
useMaterials = true;
break;
case 2:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.FisherGirl);
break;
case 3:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.Gypsy);
break;
case 4:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.HatSet);
break;
case 5:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.Jester);
break;
case 6:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.Lady);
break;
case 7:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.MaleLeatherSet);
useMaterials = true;
break;
case 8:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.Pirate);
break;
case 9:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.ShoeSet);
useMaterials = Core.ML;
break;
case 10:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.StuddedSet);
useMaterials = true;
break;
case 11:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.TownCrier);
break;
case 12:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.Wizard);
break;
case 13:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.BoneSet);
useMaterials = true;
break;
}
[Constructible]
public LargeTailorBOD()
{
LargeBulkEntry[] entries;
bool useMaterials = false;
int hue = 0x483;
int amountMax = Utility.RandomList(10, 15, 20, 20);
bool reqExceptional = 0.825 > Utility.RandomDouble();
switch ( Utility.Random( 14 ) )
{
default:
case 0: entries = LargeBulkEntry.ConvertEntries( this, LargeBulkEntry.Farmer ); break;
case 1: entries = LargeBulkEntry.ConvertEntries( this, LargeBulkEntry.FemaleLeatherSet ); useMaterials = true; break;
case 2: entries = LargeBulkEntry.ConvertEntries( this, LargeBulkEntry.FisherGirl ); break;
case 3: entries = LargeBulkEntry.ConvertEntries( this, LargeBulkEntry.Gypsy ); break;
case 4: entries = LargeBulkEntry.ConvertEntries( this, LargeBulkEntry.HatSet ); break;
case 5: entries = LargeBulkEntry.ConvertEntries( this, LargeBulkEntry.Jester ); break;
case 6: entries = LargeBulkEntry.ConvertEntries( this, LargeBulkEntry.Lady ); break;
case 7: entries = LargeBulkEntry.ConvertEntries( this, LargeBulkEntry.MaleLeatherSet ); useMaterials = true; break;
case 8: entries = LargeBulkEntry.ConvertEntries( this, LargeBulkEntry.Pirate ); break;
case 9: entries = LargeBulkEntry.ConvertEntries( this, LargeBulkEntry.ShoeSet ); useMaterials = Core.ML; break;
case 10: entries = LargeBulkEntry.ConvertEntries( this, LargeBulkEntry.StuddedSet ); useMaterials = true; break;
case 11: entries = LargeBulkEntry.ConvertEntries( this, LargeBulkEntry.TownCrier ); break;
case 12: entries = LargeBulkEntry.ConvertEntries( this, LargeBulkEntry.Wizard ); break;
case 13: entries = LargeBulkEntry.ConvertEntries( this, LargeBulkEntry.BoneSet ); useMaterials = true; break;
}
BulkMaterialType material;
int hue = 0x483;
int amountMax = Utility.RandomList( 10, 15, 20, 20 );
bool reqExceptional = ( 0.825 > Utility.RandomDouble() );
if (useMaterials)
material = GetRandomMaterial(BulkMaterialType.Spined, m_TailoringMaterialChances);
else
material = BulkMaterialType.None;
BulkMaterialType material;
Hue = hue;
AmountMax = amountMax;
Entries = entries;
RequireExceptional = reqExceptional;
Material = material;
}
if ( useMaterials )
material = GetRandomMaterial( BulkMaterialType.Spined, m_TailoringMaterialChances );
else
material = BulkMaterialType.None;
public LargeTailorBOD(int amountMax, bool reqExceptional, BulkMaterialType mat, LargeBulkEntry[] entries)
{
Hue = 0x483;
AmountMax = amountMax;
Entries = entries;
RequireExceptional = reqExceptional;
Material = mat;
}
Hue = hue;
AmountMax = amountMax;
Entries = entries;
RequireExceptional = reqExceptional;
Material = material;
}
public LargeTailorBOD(Serial serial) : base(serial)
{
}
public LargeTailorBOD( int amountMax, bool reqExceptional, BulkMaterialType mat, LargeBulkEntry[] entries )
{
Hue = 0x483;
AmountMax = amountMax;
Entries = entries;
RequireExceptional = reqExceptional;
Material = mat;
}
public override int ComputeFame()
{
return TailorRewardCalculator.Instance.ComputeFame(this);
}
public override List<Item> ComputeRewards( bool full )
{
List<Item> list = new List<Item>();
public override int ComputeGold()
{
return TailorRewardCalculator.Instance.ComputeGold(this);
}
RewardGroup rewardGroup = TailorRewardCalculator.Instance.LookupRewards( TailorRewardCalculator.Instance.ComputePoints( this ) );
public override List<Item> ComputeRewards(bool full)
{
List<Item> list = new List<Item>();
if ( rewardGroup != null )
{
if ( full )
{
for ( int i = 0; i < rewardGroup.Items.Length; ++i )
{
Item item = rewardGroup.Items[i].Construct();
RewardGroup rewardGroup =
TailorRewardCalculator.Instance.LookupRewards(TailorRewardCalculator.Instance.ComputePoints(this));
if ( item != null )
list.Add( item );
}
}
else
{
RewardItem rewardItem = rewardGroup.AcquireItem();
if (rewardGroup != null)
{
if (full)
{
for (int i = 0; i < rewardGroup.Items.Length; ++i)
{
Item item = rewardGroup.Items[i].Construct();
Item item = rewardItem?.Construct();
if (item != null)
list.Add(item);
}
}
else
{
RewardItem rewardItem = rewardGroup.AcquireItem();
if ( item != null )
list.Add( item );
}
}
Item item = rewardItem?.Construct();
return list;
}
if (item != null)
list.Add(item);
}
}
public LargeTailorBOD( Serial serial ) : base( serial )
{
}
return list;
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write( (int) 0 ); // version
}
writer.Write(0); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
int version = reader.ReadInt();
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,290 +1,329 @@
using System;
using Server.Items;
using System.Collections.Generic;
using Server.Items;
using Server.Mobiles;
namespace Server.Engines.BulkOrders
{
[TypeAlias( "Scripts.Engines.BulkOrders.SmallBOD" )]
public abstract class SmallBOD : Item
{
private int m_AmountCur, m_AmountMax;
private int m_Number;
private bool m_RequireExceptional;
private BulkMaterialType m_Material;
[TypeAlias("Scripts.Engines.BulkOrders.SmallBOD")]
public abstract class SmallBOD : Item
{
private int m_AmountCur, m_AmountMax;
private BulkMaterialType m_Material;
private int m_Number;
private bool m_RequireExceptional;
[CommandProperty( AccessLevel.GameMaster )]
public int AmountCur{ get => m_AmountCur;
set{ m_AmountCur = value; InvalidateProperties(); } }
[Constructible]
public SmallBOD(int hue, int amountMax, Type type, int number, int graphic, bool requireExeptional,
BulkMaterialType material) : base(Core.AOS ? 0x2258 : 0x14EF)
{
Weight = 1.0;
Hue = hue; // Blacksmith: 0x44E; Tailoring: 0x483
LootType = LootType.Blessed;
[CommandProperty( AccessLevel.GameMaster )]
public int AmountMax{ get => m_AmountMax;
set{ m_AmountMax = value; InvalidateProperties(); } }
m_AmountMax = amountMax;
Type = type;
m_Number = number;
Graphic = graphic;
m_RequireExceptional = requireExeptional;
m_Material = material;
}
[CommandProperty( AccessLevel.GameMaster )]
public Type Type { get; set; }
public SmallBOD() : base(Core.AOS ? 0x2258 : 0x14EF)
{
Weight = 1.0;
LootType = LootType.Blessed;
}
[CommandProperty( AccessLevel.GameMaster )]
public int Number{ get => m_Number;
set{ m_Number = value; InvalidateProperties(); } }
public SmallBOD(Serial serial) : base(serial)
{
}
[CommandProperty( AccessLevel.GameMaster )]
public int Graphic { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int AmountCur
{
get => m_AmountCur;
set
{
m_AmountCur = value;
InvalidateProperties();
}
}
[CommandProperty( AccessLevel.GameMaster )]
public bool RequireExceptional{ get => m_RequireExceptional;
set{ m_RequireExceptional = value; InvalidateProperties(); } }
[CommandProperty(AccessLevel.GameMaster)]
public int AmountMax
{
get => m_AmountMax;
set
{
m_AmountMax = value;
InvalidateProperties();
}
}
[CommandProperty( AccessLevel.GameMaster )]
public BulkMaterialType Material{ get => m_Material;
set{ m_Material = value; InvalidateProperties(); } }
[CommandProperty(AccessLevel.GameMaster)]
public Type Type{ get; set; }
[CommandProperty( AccessLevel.GameMaster )]
public bool Complete => ( m_AmountCur == m_AmountMax );
[CommandProperty(AccessLevel.GameMaster)]
public int Number
{
get => m_Number;
set
{
m_Number = value;
InvalidateProperties();
}
}
public override int LabelNumber => 1045151; // a bulk order deed
[CommandProperty(AccessLevel.GameMaster)]
public int Graphic{ get; set; }
[Constructible]
public SmallBOD( int hue, int amountMax, Type type, int number, int graphic, bool requireExeptional, BulkMaterialType material ) : base( Core.AOS ? 0x2258 : 0x14EF )
{
Weight = 1.0;
Hue = hue; // Blacksmith: 0x44E; Tailoring: 0x483
LootType = LootType.Blessed;
[CommandProperty(AccessLevel.GameMaster)]
public bool RequireExceptional
{
get => m_RequireExceptional;
set
{
m_RequireExceptional = value;
InvalidateProperties();
}
}
m_AmountMax = amountMax;
Type = type;
m_Number = number;
Graphic = graphic;
m_RequireExceptional = requireExeptional;
m_Material = material;
}
[CommandProperty(AccessLevel.GameMaster)]
public BulkMaterialType Material
{
get => m_Material;
set
{
m_Material = value;
InvalidateProperties();
}
}
public SmallBOD() : base( Core.AOS ? 0x2258 : 0x14EF )
{
Weight = 1.0;
LootType = LootType.Blessed;
}
[CommandProperty(AccessLevel.GameMaster)]
public bool Complete => m_AmountCur == m_AmountMax;
public static BulkMaterialType GetRandomMaterial( BulkMaterialType start, double[] chances )
{
double random = Utility.RandomDouble();
public override int LabelNumber => 1045151; // a bulk order deed
for ( int i = 0; i < chances.Length; ++i )
{
if ( random < chances[i] )
return ( i == 0 ? BulkMaterialType.None : start + (i - 1) );
public static BulkMaterialType GetRandomMaterial(BulkMaterialType start, double[] chances)
{
double random = Utility.RandomDouble();
random -= chances[i];
}
for (int i = 0; i < chances.Length; ++i)
{
if (random < chances[i])
return i == 0 ? BulkMaterialType.None : start + (i - 1);
return BulkMaterialType.None;
}
random -= chances[i];
}
public override void GetProperties( ObjectPropertyList list )
{
base.GetProperties( list );
return BulkMaterialType.None;
}
list.Add( 1060654 ); // small bulk order
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
if ( m_RequireExceptional )
list.Add( 1045141 ); // All items must be exceptional.
list.Add(1060654); // small bulk order
if ( m_Material != BulkMaterialType.None )
list.Add( SmallBODGump.GetMaterialNumberFor( m_Material ) ); // All items must be made with x material.
if (m_RequireExceptional)
list.Add(1045141); // All items must be exceptional.
list.Add( 1060656, m_AmountMax.ToString() ); // amount to make: ~1_val~
list.Add( 1060658, "#{0}\t{1}", m_Number, m_AmountCur ); // ~1_val~: ~2_val~
}
if (m_Material != BulkMaterialType.None)
list.Add(SmallBODGump.GetMaterialNumberFor(m_Material)); // All items must be made with x material.
public override void OnDoubleClick( Mobile from )
{
if ( IsChildOf( from.Backpack ) || InSecureTrade || RootParent is PlayerVendor )
from.SendGump( new SmallBODGump( from, this ) );
else
from.SendLocalizedMessage( 1045156 ); // You must have the deed in your backpack to use it.
}
list.Add(1060656, m_AmountMax.ToString()); // amount to make: ~1_val~
list.Add(1060658, "#{0}\t{1}", m_Number, m_AmountCur); // ~1_val~: ~2_val~
}
public override void OnDoubleClickNotAccessible( Mobile from )
{
OnDoubleClick( from );
}
public override void OnDoubleClick(Mobile from)
{
if (IsChildOf(from.Backpack) || InSecureTrade || RootParent is PlayerVendor)
from.SendGump(new SmallBODGump(from, this));
else
from.SendLocalizedMessage(1045156); // You must have the deed in your backpack to use it.
}
public override void OnDoubleClickSecureTrade( Mobile from )
{
OnDoubleClick( from );
}
public override void OnDoubleClickNotAccessible(Mobile from)
{
OnDoubleClick(from);
}
public void BeginCombine( Mobile from )
{
if ( m_AmountCur < m_AmountMax )
from.Target = new SmallBODTarget( this );
else
from.SendLocalizedMessage( 1045166 ); // The maximum amount of requested items have already been combined to this deed.
}
public override void OnDoubleClickSecureTrade(Mobile from)
{
OnDoubleClick(from);
}
public abstract List<Item> ComputeRewards( bool full );
public abstract int ComputeGold();
public abstract int ComputeFame();
public void BeginCombine(Mobile from)
{
if (m_AmountCur < m_AmountMax)
from.Target = new SmallBODTarget(this);
else
from.SendLocalizedMessage(
1045166); // The maximum amount of requested items have already been combined to this deed.
}
public virtual void GetRewards( out Item reward, out int gold, out int fame )
{
reward = null;
gold = ComputeGold();
fame = ComputeFame();
public abstract List<Item> ComputeRewards(bool full);
public abstract int ComputeGold();
public abstract int ComputeFame();
List<Item> rewards = ComputeRewards( false );
public virtual void GetRewards(out Item reward, out int gold, out int fame)
{
reward = null;
gold = ComputeGold();
fame = ComputeFame();
if ( rewards.Count > 0 )
{
reward = rewards[Utility.Random( rewards.Count )];
List<Item> rewards = ComputeRewards(false);
for ( int i = 0; i < rewards.Count; ++i )
{
if ( rewards[i] != reward )
rewards[i].Delete();
}
}
}
if (rewards.Count > 0)
{
reward = rewards[Utility.Random(rewards.Count)];
public static BulkMaterialType GetMaterial( CraftResource resource )
{
switch ( resource )
{
case CraftResource.DullCopper: return BulkMaterialType.DullCopper;
case CraftResource.ShadowIron: return BulkMaterialType.ShadowIron;
case CraftResource.Copper: return BulkMaterialType.Copper;
case CraftResource.Bronze: return BulkMaterialType.Bronze;
case CraftResource.Gold: return BulkMaterialType.Gold;
case CraftResource.Agapite: return BulkMaterialType.Agapite;
case CraftResource.Verite: return BulkMaterialType.Verite;
case CraftResource.Valorite: return BulkMaterialType.Valorite;
case CraftResource.SpinedLeather: return BulkMaterialType.Spined;
case CraftResource.HornedLeather: return BulkMaterialType.Horned;
case CraftResource.BarbedLeather: return BulkMaterialType.Barbed;
}
for (int i = 0; i < rewards.Count; ++i)
if (rewards[i] != reward)
rewards[i].Delete();
}
}
return BulkMaterialType.None;
}
public static BulkMaterialType GetMaterial(CraftResource resource)
{
switch (resource)
{
case CraftResource.DullCopper: return BulkMaterialType.DullCopper;
case CraftResource.ShadowIron: return BulkMaterialType.ShadowIron;
case CraftResource.Copper: return BulkMaterialType.Copper;
case CraftResource.Bronze: return BulkMaterialType.Bronze;
case CraftResource.Gold: return BulkMaterialType.Gold;
case CraftResource.Agapite: return BulkMaterialType.Agapite;
case CraftResource.Verite: return BulkMaterialType.Verite;
case CraftResource.Valorite: return BulkMaterialType.Valorite;
case CraftResource.SpinedLeather: return BulkMaterialType.Spined;
case CraftResource.HornedLeather: return BulkMaterialType.Horned;
case CraftResource.BarbedLeather: return BulkMaterialType.Barbed;
}
public void EndCombine( Mobile from, object o )
{
if ( o is Item item && item.IsChildOf( from.Backpack ) )
{
Type objectType = item.GetType();
return BulkMaterialType.None;
}
if ( m_AmountCur >= m_AmountMax )
{
from.SendLocalizedMessage( 1045166 ); // The maximum amount of requested items have already been combined to this deed.
}
else if ( Type == null || (objectType != Type && !objectType.IsSubclassOf( Type )) || (!(item is BaseWeapon) && !(item is BaseArmor) && !(item is BaseClothing)) )
{
from.SendLocalizedMessage( 1045169 ); // The item is not in the request.
}
else
{
BaseArmor armor = item as BaseArmor;
BaseClothing clothing = item as BaseClothing;
public void EndCombine(Mobile from, object o)
{
if (o is Item item && item.IsChildOf(from.Backpack))
{
Type objectType = item.GetType();
BulkMaterialType material = GetMaterial( armor?.Resource ?? clothing?.Resource ?? CraftResource.None );
if (m_AmountCur >= m_AmountMax)
{
from.SendLocalizedMessage(
1045166); // The maximum amount of requested items have already been combined to this deed.
}
else if (Type == null || objectType != Type && !objectType.IsSubclassOf(Type) ||
!(item is BaseWeapon) && !(item is BaseArmor) && !(item is BaseClothing))
{
from.SendLocalizedMessage(1045169); // The item is not in the request.
}
else
{
BaseArmor armor = item as BaseArmor;
BaseClothing clothing = item as BaseClothing;
if ( m_Material >= BulkMaterialType.DullCopper && m_Material <= BulkMaterialType.Valorite && material != m_Material )
{
from.SendLocalizedMessage( 1045168 ); // The item is not made from the requested ore.
}
else if ( m_Material >= BulkMaterialType.Spined && m_Material <= BulkMaterialType.Barbed && material != m_Material )
{
from.SendLocalizedMessage( 1049352 ); // The item is not made from the requested leather type.
}
else
{
bool isExceptional;
BulkMaterialType material = GetMaterial(armor?.Resource ?? clothing?.Resource ?? CraftResource.None);
if ( item is BaseWeapon weapon )
isExceptional = weapon.Quality == WeaponQuality.Exceptional;
else if ( armor != null )
isExceptional = armor.Quality == ArmorQuality.Exceptional;
else
isExceptional = clothing.Quality == ClothingQuality.Exceptional;
if (m_Material >= BulkMaterialType.DullCopper && m_Material <= BulkMaterialType.Valorite &&
material != m_Material)
{
from.SendLocalizedMessage(1045168); // The item is not made from the requested ore.
}
else if (m_Material >= BulkMaterialType.Spined && m_Material <= BulkMaterialType.Barbed &&
material != m_Material)
{
from.SendLocalizedMessage(1049352); // The item is not made from the requested leather type.
}
else
{
bool isExceptional;
if ( m_RequireExceptional && !isExceptional )
{
from.SendLocalizedMessage( 1045167 ); // The item must be exceptional.
}
else
{
item.Delete();
++AmountCur;
if (item is BaseWeapon weapon)
isExceptional = weapon.Quality == WeaponQuality.Exceptional;
else if (armor != null)
isExceptional = armor.Quality == ArmorQuality.Exceptional;
else
isExceptional = clothing.Quality == ClothingQuality.Exceptional;
from.SendLocalizedMessage( 1045170 ); // The item has been combined with the deed.
if (m_RequireExceptional && !isExceptional)
{
from.SendLocalizedMessage(1045167); // The item must be exceptional.
}
else
{
item.Delete();
++AmountCur;
from.SendGump( new SmallBODGump( from, this ) );
from.SendLocalizedMessage(1045170); // The item has been combined with the deed.
if ( m_AmountCur < m_AmountMax )
BeginCombine( from );
}
}
}
}
else
{
from.SendLocalizedMessage( 1045158 ); // You must have the item in your backpack to target it.
}
}
from.SendGump(new SmallBODGump(from, this));
public SmallBOD( Serial serial ) : base( serial )
{
}
if (m_AmountCur < m_AmountMax)
BeginCombine(from);
}
}
}
}
else
{
from.SendLocalizedMessage(1045158); // You must have the item in your backpack to target it.
}
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write( (int) 0 ); // version
writer.Write(0); // version
writer.Write( m_AmountCur );
writer.Write( m_AmountMax );
writer.Write( Type == null ? null : Type.FullName );
writer.Write( m_Number );
writer.Write( Graphic );
writer.Write( m_RequireExceptional );
writer.Write( (int) m_Material );
}
writer.Write(m_AmountCur);
writer.Write(m_AmountMax);
writer.Write(Type == null ? null : Type.FullName);
writer.Write(m_Number);
writer.Write(Graphic);
writer.Write(m_RequireExceptional);
writer.Write((int)m_Material);
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
int version = reader.ReadInt();
switch ( version )
{
case 0:
{
m_AmountCur = reader.ReadInt();
m_AmountMax = reader.ReadInt();
switch (version)
{
case 0:
{
m_AmountCur = reader.ReadInt();
m_AmountMax = reader.ReadInt();
string type = reader.ReadString();
string type = reader.ReadString();
if ( type != null )
Type = ScriptCompiler.FindTypeByFullName( type );
if (type != null)
Type = ScriptCompiler.FindTypeByFullName(type);
m_Number = reader.ReadInt();
Graphic = reader.ReadInt();
m_RequireExceptional = reader.ReadBool();
m_Material = (BulkMaterialType)reader.ReadInt();
m_Number = reader.ReadInt();
Graphic = reader.ReadInt();
m_RequireExceptional = reader.ReadBool();
m_Material = (BulkMaterialType)reader.ReadInt();
break;
}
}
break;
}
}
if ( Weight == 0.0 )
Weight = 1.0;
if (Weight == 0.0)
Weight = 1.0;
if ( Core.AOS && ItemID == 0x14EF )
ItemID = 0x2258;
if (Core.AOS && ItemID == 0x14EF)
ItemID = 0x2258;
if ( Parent == null && Map == Map.Internal && Location == Point3D.Zero )
Delete();
}
}
}
if (Parent == null && Map == Map.Internal && Location == Point3D.Zero)
Delete();
}
}
}

View file

@ -3,89 +3,91 @@ using Server.Network;
namespace Server.Engines.BulkOrders
{
public class SmallBODAcceptGump : Gump
{
private SmallBOD m_Deed;
private Mobile m_From;
public class SmallBODAcceptGump : Gump
{
private SmallBOD m_Deed;
private Mobile m_From;
public SmallBODAcceptGump( Mobile from, SmallBOD deed ) : base( 50, 50 )
{
m_From = from;
m_Deed = deed;
public SmallBODAcceptGump(Mobile from, SmallBOD deed) : base(50, 50)
{
m_From = from;
m_Deed = deed;
m_From.CloseGump( typeof( LargeBODAcceptGump ) );
m_From.CloseGump( typeof( SmallBODAcceptGump ) );
m_From.CloseGump(typeof(LargeBODAcceptGump));
m_From.CloseGump(typeof(SmallBODAcceptGump));
AddPage( 0 );
AddPage(0);
AddBackground( 25, 10, 430, 264, 5054 );
AddBackground(25, 10, 430, 264, 5054);
AddImageTiled( 33, 20, 413, 245, 2624 );
AddAlphaRegion( 33, 20, 413, 245 );
AddImageTiled(33, 20, 413, 245, 2624);
AddAlphaRegion(33, 20, 413, 245);
AddImage( 20, 5, 10460 );
AddImage( 430, 5, 10460 );
AddImage( 20, 249, 10460 );
AddImage( 430, 249, 10460 );
AddImage(20, 5, 10460);
AddImage(430, 5, 10460);
AddImage(20, 249, 10460);
AddImage(430, 249, 10460);
AddHtmlLocalized( 190, 25, 120, 20, 1045133, 0x7FFF, false, false ); // A bulk order
AddHtmlLocalized( 40, 48, 350, 20, 1045135, 0x7FFF, false, false ); // Ah! Thanks for the goods! Would you help me out?
AddHtmlLocalized(190, 25, 120, 20, 1045133, 0x7FFF, false, false); // A bulk order
AddHtmlLocalized(40, 48, 350, 20, 1045135, 0x7FFF, false,
false); // Ah! Thanks for the goods! Would you help me out?
AddHtmlLocalized( 40, 72, 210, 20, 1045138, 0x7FFF, false, false ); // Amount to make:
AddLabel( 250, 72, 1152, deed.AmountMax.ToString() );
AddHtmlLocalized(40, 72, 210, 20, 1045138, 0x7FFF, false, false); // Amount to make:
AddLabel(250, 72, 1152, deed.AmountMax.ToString());
AddHtmlLocalized( 40, 96, 120, 20, 1045136, 0x7FFF, false, false ); // Item requested:
AddItem( 385, 96, deed.Graphic );
AddHtmlLocalized( 40, 120, 210, 20, deed.Number, 0xFFFFFF, false, false );
AddHtmlLocalized(40, 96, 120, 20, 1045136, 0x7FFF, false, false); // Item requested:
AddItem(385, 96, deed.Graphic);
AddHtmlLocalized(40, 120, 210, 20, deed.Number, 0xFFFFFF, false, false);
if ( deed.RequireExceptional || deed.Material != BulkMaterialType.None )
{
AddHtmlLocalized( 40, 144, 210, 20, 1045140, 0x7FFF, false, false ); // Special requirements to meet:
if (deed.RequireExceptional || deed.Material != BulkMaterialType.None)
{
AddHtmlLocalized(40, 144, 210, 20, 1045140, 0x7FFF, false, false); // Special requirements to meet:
if ( deed.RequireExceptional )
AddHtmlLocalized( 40, 168, 350, 20, 1045141, 0x7FFF, false, false ); // All items must be exceptional.
if (deed.RequireExceptional)
AddHtmlLocalized(40, 168, 350, 20, 1045141, 0x7FFF, false, false); // All items must be exceptional.
if ( deed.Material != BulkMaterialType.None )
AddHtmlLocalized( 40, deed.RequireExceptional ? 192 : 168, 350, 20, GetMaterialNumberFor( deed.Material ), 0x7FFF, false, false ); // All items must be made with x material.
}
if (deed.Material != BulkMaterialType.None)
AddHtmlLocalized(40, deed.RequireExceptional ? 192 : 168, 350, 20, GetMaterialNumberFor(deed.Material),
0x7FFF, false, false); // All items must be made with x material.
}
AddHtmlLocalized( 40, 216, 350, 20, 1045139, 0x7FFF, false, false ); // Do you want to accept this order?
AddHtmlLocalized(40, 216, 350, 20, 1045139, 0x7FFF, false, false); // Do you want to accept this order?
AddButton( 100, 240, 4005, 4007, 1, GumpButtonType.Reply, 0 );
AddHtmlLocalized( 135, 240, 120, 20, 1006044, 0x7FFF, false, false ); // Ok
AddButton(100, 240, 4005, 4007, 1, GumpButtonType.Reply, 0);
AddHtmlLocalized(135, 240, 120, 20, 1006044, 0x7FFF, false, false); // Ok
AddButton( 275, 240, 4005, 4007, 0, GumpButtonType.Reply, 0 );
AddHtmlLocalized( 310, 240, 120, 20, 1011012, 0x7FFF, false, false ); // CANCEL
}
AddButton(275, 240, 4005, 4007, 0, GumpButtonType.Reply, 0);
AddHtmlLocalized(310, 240, 120, 20, 1011012, 0x7FFF, false, false); // CANCEL
}
public override void OnResponse( NetState sender, RelayInfo info )
{
if ( info.ButtonID == 1 ) // Ok
{
if ( m_From.PlaceInBackpack( m_Deed ) )
{
m_From.SendLocalizedMessage( 1045152 ); // The bulk order deed has been placed in your backpack.
}
else
{
m_From.SendLocalizedMessage( 1045150 ); // There is not enough room in your backpack for the deed.
m_Deed.Delete();
}
}
else
{
m_Deed.Delete();
}
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (info.ButtonID == 1) // Ok
{
if (m_From.PlaceInBackpack(m_Deed))
{
m_From.SendLocalizedMessage(1045152); // The bulk order deed has been placed in your backpack.
}
else
{
m_From.SendLocalizedMessage(1045150); // There is not enough room in your backpack for the deed.
m_Deed.Delete();
}
}
else
{
m_Deed.Delete();
}
}
public static int GetMaterialNumberFor( BulkMaterialType material )
{
if ( material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Valorite )
return 1045142 + (int)(material - BulkMaterialType.DullCopper);
if ( material >= BulkMaterialType.Spined && material <= BulkMaterialType.Barbed )
return 1049348 + (int)(material - BulkMaterialType.Spined);
public static int GetMaterialNumberFor(BulkMaterialType material)
{
if (material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Valorite)
return 1045142 + (material - BulkMaterialType.DullCopper);
if (material >= BulkMaterialType.Spined && material <= BulkMaterialType.Barbed)
return 1049348 + (material - BulkMaterialType.Spined);
return 0;
}
}
return 0;
}
}
}

View file

@ -3,79 +3,80 @@ using Server.Network;
namespace Server.Engines.BulkOrders
{
public class SmallBODGump : Gump
{
private SmallBOD m_Deed;
private Mobile m_From;
public class SmallBODGump : Gump
{
private SmallBOD m_Deed;
private Mobile m_From;
public SmallBODGump( Mobile from, SmallBOD deed ) : base( 25, 25 )
{
m_From = from;
m_Deed = deed;
public SmallBODGump(Mobile from, SmallBOD deed) : base(25, 25)
{
m_From = from;
m_Deed = deed;
m_From.CloseGump( typeof( LargeBODGump ) );
m_From.CloseGump( typeof( SmallBODGump ) );
m_From.CloseGump(typeof(LargeBODGump));
m_From.CloseGump(typeof(SmallBODGump));
AddPage( 0 );
AddPage(0);
AddBackground( 50, 10, 455, 260, 5054 );
AddImageTiled( 58, 20, 438, 241, 2624 );
AddAlphaRegion( 58, 20, 438, 241 );
AddBackground(50, 10, 455, 260, 5054);
AddImageTiled(58, 20, 438, 241, 2624);
AddAlphaRegion(58, 20, 438, 241);
AddImage( 45, 5, 10460 );
AddImage( 480, 5, 10460 );
AddImage( 45, 245, 10460 );
AddImage( 480, 245, 10460 );
AddImage(45, 5, 10460);
AddImage(480, 5, 10460);
AddImage(45, 245, 10460);
AddImage(480, 245, 10460);
AddHtmlLocalized( 225, 25, 120, 20, 1045133, 0x7FFF, false, false ); // A bulk order
AddHtmlLocalized(225, 25, 120, 20, 1045133, 0x7FFF, false, false); // A bulk order
AddHtmlLocalized( 75, 48, 250, 20, 1045138, 0x7FFF, false, false ); // Amount to make:
AddLabel( 275, 48, 1152, deed.AmountMax.ToString() );
AddHtmlLocalized(75, 48, 250, 20, 1045138, 0x7FFF, false, false); // Amount to make:
AddLabel(275, 48, 1152, deed.AmountMax.ToString());
AddHtmlLocalized( 275, 76, 200, 20, 1045153, 0x7FFF, false, false ); // Amount finished:
AddHtmlLocalized( 75, 72, 120, 20, 1045136, 0x7FFF, false, false ); // Item requested:
AddHtmlLocalized(275, 76, 200, 20, 1045153, 0x7FFF, false, false); // Amount finished:
AddHtmlLocalized(75, 72, 120, 20, 1045136, 0x7FFF, false, false); // Item requested:
AddItem( 410, 72, deed.Graphic );
AddItem(410, 72, deed.Graphic);
AddHtmlLocalized( 75, 96, 210, 20, deed.Number, 0x7FFF, false, false );
AddLabel( 275, 96, 0x480, deed.AmountCur.ToString() );
AddHtmlLocalized(75, 96, 210, 20, deed.Number, 0x7FFF, false, false);
AddLabel(275, 96, 0x480, deed.AmountCur.ToString());
if ( deed.RequireExceptional || deed.Material != BulkMaterialType.None )
AddHtmlLocalized( 75, 120, 200, 20, 1045140, 0x7FFF, false, false ); // Special requirements to meet:
if (deed.RequireExceptional || deed.Material != BulkMaterialType.None)
AddHtmlLocalized(75, 120, 200, 20, 1045140, 0x7FFF, false, false); // Special requirements to meet:
if ( deed.RequireExceptional )
AddHtmlLocalized( 75, 144, 300, 20, 1045141, 0x7FFF, false, false ); // All items must be exceptional.
if (deed.RequireExceptional)
AddHtmlLocalized(75, 144, 300, 20, 1045141, 0x7FFF, false, false); // All items must be exceptional.
if ( deed.Material != BulkMaterialType.None )
AddHtmlLocalized( 75, deed.RequireExceptional ? 168 : 144, 300, 20, GetMaterialNumberFor( deed.Material ), 0x7FFF, false, false ); // All items must be made with x material.
if (deed.Material != BulkMaterialType.None)
AddHtmlLocalized(75, deed.RequireExceptional ? 168 : 144, 300, 20, GetMaterialNumberFor(deed.Material),
0x7FFF, false, false); // All items must be made with x material.
AddButton( 125, 192, 4005, 4007, 2, GumpButtonType.Reply, 0 );
AddHtmlLocalized( 160, 192, 300, 20, 1045154, 0x7FFF, false, false ); // Combine this deed with the item requested.
AddButton(125, 192, 4005, 4007, 2, GumpButtonType.Reply, 0);
AddHtmlLocalized(160, 192, 300, 20, 1045154, 0x7FFF, false, false); // Combine this deed with the item requested.
AddButton( 125, 216, 4005, 4007, 1, GumpButtonType.Reply, 0 );
AddHtmlLocalized( 160, 216, 120, 20, 1011441, 0x7FFF, false, false ); // EXIT
}
AddButton(125, 216, 4005, 4007, 1, GumpButtonType.Reply, 0);
AddHtmlLocalized(160, 216, 120, 20, 1011441, 0x7FFF, false, false); // EXIT
}
public override void OnResponse( NetState sender, RelayInfo info )
{
if ( m_Deed.Deleted || !m_Deed.IsChildOf( m_From.Backpack ) )
return;
public override void OnResponse(NetState sender, RelayInfo info)
{
if (m_Deed.Deleted || !m_Deed.IsChildOf(m_From.Backpack))
return;
if ( info.ButtonID == 2 ) // Combine
{
m_From.SendGump( new SmallBODGump( m_From, m_Deed ) );
m_Deed.BeginCombine( m_From );
}
}
if (info.ButtonID == 2) // Combine
{
m_From.SendGump(new SmallBODGump(m_From, m_Deed));
m_Deed.BeginCombine(m_From);
}
}
public static int GetMaterialNumberFor( BulkMaterialType material )
{
if ( material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Valorite )
return 1045142 + (int)(material - BulkMaterialType.DullCopper);
if ( material >= BulkMaterialType.Spined && material <= BulkMaterialType.Barbed )
return 1049348 + (int)(material - BulkMaterialType.Spined);
public static int GetMaterialNumberFor(BulkMaterialType material)
{
if (material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Valorite)
return 1045142 + (material - BulkMaterialType.DullCopper);
if (material >= BulkMaterialType.Spined && material <= BulkMaterialType.Barbed)
return 1049348 + (material - BulkMaterialType.Spined);
return 0;
}
}
return 0;
}
}
}

View file

@ -2,21 +2,21 @@ using Server.Targeting;
namespace Server.Engines.BulkOrders
{
public class SmallBODTarget : Target
{
private SmallBOD m_Deed;
public class SmallBODTarget : Target
{
private SmallBOD m_Deed;
public SmallBODTarget( SmallBOD deed ) : base( 18, false, TargetFlags.None )
{
m_Deed = deed;
}
public SmallBODTarget(SmallBOD deed) : base(18, false, TargetFlags.None)
{
m_Deed = deed;
}
protected override void OnTarget( Mobile from, object targeted )
{
if ( m_Deed.Deleted || !m_Deed.IsChildOf( from.Backpack ) )
return;
protected override void OnTarget(Mobile from, object targeted)
{
if (m_Deed.Deleted || !m_Deed.IsChildOf(from.Backpack))
return;
m_Deed.EndCombine( from, targeted );
}
}
m_Deed.EndCombine(from, targeted);
}
}
}

View file

@ -5,234 +5,257 @@ using Mat = Server.Engines.BulkOrders.BulkMaterialType;
namespace Server.Engines.BulkOrders
{
[TypeAlias( "Scripts.Engines.BulkOrders.SmallSmithBOD" )]
public class SmallSmithBOD : SmallBOD
{
public static double[] m_BlacksmithMaterialChances = {
0.501953125, // None
0.250000000, // Dull Copper
0.125000000, // Shadow Iron
0.062500000, // Copper
0.031250000, // Bronze
0.015625000, // Gold
0.007812500, // Agapite
0.003906250, // Verite
0.001953125 // Valorite
};
[TypeAlias("Scripts.Engines.BulkOrders.SmallSmithBOD")]
public class SmallSmithBOD : SmallBOD
{
public static double[] m_BlacksmithMaterialChances =
{
0.501953125, // None
0.250000000, // Dull Copper
0.125000000, // Shadow Iron
0.062500000, // Copper
0.031250000, // Bronze
0.015625000, // Gold
0.007812500, // Agapite
0.003906250, // Verite
0.001953125 // Valorite
};
public override int ComputeFame()
{
return SmithRewardCalculator.Instance.ComputeFame( this );
}
private SmallSmithBOD(SmallBulkEntry entry, BulkMaterialType material, int amountMax, bool reqExceptional)
{
Hue = 0x44E;
AmountMax = amountMax;
Type = entry.Type;
Number = entry.Number;
Graphic = entry.Graphic;
RequireExceptional = reqExceptional;
Material = material;
}
public override int ComputeGold()
{
return SmithRewardCalculator.Instance.ComputeGold( this );
}
[Constructible]
public SmallSmithBOD()
{
SmallBulkEntry[] entries;
bool useMaterials;
public override List<Item> ComputeRewards( bool full )
{
List<Item> list = new List<Item>();
if (useMaterials = Utility.RandomBool())
entries = SmallBulkEntry.BlacksmithArmor;
else
entries = SmallBulkEntry.BlacksmithWeapons;
RewardGroup rewardGroup = SmithRewardCalculator.Instance.LookupRewards( SmithRewardCalculator.Instance.ComputePoints( this ) );
if (entries.Length > 0)
{
int hue = 0x44E;
int amountMax = Utility.RandomList(10, 15, 20);
if ( rewardGroup != null )
{
if ( full )
{
for ( int i = 0; i < rewardGroup.Items.Length; ++i )
{
Item item = rewardGroup.Items[i].Construct();
BulkMaterialType material;
if ( item != null )
list.Add( item );
}
}
else
{
RewardItem rewardItem = rewardGroup.AcquireItem();
if (useMaterials)
material = GetRandomMaterial(BulkMaterialType.DullCopper, m_BlacksmithMaterialChances);
else
material = BulkMaterialType.None;
Item item = rewardItem?.Construct();
bool reqExceptional = Utility.RandomBool() || material == BulkMaterialType.None;
if ( item != null )
list.Add( item );
}
}
SmallBulkEntry entry = entries[Utility.Random(entries.Length)];
return list;
}
Hue = hue;
AmountMax = amountMax;
Type = entry.Type;
Number = entry.Number;
Graphic = entry.Graphic;
RequireExceptional = reqExceptional;
Material = material;
}
}
public static SmallSmithBOD CreateRandomFor( Mobile m )
{
SmallBulkEntry[] entries;
bool useMaterials;
public SmallSmithBOD(int amountCur, int amountMax, Type type, int number, int graphic, bool reqExceptional,
BulkMaterialType mat)
{
Hue = 0x44E;
AmountMax = amountMax;
AmountCur = amountCur;
Type = type;
Number = number;
Graphic = graphic;
RequireExceptional = reqExceptional;
Material = mat;
}
if ( useMaterials = Utility.RandomBool() )
entries = SmallBulkEntry.BlacksmithArmor;
else
entries = SmallBulkEntry.BlacksmithWeapons;
public SmallSmithBOD(Serial serial) : base(serial)
{
}
if ( entries.Length > 0 )
{
double theirSkill = m.Skills[SkillName.Blacksmith].Base;
int amountMax;
public override int ComputeFame()
{
return SmithRewardCalculator.Instance.ComputeFame(this);
}
if ( theirSkill >= 70.1 )
amountMax = Utility.RandomList( 10, 15, 20, 20 );
else if ( theirSkill >= 50.1 )
amountMax = Utility.RandomList( 10, 15, 15, 20 );
else
amountMax = Utility.RandomList( 10, 10, 15, 20 );
public override int ComputeGold()
{
return SmithRewardCalculator.Instance.ComputeGold(this);
}
BulkMaterialType material = BulkMaterialType.None;
public override List<Item> ComputeRewards(bool full)
{
List<Item> list = new List<Item>();
if ( useMaterials && theirSkill >= 70.1 )
{
for ( int i = 0; i < 20; ++i )
{
BulkMaterialType check = GetRandomMaterial( BulkMaterialType.DullCopper, m_BlacksmithMaterialChances );
double skillReq = 0.0;
RewardGroup rewardGroup =
SmithRewardCalculator.Instance.LookupRewards(SmithRewardCalculator.Instance.ComputePoints(this));
switch ( check )
{
case BulkMaterialType.DullCopper: skillReq = 65.0; break;
case BulkMaterialType.ShadowIron: skillReq = 70.0; break;
case BulkMaterialType.Copper: skillReq = 75.0; break;
case BulkMaterialType.Bronze: skillReq = 80.0; break;
case BulkMaterialType.Gold: skillReq = 85.0; break;
case BulkMaterialType.Agapite: skillReq = 90.0; break;
case BulkMaterialType.Verite: skillReq = 95.0; break;
case BulkMaterialType.Valorite: skillReq = 100.0; break;
case BulkMaterialType.Spined: skillReq = 65.0; break;
case BulkMaterialType.Horned: skillReq = 80.0; break;
case BulkMaterialType.Barbed: skillReq = 99.0; break;
}
if (rewardGroup != null)
{
if (full)
{
for (int i = 0; i < rewardGroup.Items.Length; ++i)
{
Item item = rewardGroup.Items[i].Construct();
if ( theirSkill >= skillReq )
{
material = check;
break;
}
}
}
if (item != null)
list.Add(item);
}
}
else
{
RewardItem rewardItem = rewardGroup.AcquireItem();
double excChance = 0.0;
Item item = rewardItem?.Construct();
if ( theirSkill >= 70.1 )
excChance = (theirSkill + 80.0) / 200.0;
if (item != null)
list.Add(item);
}
}
bool reqExceptional = ( excChance > Utility.RandomDouble() );
return list;
}
CraftSystem system = DefBlacksmithy.CraftSystem;
public static SmallSmithBOD CreateRandomFor(Mobile m)
{
SmallBulkEntry[] entries;
bool useMaterials;
List<SmallBulkEntry> validEntries = new List<SmallBulkEntry>();
if (useMaterials = Utility.RandomBool())
entries = SmallBulkEntry.BlacksmithArmor;
else
entries = SmallBulkEntry.BlacksmithWeapons;
for ( int i = 0; i < entries.Length; ++i )
{
CraftItem item = system.CraftItems.SearchFor( entries[i].Type );
if (entries.Length > 0)
{
double theirSkill = m.Skills[SkillName.Blacksmith].Base;
int amountMax;
if ( item != null )
{
bool allRequiredSkills = true;
double chance = item.GetSuccessChance( m, null, system, false, ref allRequiredSkills );
if (theirSkill >= 70.1)
amountMax = Utility.RandomList(10, 15, 20, 20);
else if (theirSkill >= 50.1)
amountMax = Utility.RandomList(10, 15, 15, 20);
else
amountMax = Utility.RandomList(10, 10, 15, 20);
if ( allRequiredSkills && chance >= 0.0 )
{
if ( reqExceptional )
chance = item.GetExceptionalChance( system, chance, m );
BulkMaterialType material = BulkMaterialType.None;
if ( chance > 0.0 )
validEntries.Add( entries[i] );
}
}
}
if (useMaterials && theirSkill >= 70.1)
for (int i = 0; i < 20; ++i)
{
BulkMaterialType check = GetRandomMaterial(BulkMaterialType.DullCopper, m_BlacksmithMaterialChances);
double skillReq = 0.0;
if ( validEntries.Count > 0 )
{
SmallBulkEntry entry = validEntries[Utility.Random( validEntries.Count )];
return new SmallSmithBOD( entry, material, amountMax, reqExceptional );
}
}
switch (check)
{
case BulkMaterialType.DullCopper:
skillReq = 65.0;
break;
case BulkMaterialType.ShadowIron:
skillReq = 70.0;
break;
case BulkMaterialType.Copper:
skillReq = 75.0;
break;
case BulkMaterialType.Bronze:
skillReq = 80.0;
break;
case BulkMaterialType.Gold:
skillReq = 85.0;
break;
case BulkMaterialType.Agapite:
skillReq = 90.0;
break;
case BulkMaterialType.Verite:
skillReq = 95.0;
break;
case BulkMaterialType.Valorite:
skillReq = 100.0;
break;
case BulkMaterialType.Spined:
skillReq = 65.0;
break;
case BulkMaterialType.Horned:
skillReq = 80.0;
break;
case BulkMaterialType.Barbed:
skillReq = 99.0;
break;
}
return null;
}
if (theirSkill >= skillReq)
{
material = check;
break;
}
}
private SmallSmithBOD( SmallBulkEntry entry, BulkMaterialType material, int amountMax, bool reqExceptional )
{
Hue = 0x44E;
AmountMax = amountMax;
Type = entry.Type;
Number = entry.Number;
Graphic = entry.Graphic;
RequireExceptional = reqExceptional;
Material = material;
}
double excChance = 0.0;
[Constructible]
public SmallSmithBOD()
{
SmallBulkEntry[] entries;
bool useMaterials;
if (theirSkill >= 70.1)
excChance = (theirSkill + 80.0) / 200.0;
if ( useMaterials = Utility.RandomBool() )
entries = SmallBulkEntry.BlacksmithArmor;
else
entries = SmallBulkEntry.BlacksmithWeapons;
bool reqExceptional = excChance > Utility.RandomDouble();
if ( entries.Length > 0 )
{
int hue = 0x44E;
int amountMax = Utility.RandomList( 10, 15, 20 );
CraftSystem system = DefBlacksmithy.CraftSystem;
BulkMaterialType material;
List<SmallBulkEntry> validEntries = new List<SmallBulkEntry>();
if ( useMaterials )
material = GetRandomMaterial( BulkMaterialType.DullCopper, m_BlacksmithMaterialChances );
else
material = BulkMaterialType.None;
for (int i = 0; i < entries.Length; ++i)
{
CraftItem item = system.CraftItems.SearchFor(entries[i].Type);
bool reqExceptional = Utility.RandomBool() || (material == BulkMaterialType.None);
if (item != null)
{
bool allRequiredSkills = true;
double chance = item.GetSuccessChance(m, null, system, false, ref allRequiredSkills);
SmallBulkEntry entry = entries[Utility.Random( entries.Length )];
if (allRequiredSkills && chance >= 0.0)
{
if (reqExceptional)
chance = item.GetExceptionalChance(system, chance, m);
Hue = hue;
AmountMax = amountMax;
Type = entry.Type;
Number = entry.Number;
Graphic = entry.Graphic;
RequireExceptional = reqExceptional;
Material = material;
}
}
if (chance > 0.0)
validEntries.Add(entries[i]);
}
}
}
public SmallSmithBOD( int amountCur, int amountMax, Type type, int number, int graphic, bool reqExceptional, BulkMaterialType mat )
{
Hue = 0x44E;
AmountMax = amountMax;
AmountCur = amountCur;
Type = type;
Number = number;
Graphic = graphic;
RequireExceptional = reqExceptional;
Material = mat;
}
if (validEntries.Count > 0)
{
SmallBulkEntry entry = validEntries[Utility.Random(validEntries.Count)];
return new SmallSmithBOD(entry, material, amountMax, reqExceptional);
}
}
public SmallSmithBOD( Serial serial ) : base( serial )
{
}
return null;
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write( (int) 0 ); // version
}
writer.Write(0); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
int version = reader.ReadInt();
}
}
}

View file

@ -4,227 +4,247 @@ using Server.Engines.Craft;
namespace Server.Engines.BulkOrders
{
public class SmallTailorBOD : SmallBOD
{
public static double[] m_TailoringMaterialChances = {
0.857421875, // None
0.125000000, // Spined
0.015625000, // Horned
0.001953125 // Barbed
};
public class SmallTailorBOD : SmallBOD
{
public static double[] m_TailoringMaterialChances =
{
0.857421875, // None
0.125000000, // Spined
0.015625000, // Horned
0.001953125 // Barbed
};
public override int ComputeFame()
{
return TailorRewardCalculator.Instance.ComputeFame( this );
}
private SmallTailorBOD(SmallBulkEntry entry, BulkMaterialType material, int amountMax, bool reqExceptional)
{
Hue = 0x483;
AmountMax = amountMax;
Type = entry.Type;
Number = entry.Number;
Graphic = entry.Graphic;
RequireExceptional = reqExceptional;
Material = material;
}
public override int ComputeGold()
{
return TailorRewardCalculator.Instance.ComputeGold( this );
}
[Constructible]
public SmallTailorBOD()
{
SmallBulkEntry[] entries;
bool useMaterials;
public override List<Item> ComputeRewards( bool full )
{
List<Item> list = new List<Item>();
if (useMaterials = Utility.RandomBool())
entries = SmallBulkEntry.TailorLeather;
else
entries = SmallBulkEntry.TailorCloth;
RewardGroup rewardGroup = TailorRewardCalculator.Instance.LookupRewards( TailorRewardCalculator.Instance.ComputePoints( this ) );
if (entries.Length > 0)
{
int hue = 0x483;
int amountMax = Utility.RandomList(10, 15, 20);
if ( rewardGroup != null )
{
if ( full )
{
for ( int i = 0; i < rewardGroup.Items.Length; ++i )
{
Item item = rewardGroup.Items[i].Construct();
BulkMaterialType material;
if ( item != null )
list.Add( item );
}
}
else
{
RewardItem rewardItem = rewardGroup.AcquireItem();
if (useMaterials)
material = GetRandomMaterial(BulkMaterialType.Spined, m_TailoringMaterialChances);
else
material = BulkMaterialType.None;
Item item = rewardItem?.Construct();
bool reqExceptional = Utility.RandomBool() || material == BulkMaterialType.None;
if ( item != null )
list.Add( item );
}
}
SmallBulkEntry entry = entries[Utility.Random(entries.Length)];
return list;
}
Hue = hue;
AmountMax = amountMax;
Type = entry.Type;
Number = entry.Number;
Graphic = entry.Graphic;
RequireExceptional = reqExceptional;
Material = material;
}
}
public static SmallTailorBOD CreateRandomFor( Mobile m )
{
SmallBulkEntry[] entries;
bool useMaterials = Utility.RandomBool();
public SmallTailorBOD(int amountCur, int amountMax, Type type, int number, int graphic, bool reqExceptional,
BulkMaterialType mat)
{
Hue = 0x483;
AmountMax = amountMax;
AmountCur = amountCur;
Type = type;
Number = number;
Graphic = graphic;
RequireExceptional = reqExceptional;
Material = mat;
}
double theirSkill = m.Skills[SkillName.Tailoring].Base;
if ( useMaterials && theirSkill >= 6.2 ) // Ugly, but the easiest leather BOD is Leather Cap which requires at least 6.2 skill.
entries = SmallBulkEntry.TailorLeather;
else
entries = SmallBulkEntry.TailorCloth;
public SmallTailorBOD(Serial serial) : base(serial)
{
}
if ( entries.Length > 0 )
{
int amountMax;
public override int ComputeFame()
{
return TailorRewardCalculator.Instance.ComputeFame(this);
}
if ( theirSkill >= 70.1 )
amountMax = Utility.RandomList( 10, 15, 20, 20 );
else if ( theirSkill >= 50.1 )
amountMax = Utility.RandomList( 10, 15, 15, 20 );
else
amountMax = Utility.RandomList( 10, 10, 15, 20 );
public override int ComputeGold()
{
return TailorRewardCalculator.Instance.ComputeGold(this);
}
BulkMaterialType material = BulkMaterialType.None;
public override List<Item> ComputeRewards(bool full)
{
List<Item> list = new List<Item>();
if ( useMaterials && theirSkill >= 70.1 )
{
for ( int i = 0; i < 20; ++i )
{
BulkMaterialType check = GetRandomMaterial( BulkMaterialType.Spined, m_TailoringMaterialChances );
double skillReq = 0.0;
RewardGroup rewardGroup =
TailorRewardCalculator.Instance.LookupRewards(TailorRewardCalculator.Instance.ComputePoints(this));
switch ( check )
{
case BulkMaterialType.DullCopper: skillReq = 65.0; break;
case BulkMaterialType.Bronze: skillReq = 80.0; break;
case BulkMaterialType.Gold: skillReq = 85.0; break;
case BulkMaterialType.Agapite: skillReq = 90.0; break;
case BulkMaterialType.Verite: skillReq = 95.0; break;
case BulkMaterialType.Valorite: skillReq = 100.0; break;
case BulkMaterialType.Spined: skillReq = 65.0; break;
case BulkMaterialType.Horned: skillReq = 80.0; break;
case BulkMaterialType.Barbed: skillReq = 99.0; break;
}
if (rewardGroup != null)
{
if (full)
{
for (int i = 0; i < rewardGroup.Items.Length; ++i)
{
Item item = rewardGroup.Items[i].Construct();
if ( theirSkill >= skillReq )
{
material = check;
break;
}
}
}
if (item != null)
list.Add(item);
}
}
else
{
RewardItem rewardItem = rewardGroup.AcquireItem();
double excChance = 0.0;
Item item = rewardItem?.Construct();
if ( theirSkill >= 70.1 )
excChance = (theirSkill + 80.0) / 200.0;
if (item != null)
list.Add(item);
}
}
bool reqExceptional = ( excChance > Utility.RandomDouble() );
return list;
}
public static SmallTailorBOD CreateRandomFor(Mobile m)
{
SmallBulkEntry[] entries;
bool useMaterials = Utility.RandomBool();
double theirSkill = m.Skills[SkillName.Tailoring].Base;
if (useMaterials && theirSkill >= 6.2
) // Ugly, but the easiest leather BOD is Leather Cap which requires at least 6.2 skill.
entries = SmallBulkEntry.TailorLeather;
else
entries = SmallBulkEntry.TailorCloth;
if (entries.Length > 0)
{
int amountMax;
if (theirSkill >= 70.1)
amountMax = Utility.RandomList(10, 15, 20, 20);
else if (theirSkill >= 50.1)
amountMax = Utility.RandomList(10, 15, 15, 20);
else
amountMax = Utility.RandomList(10, 10, 15, 20);
BulkMaterialType material = BulkMaterialType.None;
if (useMaterials && theirSkill >= 70.1)
for (int i = 0; i < 20; ++i)
{
BulkMaterialType check = GetRandomMaterial(BulkMaterialType.Spined, m_TailoringMaterialChances);
double skillReq = 0.0;
switch (check)
{
case BulkMaterialType.DullCopper:
skillReq = 65.0;
break;
case BulkMaterialType.Bronze:
skillReq = 80.0;
break;
case BulkMaterialType.Gold:
skillReq = 85.0;
break;
case BulkMaterialType.Agapite:
skillReq = 90.0;
break;
case BulkMaterialType.Verite:
skillReq = 95.0;
break;
case BulkMaterialType.Valorite:
skillReq = 100.0;
break;
case BulkMaterialType.Spined:
skillReq = 65.0;
break;
case BulkMaterialType.Horned:
skillReq = 80.0;
break;
case BulkMaterialType.Barbed:
skillReq = 99.0;
break;
}
if (theirSkill >= skillReq)
{
material = check;
break;
}
}
double excChance = 0.0;
if (theirSkill >= 70.1)
excChance = (theirSkill + 80.0) / 200.0;
bool reqExceptional = excChance > Utility.RandomDouble();
CraftSystem system = DefTailoring.CraftSystem;
CraftSystem system = DefTailoring.CraftSystem;
List<SmallBulkEntry> validEntries = new List<SmallBulkEntry>();
List<SmallBulkEntry> validEntries = new List<SmallBulkEntry>();
for ( int i = 0; i < entries.Length; ++i )
{
CraftItem item = system.CraftItems.SearchFor( entries[i].Type );
for (int i = 0; i < entries.Length; ++i)
{
CraftItem item = system.CraftItems.SearchFor(entries[i].Type);
if ( item != null )
{
bool allRequiredSkills = true;
double chance = item.GetSuccessChance( m, null, system, false, ref allRequiredSkills );
if (item != null)
{
bool allRequiredSkills = true;
double chance = item.GetSuccessChance(m, null, system, false, ref allRequiredSkills);
if ( allRequiredSkills && chance >= 0.0 )
{
if ( reqExceptional )
chance = item.GetExceptionalChance( system, chance, m );
if (allRequiredSkills && chance >= 0.0)
{
if (reqExceptional)
chance = item.GetExceptionalChance(system, chance, m);
if ( chance > 0.0 )
validEntries.Add( entries[i] );
}
}
}
if (chance > 0.0)
validEntries.Add(entries[i]);
}
}
}
if ( validEntries.Count > 0 )
{
SmallBulkEntry entry = validEntries[Utility.Random( validEntries.Count )];
return new SmallTailorBOD( entry, material, amountMax, reqExceptional );
}
}
if (validEntries.Count > 0)
{
SmallBulkEntry entry = validEntries[Utility.Random(validEntries.Count)];
return new SmallTailorBOD(entry, material, amountMax, reqExceptional);
}
}
return null;
}
return null;
}
private SmallTailorBOD( SmallBulkEntry entry, BulkMaterialType material, int amountMax, bool reqExceptional )
{
Hue = 0x483;
AmountMax = amountMax;
Type = entry.Type;
Number = entry.Number;
Graphic = entry.Graphic;
RequireExceptional = reqExceptional;
Material = material;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
[Constructible]
public SmallTailorBOD()
{
SmallBulkEntry[] entries;
bool useMaterials;
writer.Write(0); // version
}
if ( useMaterials = Utility.RandomBool() )
entries = SmallBulkEntry.TailorLeather;
else
entries = SmallBulkEntry.TailorCloth;
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
if ( entries.Length > 0 )
{
int hue = 0x483;
int amountMax = Utility.RandomList( 10, 15, 20 );
BulkMaterialType material;
if ( useMaterials )
material = GetRandomMaterial( BulkMaterialType.Spined, m_TailoringMaterialChances );
else
material = BulkMaterialType.None;
bool reqExceptional = Utility.RandomBool() || (material == BulkMaterialType.None);
SmallBulkEntry entry = entries[Utility.Random( entries.Length )];
Hue = hue;
AmountMax = amountMax;
Type = entry.Type;
Number = entry.Number;
Graphic = entry.Graphic;
RequireExceptional = reqExceptional;
Material = material;
}
}
public SmallTailorBOD( int amountCur, int amountMax, Type type, int number, int graphic, bool reqExceptional, BulkMaterialType mat )
{
Hue = 0x483;
AmountMax = amountMax;
AmountCur = amountCur;
Type = type;
Number = number;
Graphic = graphic;
RequireExceptional = reqExceptional;
Material = mat;
}
public SmallTailorBOD( Serial serial ) : base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int) 0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
}
}
int version = reader.ReadInt();
}
}
}

View file

@ -2,53 +2,53 @@ using Server.Items;
namespace Server.Engines.CannedEvil
{
public class ChampionAltar : PentagramAddon
{
private ChampionSpawn m_Spawn;
public class ChampionAltar : PentagramAddon
{
private ChampionSpawn m_Spawn;
public ChampionAltar( ChampionSpawn spawn )
{
m_Spawn = spawn;
}
public ChampionAltar(ChampionSpawn spawn)
{
m_Spawn = spawn;
}
public override void OnAfterDelete()
{
base.OnAfterDelete();
public ChampionAltar(Serial serial) : base(serial)
{
}
m_Spawn?.Delete();
}
public override void OnAfterDelete()
{
base.OnAfterDelete();
public ChampionAltar( Serial serial ) : base( serial )
{
}
m_Spawn?.Delete();
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write( (int) 0 ); // version
writer.Write(0); // version
writer.Write( m_Spawn );
}
writer.Write(m_Spawn);
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
int version = reader.ReadInt();
switch ( version )
{
case 0:
{
m_Spawn = reader.ReadItem() as ChampionSpawn;
switch (version)
{
case 0:
{
m_Spawn = reader.ReadItem() as ChampionSpawn;
if ( m_Spawn == null )
Delete();
if (m_Spawn == null)
Delete();
break;
}
}
}
}
break;
}
}
}
}
}

View file

@ -2,84 +2,84 @@ using Server.Items;
namespace Server.Engines.CannedEvil
{
public class ChampionPlatform : BaseAddon
{
private ChampionSpawn m_Spawn;
public class ChampionPlatform : BaseAddon
{
private ChampionSpawn m_Spawn;
public ChampionPlatform( ChampionSpawn spawn )
{
m_Spawn = spawn;
public ChampionPlatform(ChampionSpawn spawn)
{
m_Spawn = spawn;
for ( int x = -2; x <= 2; ++x )
for ( int y = -2; y <= 2; ++y )
AddComponent( 0x750, x, y, -5 );
for (int x = -2; x <= 2; ++x)
for (int y = -2; y <= 2; ++y)
AddComponent(0x750, x, y, -5);
for ( int x = -1; x <= 1; ++x )
for ( int y = -1; y <= 1; ++y )
AddComponent( 0x750, x, y, 0 );
for (int x = -1; x <= 1; ++x)
for (int y = -1; y <= 1; ++y)
AddComponent(0x750, x, y, 0);
for ( int i = -1; i <= 1; ++i )
{
AddComponent( 0x751, i, 2, 0 );
AddComponent( 0x752, 2, i, 0 );
for (int i = -1; i <= 1; ++i)
{
AddComponent(0x751, i, 2, 0);
AddComponent(0x752, 2, i, 0);
AddComponent( 0x753, i, -2, 0 );
AddComponent( 0x754, -2, i, 0 );
}
AddComponent(0x753, i, -2, 0);
AddComponent(0x754, -2, i, 0);
}
AddComponent( 0x759, -2, -2, 0 );
AddComponent( 0x75A, 2, 2, 0 );
AddComponent( 0x75B, -2, 2, 0 );
AddComponent( 0x75C, 2, -2, 0 );
}
AddComponent(0x759, -2, -2, 0);
AddComponent(0x75A, 2, 2, 0);
AddComponent(0x75B, -2, 2, 0);
AddComponent(0x75C, 2, -2, 0);
}
public void AddComponent( int id, int x, int y, int z )
{
AddonComponent ac = new AddonComponent( id );
public ChampionPlatform(Serial serial) : base(serial)
{
}
ac.Hue = 0x497;
public void AddComponent(int id, int x, int y, int z)
{
AddonComponent ac = new AddonComponent(id);
AddComponent( ac, x, y, z );
}
ac.Hue = 0x497;
public override void OnAfterDelete()
{
base.OnAfterDelete();
AddComponent(ac, x, y, z);
}
m_Spawn?.Delete();
}
public override void OnAfterDelete()
{
base.OnAfterDelete();
public ChampionPlatform( Serial serial ) : base( serial )
{
}
m_Spawn?.Delete();
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write( (int) 0 ); // version
writer.Write(0); // version
writer.Write( m_Spawn );
}
writer.Write(m_Spawn);
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
int version = reader.ReadInt();
switch ( version )
{
case 0:
{
m_Spawn = reader.ReadItem() as ChampionSpawn;
switch (version)
{
case 0:
{
m_Spawn = reader.ReadItem() as ChampionSpawn;
if ( m_Spawn == null )
Delete();
if (m_Spawn == null)
Delete();
break;
}
}
}
}
break;
}
}
}
}
}

View file

@ -2,71 +2,88 @@ using Server.Engines.CannedEvil;
namespace Server.Items
{
public class ChampionSkull : Item
{
private ChampionSkullType m_Type;
public class ChampionSkull : Item
{
private ChampionSkullType m_Type;
[CommandProperty( AccessLevel.GameMaster )]
public ChampionSkullType Type{ get => m_Type;
set{ m_Type = value; InvalidateProperties(); } }
[Constructible]
public ChampionSkull(ChampionSkullType type) : base(0x1AE1)
{
m_Type = type;
LootType = LootType.Cursed;
public override int LabelNumber => 1049479 + (int)m_Type;
// TODO: All hue values
switch (type)
{
case ChampionSkullType.Power:
Hue = 0x159;
break;
case ChampionSkullType.Venom:
Hue = 0x172;
break;
case ChampionSkullType.Greed:
Hue = 0x1EE;
break;
case ChampionSkullType.Death:
Hue = 0x025;
break;
case ChampionSkullType.Pain:
Hue = 0x035;
break;
}
}
[Constructible]
public ChampionSkull( ChampionSkullType type ) : base( 0x1AE1 )
{
m_Type = type;
LootType = LootType.Cursed;
public ChampionSkull(Serial serial) : base(serial)
{
}
// TODO: All hue values
switch ( type )
{
case ChampionSkullType.Power: Hue = 0x159; break;
case ChampionSkullType.Venom: Hue = 0x172; break;
case ChampionSkullType.Greed: Hue = 0x1EE; break;
case ChampionSkullType.Death: Hue = 0x025; break;
case ChampionSkullType.Pain: Hue = 0x035; break;
}
}
[CommandProperty(AccessLevel.GameMaster)]
public ChampionSkullType Type
{
get => m_Type;
set
{
m_Type = value;
InvalidateProperties();
}
}
public ChampionSkull( Serial serial ) : base( serial )
{
}
public override int LabelNumber => 1049479 + (int)m_Type;
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write( (int) 1 ); // version
writer.Write(1); // version
writer.Write( (int) m_Type );
}
writer.Write((int)m_Type);
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
int version = reader.ReadInt();
switch ( version )
{
case 1:
case 0:
{
m_Type = (ChampionSkullType)reader.ReadInt();
switch (version)
{
case 1:
case 0:
{
m_Type = (ChampionSkullType)reader.ReadInt();
break;
}
}
break;
}
}
if ( version == 0 )
{
if ( LootType != LootType.Cursed )
LootType = LootType.Cursed;
if (version == 0)
{
if (LootType != LootType.Cursed)
LootType = LootType.Cursed;
if ( Insured )
Insured = false;
}
}
}
}
if (Insured)
Insured = false;
}
}
}
}

View file

@ -1,172 +1,184 @@
using Server.Items;
using Server.Targeting;
using Server.Mobiles;
using Server.Targeting;
namespace Server.Engines.CannedEvil
{
public class ChampionSkullBrazier : AddonComponent
{
private ChampionSkullType m_Type;
private Item m_Skull;
public class ChampionSkullBrazier : AddonComponent
{
private Item m_Skull;
private ChampionSkullType m_Type;
[CommandProperty( AccessLevel.GameMaster )]
public ChampionSkullPlatform Platform { get; private set; }
public ChampionSkullBrazier(ChampionSkullPlatform platform, ChampionSkullType type) : base(0x19BB)
{
Hue = 0x455;
Light = LightType.Circle300;
[CommandProperty( AccessLevel.GameMaster )]
public ChampionSkullType Type{ get => m_Type;
set{ m_Type = value; InvalidateProperties(); } }
Platform = platform;
m_Type = type;
}
[CommandProperty( AccessLevel.GameMaster )]
public Item Skull{ get => m_Skull;
set{ m_Skull = value;
Platform?.Validate();
} }
public ChampionSkullBrazier(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1049489 + (int)m_Type;
[CommandProperty(AccessLevel.GameMaster)]
public ChampionSkullPlatform Platform{ get; private set; }
public ChampionSkullBrazier( ChampionSkullPlatform platform, ChampionSkullType type ) : base( 0x19BB )
{
Hue = 0x455;
Light = LightType.Circle300;
[CommandProperty(AccessLevel.GameMaster)]
public ChampionSkullType Type
{
get => m_Type;
set
{
m_Type = value;
InvalidateProperties();
}
}
Platform = platform;
m_Type = type;
}
[CommandProperty(AccessLevel.GameMaster)]
public Item Skull
{
get => m_Skull;
set
{
m_Skull = value;
Platform?.Validate();
}
}
public ChampionSkullBrazier( Serial serial ) : base( serial )
{
}
public override int LabelNumber => 1049489 + (int)m_Type;
public override void OnDoubleClick( Mobile from )
{
Platform?.Validate();
public override void OnDoubleClick(Mobile from)
{
Platform?.Validate();
BeginSacrifice( from );
}
BeginSacrifice(from);
}
public void BeginSacrifice( Mobile from )
{
if ( Deleted )
return;
public void BeginSacrifice(Mobile from)
{
if (Deleted)
return;
if ( m_Skull != null && m_Skull.Deleted )
Skull = null;
if (m_Skull != null && m_Skull.Deleted)
Skull = null;
if ( from.Map != Map || !from.InRange( GetWorldLocation(), 3 ) )
{
from.SendLocalizedMessage( 500446 ); // That is too far away.
}
else if ( !Harrower.CanSpawn )
{
from.SendMessage( "The harrower has already been spawned." );
}
else if ( m_Skull == null )
{
from.SendLocalizedMessage( 1049485 ); // What would you like to sacrifice?
from.Target = new SacrificeTarget( this );
}
else
{
SendLocalizedMessageTo( from, 1049487, "" ); // I already have my champions awakening skull!
}
}
if (from.Map != Map || !from.InRange(GetWorldLocation(), 3))
{
from.SendLocalizedMessage(500446); // That is too far away.
}
else if (!Harrower.CanSpawn)
{
from.SendMessage("The harrower has already been spawned.");
}
else if (m_Skull == null)
{
from.SendLocalizedMessage(1049485); // What would you like to sacrifice?
from.Target = new SacrificeTarget(this);
}
else
{
SendLocalizedMessageTo(from, 1049487, ""); // I already have my champions awakening skull!
}
}
public void EndSacrifice( Mobile from, ChampionSkull skull )
{
if ( Deleted )
return;
public void EndSacrifice(Mobile from, ChampionSkull skull)
{
if (Deleted)
return;
if ( m_Skull != null && m_Skull.Deleted )
Skull = null;
if (m_Skull != null && m_Skull.Deleted)
Skull = null;
if ( from.Map != Map || !from.InRange( GetWorldLocation(), 3 ) )
{
from.SendLocalizedMessage( 500446 ); // That is too far away.
}
else if ( !Harrower.CanSpawn )
{
from.SendMessage( "The harrower has already been spawned." );
}
else if ( skull == null )
{
SendLocalizedMessageTo( from, 1049488, "" ); // That is not my champions awakening skull!
}
else if ( m_Skull != null )
{
SendLocalizedMessageTo( from, 1049487, "" ); // I already have my champions awakening skull!
}
else if ( !skull.IsChildOf( from.Backpack ) )
{
from.SendLocalizedMessage( 1049486 ); // You can only sacrifice items that are in your backpack!
}
else
{
if ( skull.Type == Type )
{
skull.Movable = false;
skull.MoveToWorld( GetWorldTop(), Map );
if (from.Map != Map || !from.InRange(GetWorldLocation(), 3))
{
from.SendLocalizedMessage(500446); // That is too far away.
}
else if (!Harrower.CanSpawn)
{
from.SendMessage("The harrower has already been spawned.");
}
else if (skull == null)
{
SendLocalizedMessageTo(from, 1049488, ""); // That is not my champions awakening skull!
}
else if (m_Skull != null)
{
SendLocalizedMessageTo(from, 1049487, ""); // I already have my champions awakening skull!
}
else if (!skull.IsChildOf(from.Backpack))
{
from.SendLocalizedMessage(1049486); // You can only sacrifice items that are in your backpack!
}
else
{
if (skull.Type == Type)
{
skull.Movable = false;
skull.MoveToWorld(GetWorldTop(), Map);
Skull = skull;
}
else
{
SendLocalizedMessageTo( from, 1049488, "" ); // That is not my champions awakening skull!
}
}
}
Skull = skull;
}
else
{
SendLocalizedMessageTo(from, 1049488, ""); // That is not my champions awakening skull!
}
}
}
private class SacrificeTarget : Target
{
private ChampionSkullBrazier m_Brazier;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
public SacrificeTarget( ChampionSkullBrazier brazier ) : base( 12, false, TargetFlags.None )
{
m_Brazier = brazier;
}
writer.Write(0); // version
protected override void OnTarget( Mobile from, object targeted )
{
m_Brazier.EndSacrifice( from, targeted as ChampionSkull );
}
}
writer.Write((int)m_Type);
writer.Write(Platform);
writer.Write(m_Skull);
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
writer.Write( (int) 0 ); // version
int version = reader.ReadInt();
writer.Write( (int) m_Type );
writer.Write( Platform );
writer.Write( m_Skull );
}
switch (version)
{
case 0:
{
m_Type = (ChampionSkullType)reader.ReadInt();
Platform = reader.ReadItem() as ChampionSkullPlatform;
m_Skull = reader.ReadItem();
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
if (Platform == null)
Delete();
int version = reader.ReadInt();
break;
}
}
switch ( version )
{
case 0:
{
m_Type = (ChampionSkullType)reader.ReadInt();
Platform = reader.ReadItem() as ChampionSkullPlatform;
m_Skull = reader.ReadItem();
if (Hue == 0x497)
Hue = 0x455;
if ( Platform == null )
Delete();
if (Light != LightType.Circle300)
Light = LightType.Circle300;
}
break;
}
}
private class SacrificeTarget : Target
{
private ChampionSkullBrazier m_Brazier;
if ( Hue == 0x497 )
Hue = 0x455;
public SacrificeTarget(ChampionSkullBrazier brazier) : base(12, false, TargetFlags.None)
{
m_Brazier = brazier;
}
if ( Light != LightType.Circle300 )
Light = LightType.Circle300;
}
}
}
protected override void OnTarget(Mobile from, object targeted)
{
m_Brazier.EndSacrifice(from, targeted as ChampionSkull);
}
}
}
}

View file

@ -3,125 +3,126 @@ using Server.Mobiles;
namespace Server.Engines.CannedEvil
{
public class ChampionSkullPlatform : BaseAddon
{
private ChampionSkullBrazier m_Power, m_Enlightenment, m_Venom, m_Pain, m_Greed, m_Death;
public class ChampionSkullPlatform : BaseAddon
{
private ChampionSkullBrazier m_Power, m_Enlightenment, m_Venom, m_Pain, m_Greed, m_Death;
[Constructible]
public ChampionSkullPlatform()
{
AddComponent( new AddonComponent( 0x71A ), -1, -1, -1 );
AddComponent( new AddonComponent( 0x709 ), 0, -1, -1 );
AddComponent( new AddonComponent( 0x709 ), 1, -1, -1 );
AddComponent( new AddonComponent( 0x709 ), -1, 0, -1 );
AddComponent( new AddonComponent( 0x709 ), 0, 0, -1 );
AddComponent( new AddonComponent( 0x709 ), 1, 0, -1 );
AddComponent( new AddonComponent( 0x709 ), -1, 1, -1 );
AddComponent( new AddonComponent( 0x709 ), 0, 1, -1 );
AddComponent( new AddonComponent( 0x71B ), 1, 1, -1 );
[Constructible]
public ChampionSkullPlatform()
{
AddComponent(new AddonComponent(0x71A), -1, -1, -1);
AddComponent(new AddonComponent(0x709), 0, -1, -1);
AddComponent(new AddonComponent(0x709), 1, -1, -1);
AddComponent(new AddonComponent(0x709), -1, 0, -1);
AddComponent(new AddonComponent(0x709), 0, 0, -1);
AddComponent(new AddonComponent(0x709), 1, 0, -1);
AddComponent(new AddonComponent(0x709), -1, 1, -1);
AddComponent(new AddonComponent(0x709), 0, 1, -1);
AddComponent(new AddonComponent(0x71B), 1, 1, -1);
AddComponent( new AddonComponent( 0x50F ), 0, -1, 4 );
AddComponent( m_Power = new ChampionSkullBrazier( this, ChampionSkullType.Power ), 0, -1, 5 );
AddComponent(new AddonComponent(0x50F), 0, -1, 4);
AddComponent(m_Power = new ChampionSkullBrazier(this, ChampionSkullType.Power), 0, -1, 5);
AddComponent( new AddonComponent( 0x50F ), 1, -1, 4 );
AddComponent( m_Enlightenment = new ChampionSkullBrazier( this, ChampionSkullType.Enlightenment ), 1, -1, 5 );
AddComponent(new AddonComponent(0x50F), 1, -1, 4);
AddComponent(m_Enlightenment = new ChampionSkullBrazier(this, ChampionSkullType.Enlightenment), 1, -1, 5);
AddComponent( new AddonComponent( 0x50F ), -1, 0, 4 );
AddComponent( m_Venom = new ChampionSkullBrazier( this, ChampionSkullType.Venom ), -1, 0, 5 );
AddComponent(new AddonComponent(0x50F), -1, 0, 4);
AddComponent(m_Venom = new ChampionSkullBrazier(this, ChampionSkullType.Venom), -1, 0, 5);
AddComponent( new AddonComponent( 0x50F ), 1, 0, 4 );
AddComponent( m_Pain = new ChampionSkullBrazier( this, ChampionSkullType.Pain ), 1, 0, 5 );
AddComponent(new AddonComponent(0x50F), 1, 0, 4);
AddComponent(m_Pain = new ChampionSkullBrazier(this, ChampionSkullType.Pain), 1, 0, 5);
AddComponent( new AddonComponent( 0x50F ), -1, 1, 4 );
AddComponent( m_Greed = new ChampionSkullBrazier( this, ChampionSkullType.Greed ), -1, 1, 5 );
AddComponent(new AddonComponent(0x50F), -1, 1, 4);
AddComponent(m_Greed = new ChampionSkullBrazier(this, ChampionSkullType.Greed), -1, 1, 5);
AddComponent( new AddonComponent( 0x50F ), 0, 1, 4 );
AddComponent( m_Death = new ChampionSkullBrazier( this, ChampionSkullType.Death ), 0, 1, 5 );
AddComponent(new AddonComponent(0x50F), 0, 1, 4);
AddComponent(m_Death = new ChampionSkullBrazier(this, ChampionSkullType.Death), 0, 1, 5);
AddonComponent comp = new LocalizedAddonComponent( 0x20D2, 1049495 );
comp.Hue = 0x482;
AddComponent( comp, 0, 0, 5 );
AddonComponent comp = new LocalizedAddonComponent(0x20D2, 1049495);
comp.Hue = 0x482;
AddComponent(comp, 0, 0, 5);
comp = new LocalizedAddonComponent( 0x0BCF, 1049496 );
comp.Hue = 0x482;
AddComponent( comp, 0, 2, -7 );
comp = new LocalizedAddonComponent(0x0BCF, 1049496);
comp.Hue = 0x482;
AddComponent(comp, 0, 2, -7);
comp = new LocalizedAddonComponent( 0x0BD0, 1049497 );
comp.Hue = 0x482;
AddComponent( comp, 2, 0, -7 );
}
comp = new LocalizedAddonComponent(0x0BD0, 1049497);
comp.Hue = 0x482;
AddComponent(comp, 2, 0, -7);
}
public void Validate()
{
if ( Validate( m_Power ) && Validate( m_Enlightenment ) && Validate( m_Venom ) && Validate( m_Pain ) && Validate( m_Greed ) && Validate( m_Death ) )
{
Mobile harrower = Harrower.Spawn( new Point3D( X, Y, Z + 6 ), Map );
public ChampionSkullPlatform(Serial serial) : base(serial)
{
}
if ( harrower == null )
return;
public void Validate()
{
if (Validate(m_Power) && Validate(m_Enlightenment) && Validate(m_Venom) && Validate(m_Pain) &&
Validate(m_Greed) && Validate(m_Death))
{
Mobile harrower = Harrower.Spawn(new Point3D(X, Y, Z + 6), Map);
Clear( m_Power );
Clear( m_Enlightenment );
Clear( m_Venom );
Clear( m_Pain );
Clear( m_Greed );
Clear( m_Death );
}
}
if (harrower == null)
return;
public void Clear( ChampionSkullBrazier brazier )
{
if ( brazier != null )
{
Effects.SendBoltEffect( brazier );
Clear(m_Power);
Clear(m_Enlightenment);
Clear(m_Venom);
Clear(m_Pain);
Clear(m_Greed);
Clear(m_Death);
}
}
brazier.Skull?.Delete();
}
}
public void Clear(ChampionSkullBrazier brazier)
{
if (brazier != null)
{
Effects.SendBoltEffect(brazier);
public bool Validate( ChampionSkullBrazier brazier )
{
return ( brazier?.Skull != null && !brazier.Skull.Deleted );
}
brazier.Skull?.Delete();
}
}
public ChampionSkullPlatform( Serial serial ) : base( serial )
{
}
public bool Validate(ChampionSkullBrazier brazier)
{
return brazier?.Skull != null && !brazier.Skull.Deleted;
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write( (int) 0 ); // version
writer.Write(0); // version
writer.Write( m_Power );
writer.Write( m_Enlightenment );
writer.Write( m_Venom );
writer.Write( m_Pain );
writer.Write( m_Greed );
writer.Write( m_Death );
}
writer.Write(m_Power);
writer.Write(m_Enlightenment);
writer.Write(m_Venom);
writer.Write(m_Pain);
writer.Write(m_Greed);
writer.Write(m_Death);
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
int version = reader.ReadInt();
switch ( version )
{
case 0:
{
m_Power = reader.ReadItem() as ChampionSkullBrazier;
m_Enlightenment = reader.ReadItem() as ChampionSkullBrazier;
m_Venom = reader.ReadItem() as ChampionSkullBrazier;
m_Pain = reader.ReadItem() as ChampionSkullBrazier;
m_Greed = reader.ReadItem() as ChampionSkullBrazier;
m_Death = reader.ReadItem() as ChampionSkullBrazier;
switch (version)
{
case 0:
{
m_Power = reader.ReadItem() as ChampionSkullBrazier;
m_Enlightenment = reader.ReadItem() as ChampionSkullBrazier;
m_Venom = reader.ReadItem() as ChampionSkullBrazier;
m_Pain = reader.ReadItem() as ChampionSkullBrazier;
m_Greed = reader.ReadItem() as ChampionSkullBrazier;
m_Death = reader.ReadItem() as ChampionSkullBrazier;
break;
}
}
}
}
break;
}
}
}
}
}

View file

@ -1,12 +1,12 @@
namespace Server.Engines.CannedEvil
{
public enum ChampionSkullType
{
Power,
Enlightenment,
Venom,
Pain,
Greed,
Death
}
public enum ChampionSkullType
{
Power,
Enlightenment,
Venom,
Pain,
Greed,
Death
}
}

File diff suppressed because it is too large Load diff

View file

@ -3,115 +3,131 @@ using Server.Mobiles;
namespace Server.Engines.CannedEvil
{
public enum ChampionSpawnType
{
Abyss,
Arachnid,
ColdBlood,
ForestLord,
VerminHorde,
UnholyTerror,
SleepingDragon,
Glade,
Pestilence
}
public enum ChampionSpawnType
{
Abyss,
Arachnid,
ColdBlood,
ForestLord,
VerminHorde,
UnholyTerror,
SleepingDragon,
Glade,
Pestilence
}
public class ChampionSpawnInfo
{
public string Name { get; }
public class ChampionSpawnInfo
{
public ChampionSpawnInfo(string name, Type champion, string[] levelNames, Type[][] spawnTypes)
{
Name = name;
Champion = champion;
LevelNames = levelNames;
SpawnTypes = spawnTypes;
}
public Type Champion { get; }
public string Name{ get; }
public Type[][] SpawnTypes { get; }
public Type Champion{ get; }
public string[] LevelNames { get; }
public Type[][] SpawnTypes{ get; }
public ChampionSpawnInfo( string name, Type champion, string[] levelNames, Type[][] spawnTypes )
{
Name = name;
Champion = champion;
LevelNames = levelNames;
SpawnTypes = spawnTypes;
}
public string[] LevelNames{ get; }
public static ChampionSpawnInfo[] Table { get; } =
{
new ChampionSpawnInfo( "Abyss", typeof( Semidar ), new[]{ "Foe", "Assassin", "Conqueror" }, new[] // Abyss
{ // Abyss
new[]{ typeof( GreaterMongbat ), typeof( Imp ) }, // Level 1
new[]{ typeof( Gargoyle ), typeof( Harpy ) }, // Level 2
new[]{ typeof( FireGargoyle ), typeof( StoneGargoyle ) }, // Level 3
new[]{ typeof( Daemon ), typeof( Succubus ) } // Level 4
} ),
new ChampionSpawnInfo( "Arachnid", typeof( Mephitis ), new[]{ "Bane", "Killer", "Vanquisher" }, new[] // Arachnid
{ // Arachnid
new[]{ typeof( Scorpion ), typeof( GiantSpider ) }, // Level 1
new[]{ typeof( TerathanDrone ), typeof( TerathanWarrior ) }, // Level 2
new[]{ typeof( DreadSpider ), typeof( TerathanMatriarch ) }, // Level 3
new[]{ typeof( PoisonElemental ), typeof( TerathanAvenger ) } // Level 4
} ),
new ChampionSpawnInfo( "Cold Blood", typeof( Rikktor ), new[]{ "Blight", "Slayer", "Destroyer" }, new[] // Cold Blood
{ // Cold Blood
new[]{ typeof( Lizardman ), typeof( Snake ) }, // Level 1
new[]{ typeof( LavaLizard ), typeof( OphidianWarrior ) }, // Level 2
new[]{ typeof( Drake ), typeof( OphidianArchmage ) }, // Level 3
new[]{ typeof( Dragon ), typeof( OphidianKnight ) } // Level 4
} ),
new ChampionSpawnInfo( "Forest Lord", typeof( LordOaks ), new[]{ "Enemy", "Curse", "Slaughterer" }, new[] // Forest Lord
{ // Forest Lord
new[]{ typeof( Pixie ), typeof( ShadowWisp ) }, // Level 1
new[]{ typeof( Kirin ), typeof( Wisp ) }, // Level 2
new[]{ typeof( Centaur ), typeof( Unicorn ) }, // Level 3
new[]{ typeof( EtherealWarrior ), typeof( SerpentineDragon ) } // Level 4
} ),
new ChampionSpawnInfo( "Vermin Horde", typeof( Barracoon ), new[]{ "Adversary", "Subjugator", "Eradicator" }, new[] // Vermin Horde
{ // Vermin Horde
new[]{ typeof( GiantRat ), typeof( Slime ) }, // Level 1
new[]{ typeof( DireWolf ), typeof( Ratman ) }, // Level 2
new[]{ typeof( HellHound ), typeof( RatmanMage ) }, // Level 3
new[]{ typeof( RatmanArcher ), typeof( SilverSerpent ) } // Level 4
} ),
new ChampionSpawnInfo( "Unholy Terror", typeof( Neira ), new[]{ "Scourge", "Punisher", "Nemesis" }, new[] // Unholy Terror
{ // Unholy Terror
(Core.AOS ?
new[]{ typeof( Bogle ), typeof( Ghoul ), typeof( Shade ), typeof( Spectre ), typeof( Wraith ) } // Level 1 (Pre-AoS)
: new[]{ typeof( Ghoul ), typeof( Shade ), typeof( Spectre ), typeof( Wraith ) } ), // Level 1
public static ChampionSpawnInfo[] Table{ get; } =
{
new ChampionSpawnInfo("Abyss", typeof(Semidar), new[] { "Foe", "Assassin", "Conqueror" }, new[] // Abyss
{
// Abyss
new[] { typeof(GreaterMongbat), typeof(Imp) }, // Level 1
new[] { typeof(Gargoyle), typeof(Harpy) }, // Level 2
new[] { typeof(FireGargoyle), typeof(StoneGargoyle) }, // Level 3
new[] { typeof(Daemon), typeof(Succubus) } // Level 4
}),
new ChampionSpawnInfo("Arachnid", typeof(Mephitis), new[] { "Bane", "Killer", "Vanquisher" }, new[] // Arachnid
{
// Arachnid
new[] { typeof(Scorpion), typeof(GiantSpider) }, // Level 1
new[] { typeof(TerathanDrone), typeof(TerathanWarrior) }, // Level 2
new[] { typeof(DreadSpider), typeof(TerathanMatriarch) }, // Level 3
new[] { typeof(PoisonElemental), typeof(TerathanAvenger) } // Level 4
}),
new ChampionSpawnInfo("Cold Blood", typeof(Rikktor), new[] { "Blight", "Slayer", "Destroyer" },
new[] // Cold Blood
{
// Cold Blood
new[] { typeof(Lizardman), typeof(Snake) }, // Level 1
new[] { typeof(LavaLizard), typeof(OphidianWarrior) }, // Level 2
new[] { typeof(Drake), typeof(OphidianArchmage) }, // Level 3
new[] { typeof(Dragon), typeof(OphidianKnight) } // Level 4
}),
new ChampionSpawnInfo("Forest Lord", typeof(LordOaks), new[] { "Enemy", "Curse", "Slaughterer" },
new[] // Forest Lord
{
// Forest Lord
new[] { typeof(Pixie), typeof(ShadowWisp) }, // Level 1
new[] { typeof(Kirin), typeof(Wisp) }, // Level 2
new[] { typeof(Centaur), typeof(Unicorn) }, // Level 3
new[] { typeof(EtherealWarrior), typeof(SerpentineDragon) } // Level 4
}),
new ChampionSpawnInfo("Vermin Horde", typeof(Barracoon), new[] { "Adversary", "Subjugator", "Eradicator" },
new[] // Vermin Horde
{
// Vermin Horde
new[] { typeof(GiantRat), typeof(Slime) }, // Level 1
new[] { typeof(DireWolf), typeof(Ratman) }, // Level 2
new[] { typeof(HellHound), typeof(RatmanMage) }, // Level 3
new[] { typeof(RatmanArcher), typeof(SilverSerpent) } // Level 4
}),
new ChampionSpawnInfo("Unholy Terror", typeof(Neira), new[] { "Scourge", "Punisher", "Nemesis" },
new[] // Unholy Terror
{
// Unholy Terror
Core.AOS
? new[]
{
typeof(Bogle), typeof(Ghoul), typeof(Shade), typeof(Spectre), typeof(Wraith)
} // Level 1 (Pre-AoS)
: new[] { typeof(Ghoul), typeof(Shade), typeof(Spectre), typeof(Wraith) }, // Level 1
new[]{ typeof( BoneMagi ), typeof( Mummy ), typeof( SkeletalMage ) }, // Level 2
new[]{ typeof( BoneKnight ), typeof( Lich ), typeof( SkeletalKnight ) }, // Level 3
new[]{ typeof( LichLord ), typeof( RottingCorpse ) } // Level 4
} ),
new ChampionSpawnInfo( "Sleeping Dragon", typeof( Serado ), new[]{ "Rival", "Challenger", "Antagonist" } , new[]
{ // Unholy Terror
new[]{ typeof( DeathwatchBeetleHatchling ), typeof( Lizardman ) },
new[]{ typeof( DeathwatchBeetle ), typeof( Kappa ) },
new[]{ typeof( LesserHiryu ), typeof( RevenantLion ) },
new[]{ typeof( Hiryu ), typeof( Oni ) }
} ),
new ChampionSpawnInfo( "Glade", typeof( Twaulo ), new[]{ "Banisher", "Enforcer", "Eradicator" } , new[]
{ // Glade
new[]{ typeof( Pixie ), typeof( ShadowWisp ) },
new[]{ typeof( Centaur ), typeof( MLDryad ) },
new[]{ typeof( Satyr ), typeof( CuSidhe ) },
new[]{ typeof( FeralTreefellow ), typeof( RagingGrizzlyBear ) }
} ),
new ChampionSpawnInfo( "The Corrupt", typeof( Ilhenir ), new[]{ "Cleanser", "Expunger", "Depurator" } , new[]
{ // Unholy Terror
new[]{ typeof( PlagueSpawn ), typeof( Bogling ) },
new[]{ typeof( PlagueBeast ), typeof( BogThing ) },
new[]{ typeof( PlagueBeastLord ), typeof( InterredGrizzle ) },
new[]{ typeof( FetidEssence ), typeof( PestilentBandage ) }
} )
};
new[] { typeof(BoneMagi), typeof(Mummy), typeof(SkeletalMage) }, // Level 2
new[] { typeof(BoneKnight), typeof(Lich), typeof(SkeletalKnight) }, // Level 3
new[] { typeof(LichLord), typeof(RottingCorpse) } // Level 4
}),
new ChampionSpawnInfo("Sleeping Dragon", typeof(Serado), new[] { "Rival", "Challenger", "Antagonist" }, new[]
{
// Unholy Terror
new[] { typeof(DeathwatchBeetleHatchling), typeof(Lizardman) },
new[] { typeof(DeathwatchBeetle), typeof(Kappa) },
new[] { typeof(LesserHiryu), typeof(RevenantLion) },
new[] { typeof(Hiryu), typeof(Oni) }
}),
new ChampionSpawnInfo("Glade", typeof(Twaulo), new[] { "Banisher", "Enforcer", "Eradicator" }, new[]
{
// Glade
new[] { typeof(Pixie), typeof(ShadowWisp) },
new[] { typeof(Centaur), typeof(MLDryad) },
new[] { typeof(Satyr), typeof(CuSidhe) },
new[] { typeof(FeralTreefellow), typeof(RagingGrizzlyBear) }
}),
new ChampionSpawnInfo("The Corrupt", typeof(Ilhenir), new[] { "Cleanser", "Expunger", "Depurator" }, new[]
{
// Unholy Terror
new[] { typeof(PlagueSpawn), typeof(Bogling) },
new[] { typeof(PlagueBeast), typeof(BogThing) },
new[] { typeof(PlagueBeastLord), typeof(InterredGrizzle) },
new[] { typeof(FetidEssence), typeof(PestilentBandage) }
})
};
public static ChampionSpawnInfo GetInfo( ChampionSpawnType type )
{
int v = (int)type;
public static ChampionSpawnInfo GetInfo(ChampionSpawnType type)
{
int v = (int)type;
if ( v < 0 || v >= Table.Length )
v = 0;
if (v < 0 || v >= Table.Length)
v = 0;
return Table[v];
}
}
}
return Table[v];
}
}
}

View file

@ -1,56 +1,56 @@
namespace Server.Items
{
public class HarrowerGate : Moongate
{
private Mobile m_Harrower;
public class HarrowerGate : Moongate
{
private Mobile m_Harrower;
public override int LabelNumber => 1049498; // dark moongate
public HarrowerGate(Mobile harrower, Point3D loc, Map map, Point3D targLoc, Map targMap) : base(targLoc, targMap)
{
m_Harrower = harrower;
public HarrowerGate( Mobile harrower, Point3D loc, Map map, Point3D targLoc, Map targMap ) : base( targLoc, targMap )
{
m_Harrower = harrower;
Dispellable = false;
ItemID = 0x1FD4;
Light = LightType.Circle300;
Dispellable = false;
ItemID = 0x1FD4;
Light = LightType.Circle300;
MoveToWorld(loc, map);
}
MoveToWorld( loc, map );
}
public HarrowerGate(Serial serial) : base(serial)
{
}
public HarrowerGate( Serial serial ) : base( serial )
{
}
public override int LabelNumber => 1049498; // dark moongate
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write( (int) 0 ); // version
writer.Write(0); // version
writer.Write( m_Harrower );
}
writer.Write(m_Harrower);
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
int version = reader.ReadInt();
switch ( version )
{
case 0:
{
m_Harrower = reader.ReadMobile();
switch (version)
{
case 0:
{
m_Harrower = reader.ReadMobile();
if ( m_Harrower == null )
Delete();
if (m_Harrower == null)
Delete();
break;
}
}
break;
}
}
if ( Light != LightType.Circle300 )
Light = LightType.Circle300;
}
}
}
if (Light != LightType.Circle300)
Light = LightType.Circle300;
}
}
}

View file

@ -2,19 +2,19 @@ using System;
namespace Server.Engines.CannedEvil
{
public class RestartTimer : Timer
{
private ChampionSpawn m_Spawn;
public class RestartTimer : Timer
{
private ChampionSpawn m_Spawn;
public RestartTimer( ChampionSpawn spawn, TimeSpan delay ) : base( delay )
{
m_Spawn = spawn;
Priority = TimerPriority.FiveSeconds;
}
public RestartTimer(ChampionSpawn spawn, TimeSpan delay) : base(delay)
{
m_Spawn = spawn;
Priority = TimerPriority.FiveSeconds;
}
protected override void OnTick()
{
m_Spawn.EndRestart();
}
}
protected override void OnTick()
{
m_Spawn.EndRestart();
}
}
}

View file

@ -2,19 +2,19 @@ using System;
namespace Server.Engines.CannedEvil
{
public class SliceTimer : Timer
{
private ChampionSpawn m_Spawn;
public class SliceTimer : Timer
{
private ChampionSpawn m_Spawn;
public SliceTimer( ChampionSpawn spawn ) : base( TimeSpan.FromSeconds( 1.0 ), TimeSpan.FromSeconds( 1.0 ) )
{
m_Spawn = spawn;
Priority = TimerPriority.OneSecond;
}
public SliceTimer(ChampionSpawn spawn) : base(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0))
{
m_Spawn = spawn;
Priority = TimerPriority.OneSecond;
}
protected override void OnTick()
{
m_Spawn.OnSlice();
}
}
protected override void OnTick()
{
m_Spawn.OnSlice();
}
}
}

View file

@ -2,103 +2,103 @@ using System;
namespace Server.Items
{
public class StarRoomGate : Moongate
{
private bool m_Decays;
private DateTime m_DecayTime;
private Timer m_Timer;
public class StarRoomGate : Moongate
{
private bool m_Decays;
private DateTime m_DecayTime;
private Timer m_Timer;
public override int LabelNumber => 1049498; // dark moongate
[Constructible]
public StarRoomGate() : this(false)
{
}
[Constructible]
public StarRoomGate() : this( false )
{
}
[Constructible]
public StarRoomGate(bool decays, Point3D loc, Map map) : this(decays)
{
MoveToWorld(loc, map);
Effects.PlaySound(loc, map, 0x20E);
}
[Constructible]
public StarRoomGate( bool decays, Point3D loc, Map map ) : this( decays )
{
MoveToWorld( loc, map );
Effects.PlaySound( loc, map, 0x20E );
}
[Constructible]
public StarRoomGate(bool decays) : base(new Point3D(5143, 1774, 0), Map.Felucca)
{
Dispellable = false;
ItemID = 0x1FD4;
[Constructible]
public StarRoomGate( bool decays ) : base( new Point3D( 5143, 1774, 0 ), Map.Felucca )
{
Dispellable = false;
ItemID = 0x1FD4;
if (decays)
{
m_Decays = true;
m_DecayTime = DateTime.UtcNow + TimeSpan.FromMinutes(2.0);
if ( decays )
{
m_Decays = true;
m_DecayTime = DateTime.UtcNow + TimeSpan.FromMinutes( 2.0 );
m_Timer = new InternalTimer(this, m_DecayTime);
m_Timer.Start();
}
}
m_Timer = new InternalTimer( this, m_DecayTime );
m_Timer.Start();
}
}
public StarRoomGate(Serial serial) : base(serial)
{
}
public StarRoomGate( Serial serial ) : base( serial )
{
}
public override int LabelNumber => 1049498; // dark moongate
public override void OnAfterDelete()
{
m_Timer?.Stop();
public override void OnAfterDelete()
{
m_Timer?.Stop();
base.OnAfterDelete();
}
base.OnAfterDelete();
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write( (int) 0 ); // version
writer.Write(0); // version
writer.Write( m_Decays );
writer.Write(m_Decays);
if ( m_Decays )
writer.WriteDeltaTime( m_DecayTime );
}
if (m_Decays)
writer.WriteDeltaTime(m_DecayTime);
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
int version = reader.ReadInt();
switch ( version )
{
case 0:
{
m_Decays = reader.ReadBool();
switch (version)
{
case 0:
{
m_Decays = reader.ReadBool();
if ( m_Decays )
{
m_DecayTime = reader.ReadDeltaTime();
if (m_Decays)
{
m_DecayTime = reader.ReadDeltaTime();
m_Timer = new InternalTimer( this, m_DecayTime );
m_Timer.Start();
}
m_Timer = new InternalTimer(this, m_DecayTime);
m_Timer.Start();
}
break;
}
}
}
break;
}
}
}
private class InternalTimer : Timer
{
private Item m_Item;
private class InternalTimer : Timer
{
private Item m_Item;
public InternalTimer( Item item, DateTime end ) : base( end - DateTime.UtcNow )
{
m_Item = item;
}
public InternalTimer(Item item, DateTime end) : base(end - DateTime.UtcNow)
{
m_Item = item;
}
protected override void OnTick()
{
m_Item.Delete();
}
}
}
}
protected override void OnTick()
{
m_Item.Delete();
}
}
}
}

Some files were not shown because too many files have changed in this diff Show more