Adds xmlspawner
This commit is contained in:
parent
48e47f9352
commit
13c3e52639
23 changed files with 28032 additions and 0 deletions
3982
Projects/UOContent/Engines/XMLSpawner/BaseXmlSpawner.cs
Normal file
3982
Projects/UOContent/Engines/XMLSpawner/BaseXmlSpawner.cs
Normal file
File diff suppressed because it is too large
Load diff
74
Projects/UOContent/Engines/XMLSpawner/ExceptionLogging.cs
Normal file
74
Projects/UOContent/Engines/XMLSpawner/ExceptionLogging.cs
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Server.Diagnostics;
|
||||
|
||||
// TODO: Replace this with serilog
|
||||
public class ExceptionLogging
|
||||
{
|
||||
public static string LogDirectory { get; set; }
|
||||
|
||||
private static StreamWriter _Output;
|
||||
|
||||
public static StreamWriter Output
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_Output == null)
|
||||
{
|
||||
_Output = new StreamWriter(Path.Combine(LogDirectory, $"{Core.Now.ToLongDateString()}.log"), true)
|
||||
{
|
||||
AutoFlush = true
|
||||
};
|
||||
|
||||
_Output.WriteLine("##############################");
|
||||
_Output.WriteLine("Exception log started on {0}", Core.Now);
|
||||
_Output.WriteLine();
|
||||
}
|
||||
|
||||
return _Output;
|
||||
}
|
||||
}
|
||||
|
||||
static ExceptionLogging()
|
||||
{
|
||||
var directory = Path.Combine(Core.BaseDirectory, "Logs/Exceptions");
|
||||
|
||||
if (!Directory.Exists(directory))
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
|
||||
LogDirectory = directory;
|
||||
}
|
||||
|
||||
public static void LogException(Exception e)
|
||||
{
|
||||
Utility.PushColor(ConsoleColor.Red);
|
||||
Console.WriteLine("Caught Exception:");
|
||||
Utility.PopColor();
|
||||
|
||||
Utility.PushColor(ConsoleColor.DarkRed);
|
||||
Console.WriteLine(e);
|
||||
Utility.PopColor();
|
||||
|
||||
Output.WriteLine("Exception Caught: {0}", Core.Now);
|
||||
Output.WriteLine(e);
|
||||
Output.WriteLine();
|
||||
}
|
||||
|
||||
public static void LogException(Exception e, string arg)
|
||||
{
|
||||
Utility.PushColor(ConsoleColor.Red);
|
||||
Console.WriteLine("Caught Exception: {0}", arg);
|
||||
Utility.PopColor();
|
||||
|
||||
Utility.PushColor(ConsoleColor.DarkRed);
|
||||
Console.WriteLine(e);
|
||||
Utility.PopColor();
|
||||
|
||||
Output.WriteLine("Exception Caught: {0}", Core.Now);
|
||||
Output.WriteLine(e);
|
||||
Output.WriteLine();
|
||||
}
|
||||
}
|
||||
134
Projects/UOContent/Engines/XMLSpawner/ItemFlags.cs
Normal file
134
Projects/UOContent/Engines/XMLSpawner/ItemFlags.cs
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
using System;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Items;
|
||||
|
||||
public partial class ItemFlags
|
||||
{
|
||||
private const int StealableFlag = 0x00200000;
|
||||
private const int TakenFlag = 0x00100000;
|
||||
|
||||
public static void SetStealable(Item target, bool value)
|
||||
{
|
||||
target?.SetSavedFlag(StealableFlag, value);
|
||||
}
|
||||
public static bool GetStealable(Item target) => target != null && target.GetSavedFlag(StealableFlag);
|
||||
|
||||
public static void SetTaken(Item target, bool value)
|
||||
{
|
||||
target?.SetSavedFlag(TakenFlag, value);
|
||||
}
|
||||
public static bool GetTaken(Item target) => target != null && target.GetSavedFlag(TakenFlag);
|
||||
|
||||
[Usage("Flag flagfield")]
|
||||
[Description("Gets the state of the specified SavedFlag on any item")]
|
||||
public static void GetFlag_OnCommand(CommandEventArgs e)
|
||||
{
|
||||
int flag=0;
|
||||
bool error = false;
|
||||
if (e.Arguments.Length > 0)
|
||||
{
|
||||
if (e.Arguments[0].StartsWith("0x"))
|
||||
{
|
||||
try{flag = Convert.ToInt32(e.Arguments[0].Substring(2), 16); } catch { error = true;}
|
||||
} else
|
||||
{
|
||||
try{flag = int.Parse(e.Arguments[0]); } catch { error = true;}
|
||||
}
|
||||
|
||||
}
|
||||
if (!error)
|
||||
{
|
||||
e.Mobile.Target = new GetFlagTarget(e,flag);
|
||||
} else
|
||||
{
|
||||
try{
|
||||
e.Mobile.SendMessage(33,"Flag: Bad flagfield argument");
|
||||
} catch {}
|
||||
}
|
||||
}
|
||||
|
||||
private class GetFlagTarget : Target
|
||||
{
|
||||
private CommandEventArgs m_e;
|
||||
private int m_flag;
|
||||
|
||||
public GetFlagTarget(CommandEventArgs e, int flag) : base (30, false, TargetFlags.None)
|
||||
{
|
||||
m_e = e;
|
||||
m_flag = flag;
|
||||
}
|
||||
protected override void OnTarget(Mobile from, object targeted)
|
||||
{
|
||||
if (targeted is Item item)
|
||||
{
|
||||
bool state = item.GetSavedFlag(m_flag);
|
||||
|
||||
from.SendMessage("Flag (0x{0:X}) = {1}",m_flag,state);
|
||||
} else
|
||||
{
|
||||
from.SendMessage("Must target an Item");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Usage("Stealable [true/false]")]
|
||||
[Description("Sets/gets the stealable flag on any item")]
|
||||
public static void SetStealable_OnCommand(CommandEventArgs e)
|
||||
{
|
||||
bool state = false;
|
||||
bool error = false;
|
||||
if (e.Arguments.Length > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
state = bool.Parse(e.Arguments[0]);
|
||||
}
|
||||
catch
|
||||
{
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
if (!error)
|
||||
{
|
||||
e.Mobile.Target = new SetStealableTarget(e, state);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class SetStealableTarget : Target
|
||||
{
|
||||
private CommandEventArgs m_e;
|
||||
private bool m_state;
|
||||
private bool set;
|
||||
|
||||
public SetStealableTarget(CommandEventArgs e, bool state) : base (30, false, TargetFlags.None)
|
||||
{
|
||||
m_e = e;
|
||||
m_state = state;
|
||||
if (e.Arguments.Length > 0)
|
||||
{
|
||||
set = true;
|
||||
}
|
||||
}
|
||||
protected override void OnTarget(Mobile from, object targeted)
|
||||
{
|
||||
if (targeted is Item item)
|
||||
{
|
||||
if (set)
|
||||
{
|
||||
SetStealable(item, m_state);
|
||||
}
|
||||
|
||||
bool state = GetStealable(item);
|
||||
|
||||
from.SendMessage("Stealable = {0}",state);
|
||||
|
||||
} else
|
||||
{
|
||||
from.SendMessage("Must target an Item");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
283
Projects/UOContent/Engines/XMLSpawner/SpawnerExporter.cs
Normal file
283
Projects/UOContent/Engines/XMLSpawner/SpawnerExporter.cs
Normal file
|
|
@ -0,0 +1,283 @@
|
|||
using Server.Commands.Generic;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using Server.Engines.Spawners;
|
||||
|
||||
/*
|
||||
** Sno's distro spawner importer/exporter
|
||||
**
|
||||
** [exportspawner filename - Saves distro spawners to XML to 'Saves/Spawners/filename'
|
||||
**
|
||||
** [importspawner filename - Restores distro spawners from 'Saves/Spawners/filename'. Note, this command does not check for
|
||||
** duplication, so if you run it more than once you will end up with multiple spawners.
|
||||
**
|
||||
** These spawns can also be imported back in as XmlSpawners by using the '[xmlimportspawners Saves/Spawners/filename' command.
|
||||
*/
|
||||
|
||||
namespace Server.Mobiles;
|
||||
|
||||
public class SpawnerExporter
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
TargetCommands.Register(new ExportSpawnerCommand());
|
||||
CommandSystem.Register("ImportSpawners", AccessLevel.Administrator, ImportSpawners_OnCommand);
|
||||
}
|
||||
|
||||
public class ExportSpawnerCommand : BaseCommand
|
||||
{
|
||||
public ExportSpawnerCommand()
|
||||
{
|
||||
AccessLevel = AccessLevel.Administrator;
|
||||
Supports = CommandSupport.Area | CommandSupport.Region | CommandSupport.Global | CommandSupport.Multi | CommandSupport.Single;
|
||||
Commands = new[] { "ExportSpawner" };
|
||||
ObjectTypes = ObjectTypes.Items;
|
||||
Usage = "ExportSpawner <filename>";
|
||||
Description = "Exports all Spawner objects to the specified filename.";
|
||||
ListOptimized = true;
|
||||
}
|
||||
|
||||
public override void ExecuteList(CommandEventArgs e, List<object> list)
|
||||
{
|
||||
string filename = e.GetString(0);
|
||||
|
||||
ArrayList spawners = new ArrayList();
|
||||
|
||||
for (int i = 0; i < list.Count; ++i)
|
||||
{
|
||||
if (list[i] is Spawner)
|
||||
{
|
||||
Spawner spawner = (Spawner)list[i];
|
||||
if (!spawner.Deleted && spawner.Map != Map.Internal && spawner.Parent == null)
|
||||
{
|
||||
spawners.Add(spawner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AddResponse($"{spawners.Count.ToString()} spawners exported to Saves/Spawners/{filename}.");
|
||||
|
||||
ExportSpawners(spawners, filename);
|
||||
}
|
||||
|
||||
public override bool ValidateArgs(BaseCommandImplementor impl, CommandEventArgs e)
|
||||
{
|
||||
if (e.Arguments.Length >= 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
e.Mobile.SendMessage($"Usage: {Usage}");
|
||||
return false;
|
||||
}
|
||||
|
||||
private void ExportSpawners(ArrayList spawners, string filename)
|
||||
{
|
||||
if (spawners.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Directory.Exists("Saves/Spawners"))
|
||||
{
|
||||
Directory.CreateDirectory("Saves/Spawners");
|
||||
}
|
||||
|
||||
string filePath = Path.Combine("Saves/Spawners", filename);
|
||||
|
||||
using (StreamWriter op = new StreamWriter(filePath))
|
||||
{
|
||||
XmlTextWriter xml = new XmlTextWriter(op)
|
||||
{
|
||||
Formatting = Formatting.Indented,
|
||||
IndentChar = '\t',
|
||||
Indentation = 1
|
||||
};
|
||||
|
||||
xml.WriteStartDocument(true);
|
||||
|
||||
xml.WriteStartElement("spawners");
|
||||
|
||||
xml.WriteAttributeString("count", spawners.Count.ToString());
|
||||
|
||||
foreach (Spawner spawner in spawners)
|
||||
{
|
||||
ExportSpawner(spawner, xml);
|
||||
}
|
||||
|
||||
xml.WriteEndElement();
|
||||
|
||||
xml.Close();
|
||||
}
|
||||
}
|
||||
|
||||
private void ExportSpawner(Spawner spawner, XmlWriter xml)
|
||||
{
|
||||
xml.WriteStartElement("spawner");
|
||||
|
||||
xml.WriteStartElement("count");
|
||||
xml.WriteString(spawner.Count.ToString());
|
||||
xml.WriteEndElement();
|
||||
|
||||
xml.WriteStartElement("group");
|
||||
xml.WriteString(spawner.Group.ToString());
|
||||
xml.WriteEndElement();
|
||||
|
||||
xml.WriteStartElement("homerange");
|
||||
xml.WriteString(spawner.HomeRange.ToString());
|
||||
xml.WriteEndElement();
|
||||
|
||||
xml.WriteStartElement("walkingrange");
|
||||
xml.WriteString(spawner.WalkingRange.ToString());
|
||||
xml.WriteEndElement();
|
||||
|
||||
xml.WriteStartElement("maxdelay");
|
||||
xml.WriteString(spawner.MaxDelay.ToString());
|
||||
xml.WriteEndElement();
|
||||
|
||||
xml.WriteStartElement("mindelay");
|
||||
xml.WriteString(spawner.MinDelay.ToString());
|
||||
xml.WriteEndElement();
|
||||
|
||||
xml.WriteStartElement("team");
|
||||
xml.WriteString(spawner.Team.ToString());
|
||||
xml.WriteEndElement();
|
||||
|
||||
xml.WriteStartElement("creaturesname");
|
||||
foreach (var entry in spawner.Entries)
|
||||
{
|
||||
xml.WriteStartElement("creaturename");
|
||||
xml.WriteString(entry.SpawnedName);
|
||||
xml.WriteEndElement();
|
||||
}
|
||||
xml.WriteEndElement();
|
||||
|
||||
// Item properties
|
||||
|
||||
xml.WriteStartElement("name");
|
||||
xml.WriteString(spawner.Name);
|
||||
xml.WriteEndElement();
|
||||
|
||||
xml.WriteStartElement("location");
|
||||
xml.WriteString(spawner.Location.ToString());
|
||||
xml.WriteEndElement();
|
||||
|
||||
xml.WriteStartElement("map");
|
||||
xml.WriteString(spawner.Map.ToString());
|
||||
xml.WriteEndElement();
|
||||
|
||||
xml.WriteEndElement();
|
||||
}
|
||||
}
|
||||
|
||||
[Usage("ImportSpawners")]
|
||||
[Description("Recreates Spawner items from the specified file.")]
|
||||
public static void ImportSpawners_OnCommand(CommandEventArgs e)
|
||||
{
|
||||
if (e.Arguments.Length >= 1)
|
||||
{
|
||||
string filename = e.GetString(0);
|
||||
string filePath = Path.Combine("Saves/Spawners", filename);
|
||||
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.Load(filePath);
|
||||
|
||||
XmlElement root = doc["spawners"];
|
||||
|
||||
int successes = 0, failures = 0;
|
||||
|
||||
foreach (XmlElement spawner in root.GetElementsByTagName("spawner"))
|
||||
{
|
||||
try
|
||||
{
|
||||
ImportSpawner(spawner);
|
||||
successes++;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
failures++;
|
||||
Diagnostics.ExceptionLogging.LogException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
e.Mobile.SendMessage("{0} spawners loaded successfully from {1}, {2} failures.", successes, filePath, failures);
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Mobile.SendMessage("File {0} does not exist.", filePath);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Mobile.SendMessage("Usage: [ImportSpawners <filename>");
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetText(XmlNode node, string defaultValue)
|
||||
{
|
||||
if (node == null)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
return node.InnerText;
|
||||
}
|
||||
|
||||
private static void ImportSpawner(XmlNode node)
|
||||
{
|
||||
int count = int.Parse(GetText(node["count"], "1"));
|
||||
int homeRange = int.Parse(GetText(node["homerange"], "4"));
|
||||
|
||||
int walkingRange = int.Parse(GetText(node["walkingrange"], "-1"));
|
||||
|
||||
int team = int.Parse(GetText(node["team"], "0"));
|
||||
|
||||
bool group = bool.Parse(GetText(node["group"], "False"));
|
||||
TimeSpan maxDelay = TimeSpan.Parse(GetText(node["maxdelay"], "10:00"));
|
||||
TimeSpan minDelay = TimeSpan.Parse(GetText(node["mindelay"], "05:00"));
|
||||
IEnumerable<string> creaturesName = LoadCreaturesName(node["creaturesname"]);
|
||||
|
||||
string name = GetText(node["name"], "Spawner");
|
||||
Point3D location = Point3D.Parse(GetText(node["location"], "Error"));
|
||||
Map map = Map.Parse(GetText(node["map"], "Error"));
|
||||
|
||||
Spawner spawner = new Spawner(count, minDelay, maxDelay, team, homeRange, creaturesName.ToArray());
|
||||
if (walkingRange >= 0)
|
||||
{
|
||||
spawner.WalkingRange = walkingRange;
|
||||
}
|
||||
|
||||
spawner.Name = name;
|
||||
spawner.MoveToWorld(location, map);
|
||||
if (spawner.Map == Map.Internal)
|
||||
{
|
||||
spawner.Delete();
|
||||
throw new Exception("Spawner created on Internal map.");
|
||||
}
|
||||
spawner.Respawn();
|
||||
}
|
||||
|
||||
private static IEnumerable<string> LoadCreaturesName(XmlElement node)
|
||||
{
|
||||
List<string> names = new List<string>();
|
||||
|
||||
if (node != null)
|
||||
{
|
||||
foreach (XmlElement ele in node.GetElementsByTagName("creaturename"))
|
||||
{
|
||||
if (ele != null)
|
||||
{
|
||||
names.Add(ele.InnerText);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,721 @@
|
|||
using Server.Commands.Generic;
|
||||
using Server.Network;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using CPA = Server.CommandPropertyAttribute;
|
||||
/*
|
||||
** modified properties gumps taken from RC0 properties gump scripts to support the special XmlSpawner properties gump
|
||||
*/
|
||||
|
||||
namespace Server.Gumps;
|
||||
|
||||
public class XmlPropertiesGump : Gump
|
||||
{
|
||||
private readonly ArrayList m_List;
|
||||
private int m_Page;
|
||||
private readonly Mobile m_Mobile;
|
||||
private readonly object m_Object;
|
||||
private readonly Stack<StackEntry> m_Stack;
|
||||
|
||||
public static readonly bool OldStyle = PropsConfig.OldStyle;
|
||||
|
||||
public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX;
|
||||
public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY;
|
||||
|
||||
public static readonly int TextHue = PropsConfig.TextHue;
|
||||
public static readonly int TextOffsetX = PropsConfig.TextOffsetX;
|
||||
|
||||
public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID;
|
||||
public static readonly int EntryGumpID = PropsConfig.EntryGumpID;
|
||||
public static readonly int BackGumpID = PropsConfig.BackGumpID;
|
||||
public static readonly int SetGumpID = PropsConfig.SetGumpID;
|
||||
|
||||
public static readonly int SetWidth = PropsConfig.SetWidth;
|
||||
public static readonly int SetOffsetX = PropsConfig.SetOffsetX, SetOffsetY = PropsConfig.SetOffsetY;
|
||||
public static readonly int SetButtonID1 = PropsConfig.SetButtonID1;
|
||||
public static readonly int SetButtonID2 = PropsConfig.SetButtonID2;
|
||||
|
||||
public static readonly int OffsetSize = PropsConfig.OffsetSize;
|
||||
|
||||
public static readonly int EntryHeight = PropsConfig.EntryHeight;
|
||||
public static readonly int BorderSize = PropsConfig.BorderSize;
|
||||
|
||||
private static readonly int NameWidth = 103;
|
||||
private static readonly int ValueWidth = 82;
|
||||
|
||||
private static readonly int EntryCount = 66;
|
||||
private static readonly int ColumnEntryCount = 22;
|
||||
|
||||
private static readonly int TypeWidth = NameWidth + OffsetSize + ValueWidth;
|
||||
|
||||
private static readonly int TotalWidth = OffsetSize + NameWidth + OffsetSize + ValueWidth + OffsetSize + SetWidth + OffsetSize;
|
||||
|
||||
public XmlPropertiesGump(Mobile mobile, object o) : base(GumpOffsetX, GumpOffsetY)
|
||||
{
|
||||
m_Mobile = mobile;
|
||||
m_Object = o;
|
||||
m_List = BuildList();
|
||||
|
||||
Initialize(0);
|
||||
}
|
||||
|
||||
public XmlPropertiesGump(Mobile mobile, object o, Stack<StackEntry> stack, StackEntry parent) : base(GumpOffsetX, GumpOffsetY)
|
||||
{
|
||||
m_Mobile = mobile;
|
||||
m_Object = o;
|
||||
m_Stack = stack;
|
||||
m_List = BuildList();
|
||||
|
||||
if (parent != null)
|
||||
{
|
||||
if (m_Stack == null)
|
||||
{
|
||||
m_Stack = new Stack<Server.Gumps.StackEntry>();
|
||||
}
|
||||
|
||||
m_Stack.Push(parent);
|
||||
}
|
||||
|
||||
Initialize(0);
|
||||
}
|
||||
|
||||
public XmlPropertiesGump(Mobile mobile, object o, Stack<StackEntry> stack, ArrayList list, int page) : base(GumpOffsetX, GumpOffsetY)
|
||||
{
|
||||
m_Mobile = mobile;
|
||||
m_Object = o;
|
||||
m_List = list;
|
||||
m_Stack = stack;
|
||||
|
||||
Initialize(page);
|
||||
}
|
||||
|
||||
private void Initialize(int page)
|
||||
{
|
||||
m_Page = page;
|
||||
|
||||
int count = m_List.Count - page * EntryCount;
|
||||
|
||||
if (count < 0)
|
||||
{
|
||||
count = 0;
|
||||
}
|
||||
else if (count > EntryCount)
|
||||
{
|
||||
count = EntryCount;
|
||||
}
|
||||
|
||||
int lastIndex = page * EntryCount + count - 1;
|
||||
|
||||
if (lastIndex >= 0 && lastIndex < m_List.Count && m_List[lastIndex] == null)
|
||||
{
|
||||
--count;
|
||||
}
|
||||
|
||||
int totalHeight = OffsetSize + (EntryHeight + OffsetSize) * (ColumnEntryCount + 1);
|
||||
|
||||
AddPage(0);
|
||||
|
||||
AddBackground(0, 0, TotalWidth * 3 + BorderSize * 2, BorderSize + totalHeight + BorderSize, BackGumpID);
|
||||
AddImageTiled(BorderSize, BorderSize + EntryHeight, (TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0)) * 3, totalHeight - EntryHeight, OffsetGumpID);
|
||||
|
||||
int x = BorderSize + OffsetSize;
|
||||
int y = BorderSize;
|
||||
|
||||
if (m_Object is Item item)
|
||||
{
|
||||
AddLabelCropped(x + TextOffsetX, y, TypeWidth - TextOffsetX, EntryHeight, TextHue, item.Name);
|
||||
}
|
||||
|
||||
int propcount = 0;
|
||||
for (int i = 0, index = page * EntryCount; i <= count && index < m_List.Count; ++i, ++index)
|
||||
{
|
||||
// do the multi column display
|
||||
int column = propcount / ColumnEntryCount;
|
||||
if (propcount % ColumnEntryCount == 0)
|
||||
{
|
||||
y = BorderSize;
|
||||
}
|
||||
|
||||
x = BorderSize + OffsetSize + column * (ValueWidth + NameWidth + OffsetSize * 2 + SetOffsetX + SetWidth);
|
||||
y += EntryHeight + OffsetSize;
|
||||
|
||||
object o = m_List[index];
|
||||
|
||||
if (o == null)
|
||||
{
|
||||
AddImageTiled(x - OffsetSize, y, TotalWidth, EntryHeight, BackGumpID + 4);
|
||||
propcount++;
|
||||
}
|
||||
else if (o is PropertyInfo prop)
|
||||
{
|
||||
propcount++;
|
||||
|
||||
// look for the default value of the equivalent property in the XmlSpawnerDefaults.DefaultEntry class
|
||||
|
||||
int huemodifier = TextHue;
|
||||
Mobiles.XmlSpawnerDefaults.DefaultEntry de = new Mobiles.XmlSpawnerDefaults.DefaultEntry();
|
||||
Type ftype = de.GetType();
|
||||
|
||||
var finfo = ftype.GetField(prop.Name);
|
||||
|
||||
// is there an equivalent default field?
|
||||
if (finfo != null)
|
||||
{
|
||||
// see if the value is different from the default
|
||||
if (ValueToString(finfo.GetValue(de)) != ValueToString(prop))
|
||||
{
|
||||
huemodifier = 68;
|
||||
}
|
||||
}
|
||||
|
||||
AddImageTiled(x, y, NameWidth, EntryHeight, EntryGumpID);
|
||||
AddLabelCropped(x + TextOffsetX, y, NameWidth - TextOffsetX, EntryHeight, huemodifier, prop.Name);
|
||||
x += NameWidth + OffsetSize;
|
||||
AddImageTiled(x, y, ValueWidth, EntryHeight, EntryGumpID);
|
||||
AddLabelCropped(x + TextOffsetX, y, ValueWidth - TextOffsetX, EntryHeight, huemodifier, ValueToString(prop));
|
||||
x += ValueWidth + OffsetSize;
|
||||
|
||||
if (SetGumpID != 0)
|
||||
{
|
||||
AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID);
|
||||
}
|
||||
|
||||
CPA cpa = GetCPA(prop);
|
||||
|
||||
if (prop.CanWrite && cpa != null && m_Mobile.AccessLevel >= cpa.WriteLevel)
|
||||
{
|
||||
AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, i + 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string[] m_BoolNames = { "True", "False" };
|
||||
public static object[] m_BoolValues = { true, false };
|
||||
|
||||
public static string[] m_PoisonNames = { "None", "Lesser", "Regular", "Greater", "Deadly", "Lethal" };
|
||||
public static object[] m_PoisonValues = { null, Poison.Lesser, Poison.Regular, Poison.Greater, Poison.Deadly, Poison.Lethal };
|
||||
|
||||
public override void OnResponse(NetState state, RelayInfo info)
|
||||
{
|
||||
Mobile from = state.Mobile;
|
||||
|
||||
if (!BaseCommand.IsAccessible(from, m_Object))
|
||||
{
|
||||
from.SendMessage("You may no longer access their properties.");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (info.ButtonID)
|
||||
{
|
||||
case 0: // Closed
|
||||
{
|
||||
if (m_Stack != null && m_Stack.Count > 0)
|
||||
{
|
||||
StackEntry entry = m_Stack.Pop();
|
||||
from.SendGump(new XmlPropertiesGump(from, entry.m_Object, m_Stack, null));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 1: // Previous
|
||||
{
|
||||
if (m_Page > 0)
|
||||
{
|
||||
from.SendGump(new XmlPropertiesGump(from, m_Object, m_Stack, m_List, m_Page - 1));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 2: // Next
|
||||
{
|
||||
if ((m_Page + 1) * EntryCount < m_List.Count)
|
||||
{
|
||||
from.SendGump(new XmlPropertiesGump(from, m_Object, m_Stack, m_List, m_Page + 1));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
int index = m_Page * EntryCount + (info.ButtonID - 3);
|
||||
|
||||
if (index >= 0 && index < m_List.Count)
|
||||
{
|
||||
PropertyInfo prop = m_List[index] as PropertyInfo;
|
||||
|
||||
if (prop == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CPA attr = GetCPA(prop);
|
||||
|
||||
if (!prop.CanWrite || attr == null || from.AccessLevel < attr.WriteLevel)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Type type = prop.PropertyType;
|
||||
|
||||
if (IsType(type, typeofMobile) || IsType(type, typeofItem))
|
||||
{
|
||||
from.SendGump(new XmlSetObjectGump(prop, from, m_Object, m_Stack, type, m_Page, m_List));
|
||||
}
|
||||
else if (IsType(type, typeofType))
|
||||
{
|
||||
from.Target = new XmlSetObjectTarget(prop, from, m_Object, m_Stack, type, m_Page, m_List);
|
||||
}
|
||||
else if (IsType(type, typeofPoint3D))
|
||||
{
|
||||
from.SendGump(new XmlSetPoint3DGump(prop, from, m_Object, m_Stack, m_Page, m_List));
|
||||
}
|
||||
else if (IsType(type, typeofPoint2D))
|
||||
{
|
||||
from.SendGump(new XmlSetPoint2DGump(prop, from, m_Object, m_Stack, m_Page, m_List));
|
||||
}
|
||||
else if (IsType(type, typeofTimeSpan))
|
||||
{
|
||||
from.SendGump(new XmlSetTimeSpanGump(prop, from, m_Object, m_Stack, m_Page, m_List));
|
||||
}
|
||||
else if (IsCustomEnum(type))
|
||||
{
|
||||
from.SendGump(new XmlSetCustomEnumGump(prop, from, m_Object, m_Stack, m_Page, m_List, GetCustomEnumNames(type)));
|
||||
}
|
||||
else if (IsType(type, typeofEnum))
|
||||
{
|
||||
from.SendGump(new XmlSetListOptionGump(prop, from, m_Object, m_Stack, m_Page, m_List, Enum.GetNames(type), GetObjects(Enum.GetValues(type))));
|
||||
}
|
||||
else if (IsType(type, typeofBool))
|
||||
{
|
||||
from.SendGump(new XmlSetListOptionGump(prop, from, m_Object, m_Stack, m_Page, m_List, m_BoolNames, m_BoolValues));
|
||||
}
|
||||
else if (IsType(type, typeofString) || IsType(type, typeofReal) || IsType(type, typeofNumeric))
|
||||
{
|
||||
from.SendGump(new XmlSetGump(prop, from, m_Object, m_Stack, m_Page, m_List));
|
||||
}
|
||||
else if (IsType(type, typeofPoison))
|
||||
{
|
||||
from.SendGump(new XmlSetListOptionGump(prop, from, m_Object, m_Stack, m_Page, m_List, m_PoisonNames, m_PoisonValues));
|
||||
}
|
||||
else if (IsType(type, typeofMap))
|
||||
{
|
||||
from.SendGump(new XmlSetListOptionGump(prop, from, m_Object, m_Stack, m_Page, m_List, Map.GetMapNames(), Map.GetMapValues()));
|
||||
}
|
||||
else if (IsType(type, typeofSkills) && m_Object is Mobile mobile)
|
||||
{
|
||||
from.SendGump(new XmlPropertiesGump(from, mobile, m_Stack, m_List, m_Page));
|
||||
from.SendGump(new SkillsGump(from, mobile));
|
||||
}
|
||||
else if (HasAttribute(type, typeofPropertyObject, true))
|
||||
{
|
||||
object obj = prop.GetValue(m_Object, null);
|
||||
|
||||
from.SendGump(obj != null
|
||||
? new XmlPropertiesGump(from, obj, m_Stack,
|
||||
new StackEntry(m_Object, prop))
|
||||
: new XmlPropertiesGump(from, m_Object, m_Stack, m_List, m_Page));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static object[] GetObjects(Array a)
|
||||
{
|
||||
object[] list = new object[a.Length];
|
||||
|
||||
for (int i = 0; i < list.Length; ++i)
|
||||
{
|
||||
list[i] = a.GetValue(i);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private static bool IsCustomEnum(Type type) => type.IsDefined(typeofCustomEnum, false);
|
||||
|
||||
private static string[] GetCustomEnumNames(Type type)
|
||||
{
|
||||
object[] attrs = type.GetCustomAttributes(typeofCustomEnum, false);
|
||||
|
||||
if (attrs.Length == 0)
|
||||
{
|
||||
return new string[0];
|
||||
}
|
||||
|
||||
CustomEnumAttribute ce = attrs[0] as CustomEnumAttribute;
|
||||
|
||||
if (ce == null)
|
||||
{
|
||||
return new string[0];
|
||||
}
|
||||
|
||||
return ce.Names;
|
||||
}
|
||||
|
||||
private static bool HasAttribute(Type type, Type check, bool inherit)
|
||||
{
|
||||
object[] objs = type.GetCustomAttributes(check, inherit);
|
||||
|
||||
return objs.Length > 0;
|
||||
}
|
||||
|
||||
private static bool IsType(Type type, Type check) => type == check || type.IsSubclassOf(check);
|
||||
|
||||
private static bool IsType(Type type, Type[] check)
|
||||
{
|
||||
for (int i = 0; i < check.Length; ++i)
|
||||
{
|
||||
if (IsType(type, check[i]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static readonly Type typeofMobile = typeof(Mobile);
|
||||
private static readonly Type typeofItem = typeof(Item);
|
||||
private static readonly Type typeofType = typeof(Type);
|
||||
private static readonly Type typeofPoint3D = typeof(Point3D);
|
||||
private static readonly Type typeofPoint2D = typeof(Point2D);
|
||||
private static readonly Type typeofTimeSpan = typeof(TimeSpan);
|
||||
private static readonly Type typeofCustomEnum = typeof(CustomEnumAttribute);
|
||||
private static readonly Type typeofEnum = typeof(Enum);
|
||||
private static readonly Type typeofBool = typeof(bool);
|
||||
private static readonly Type typeofString = typeof(string);
|
||||
private static readonly Type typeofPoison = typeof(Poison);
|
||||
private static readonly Type typeofMap = typeof(Map);
|
||||
private static readonly Type typeofSkills = typeof(Skills);
|
||||
private static readonly Type typeofPropertyObject = typeof(PropertyObjectAttribute);
|
||||
private static readonly Type typeofNoSort = typeof(NoSortAttribute);
|
||||
|
||||
private static readonly Type[] typeofReal =
|
||||
{
|
||||
typeof(float),
|
||||
typeof(double)
|
||||
};
|
||||
|
||||
private static readonly Type[] typeofNumeric =
|
||||
{
|
||||
typeof(byte),
|
||||
typeof(short),
|
||||
typeof(int),
|
||||
typeof(long),
|
||||
typeof(sbyte),
|
||||
typeof(ushort),
|
||||
typeof(uint),
|
||||
typeof(ulong)
|
||||
};
|
||||
|
||||
private string ValueToString(PropertyInfo prop) => ValueToString(m_Object, prop);
|
||||
|
||||
public static string ValueToString(object obj, PropertyInfo prop)
|
||||
{
|
||||
try
|
||||
{
|
||||
return ValueToString(prop.GetValue(obj, null));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return $"!{e.GetType()}!";
|
||||
}
|
||||
}
|
||||
|
||||
public static string ValueToString(object o)
|
||||
{
|
||||
if (o == null)
|
||||
{
|
||||
return "-null-";
|
||||
}
|
||||
|
||||
if (o is string s1)
|
||||
{
|
||||
return $"\"{s1}\"";
|
||||
}
|
||||
|
||||
if (o is bool)
|
||||
{
|
||||
return o.ToString();
|
||||
}
|
||||
|
||||
if (o is char c)
|
||||
{
|
||||
return $"0x{(int)c:X} '{c}'";
|
||||
}
|
||||
|
||||
if (o is Serial s)
|
||||
{
|
||||
if (s.IsValid)
|
||||
{
|
||||
if (s.IsItem)
|
||||
{
|
||||
return $"(I) 0x{s.Value:X}";
|
||||
}
|
||||
if (s.IsMobile)
|
||||
{
|
||||
return $"(M) 0x{s.Value:X}";
|
||||
}
|
||||
}
|
||||
|
||||
return $"(?) 0x{s.Value:X}";
|
||||
}
|
||||
|
||||
if (o is byte || o is sbyte || o is short || o is ushort || o is int || o is uint || o is long || o is ulong)
|
||||
{
|
||||
return string.Format("{0} (0x{0:X})", o);
|
||||
}
|
||||
|
||||
if (o is double)
|
||||
{
|
||||
return o.ToString();
|
||||
}
|
||||
|
||||
if (o is Mobile mobile)
|
||||
{
|
||||
return $"(M) 0x{mobile.Serial.Value:X} \"{mobile.Name}\"";
|
||||
}
|
||||
|
||||
if (o is Item item)
|
||||
{
|
||||
return $"(I) 0x{item.Serial:X}";
|
||||
}
|
||||
|
||||
if (o is Type type)
|
||||
{
|
||||
return type.Name;
|
||||
}
|
||||
|
||||
return o.ToString();
|
||||
}
|
||||
|
||||
private ArrayList BuildList()
|
||||
{
|
||||
Type type = m_Object.GetType();
|
||||
|
||||
PropertyInfo[] props = type.GetProperties(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public);
|
||||
|
||||
ArrayList groups = GetGroups(type, props);
|
||||
ArrayList list = new ArrayList();
|
||||
|
||||
for (int i = 0; i < groups.Count; ++i)
|
||||
{
|
||||
DictionaryEntry de = (DictionaryEntry)groups[i];
|
||||
ArrayList groupList = (ArrayList)de.Value;
|
||||
|
||||
if (!HasAttribute((Type)de.Key, typeofNoSort, false))
|
||||
{
|
||||
groupList.Sort(PropertySorter.Instance);
|
||||
}
|
||||
|
||||
if (i != 0)
|
||||
{
|
||||
list.Add(null);
|
||||
}
|
||||
|
||||
list.Add(de.Key);
|
||||
list.AddRange(groupList);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private static readonly Type typeofCPA = typeof(CPA);
|
||||
private static readonly Type typeofObject = typeof(object);
|
||||
|
||||
private static CPA GetCPA(PropertyInfo prop)
|
||||
{
|
||||
object[] attrs = prop.GetCustomAttributes(typeofCPA, false);
|
||||
|
||||
if (attrs.Length > 0)
|
||||
{
|
||||
return attrs[0] as CPA;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private ArrayList GetGroups(Type objectType, PropertyInfo[] props)
|
||||
{
|
||||
Hashtable groups = new Hashtable();
|
||||
|
||||
for (int i = 0; i < props.Length; ++i)
|
||||
{
|
||||
PropertyInfo prop = props[i];
|
||||
|
||||
if (prop.CanRead)
|
||||
{
|
||||
CPA attr = GetCPA(prop);
|
||||
|
||||
if (attr != null && m_Mobile.AccessLevel >= attr.ReadLevel)
|
||||
{
|
||||
Type type = prop.DeclaringType;
|
||||
|
||||
while (true)
|
||||
{
|
||||
Type baseType = type.BaseType;
|
||||
|
||||
if (baseType == null || baseType == typeofObject)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (baseType.GetProperty(prop.Name, prop.PropertyType) != null)
|
||||
{
|
||||
type = baseType;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList list = (ArrayList)groups[type];
|
||||
|
||||
if (list == null)
|
||||
{
|
||||
groups[type] = list = new ArrayList();
|
||||
}
|
||||
|
||||
list.Add(prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList sorted = new ArrayList(groups);
|
||||
|
||||
sorted.Sort(new GroupComparer(objectType));
|
||||
|
||||
return sorted;
|
||||
}
|
||||
|
||||
public static object GetObjectFromString(Type t, string s)
|
||||
{
|
||||
if (t == typeof(string))
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
if (t == typeof(byte) || t == typeof(sbyte) || t == typeof(short) || t == typeof(ushort) || t == typeof(int) || t == typeof(uint) || t == typeof(long) || t == typeof(ulong))
|
||||
{
|
||||
if (s.StartsWith("0x"))
|
||||
{
|
||||
if (t == typeof(ulong) || t == typeof(uint) || t == typeof(ushort) || t == typeof(byte))
|
||||
{
|
||||
return Convert.ChangeType(Convert.ToUInt64(s.Substring(2), 16), t);
|
||||
}
|
||||
|
||||
return Convert.ChangeType(Convert.ToInt64(s.Substring(2), 16), t);
|
||||
}
|
||||
|
||||
return Convert.ChangeType(s, t);
|
||||
}
|
||||
|
||||
if (t == typeof(double) || t == typeof(float))
|
||||
{
|
||||
return Convert.ChangeType(s, t);
|
||||
}
|
||||
if (t.IsDefined(typeof(ParsableAttribute), false))
|
||||
{
|
||||
MethodInfo parseMethod = t.GetMethod("Parse", new[] { typeof(string) });
|
||||
|
||||
return parseMethod.Invoke(null, new object[] { s });
|
||||
}
|
||||
|
||||
throw new Exception("bad");
|
||||
}
|
||||
|
||||
private class PropertySorter : IComparer
|
||||
{
|
||||
public static readonly PropertySorter Instance = new();
|
||||
|
||||
private PropertySorter()
|
||||
{
|
||||
}
|
||||
|
||||
public int Compare(object x, object y)
|
||||
{
|
||||
if (x == null && y == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (x == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (y == null)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
PropertyInfo a = x as PropertyInfo;
|
||||
PropertyInfo b = y as PropertyInfo;
|
||||
|
||||
if (a == null || b == null)
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
return a.Name.CompareTo(b.Name);
|
||||
}
|
||||
}
|
||||
|
||||
private class GroupComparer : IComparer
|
||||
{
|
||||
private readonly Type m_Start;
|
||||
|
||||
public GroupComparer(Type start) => m_Start = start;
|
||||
|
||||
private static readonly Type typeofObject = typeof(object);
|
||||
|
||||
private int GetDistance(Type type)
|
||||
{
|
||||
Type current = m_Start;
|
||||
|
||||
int dist;
|
||||
|
||||
for (dist = 0; current != null && current != typeofObject && current != type; ++dist)
|
||||
{
|
||||
current = current.BaseType;
|
||||
}
|
||||
|
||||
return dist;
|
||||
}
|
||||
|
||||
public int Compare(object x, object y)
|
||||
{
|
||||
if (x == null && y == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (x == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (y == null)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(x is DictionaryEntry de1) || !(y is DictionaryEntry de2))
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
Type a = (Type)de1.Key;
|
||||
Type b = (Type)de2.Key;
|
||||
|
||||
return GetDistance(a).CompareTo(GetDistance(b));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
using Server.Commands;
|
||||
using Server.Network;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Server.Gumps;
|
||||
|
||||
public class XmlSetCustomEnumGump : XmlSetListOptionGump
|
||||
{
|
||||
private readonly string[] m_Names;
|
||||
public XmlSetCustomEnumGump(PropertyInfo prop, Mobile mobile, object o, Stack<StackEntry> stack, int propspage, ArrayList list, string[] names) : base(prop, mobile, o, stack, propspage, list, names, null)
|
||||
{
|
||||
m_Names = names;
|
||||
}
|
||||
|
||||
public override void OnResponse(NetState sender, RelayInfo relayInfo)
|
||||
{
|
||||
int index = relayInfo.ButtonID - 1;
|
||||
|
||||
if (index >= 0 && index < m_Names.Length)
|
||||
{
|
||||
try
|
||||
{
|
||||
MethodInfo info = m_Property.PropertyType.GetMethod("Parse", new[] { typeof(string) });
|
||||
|
||||
CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, m_Names[index]);
|
||||
|
||||
if (info != null)
|
||||
{
|
||||
m_Property.SetValue(m_Object, info.Invoke(null, new object[] { m_Names[index] }), null);
|
||||
}
|
||||
else if (m_Property.PropertyType == typeof(Enum) || m_Property.PropertyType.IsSubclassOf(typeof(Enum)))
|
||||
{
|
||||
m_Property.SetValue(m_Object, Enum.Parse(m_Property.PropertyType, m_Names[index], false), null);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
m_Mobile.SendMessage("An exception was caught. The property may not have changed.");
|
||||
}
|
||||
}
|
||||
|
||||
m_Mobile.SendGump(new XmlPropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,250 @@
|
|||
using Server.Commands;
|
||||
using Server.HuePickers;
|
||||
using Server.Network;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Server.Gumps;
|
||||
|
||||
public class XmlSetGump : Gump
|
||||
{
|
||||
private readonly PropertyInfo m_Property;
|
||||
private readonly Mobile m_Mobile;
|
||||
private readonly object m_Object;
|
||||
private readonly Stack<StackEntry> m_Stack;
|
||||
private readonly int m_Page;
|
||||
private readonly ArrayList m_List;
|
||||
|
||||
public static readonly bool OldStyle = PropsConfig.OldStyle;
|
||||
|
||||
public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX;
|
||||
public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY;
|
||||
|
||||
public static readonly int TextHue = PropsConfig.TextHue;
|
||||
public static readonly int TextOffsetX = PropsConfig.TextOffsetX;
|
||||
|
||||
public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID;
|
||||
public static readonly int EntryGumpID = PropsConfig.EntryGumpID;
|
||||
public static readonly int BackGumpID = PropsConfig.BackGumpID;
|
||||
public static readonly int SetGumpID = PropsConfig.SetGumpID;
|
||||
|
||||
public static readonly int SetWidth = PropsConfig.SetWidth;
|
||||
public static readonly int SetOffsetX = PropsConfig.SetOffsetX, SetOffsetY = PropsConfig.SetOffsetY;
|
||||
public static readonly int SetButtonID1 = PropsConfig.SetButtonID1;
|
||||
public static readonly int SetButtonID2 = PropsConfig.SetButtonID2;
|
||||
|
||||
public static readonly int OffsetSize = PropsConfig.OffsetSize;
|
||||
|
||||
public static readonly int EntryHeight = PropsConfig.EntryHeight;
|
||||
public static readonly int BorderSize = PropsConfig.BorderSize;
|
||||
|
||||
private static readonly int EntryWidth = 212;
|
||||
|
||||
private static readonly int TotalWidth = OffsetSize + EntryWidth + OffsetSize + SetWidth + OffsetSize;
|
||||
private static readonly int TotalHeight = OffsetSize + 2 * (EntryHeight + OffsetSize);
|
||||
|
||||
private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize;
|
||||
private static readonly int BackHeight = BorderSize + TotalHeight + BorderSize;
|
||||
|
||||
public XmlSetGump(PropertyInfo prop, Mobile mobile, object o, Stack<StackEntry> stack, int page, ArrayList list) : base(GumpOffsetX, GumpOffsetY)
|
||||
{
|
||||
m_Property = prop;
|
||||
m_Mobile = mobile;
|
||||
m_Object = o;
|
||||
m_Stack = stack;
|
||||
m_Page = page;
|
||||
m_List = list;
|
||||
|
||||
bool canNull = !prop.PropertyType.IsValueType;
|
||||
bool canDye = prop.IsDefined(typeof(HueAttribute), false);
|
||||
|
||||
int xextend = 0;
|
||||
if (prop.PropertyType == typeof(string))
|
||||
{
|
||||
xextend = 300;
|
||||
}
|
||||
|
||||
object val = prop.GetValue(m_Object, null);
|
||||
|
||||
var initialText = val == null ? "" : val.ToString();
|
||||
|
||||
AddPage(0);
|
||||
|
||||
AddBackground(0, 0, BackWidth + xextend, BackHeight + (canNull ? EntryHeight + OffsetSize : 0) + (canDye ? EntryHeight + OffsetSize : 0), BackGumpID);
|
||||
AddImageTiled(BorderSize, BorderSize, TotalWidth + xextend - (OldStyle ? SetWidth + OffsetSize : 0), TotalHeight + (canNull ? EntryHeight + OffsetSize : 0) + (canDye ? EntryHeight + OffsetSize : 0), OffsetGumpID);
|
||||
|
||||
int x = BorderSize + OffsetSize;
|
||||
int y = BorderSize + OffsetSize;
|
||||
|
||||
AddImageTiled(x, y, EntryWidth + xextend, EntryHeight, EntryGumpID);
|
||||
AddLabelCropped(x + TextOffsetX, y, EntryWidth + xextend - TextOffsetX, EntryHeight, TextHue, prop.Name);
|
||||
x += EntryWidth + xextend + OffsetSize;
|
||||
|
||||
if (SetGumpID != 0)
|
||||
{
|
||||
AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID);
|
||||
}
|
||||
|
||||
x = BorderSize + OffsetSize;
|
||||
y += EntryHeight + OffsetSize;
|
||||
|
||||
AddImageTiled(x, y, EntryWidth + xextend, EntryHeight, EntryGumpID);
|
||||
AddTextEntry(x + TextOffsetX, y, EntryWidth + xextend - TextOffsetX, EntryHeight, TextHue, 0, initialText);
|
||||
x += EntryWidth + xextend + OffsetSize;
|
||||
|
||||
if (SetGumpID != 0)
|
||||
{
|
||||
AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID);
|
||||
}
|
||||
|
||||
AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 1);
|
||||
|
||||
if (canNull)
|
||||
{
|
||||
x = BorderSize + OffsetSize;
|
||||
y += EntryHeight + OffsetSize;
|
||||
|
||||
AddImageTiled(x, y, EntryWidth + xextend, EntryHeight, EntryGumpID);
|
||||
AddLabelCropped(x + TextOffsetX, y, EntryWidth + xextend - TextOffsetX, EntryHeight, TextHue, "Null");
|
||||
x += EntryWidth + xextend + OffsetSize;
|
||||
|
||||
if (SetGumpID != 0)
|
||||
{
|
||||
AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID);
|
||||
}
|
||||
|
||||
AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 2);
|
||||
}
|
||||
|
||||
if (canDye)
|
||||
{
|
||||
x = BorderSize + OffsetSize;
|
||||
y += EntryHeight + OffsetSize;
|
||||
|
||||
AddImageTiled(x, y, EntryWidth + xextend, EntryHeight, EntryGumpID);
|
||||
AddLabelCropped(x + TextOffsetX, y, EntryWidth + xextend - TextOffsetX, EntryHeight, TextHue, "Hue Picker");
|
||||
x += EntryWidth + xextend + OffsetSize;
|
||||
|
||||
if (SetGumpID != 0)
|
||||
{
|
||||
AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID);
|
||||
}
|
||||
|
||||
AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 3);
|
||||
}
|
||||
}
|
||||
|
||||
private class InternalPicker : HuePicker
|
||||
{
|
||||
private readonly PropertyInfo m_Property;
|
||||
private readonly Mobile m_Mobile;
|
||||
private readonly object m_Object;
|
||||
private readonly Stack<StackEntry> m_Stack;
|
||||
private readonly int m_Page;
|
||||
private readonly ArrayList m_List;
|
||||
|
||||
public InternalPicker(PropertyInfo prop, Mobile mobile, object o, Stack<StackEntry> stack, int page, ArrayList list) : base(((IHued)o).HuedItemID)
|
||||
{
|
||||
m_Property = prop;
|
||||
m_Mobile = mobile;
|
||||
m_Object = o;
|
||||
m_Stack = stack;
|
||||
m_Page = page;
|
||||
m_List = list;
|
||||
}
|
||||
|
||||
public override void OnResponse(int hue)
|
||||
{
|
||||
try
|
||||
{
|
||||
CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, hue.ToString());
|
||||
m_Property.SetValue(m_Object, hue, null);
|
||||
}
|
||||
catch
|
||||
{
|
||||
m_Mobile.SendMessage("An exception was caught. The property may not have changed.");
|
||||
}
|
||||
|
||||
m_Mobile.SendGump(new XmlPropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page));
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnResponse(NetState sender, RelayInfo info)
|
||||
{
|
||||
object toSet;
|
||||
bool shouldSet, shouldSend = true;
|
||||
|
||||
switch (info.ButtonID)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
TextRelay text = info.GetTextEntry(0);
|
||||
|
||||
if (text != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
toSet = XmlPropertiesGump.GetObjectFromString(m_Property.PropertyType, text.Text);
|
||||
shouldSet = true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
toSet = null;
|
||||
shouldSet = false;
|
||||
m_Mobile.SendMessage("Bad format");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
toSet = null;
|
||||
shouldSet = false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 2: // Null
|
||||
{
|
||||
toSet = null;
|
||||
shouldSet = true;
|
||||
|
||||
break;
|
||||
}
|
||||
case 3: // Hue Picker
|
||||
{
|
||||
toSet = null;
|
||||
shouldSet = false;
|
||||
shouldSend = false;
|
||||
|
||||
m_Mobile.SendHuePicker(new InternalPicker(m_Property, m_Mobile, m_Object, m_Stack, m_Page, m_List));
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
toSet = null;
|
||||
shouldSet = false;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldSet)
|
||||
{
|
||||
try
|
||||
{
|
||||
CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, toSet == null ? "(null)" : toSet.ToString());
|
||||
m_Property.SetValue(m_Object, toSet, null);
|
||||
}
|
||||
catch
|
||||
{
|
||||
m_Mobile.SendMessage("An exception was caught. The property may not have changed.");
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldSend)
|
||||
{
|
||||
m_Mobile.SendGump(new XmlPropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
using Server.Commands;
|
||||
using Server.Network;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Server.Gumps;
|
||||
|
||||
public class XmlSetListOptionGump : Gump
|
||||
{
|
||||
protected PropertyInfo m_Property;
|
||||
protected Mobile m_Mobile;
|
||||
protected object m_Object;
|
||||
protected Stack<StackEntry> m_Stack;
|
||||
protected int m_Page;
|
||||
protected ArrayList m_List;
|
||||
|
||||
public static readonly bool OldStyle = PropsConfig.OldStyle;
|
||||
|
||||
public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX;
|
||||
public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY;
|
||||
|
||||
public static readonly int TextHue = PropsConfig.TextHue;
|
||||
public static readonly int TextOffsetX = PropsConfig.TextOffsetX;
|
||||
|
||||
public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID;
|
||||
public static readonly int HeaderGumpID = PropsConfig.HeaderGumpID;
|
||||
public static readonly int EntryGumpID = PropsConfig.EntryGumpID;
|
||||
public static readonly int BackGumpID = PropsConfig.BackGumpID;
|
||||
public static readonly int SetGumpID = PropsConfig.SetGumpID;
|
||||
|
||||
public static readonly int SetWidth = PropsConfig.SetWidth;
|
||||
public static readonly int SetOffsetX = PropsConfig.SetOffsetX, SetOffsetY = PropsConfig.SetOffsetY;
|
||||
public static readonly int SetButtonID1 = PropsConfig.SetButtonID1;
|
||||
public static readonly int SetButtonID2 = PropsConfig.SetButtonID2;
|
||||
|
||||
public static readonly int PrevWidth = PropsConfig.PrevWidth;
|
||||
public static readonly int PrevOffsetX = PropsConfig.PrevOffsetX, PrevOffsetY = PropsConfig.PrevOffsetY;
|
||||
public static readonly int PrevButtonID1 = PropsConfig.PrevButtonID1;
|
||||
public static readonly int PrevButtonID2 = PropsConfig.PrevButtonID2;
|
||||
|
||||
public static readonly int NextWidth = PropsConfig.NextWidth;
|
||||
public static readonly int NextOffsetX = PropsConfig.NextOffsetX, NextOffsetY = PropsConfig.NextOffsetY;
|
||||
public static readonly int NextButtonID1 = PropsConfig.NextButtonID1;
|
||||
public static readonly int NextButtonID2 = PropsConfig.NextButtonID2;
|
||||
|
||||
public static readonly int OffsetSize = PropsConfig.OffsetSize;
|
||||
|
||||
public static readonly int EntryHeight = PropsConfig.EntryHeight;
|
||||
public static readonly int BorderSize = PropsConfig.BorderSize;
|
||||
|
||||
private static readonly int EntryWidth = 212;
|
||||
private static readonly int EntryCount = 13;
|
||||
|
||||
private static readonly int TotalWidth = OffsetSize + EntryWidth + OffsetSize + SetWidth + OffsetSize;
|
||||
|
||||
private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize;
|
||||
|
||||
private static readonly bool PrevLabel = OldStyle, NextLabel = OldStyle;
|
||||
|
||||
private static readonly int PrevLabelOffsetX = PrevWidth + 1;
|
||||
private static readonly int PrevLabelOffsetY = 0;
|
||||
|
||||
private static readonly int NextLabelOffsetX = -29;
|
||||
private static readonly int NextLabelOffsetY = 0;
|
||||
|
||||
protected object[] m_Values;
|
||||
|
||||
public XmlSetListOptionGump(PropertyInfo prop, Mobile mobile, object o, Stack<StackEntry> stack, int propspage, ArrayList list, string[] names, object[] values) : base(GumpOffsetX, GumpOffsetY)
|
||||
{
|
||||
m_Property = prop;
|
||||
m_Mobile = mobile;
|
||||
m_Object = o;
|
||||
m_Stack = stack;
|
||||
m_Page = propspage;
|
||||
m_List = list;
|
||||
|
||||
m_Values = values;
|
||||
|
||||
int pages = (names.Length + EntryCount - 1) / EntryCount;
|
||||
int index = 0;
|
||||
|
||||
for (int page = 1; page <= pages; ++page)
|
||||
{
|
||||
AddPage(page);
|
||||
|
||||
int start = (page - 1) * EntryCount;
|
||||
int count = names.Length - start;
|
||||
|
||||
if (count > EntryCount)
|
||||
{
|
||||
count = EntryCount;
|
||||
}
|
||||
|
||||
int totalHeight = OffsetSize + (count + 2) * (EntryHeight + OffsetSize);
|
||||
int backHeight = BorderSize + totalHeight + BorderSize;
|
||||
|
||||
AddBackground(0, 0, BackWidth, backHeight, BackGumpID);
|
||||
AddImageTiled(BorderSize, BorderSize, TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), totalHeight, OffsetGumpID);
|
||||
|
||||
|
||||
|
||||
int x = BorderSize + OffsetSize;
|
||||
int y = BorderSize + OffsetSize;
|
||||
|
||||
int emptyWidth = TotalWidth - PrevWidth - NextWidth - OffsetSize * 4 - (OldStyle ? SetWidth + OffsetSize : 0);
|
||||
|
||||
AddImageTiled(x, y, PrevWidth, EntryHeight, HeaderGumpID);
|
||||
|
||||
if (page > 1)
|
||||
{
|
||||
AddButton(x + PrevOffsetX, y + PrevOffsetY, PrevButtonID1, PrevButtonID2, 0, GumpButtonType.Page, page - 1);
|
||||
|
||||
if (PrevLabel)
|
||||
{
|
||||
AddLabel(x + PrevLabelOffsetX, y + PrevLabelOffsetY, TextHue, "Previous");
|
||||
}
|
||||
}
|
||||
|
||||
x += PrevWidth + OffsetSize;
|
||||
|
||||
if (!OldStyle)
|
||||
{
|
||||
AddImageTiled(x - (OldStyle ? OffsetSize : 0), y, emptyWidth + (OldStyle ? OffsetSize * 2 : 0), EntryHeight, HeaderGumpID);
|
||||
}
|
||||
|
||||
x += emptyWidth + OffsetSize;
|
||||
|
||||
if (!OldStyle)
|
||||
{
|
||||
AddImageTiled(x, y, NextWidth, EntryHeight, HeaderGumpID);
|
||||
}
|
||||
|
||||
if (page < pages)
|
||||
{
|
||||
AddButton(x + NextOffsetX, y + NextOffsetY, NextButtonID1, NextButtonID2, 0, GumpButtonType.Page, page + 1);
|
||||
|
||||
if (NextLabel)
|
||||
{
|
||||
AddLabel(x + NextLabelOffsetX, y + NextLabelOffsetY, TextHue, "Next");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
AddRect(0, prop.Name, 0);
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
AddRect(i + 1, names[index], ++index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AddRect(int index, string str, int button)
|
||||
{
|
||||
int x = BorderSize + OffsetSize;
|
||||
int y = BorderSize + OffsetSize + (index + 1) * (EntryHeight + OffsetSize);
|
||||
|
||||
AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID);
|
||||
AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, str);
|
||||
|
||||
x += EntryWidth + OffsetSize;
|
||||
|
||||
if (SetGumpID != 0)
|
||||
{
|
||||
AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID);
|
||||
}
|
||||
|
||||
if (button != 0)
|
||||
{
|
||||
AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, button);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnResponse(NetState sender, RelayInfo info)
|
||||
{
|
||||
int index = info.ButtonID - 1;
|
||||
|
||||
if (index >= 0 && index < m_Values.Length)
|
||||
{
|
||||
try
|
||||
{
|
||||
object toSet = m_Values[index];
|
||||
CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, toSet == null ? "(-null-)" : toSet.ToString());
|
||||
m_Property.SetValue(m_Object, toSet, null);
|
||||
}
|
||||
catch
|
||||
{
|
||||
m_Mobile.SendMessage("An exception was caught. The property may not have changed.");
|
||||
}
|
||||
}
|
||||
|
||||
m_Mobile.SendGump(new XmlPropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,302 @@
|
|||
using Server.Commands;
|
||||
using Server.Commands.Generic;
|
||||
using Server.Network;
|
||||
using Server.Prompts;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Server.Gumps;
|
||||
|
||||
public class XmlSetObjectGump : Gump
|
||||
{
|
||||
private readonly PropertyInfo m_Property;
|
||||
private readonly Mobile m_Mobile;
|
||||
private readonly object m_Object;
|
||||
private readonly Stack<StackEntry> m_Stack;
|
||||
private readonly Type m_Type;
|
||||
private readonly int m_Page;
|
||||
private readonly ArrayList m_List;
|
||||
|
||||
public static readonly bool OldStyle = PropsConfig.OldStyle;
|
||||
|
||||
public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX;
|
||||
public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY;
|
||||
|
||||
public static readonly int TextHue = PropsConfig.TextHue;
|
||||
public static readonly int TextOffsetX = PropsConfig.TextOffsetX;
|
||||
|
||||
public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID;
|
||||
public static readonly int EntryGumpID = PropsConfig.EntryGumpID;
|
||||
public static readonly int BackGumpID = PropsConfig.BackGumpID;
|
||||
public static readonly int SetGumpID = PropsConfig.SetGumpID;
|
||||
|
||||
public static readonly int SetWidth = PropsConfig.SetWidth;
|
||||
public static readonly int SetOffsetX = PropsConfig.SetOffsetX, SetOffsetY = PropsConfig.SetOffsetY;
|
||||
public static readonly int SetButtonID1 = PropsConfig.SetButtonID1;
|
||||
public static readonly int SetButtonID2 = PropsConfig.SetButtonID2;
|
||||
|
||||
public static readonly int OffsetSize = PropsConfig.OffsetSize;
|
||||
|
||||
public static readonly int EntryHeight = PropsConfig.EntryHeight;
|
||||
public static readonly int BorderSize = PropsConfig.BorderSize;
|
||||
|
||||
private static readonly int EntryWidth = 212;
|
||||
|
||||
private static readonly int TotalWidth = OffsetSize + EntryWidth + OffsetSize + SetWidth + OffsetSize;
|
||||
private static readonly int TotalHeight = OffsetSize + 5 * (EntryHeight + OffsetSize);
|
||||
|
||||
private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize;
|
||||
private static readonly int BackHeight = BorderSize + TotalHeight + BorderSize;
|
||||
|
||||
public XmlSetObjectGump(PropertyInfo prop, Mobile mobile, object o, Stack<StackEntry> stack, Type type, int page, ArrayList list) : base(GumpOffsetX, GumpOffsetY)
|
||||
{
|
||||
m_Property = prop;
|
||||
m_Mobile = mobile;
|
||||
m_Object = o;
|
||||
m_Stack = stack;
|
||||
m_Type = type;
|
||||
m_Page = page;
|
||||
m_List = list;
|
||||
|
||||
string initialText = XmlPropertiesGump.ValueToString(o, prop);
|
||||
|
||||
AddPage(0);
|
||||
|
||||
AddBackground(0, 0, BackWidth, BackHeight, BackGumpID);
|
||||
AddImageTiled(BorderSize, BorderSize, TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), TotalHeight, OffsetGumpID);
|
||||
|
||||
int x = BorderSize + OffsetSize;
|
||||
int y = BorderSize + OffsetSize;
|
||||
|
||||
AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID);
|
||||
AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, prop.Name);
|
||||
x += EntryWidth + OffsetSize;
|
||||
|
||||
if (SetGumpID != 0)
|
||||
{
|
||||
AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID);
|
||||
}
|
||||
|
||||
x = BorderSize + OffsetSize;
|
||||
y += EntryHeight + OffsetSize;
|
||||
|
||||
AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID);
|
||||
AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, initialText);
|
||||
x += EntryWidth + OffsetSize;
|
||||
|
||||
if (SetGumpID != 0)
|
||||
{
|
||||
AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID);
|
||||
}
|
||||
|
||||
AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 1);
|
||||
|
||||
x = BorderSize + OffsetSize;
|
||||
y += EntryHeight + OffsetSize;
|
||||
|
||||
AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID);
|
||||
AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, "Change by Serial");
|
||||
x += EntryWidth + OffsetSize;
|
||||
|
||||
if (SetGumpID != 0)
|
||||
{
|
||||
AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID);
|
||||
}
|
||||
|
||||
AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 2);
|
||||
|
||||
x = BorderSize + OffsetSize;
|
||||
y += EntryHeight + OffsetSize;
|
||||
|
||||
AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID);
|
||||
AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, "Nullify");
|
||||
x += EntryWidth + OffsetSize;
|
||||
|
||||
if (SetGumpID != 0)
|
||||
{
|
||||
AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID);
|
||||
}
|
||||
|
||||
AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 3);
|
||||
|
||||
x = BorderSize + OffsetSize;
|
||||
y += EntryHeight + OffsetSize;
|
||||
|
||||
AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID);
|
||||
AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, "View Properties");
|
||||
x += EntryWidth + OffsetSize;
|
||||
|
||||
if (SetGumpID != 0)
|
||||
{
|
||||
AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID);
|
||||
}
|
||||
|
||||
AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 4);
|
||||
}
|
||||
|
||||
private class InternalPrompt : Prompt
|
||||
{
|
||||
private readonly PropertyInfo m_Property;
|
||||
private readonly Mobile m_Mobile;
|
||||
private readonly object m_Object;
|
||||
private readonly Stack<StackEntry> m_Stack;
|
||||
private readonly Type m_Type;
|
||||
private readonly int m_Page;
|
||||
private readonly ArrayList m_List;
|
||||
|
||||
public InternalPrompt(PropertyInfo prop, Mobile mobile, object o, Stack<StackEntry> stack, Type type, int page, ArrayList list)
|
||||
{
|
||||
m_Property = prop;
|
||||
m_Mobile = mobile;
|
||||
m_Object = o;
|
||||
m_Stack = stack;
|
||||
m_Type = type;
|
||||
m_Page = page;
|
||||
m_List = list;
|
||||
}
|
||||
|
||||
public override void OnCancel(Mobile from)
|
||||
{
|
||||
m_Mobile.SendGump(new XmlSetObjectGump(m_Property, m_Mobile, m_Object, m_Stack, m_Type, m_Page, m_List));
|
||||
}
|
||||
|
||||
public override void OnResponse(Mobile from, string text)
|
||||
{
|
||||
object toSet;
|
||||
bool shouldSet;
|
||||
|
||||
try
|
||||
{
|
||||
var serial = Utility.ToUInt32(text);
|
||||
toSet = World.FindEntity((Serial)serial);
|
||||
|
||||
if (toSet == null)
|
||||
{
|
||||
shouldSet = false;
|
||||
m_Mobile.SendMessage("No object with that serial was found.");
|
||||
}
|
||||
else if (!m_Type.IsInstanceOfType(toSet))
|
||||
{
|
||||
toSet = null;
|
||||
shouldSet = false;
|
||||
m_Mobile.SendMessage("The object with that serial could not be assigned to a property of type : {0}", m_Type.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
shouldSet = true;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
toSet = null;
|
||||
shouldSet = false;
|
||||
m_Mobile.SendMessage("Bad format");
|
||||
}
|
||||
|
||||
if (shouldSet)
|
||||
{
|
||||
try
|
||||
{
|
||||
CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, toSet.ToString());
|
||||
m_Property.SetValue(m_Object, toSet, null);
|
||||
}
|
||||
catch
|
||||
{
|
||||
m_Mobile.SendMessage("An exception was caught. The property may not have changed.");
|
||||
}
|
||||
}
|
||||
|
||||
m_Mobile.SendGump(new XmlSetObjectGump(m_Property, m_Mobile, m_Object, m_Stack, m_Type, m_Page, m_List));
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnResponse(NetState sender, RelayInfo info)
|
||||
{
|
||||
bool shouldSet, shouldSend = true;
|
||||
object viewProps = null;
|
||||
|
||||
switch (info.ButtonID)
|
||||
{
|
||||
case 0: // closed
|
||||
{
|
||||
m_Mobile.SendGump(new XmlPropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page));
|
||||
shouldSet = false;
|
||||
shouldSend = false;
|
||||
|
||||
break;
|
||||
}
|
||||
case 1: // Change by Target
|
||||
{
|
||||
m_Mobile.Target = new XmlSetObjectTarget(m_Property, m_Mobile, m_Object, m_Stack, m_Type, m_Page, m_List);
|
||||
shouldSet = false;
|
||||
shouldSend = false;
|
||||
break;
|
||||
}
|
||||
case 2: // Change by Serial
|
||||
{
|
||||
shouldSet = false;
|
||||
shouldSend = false;
|
||||
m_Mobile.SendMessage("Enter the serial you wish to find:");
|
||||
m_Mobile.Prompt = new InternalPrompt(m_Property, m_Mobile, m_Object, m_Stack, m_Type, m_Page, m_List);
|
||||
|
||||
break;
|
||||
}
|
||||
case 3: // Nullify
|
||||
{
|
||||
shouldSet = true;
|
||||
break;
|
||||
}
|
||||
case 4: // View Properties
|
||||
{
|
||||
shouldSet = false;
|
||||
|
||||
object obj = m_Property.GetValue(m_Object, null);
|
||||
|
||||
if (obj == null)
|
||||
{
|
||||
m_Mobile.SendMessage("The property is null and so you cannot view its properties.");
|
||||
}
|
||||
else if (!BaseCommand.IsAccessible(m_Mobile, obj))
|
||||
{
|
||||
m_Mobile.SendMessage("You may not view their properties.");
|
||||
}
|
||||
else
|
||||
{
|
||||
viewProps = obj;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
shouldSet = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldSet)
|
||||
{
|
||||
try
|
||||
{
|
||||
CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, "(null)");
|
||||
m_Property.SetValue(m_Object, null, null);
|
||||
}
|
||||
catch
|
||||
{
|
||||
m_Mobile.SendMessage("An exception was caught. The property may not have changed.");
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldSend)
|
||||
{
|
||||
m_Mobile.SendGump(new XmlSetObjectGump(m_Property, m_Mobile, m_Object, m_Stack, m_Type, m_Page, m_List));
|
||||
}
|
||||
|
||||
if (viewProps != null)
|
||||
{
|
||||
m_Mobile.SendGump(new XmlPropertiesGump(m_Mobile, viewProps));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
using Server.Commands;
|
||||
using Server.Items;
|
||||
using Server.Targeting;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Server.Gumps;
|
||||
|
||||
public class XmlSetObjectTarget : Target
|
||||
{
|
||||
private readonly PropertyInfo m_Property;
|
||||
private readonly Mobile m_Mobile;
|
||||
private readonly object m_Object;
|
||||
private readonly Stack<StackEntry> m_Stack;
|
||||
private readonly Type m_Type;
|
||||
private readonly int m_Page;
|
||||
private readonly ArrayList m_List;
|
||||
|
||||
public XmlSetObjectTarget(PropertyInfo prop, Mobile mobile, object o, Stack<StackEntry> stack, Type type, int page, ArrayList list) : base(-1, false, TargetFlags.None)
|
||||
{
|
||||
m_Property = prop;
|
||||
m_Mobile = mobile;
|
||||
m_Object = o;
|
||||
m_Stack = stack;
|
||||
m_Type = type;
|
||||
m_Page = page;
|
||||
m_List = list;
|
||||
}
|
||||
|
||||
protected override void OnTarget(Mobile from, object targeted)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (m_Type == typeof(Type))
|
||||
{
|
||||
targeted = targeted.GetType();
|
||||
}
|
||||
else if ((m_Type == typeof(BaseAddon) || m_Type.IsAssignableFrom(typeof(BaseAddon))) && targeted is AddonComponent component)
|
||||
{
|
||||
targeted = component.Addon;
|
||||
}
|
||||
|
||||
if (m_Type.IsInstanceOfType(targeted))
|
||||
{
|
||||
CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, targeted.ToString());
|
||||
m_Property.SetValue(m_Object, targeted, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Mobile.SendMessage("That cannot be assigned to a property of type : {0}", m_Type.Name);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
m_Mobile.SendMessage("An exception was caught. The property may not have changed.");
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnTargetFinish(Mobile from)
|
||||
{
|
||||
if (m_Type == typeof(Type))
|
||||
{
|
||||
from.SendGump(new XmlPropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page));
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendGump(new XmlSetObjectGump(m_Property, m_Mobile, m_Object, m_Stack, m_Type, m_Page, m_List));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,235 @@
|
|||
using Server.Commands;
|
||||
using Server.Network;
|
||||
using Server.Targeting;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Server.Gumps;
|
||||
|
||||
public class XmlSetPoint2DGump : Gump
|
||||
{
|
||||
private readonly PropertyInfo m_Property;
|
||||
private readonly Mobile m_Mobile;
|
||||
private readonly object m_Object;
|
||||
private readonly Stack<StackEntry> m_Stack;
|
||||
private readonly int m_Page;
|
||||
private readonly ArrayList m_List;
|
||||
|
||||
public static readonly bool OldStyle = PropsConfig.OldStyle;
|
||||
|
||||
public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX;
|
||||
public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY;
|
||||
|
||||
public static readonly int TextHue = PropsConfig.TextHue;
|
||||
public static readonly int TextOffsetX = PropsConfig.TextOffsetX;
|
||||
|
||||
public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID;
|
||||
public static readonly int EntryGumpID = PropsConfig.EntryGumpID;
|
||||
public static readonly int BackGumpID = PropsConfig.BackGumpID;
|
||||
public static readonly int SetGumpID = PropsConfig.SetGumpID;
|
||||
|
||||
public static readonly int SetWidth = PropsConfig.SetWidth;
|
||||
public static readonly int SetOffsetX = PropsConfig.SetOffsetX, SetOffsetY = PropsConfig.SetOffsetY;
|
||||
public static readonly int SetButtonID1 = PropsConfig.SetButtonID1;
|
||||
public static readonly int SetButtonID2 = PropsConfig.SetButtonID2;
|
||||
|
||||
public static readonly int OffsetSize = PropsConfig.OffsetSize;
|
||||
|
||||
public static readonly int EntryHeight = PropsConfig.EntryHeight;
|
||||
public static readonly int BorderSize = PropsConfig.BorderSize;
|
||||
|
||||
private static readonly int CoordWidth = 105;
|
||||
private static readonly int EntryWidth = CoordWidth + OffsetSize + CoordWidth;
|
||||
|
||||
private static readonly int TotalWidth = OffsetSize + EntryWidth + OffsetSize + SetWidth + OffsetSize;
|
||||
private static readonly int TotalHeight = OffsetSize + 4 * (EntryHeight + OffsetSize);
|
||||
|
||||
private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize;
|
||||
private static readonly int BackHeight = BorderSize + TotalHeight + BorderSize;
|
||||
|
||||
public XmlSetPoint2DGump(PropertyInfo prop, Mobile mobile, object o, Stack<StackEntry> stack, int page, ArrayList list) : base(GumpOffsetX, GumpOffsetY)
|
||||
{
|
||||
m_Property = prop;
|
||||
m_Mobile = mobile;
|
||||
m_Object = o;
|
||||
m_Stack = stack;
|
||||
m_Page = page;
|
||||
m_List = list;
|
||||
|
||||
Point2D p = (Point2D)prop.GetValue(o, null);
|
||||
|
||||
AddPage(0);
|
||||
|
||||
AddBackground(0, 0, BackWidth, BackHeight, BackGumpID);
|
||||
AddImageTiled(BorderSize, BorderSize, TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), TotalHeight, OffsetGumpID);
|
||||
|
||||
int x = BorderSize + OffsetSize;
|
||||
int y = BorderSize + OffsetSize;
|
||||
|
||||
AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID);
|
||||
AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, prop.Name);
|
||||
x += EntryWidth + OffsetSize;
|
||||
|
||||
if (SetGumpID != 0)
|
||||
{
|
||||
AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID);
|
||||
}
|
||||
|
||||
x = BorderSize + OffsetSize;
|
||||
y += EntryHeight + OffsetSize;
|
||||
|
||||
AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID);
|
||||
AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, "Use your location");
|
||||
x += EntryWidth + OffsetSize;
|
||||
|
||||
if (SetGumpID != 0)
|
||||
{
|
||||
AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID);
|
||||
}
|
||||
|
||||
AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 1);
|
||||
|
||||
x = BorderSize + OffsetSize;
|
||||
y += EntryHeight + OffsetSize;
|
||||
|
||||
AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID);
|
||||
AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, "Target a location");
|
||||
x += EntryWidth + OffsetSize;
|
||||
|
||||
if (SetGumpID != 0)
|
||||
{
|
||||
AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID);
|
||||
}
|
||||
|
||||
AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 2);
|
||||
|
||||
x = BorderSize + OffsetSize;
|
||||
y += EntryHeight + OffsetSize;
|
||||
|
||||
AddImageTiled(x, y, CoordWidth, EntryHeight, EntryGumpID);
|
||||
AddLabelCropped(x + TextOffsetX, y, CoordWidth - TextOffsetX, EntryHeight, TextHue, "X:");
|
||||
AddTextEntry(x + 16, y, CoordWidth - 16, EntryHeight, TextHue, 0, p.X.ToString());
|
||||
x += CoordWidth + OffsetSize;
|
||||
|
||||
AddImageTiled(x, y, CoordWidth, EntryHeight, EntryGumpID);
|
||||
AddLabelCropped(x + TextOffsetX, y, CoordWidth - TextOffsetX, EntryHeight, TextHue, "Y:");
|
||||
AddTextEntry(x + 16, y, CoordWidth - 16, EntryHeight, TextHue, 1, p.Y.ToString());
|
||||
x += CoordWidth + OffsetSize;
|
||||
|
||||
if (SetGumpID != 0)
|
||||
{
|
||||
AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID);
|
||||
}
|
||||
|
||||
AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 3);
|
||||
}
|
||||
|
||||
private class InternalTarget : Target
|
||||
{
|
||||
private readonly PropertyInfo m_Property;
|
||||
private readonly Mobile m_Mobile;
|
||||
private readonly object m_Object;
|
||||
private readonly Stack<StackEntry> m_Stack;
|
||||
private readonly int m_Page;
|
||||
private readonly ArrayList m_List;
|
||||
|
||||
public InternalTarget(PropertyInfo prop, Mobile mobile, object o, Stack<StackEntry> stack, int page, ArrayList list) : base(-1, true, TargetFlags.None)
|
||||
{
|
||||
m_Property = prop;
|
||||
m_Mobile = mobile;
|
||||
m_Object = o;
|
||||
m_Stack = stack;
|
||||
m_Page = page;
|
||||
m_List = list;
|
||||
}
|
||||
|
||||
protected override void OnTarget(Mobile from, object targeted)
|
||||
{
|
||||
IPoint3D p = targeted as IPoint3D;
|
||||
|
||||
if (p != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, new Point2D(p.X, p.Y).ToString());
|
||||
m_Property.SetValue(m_Object, new Point2D(p.X, p.Y), null);
|
||||
}
|
||||
catch
|
||||
{
|
||||
m_Mobile.SendMessage("An exception was caught. The property may not have changed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnTargetFinish(Mobile from)
|
||||
{
|
||||
m_Mobile.SendGump(new XmlPropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page));
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnResponse(NetState sender, RelayInfo info)
|
||||
{
|
||||
Point2D toSet;
|
||||
bool shouldSet, shouldSend;
|
||||
|
||||
switch (info.ButtonID)
|
||||
{
|
||||
case 1: // Current location
|
||||
{
|
||||
toSet = new Point2D(m_Mobile.X, m_Mobile.Y);
|
||||
shouldSet = true;
|
||||
shouldSend = true;
|
||||
|
||||
break;
|
||||
}
|
||||
case 2: // Pick location
|
||||
{
|
||||
m_Mobile.Target = new InternalTarget(m_Property, m_Mobile, m_Object, m_Stack, m_Page, m_List);
|
||||
|
||||
toSet = Point2D.Zero;
|
||||
shouldSet = false;
|
||||
shouldSend = false;
|
||||
|
||||
break;
|
||||
}
|
||||
case 3: // Use values
|
||||
{
|
||||
TextRelay x = info.GetTextEntry(0);
|
||||
TextRelay y = info.GetTextEntry(1);
|
||||
|
||||
toSet = new Point2D(x == null ? 0 : Utility.ToInt32(x.Text), y == null ? 0 : Utility.ToInt32(y.Text));
|
||||
shouldSet = true;
|
||||
shouldSend = true;
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
toSet = Point2D.Zero;
|
||||
shouldSet = false;
|
||||
shouldSend = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldSet)
|
||||
{
|
||||
try
|
||||
{
|
||||
CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, toSet.ToString());
|
||||
m_Property.SetValue(m_Object, toSet, null);
|
||||
}
|
||||
catch
|
||||
{
|
||||
m_Mobile.SendMessage("An exception was caught. The property may not have changed.");
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldSend)
|
||||
{
|
||||
m_Mobile.SendGump(new XmlPropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,241 @@
|
|||
using Server.Commands;
|
||||
using Server.Network;
|
||||
using Server.Targeting;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Server.Gumps;
|
||||
|
||||
public class XmlSetPoint3DGump : Gump
|
||||
{
|
||||
private readonly PropertyInfo m_Property;
|
||||
private readonly Mobile m_Mobile;
|
||||
private readonly object m_Object;
|
||||
private readonly Stack<StackEntry> m_Stack;
|
||||
private readonly int m_Page;
|
||||
private readonly ArrayList m_List;
|
||||
|
||||
public static readonly bool OldStyle = PropsConfig.OldStyle;
|
||||
|
||||
public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX;
|
||||
public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY;
|
||||
|
||||
public static readonly int TextHue = PropsConfig.TextHue;
|
||||
public static readonly int TextOffsetX = PropsConfig.TextOffsetX;
|
||||
|
||||
public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID;
|
||||
public static readonly int EntryGumpID = PropsConfig.EntryGumpID;
|
||||
public static readonly int BackGumpID = PropsConfig.BackGumpID;
|
||||
public static readonly int SetGumpID = PropsConfig.SetGumpID;
|
||||
|
||||
public static readonly int SetWidth = PropsConfig.SetWidth;
|
||||
public static readonly int SetOffsetX = PropsConfig.SetOffsetX, SetOffsetY = PropsConfig.SetOffsetY;
|
||||
public static readonly int SetButtonID1 = PropsConfig.SetButtonID1;
|
||||
public static readonly int SetButtonID2 = PropsConfig.SetButtonID2;
|
||||
|
||||
public static readonly int OffsetSize = PropsConfig.OffsetSize;
|
||||
|
||||
public static readonly int EntryHeight = PropsConfig.EntryHeight;
|
||||
public static readonly int BorderSize = PropsConfig.BorderSize;
|
||||
|
||||
private static readonly int CoordWidth = 70;
|
||||
private static readonly int EntryWidth = CoordWidth + OffsetSize + CoordWidth + OffsetSize + CoordWidth;
|
||||
|
||||
private static readonly int TotalWidth = OffsetSize + EntryWidth + OffsetSize + SetWidth + OffsetSize;
|
||||
private static readonly int TotalHeight = OffsetSize + 4 * (EntryHeight + OffsetSize);
|
||||
|
||||
private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize;
|
||||
private static readonly int BackHeight = BorderSize + TotalHeight + BorderSize;
|
||||
|
||||
public XmlSetPoint3DGump(PropertyInfo prop, Mobile mobile, object o, Stack<StackEntry> stack, int page, ArrayList list) : base(GumpOffsetX, GumpOffsetY)
|
||||
{
|
||||
m_Property = prop;
|
||||
m_Mobile = mobile;
|
||||
m_Object = o;
|
||||
m_Stack = stack;
|
||||
m_Page = page;
|
||||
m_List = list;
|
||||
|
||||
Point3D p = (Point3D)prop.GetValue(o, null);
|
||||
|
||||
AddPage(0);
|
||||
|
||||
AddBackground(0, 0, BackWidth, BackHeight, BackGumpID);
|
||||
AddImageTiled(BorderSize, BorderSize, TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), TotalHeight, OffsetGumpID);
|
||||
|
||||
int x = BorderSize + OffsetSize;
|
||||
int y = BorderSize + OffsetSize;
|
||||
|
||||
AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID);
|
||||
AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, prop.Name);
|
||||
x += EntryWidth + OffsetSize;
|
||||
|
||||
if (SetGumpID != 0)
|
||||
{
|
||||
AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID);
|
||||
}
|
||||
|
||||
x = BorderSize + OffsetSize;
|
||||
y += EntryHeight + OffsetSize;
|
||||
|
||||
AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID);
|
||||
AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, "Use your location");
|
||||
x += EntryWidth + OffsetSize;
|
||||
|
||||
if (SetGumpID != 0)
|
||||
{
|
||||
AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID);
|
||||
}
|
||||
|
||||
AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 1);
|
||||
|
||||
x = BorderSize + OffsetSize;
|
||||
y += EntryHeight + OffsetSize;
|
||||
|
||||
AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID);
|
||||
AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, "Target a location");
|
||||
x += EntryWidth + OffsetSize;
|
||||
|
||||
if (SetGumpID != 0)
|
||||
{
|
||||
AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID);
|
||||
}
|
||||
|
||||
AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 2);
|
||||
|
||||
x = BorderSize + OffsetSize;
|
||||
y += EntryHeight + OffsetSize;
|
||||
|
||||
AddImageTiled(x, y, CoordWidth, EntryHeight, EntryGumpID);
|
||||
AddLabelCropped(x + TextOffsetX, y, CoordWidth - TextOffsetX, EntryHeight, TextHue, "X:");
|
||||
AddTextEntry(x + 16, y, CoordWidth - 16, EntryHeight, TextHue, 0, p.X.ToString());
|
||||
x += CoordWidth + OffsetSize;
|
||||
|
||||
AddImageTiled(x, y, CoordWidth, EntryHeight, EntryGumpID);
|
||||
AddLabelCropped(x + TextOffsetX, y, CoordWidth - TextOffsetX, EntryHeight, TextHue, "Y:");
|
||||
AddTextEntry(x + 16, y, CoordWidth - 16, EntryHeight, TextHue, 1, p.Y.ToString());
|
||||
x += CoordWidth + OffsetSize;
|
||||
|
||||
AddImageTiled(x, y, CoordWidth, EntryHeight, EntryGumpID);
|
||||
AddLabelCropped(x + TextOffsetX, y, CoordWidth - TextOffsetX, EntryHeight, TextHue, "Z:");
|
||||
AddTextEntry(x + 16, y, CoordWidth - 16, EntryHeight, TextHue, 2, p.Z.ToString());
|
||||
x += CoordWidth + OffsetSize;
|
||||
|
||||
if (SetGumpID != 0)
|
||||
{
|
||||
AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID);
|
||||
}
|
||||
|
||||
AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 3);
|
||||
}
|
||||
|
||||
private class InternalTarget : Target
|
||||
{
|
||||
private readonly PropertyInfo m_Property;
|
||||
private readonly Mobile m_Mobile;
|
||||
private readonly object m_Object;
|
||||
private readonly Stack<StackEntry> m_Stack;
|
||||
private readonly int m_Page;
|
||||
private readonly ArrayList m_List;
|
||||
|
||||
public InternalTarget(PropertyInfo prop, Mobile mobile, object o, Stack<StackEntry> stack, int page, ArrayList list) : base(-1, true, TargetFlags.None)
|
||||
{
|
||||
m_Property = prop;
|
||||
m_Mobile = mobile;
|
||||
m_Object = o;
|
||||
m_Stack = stack;
|
||||
m_Page = page;
|
||||
m_List = list;
|
||||
}
|
||||
|
||||
protected override void OnTarget(Mobile from, object targeted)
|
||||
{
|
||||
IPoint3D p = targeted as IPoint3D;
|
||||
|
||||
if (p != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, new Point3D(p).ToString());
|
||||
m_Property.SetValue(m_Object, new Point3D(p), null);
|
||||
}
|
||||
catch
|
||||
{
|
||||
m_Mobile.SendMessage("An exception was caught. The property may not have changed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnTargetFinish(Mobile from)
|
||||
{
|
||||
m_Mobile.SendGump(new XmlPropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page));
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnResponse(NetState sender, RelayInfo info)
|
||||
{
|
||||
Point3D toSet;
|
||||
bool shouldSet, shouldSend;
|
||||
|
||||
switch (info.ButtonID)
|
||||
{
|
||||
case 1: // Current location
|
||||
{
|
||||
toSet = m_Mobile.Location;
|
||||
shouldSet = true;
|
||||
shouldSend = true;
|
||||
|
||||
break;
|
||||
}
|
||||
case 2: // Pick location
|
||||
{
|
||||
m_Mobile.Target = new InternalTarget(m_Property, m_Mobile, m_Object, m_Stack, m_Page, m_List);
|
||||
|
||||
toSet = Point3D.Zero;
|
||||
shouldSet = false;
|
||||
shouldSend = false;
|
||||
|
||||
break;
|
||||
}
|
||||
case 3: // Use values
|
||||
{
|
||||
TextRelay x = info.GetTextEntry(0);
|
||||
TextRelay y = info.GetTextEntry(1);
|
||||
TextRelay z = info.GetTextEntry(2);
|
||||
|
||||
toSet = new Point3D(x == null ? 0 : Utility.ToInt32(x.Text), y == null ? 0 : Utility.ToInt32(y.Text), z == null ? 0 : Utility.ToInt32(z.Text));
|
||||
shouldSet = true;
|
||||
shouldSend = true;
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
toSet = Point3D.Zero;
|
||||
shouldSet = false;
|
||||
shouldSend = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldSet)
|
||||
{
|
||||
try
|
||||
{
|
||||
CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, toSet.ToString());
|
||||
m_Property.SetValue(m_Object, toSet, null);
|
||||
}
|
||||
catch
|
||||
{
|
||||
m_Mobile.SendMessage("An exception was caught. The property may not have changed.");
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldSend)
|
||||
{
|
||||
m_Mobile.SendGump(new XmlPropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,240 @@
|
|||
using Server.Commands;
|
||||
using Server.Network;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Server.Gumps;
|
||||
|
||||
public class XmlSetTimeSpanGump : Gump
|
||||
{
|
||||
private readonly PropertyInfo m_Property;
|
||||
private readonly Mobile m_Mobile;
|
||||
private readonly object m_Object;
|
||||
private readonly Stack<StackEntry> m_Stack;
|
||||
private readonly int m_Page;
|
||||
private readonly ArrayList m_List;
|
||||
|
||||
public static readonly bool OldStyle = PropsConfig.OldStyle;
|
||||
|
||||
public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX;
|
||||
public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY;
|
||||
|
||||
public static readonly int TextHue = PropsConfig.TextHue;
|
||||
public static readonly int TextOffsetX = PropsConfig.TextOffsetX;
|
||||
|
||||
public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID;
|
||||
public static readonly int EntryGumpID = PropsConfig.EntryGumpID;
|
||||
public static readonly int BackGumpID = PropsConfig.BackGumpID;
|
||||
public static readonly int SetGumpID = PropsConfig.SetGumpID;
|
||||
|
||||
public static readonly int SetWidth = PropsConfig.SetWidth;
|
||||
public static readonly int SetOffsetX = PropsConfig.SetOffsetX, SetOffsetY = PropsConfig.SetOffsetY;
|
||||
public static readonly int SetButtonID1 = PropsConfig.SetButtonID1;
|
||||
public static readonly int SetButtonID2 = PropsConfig.SetButtonID2;
|
||||
|
||||
public static readonly int OffsetSize = PropsConfig.OffsetSize;
|
||||
|
||||
public static readonly int EntryHeight = PropsConfig.EntryHeight;
|
||||
public static readonly int BorderSize = PropsConfig.BorderSize;
|
||||
|
||||
private static readonly int EntryWidth = 212;
|
||||
|
||||
private static readonly int TotalWidth = OffsetSize + EntryWidth + OffsetSize + SetWidth + OffsetSize;
|
||||
private static readonly int TotalHeight = OffsetSize + 7 * (EntryHeight + OffsetSize);
|
||||
|
||||
private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize;
|
||||
private static readonly int BackHeight = BorderSize + TotalHeight + BorderSize;
|
||||
|
||||
public XmlSetTimeSpanGump(PropertyInfo prop, Mobile mobile, object o, Stack<StackEntry> stack, int page, ArrayList list) : base(GumpOffsetX, GumpOffsetY)
|
||||
{
|
||||
m_Property = prop;
|
||||
m_Mobile = mobile;
|
||||
m_Object = o;
|
||||
m_Stack = stack;
|
||||
m_Page = page;
|
||||
m_List = list;
|
||||
|
||||
TimeSpan ts = (TimeSpan)prop.GetValue(o, null);
|
||||
|
||||
AddPage(0);
|
||||
|
||||
AddBackground(0, 0, BackWidth, BackHeight, BackGumpID);
|
||||
AddImageTiled(BorderSize, BorderSize, TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), TotalHeight, OffsetGumpID);
|
||||
|
||||
AddRect(0, prop.Name, 0, -1);
|
||||
AddRect(1, ts.ToString(), 0, -1);
|
||||
AddRect(2, "Zero", 1, -1);
|
||||
AddRect(3, "From H:M:S", 2, -1);
|
||||
AddRect(4, "H:", 3, 0);
|
||||
AddRect(5, "M:", 4, 1);
|
||||
AddRect(6, "S:", 5, 2);
|
||||
}
|
||||
|
||||
private void AddRect(int index, string str, int button, int text)
|
||||
{
|
||||
int x = BorderSize + OffsetSize;
|
||||
int y = BorderSize + OffsetSize + index * (EntryHeight + OffsetSize);
|
||||
|
||||
AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID);
|
||||
AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, str);
|
||||
|
||||
if (text != -1)
|
||||
{
|
||||
AddTextEntry(x + 16 + TextOffsetX, y, EntryWidth - TextOffsetX - 16, EntryHeight, TextHue, text, "");
|
||||
}
|
||||
|
||||
x += EntryWidth + OffsetSize;
|
||||
|
||||
if (SetGumpID != 0)
|
||||
{
|
||||
AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID);
|
||||
}
|
||||
|
||||
if (button != 0)
|
||||
{
|
||||
AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, button);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnResponse(NetState sender, RelayInfo info)
|
||||
{
|
||||
TimeSpan toSet;
|
||||
bool shouldSet, shouldSend;
|
||||
|
||||
TextRelay h = info.GetTextEntry(0);
|
||||
TextRelay m = info.GetTextEntry(1);
|
||||
TextRelay s = info.GetTextEntry(2);
|
||||
|
||||
switch (info.ButtonID)
|
||||
{
|
||||
case 1: // Zero
|
||||
{
|
||||
toSet = TimeSpan.Zero;
|
||||
shouldSet = true;
|
||||
shouldSend = true;
|
||||
|
||||
break;
|
||||
}
|
||||
case 2: // From H:M:S
|
||||
{
|
||||
if (h != null && m != null && s != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
toSet = TimeSpan.Parse($"{h.Text}:{m.Text}:{s.Text}");
|
||||
shouldSet = true;
|
||||
shouldSend = true;
|
||||
|
||||
break;
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
toSet = TimeSpan.Zero;
|
||||
shouldSet = false;
|
||||
shouldSend = false;
|
||||
|
||||
break;
|
||||
}
|
||||
case 3: // From H
|
||||
{
|
||||
if (h != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
toSet = TimeSpan.FromHours(Utility.ToDouble(h.Text));
|
||||
shouldSet = true;
|
||||
shouldSend = true;
|
||||
|
||||
break;
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
toSet = TimeSpan.Zero;
|
||||
shouldSet = false;
|
||||
shouldSend = false;
|
||||
|
||||
break;
|
||||
}
|
||||
case 4: // From M
|
||||
{
|
||||
if (m != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
toSet = TimeSpan.FromMinutes(Utility.ToDouble(m.Text));
|
||||
shouldSet = true;
|
||||
shouldSend = true;
|
||||
|
||||
break;
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
toSet = TimeSpan.Zero;
|
||||
shouldSet = false;
|
||||
shouldSend = false;
|
||||
|
||||
break;
|
||||
}
|
||||
case 5: // From S
|
||||
{
|
||||
if (s != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
toSet = TimeSpan.FromSeconds(Utility.ToDouble(s.Text));
|
||||
shouldSet = true;
|
||||
shouldSend = true;
|
||||
|
||||
break;
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
toSet = TimeSpan.Zero;
|
||||
shouldSet = false;
|
||||
shouldSend = false;
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
toSet = TimeSpan.Zero;
|
||||
shouldSet = false;
|
||||
shouldSend = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldSet)
|
||||
{
|
||||
try
|
||||
{
|
||||
CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, toSet.ToString());
|
||||
m_Property.SetValue(m_Object, toSet, null);
|
||||
}
|
||||
catch
|
||||
{
|
||||
m_Mobile.SendMessage("An exception was caught. The property may not have changed.");
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldSend)
|
||||
{
|
||||
m_Mobile.SendGump(new XmlPropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page));
|
||||
}
|
||||
}
|
||||
}
|
||||
12776
Projects/UOContent/Engines/XMLSpawner/XmlSpawner.cs
Normal file
12776
Projects/UOContent/Engines/XMLSpawner/XmlSpawner.cs
Normal file
File diff suppressed because it is too large
Load diff
1331
Projects/UOContent/Engines/XMLSpawner/XmlSpawnerGumps.cs
Normal file
1331
Projects/UOContent/Engines/XMLSpawner/XmlSpawnerGumps.cs
Normal file
File diff suppressed because it is too large
Load diff
296
Projects/UOContent/Engines/XMLSpawner/XmlSpawnerSkillCheck.cs
Normal file
296
Projects/UOContent/Engines/XMLSpawner/XmlSpawnerSkillCheck.cs
Normal file
|
|
@ -0,0 +1,296 @@
|
|||
using System.Collections;
|
||||
using Server.Items;
|
||||
using CPA = Server.CommandPropertyAttribute;
|
||||
using Server.Misc;
|
||||
|
||||
namespace Server.Mobiles;
|
||||
|
||||
public class XmlSpawnerSkillCheck
|
||||
{
|
||||
// alternate skillcheck hooks to replace those in SkillCheck.cs
|
||||
public static bool Mobile_SkillCheckLocation(Mobile from, SkillName skillName, double minSkill, double maxSkill)
|
||||
{
|
||||
Skill skill = from.Skills[skillName];
|
||||
|
||||
if (skill == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// call the default skillcheck handler
|
||||
bool success = SkillCheck.Mobile_SkillCheckLocation( from, skillName, minSkill, maxSkill);
|
||||
|
||||
// call the xmlspawner skillcheck handler
|
||||
CheckSkillUse(from, skill, success);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
public static bool Mobile_SkillCheckDirectLocation(Mobile from, SkillName skillName, double chance)
|
||||
{
|
||||
Skill skill = from.Skills[skillName];
|
||||
|
||||
if (skill == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// call the default skillcheck handler
|
||||
bool success = SkillCheck.Mobile_SkillCheckDirectLocation( from, skillName, chance);
|
||||
|
||||
// call the xmlspawner skillcheck handler
|
||||
CheckSkillUse(from, skill, success);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
public static bool Mobile_SkillCheckTarget(Mobile from, SkillName skillName, object target, double minSkill, double maxSkill)
|
||||
{
|
||||
Skill skill = from.Skills[skillName];
|
||||
|
||||
if (skill == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// call the default skillcheck handler
|
||||
bool success = SkillCheck.Mobile_SkillCheckTarget( from, skillName, target, minSkill, maxSkill);
|
||||
|
||||
// call the xmlspawner skillcheck handler
|
||||
CheckSkillUse(from, skill, success);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
public static bool Mobile_SkillCheckDirectTarget(Mobile from, SkillName skillName, object target, double chance)
|
||||
{
|
||||
Skill skill = from.Skills[skillName];
|
||||
|
||||
if (skill == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// call the default skillcheck handler
|
||||
bool success = SkillCheck.Mobile_SkillCheckDirectTarget( from, skillName, target, chance);
|
||||
|
||||
// call the xmlspawner skillcheck handler
|
||||
CheckSkillUse(from, skill, success);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
public class RegisteredSkill
|
||||
{
|
||||
public const int MaxSkills = 52;
|
||||
public const SkillName Invalid = (SkillName)(-1);
|
||||
|
||||
public object target;
|
||||
public SkillName sid;
|
||||
|
||||
// note the extra skill MaxSkills +1 is used for any unknown skill that falls outside of the known 52
|
||||
private static ArrayList[] m_FeluccaSkillList = new ArrayList[MaxSkills+1];
|
||||
private static ArrayList[] m_TrammelSkillList = new ArrayList[MaxSkills+1];
|
||||
private static ArrayList[] m_MalasSkillList = new ArrayList[MaxSkills+1];
|
||||
private static ArrayList[] m_IlshenarSkillList = new ArrayList[MaxSkills+1];
|
||||
private static ArrayList[] m_TokunoSkillList = new ArrayList[MaxSkills+1];
|
||||
|
||||
// primary function that returns the list of objects (spawners) that are associated with a given skillname by map
|
||||
public static ArrayList TriggerList(SkillName index, Map map)
|
||||
{
|
||||
if (map == null || map == Map.Internal)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
ArrayList[] maplist;
|
||||
|
||||
// get the list for the specified map
|
||||
|
||||
if (map == Map.Felucca)
|
||||
{
|
||||
maplist = m_FeluccaSkillList;
|
||||
}
|
||||
else if (map == Map.Ilshenar)
|
||||
{
|
||||
maplist = m_IlshenarSkillList;
|
||||
}
|
||||
else if (map == Map.Malas)
|
||||
{
|
||||
maplist = m_MalasSkillList;
|
||||
}
|
||||
else if (map == Map.Trammel)
|
||||
{
|
||||
maplist = m_TrammelSkillList;
|
||||
}
|
||||
else if (map == Map.Tokuno)
|
||||
{
|
||||
maplist = m_TokunoSkillList;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// is it one of the standard 52 skills
|
||||
if ((int)index >= 0 && (int)index < MaxSkills)
|
||||
{
|
||||
return maplist[(int)index] ??= new ArrayList();
|
||||
}
|
||||
|
||||
// otherwise pull it out of the final slot for unknown skills. I dont know of a condition that would lead to
|
||||
// additional skills being registered but it will support them if they are
|
||||
return maplist[MaxSkills] ??= new ArrayList();
|
||||
}
|
||||
}
|
||||
|
||||
public static void RegisterSkillTrigger(object o, SkillName s, Map map)
|
||||
{
|
||||
if (o == null || s == RegisteredSkill.Invalid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// go through the list and if the spawner is not on it yet, then add it
|
||||
bool found = false;
|
||||
|
||||
ArrayList skilllist = RegisteredSkill.TriggerList(s, map);
|
||||
|
||||
if (skilllist == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach(RegisteredSkill rs in skilllist)
|
||||
{
|
||||
if (rs.target == o && rs.sid == s)
|
||||
{
|
||||
found = true;
|
||||
// dont register a skill if it is already on the list for this spawner
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if it hasnt already been added to the list, then add it
|
||||
if (!found)
|
||||
{
|
||||
RegisteredSkill newrs = new RegisteredSkill();
|
||||
newrs.target = o;
|
||||
newrs.sid = s;
|
||||
|
||||
skilllist.Add(newrs);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static void UnRegisterSkillTrigger(object o, SkillName s, Map map, bool all)
|
||||
{
|
||||
if (o == null || s == RegisteredSkill.Invalid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// go through the list and if the spawner is on it regardless of the skill registered, then remove it
|
||||
if (all)
|
||||
{
|
||||
for(int i = 0;i<RegisteredSkill.MaxSkills+1;i++)
|
||||
{
|
||||
ArrayList skilllist = RegisteredSkill.TriggerList((SkillName)i, map);
|
||||
|
||||
if (skilllist == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach(RegisteredSkill rs in skilllist)
|
||||
{
|
||||
if (rs.target == o)
|
||||
{
|
||||
skilllist.Remove(rs);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ArrayList skilllist = RegisteredSkill.TriggerList(s, map);
|
||||
|
||||
if (skilllist == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// if the all flag is not set then just remove the spawner from the list for the specified skill
|
||||
foreach(RegisteredSkill rs in skilllist)
|
||||
{
|
||||
if (rs.target == o && rs.sid == s)
|
||||
{
|
||||
skilllist.Remove(rs);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// determines whether XmlSpawner, XmlAttachment, or XmlQuest OnSkillUse methods should be invoked.
|
||||
public static void CheckSkillUse(Mobile m, Skill skill, bool success)
|
||||
{
|
||||
if (!(m is PlayerMobile) || skill == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
// first check for any attachments that might support OnSkillUse
|
||||
ArrayList list = XmlAttach.FindAttachments(m);
|
||||
if (list != null && list.Count > 0)
|
||||
{
|
||||
foreach(XmlAttachment a in list)
|
||||
{
|
||||
if (a != null && !a.Deleted && a.HandlesOnSkillUse)
|
||||
{
|
||||
a.OnSkillUse(m, skill, success);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// then check for registered skills
|
||||
ArrayList skilllist = RegisteredSkill.TriggerList(skill.SkillName, m.Map);
|
||||
|
||||
if (skilllist == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// determine whether there are any registered objects for this skill
|
||||
foreach(RegisteredSkill rs in skilllist)
|
||||
{
|
||||
if (rs.sid == skill.SkillName)
|
||||
{
|
||||
// if so then invoke their skill handlers
|
||||
if (rs.target is XmlSpawner spawner)
|
||||
{
|
||||
if (spawner.HandlesOnSkillUse)
|
||||
{
|
||||
// call the spawner handler
|
||||
spawner.OnSkillUse(m, skill, success);
|
||||
}
|
||||
} else
|
||||
if (rs.target is IXmlQuest quest)
|
||||
{
|
||||
if (quest.HandlesOnSkillUse)
|
||||
{
|
||||
// call the xmlquest handler
|
||||
quest.OnSkillUse(m, skill, success);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
80
Projects/UOContent/Engines/XMLSpawner/XmlTextEntryBook.cs
Normal file
80
Projects/UOContent/Engines/XMLSpawner/XmlTextEntryBook.cs
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
namespace Server.Items;
|
||||
|
||||
public class XmlTextEntryBook : BaseBook
|
||||
{
|
||||
public XmlTextEntryBook(int itemID, string title, string author, int pageCount, bool writable) : base(itemID, title, author, pageCount, writable)
|
||||
{
|
||||
}
|
||||
|
||||
public XmlTextEntryBook(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public void FillTextEntryBook(string text)
|
||||
{
|
||||
int pagenum = 0;
|
||||
int current = 0;
|
||||
|
||||
// break up the text into single line length pieces
|
||||
while (text != null && current < text.Length)
|
||||
{
|
||||
int lineCount = 10;
|
||||
string[] lines = new string[lineCount];
|
||||
|
||||
// place the line on the page
|
||||
for (int i = 0; i < lineCount; i++)
|
||||
{
|
||||
if (current < text.Length)
|
||||
{
|
||||
// make each line 25 chars long
|
||||
int length = text.Length - current;
|
||||
if (length > 20)
|
||||
{
|
||||
length = 20;
|
||||
}
|
||||
|
||||
lines[i] = text.Substring(current, length);
|
||||
current += length;
|
||||
}
|
||||
else
|
||||
{
|
||||
// fill up the remaining lines
|
||||
lines[i] = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
if (pagenum >= PagesCount)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Pages[pagenum].Lines = lines;
|
||||
pagenum++;
|
||||
}
|
||||
// empty the remaining contents
|
||||
for (int j = pagenum; j < PagesCount; j++)
|
||||
{
|
||||
if (Pages[j].Lines.Length > 0)
|
||||
{
|
||||
for (int i = 0; i < Pages[j].Lines.Length; i++)
|
||||
{
|
||||
Pages[j].Lines[i] = string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
reader.ReadInt();
|
||||
|
||||
Delete();
|
||||
}
|
||||
}
|
||||
468
Projects/UOContent/Engines/XMLSpawner/XmlUtils/WriteMulti.cs
Normal file
468
Projects/UOContent/Engines/XMLSpawner/XmlUtils/WriteMulti.cs
Normal file
|
|
@ -0,0 +1,468 @@
|
|||
using System.IO;
|
||||
using System.Collections;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Engines.XmlSpawner2;
|
||||
|
||||
public class WriteMulti
|
||||
{
|
||||
private class TileEntry
|
||||
{
|
||||
public int ID;
|
||||
public int X;
|
||||
public int Y;
|
||||
public int Z;
|
||||
|
||||
public TileEntry(int id, int x, int y, int z)
|
||||
{
|
||||
ID = id;
|
||||
X = x;
|
||||
Y = y;
|
||||
Z = z;
|
||||
}
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
|
||||
CommandSystem.Register("WriteMulti", XmlSpawner.DiskAccessLevel, WriteMulti_OnCommand);
|
||||
}
|
||||
|
||||
[Usage("WriteMulti <MultiFile> [zmin zmax][-noitems][-nostatics][-nomultis][-noaddons][-invisible]")]
|
||||
[Description("Creates a multi text file from the objects within the targeted area. The min/max z range can also be specified.")]
|
||||
public static void WriteMulti_OnCommand(CommandEventArgs e)
|
||||
{
|
||||
if (e == null || e.Mobile == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.Mobile.AccessLevel < XmlSpawner.DiskAccessLevel)
|
||||
{
|
||||
e.Mobile.SendMessage("You do not have rights to perform this command.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.Arguments != null && e.Arguments.Length < 1)
|
||||
{
|
||||
e.Mobile.SendMessage("Usage: {0} <MultiFile> [zmin zmax][-noitems][-nostatics][-nomultis][-noaddons][-invisible]", e.Command);
|
||||
return;
|
||||
}
|
||||
|
||||
string filename = e.Arguments[0];
|
||||
|
||||
int zmin = int.MinValue;
|
||||
int zmax = int.MinValue;
|
||||
bool includeitems = true;
|
||||
bool includestatics = true;
|
||||
bool includemultis = true;
|
||||
bool includeaddons = true;
|
||||
bool includeinvisible = false;
|
||||
|
||||
if (e.Arguments.Length > 1)
|
||||
{
|
||||
int index = 1;
|
||||
while (index < e.Arguments.Length)
|
||||
{
|
||||
if (e.Arguments[index] == "-noitems")
|
||||
{
|
||||
includeitems = false;
|
||||
index++;
|
||||
}
|
||||
else if (e.Arguments[index] == "-nostatics")
|
||||
{
|
||||
includestatics = false;
|
||||
index++;
|
||||
}
|
||||
else if (e.Arguments[index] == "-nomultis")
|
||||
{
|
||||
includemultis = false;
|
||||
index++;
|
||||
}
|
||||
else if (e.Arguments[index] == "-noaddons")
|
||||
{
|
||||
includeaddons = false;
|
||||
index++;
|
||||
}
|
||||
else if (e.Arguments[index] == "-invisible")
|
||||
{
|
||||
includeinvisible = true;
|
||||
index++;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
zmin = int.Parse(e.Arguments[index++]);
|
||||
zmax = int.Parse(e.Arguments[index++]);
|
||||
}
|
||||
catch
|
||||
{
|
||||
e.Mobile.SendMessage("{0} : Invalid zmin zmax arguments", e.Command);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string dirname;
|
||||
if (Directory.Exists(XmlSpawner.XmlSpawnDir) && filename != null && !filename.StartsWith("/") && !filename.StartsWith("\\"))
|
||||
{
|
||||
// put it in the defaults directory if it exists
|
||||
dirname = $"{XmlSpawner.XmlSpawnDir}/{filename}";
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise just put it in the main installation dir
|
||||
dirname = filename;
|
||||
}
|
||||
|
||||
// check to see if the file already exists and can be written to by the owner
|
||||
if (File.Exists(dirname))
|
||||
{
|
||||
|
||||
// check the file
|
||||
try
|
||||
{
|
||||
StreamReader op = new StreamReader(dirname, false);
|
||||
|
||||
if (op == null)
|
||||
{
|
||||
e.Mobile.SendMessage("Cannot access file {0}", dirname);
|
||||
return;
|
||||
}
|
||||
|
||||
string line = op.ReadLine();
|
||||
|
||||
op.Close();
|
||||
|
||||
// check the first line
|
||||
if (line != null && line.Length > 0)
|
||||
{
|
||||
|
||||
string[] args = line.Split(" ".ToCharArray(), 3);
|
||||
if (args == null || args.Length < 3)
|
||||
{
|
||||
e.Mobile.SendMessage("Cannot overwrite file {0} : not owner", dirname);
|
||||
return;
|
||||
}
|
||||
|
||||
if (args[2] != e.Mobile.Name)
|
||||
{
|
||||
e.Mobile.SendMessage("Cannot overwrite file {0} : not owner", dirname);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Mobile.SendMessage("Cannot overwrite file {0} : not owner", dirname);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
catch
|
||||
{
|
||||
e.Mobile.SendMessage("Cannot overwrite file {0}", dirname);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DefineMultiArea(e.Mobile, dirname, zmin, zmax, includeitems, includestatics, includemultis, includeinvisible, includeaddons);
|
||||
}
|
||||
|
||||
public static void DefineMultiArea(Mobile m, string dirname, int zmin, int zmax, bool includeitems, bool includestatics,
|
||||
bool includemultis, bool includeinvisible, bool includeaddons)
|
||||
{
|
||||
BoundingBoxPicker.Begin(
|
||||
m,
|
||||
(map, start, end) => DefineMultiArea_Callback(
|
||||
m,
|
||||
map,
|
||||
start,
|
||||
end,
|
||||
dirname,
|
||||
zmin,
|
||||
zmax,
|
||||
includeitems,
|
||||
includestatics,
|
||||
includemultis,
|
||||
includeinvisible,
|
||||
includeaddons
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private static void DefineMultiArea_Callback(
|
||||
Mobile from,
|
||||
Map map,
|
||||
Point3D start,
|
||||
Point3D end,
|
||||
string dirname,
|
||||
int zmin,
|
||||
int zmax,
|
||||
bool includeitems,
|
||||
bool includestatics,
|
||||
bool includemultis,
|
||||
bool includeinvisible,
|
||||
bool includeaddons
|
||||
)
|
||||
{
|
||||
if (from != null && map != null)
|
||||
{
|
||||
ArrayList itemlist = new ArrayList();
|
||||
ArrayList staticlist = new ArrayList();
|
||||
ArrayList tilelist = new ArrayList();
|
||||
|
||||
int sx = start.X > end.X ? end.X : start.X;
|
||||
int sy = start.Y > end.Y ? end.Y : start.Y;
|
||||
int ex = start.X < end.X ? end.X : start.X;
|
||||
int ey = start.Y < end.Y ? end.Y : start.Y;
|
||||
|
||||
// find all of the world-placed items within the specified area
|
||||
if (includeitems)
|
||||
{
|
||||
// make the first pass for items only
|
||||
IPooledEnumerable eable = map.GetItemsInBounds(new Rectangle2D(sx, sy, ex - sx + 1, ey - sy + 1));
|
||||
|
||||
foreach (Item item in eable)
|
||||
{
|
||||
// is it within the bounding area
|
||||
if (item.Parent == null && (zmin == int.MinValue || item.Location.Z >= zmin && item.Location.Z <= zmax))
|
||||
{
|
||||
// add the item
|
||||
if ((includeinvisible || item.Visible) && item.ItemID <= 16383)
|
||||
{
|
||||
itemlist.Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eable.Free();
|
||||
|
||||
int searchrange = 100;
|
||||
|
||||
// make the second expanded pass to pick up addon components and multi components
|
||||
eable = map.GetItemsInBounds(new Rectangle2D(sx - searchrange, sy - searchrange, ex - sy + searchrange * 2 + 1,
|
||||
ey - sy + searchrange * 2 + 1));
|
||||
|
||||
foreach (Item item in eable)
|
||||
{
|
||||
// is it within the bounding area
|
||||
if (item.Parent == null)
|
||||
{
|
||||
|
||||
if (item is BaseAddon addon && includeaddons)
|
||||
{
|
||||
// go through all of the addon components
|
||||
foreach (AddonComponent c in addon.Components)
|
||||
{
|
||||
int x = c.X;
|
||||
int y = c.Y;
|
||||
int z = c.Z;
|
||||
|
||||
if ((includeinvisible || addon.Visible) && (addon.ItemID <= 16383 || includemultis) &&
|
||||
x >= sx && x <= ex && y >= sy && y <= ey && (zmin == int.MinValue || z >= zmin && z <= zmax))
|
||||
{
|
||||
itemlist.Add(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (item is BaseMulti multi && includemultis)
|
||||
{
|
||||
// go through all of the multi components
|
||||
MultiComponentList mcl = multi.Components;
|
||||
if (mcl != null && mcl.List != null)
|
||||
{
|
||||
for (int i = 0; i < mcl.List.Length; i++)
|
||||
{
|
||||
MultiTileEntry t = mcl.List[i];
|
||||
|
||||
int x = t.OffsetX + multi.X;
|
||||
int y = t.OffsetY + multi.Y;
|
||||
int z = t.OffsetZ + multi.Z;
|
||||
int itemID = t.ItemId & 0x3FFF;
|
||||
|
||||
if (x >= sx && x <= ex && y >= sy && y <= ey && (zmin == int.MinValue || z >= zmin && z <= zmax))
|
||||
{
|
||||
tilelist.Add(new TileEntry(itemID, x, y, z));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eable.Free();
|
||||
}
|
||||
|
||||
// find all of the static tiles within the specified area
|
||||
if (includestatics)
|
||||
{
|
||||
// count the statics
|
||||
for (int x = sx; x < ex; x++)
|
||||
{
|
||||
for (int y = sy; y < ey; y++)
|
||||
{
|
||||
StaticTile[] statics = map.Tiles.GetStaticTiles(x, y, false);
|
||||
|
||||
for (int j = 0; j < statics.Length; j++)
|
||||
{
|
||||
if (zmin == int.MinValue || statics[j].Z >= zmin && statics[j].Z <= zmax)
|
||||
{
|
||||
staticlist.Add(new TileEntry(statics[j].ID & 0x3FFF, x, y, statics[j].Z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int nstatics = staticlist.Count;
|
||||
int nitems = itemlist.Count;
|
||||
int ntiles = tilelist.Count;
|
||||
|
||||
int ntotal = nitems + nstatics + ntiles;
|
||||
|
||||
int ninvisible = 0;
|
||||
int nmultis = ntiles;
|
||||
int naddons = 0;
|
||||
|
||||
foreach (Item item in itemlist)
|
||||
{
|
||||
int x = item.X - from.X;
|
||||
int y = item.Y - from.Y;
|
||||
int z = item.Z - from.Z;
|
||||
|
||||
if (item.ItemID > 16383)
|
||||
{
|
||||
nmultis++;
|
||||
}
|
||||
if (!item.Visible)
|
||||
{
|
||||
ninvisible++;
|
||||
}
|
||||
if (item is BaseAddon || item is AddonComponent)
|
||||
{
|
||||
naddons++;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// open the file, overwrite any previous contents
|
||||
StreamWriter op = new StreamWriter(dirname, false);
|
||||
|
||||
if (op != null)
|
||||
{
|
||||
// write the header
|
||||
op.WriteLine("1 version {0}", from.Name);
|
||||
op.WriteLine("{0} num components", ntotal);
|
||||
|
||||
// write out the items
|
||||
foreach (Item item in itemlist)
|
||||
{
|
||||
|
||||
int x = item.X - from.X;
|
||||
int y = item.Y - from.Y;
|
||||
int z = item.Z - from.Z;
|
||||
|
||||
if (item.Hue > 0)
|
||||
{
|
||||
// format is x y z visible hue
|
||||
op.WriteLine("{0} {1} {2} {3} {4} {5}", item.ItemID, x, y, z, item.Visible ? 1 : 0, item.Hue);
|
||||
}
|
||||
else
|
||||
{
|
||||
// format is x y z visible
|
||||
op.WriteLine("{0} {1} {2} {3} {4}", item.ItemID, x, y, z, item.Visible ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (includestatics)
|
||||
{
|
||||
foreach (TileEntry s in staticlist)
|
||||
{
|
||||
int x = s.X - from.X;
|
||||
int y = s.Y - from.Y;
|
||||
int z = s.Z - from.Z;
|
||||
int ID = s.ID;
|
||||
op.WriteLine("{0} {1} {2} {3} {4}", ID, x, y, z, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (includemultis)
|
||||
{
|
||||
foreach (TileEntry s in tilelist)
|
||||
{
|
||||
int x = s.X - from.X;
|
||||
int y = s.Y - from.Y;
|
||||
int z = s.Z - from.Z;
|
||||
int ID = s.ID;
|
||||
op.WriteLine("{0} {1} {2} {3} {4}", ID, x, y, z, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
op.Close();
|
||||
}
|
||||
catch
|
||||
{
|
||||
from.SendMessage("Error writing multi file {0}", dirname);
|
||||
return;
|
||||
}
|
||||
|
||||
from.SendMessage(66, "WriteMulti results:");
|
||||
|
||||
if (includeitems)
|
||||
{
|
||||
from.SendMessage(66, "Included {0} items", nitems);
|
||||
|
||||
if (includemultis)
|
||||
{
|
||||
from.SendMessage("{0} multis", nmultis);
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendMessage(33, "Ignored multis");
|
||||
}
|
||||
|
||||
if (includeinvisible)
|
||||
{
|
||||
from.SendMessage("{0} invisible", ninvisible);
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendMessage(33, "Ignored invisible");
|
||||
}
|
||||
|
||||
if (includeaddons)
|
||||
{
|
||||
from.SendMessage("{0} addons", naddons);
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendMessage(33, "Ignored addons");
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendMessage(33, "Ignored items");
|
||||
}
|
||||
|
||||
if (includestatics)
|
||||
{
|
||||
from.SendMessage(66, "Included {0} statics", nstatics);
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendMessage(33, "Ignored statics");
|
||||
}
|
||||
|
||||
from.SendMessage(66, "Saved {0} components to {1}", ntotal, dirname);
|
||||
}
|
||||
}
|
||||
}
|
||||
1774
Projects/UOContent/Engines/XMLSpawner/XmlUtils/XmlAdd.cs
Normal file
1774
Projects/UOContent/Engines/XMLSpawner/XmlUtils/XmlAdd.cs
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,477 @@
|
|||
using Server.Mobiles;
|
||||
using Server.Network;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
|
||||
namespace Server.Gumps;
|
||||
|
||||
public abstract class XmlAddCAGNode
|
||||
{
|
||||
public abstract string Caption { get; }
|
||||
public abstract void OnClick(Mobile from, int page, int index, Gump gump);
|
||||
}
|
||||
|
||||
public class XmlAddCAGObject : XmlAddCAGNode
|
||||
{
|
||||
private readonly Type m_Type;
|
||||
private readonly XmlAddCAGCategory m_Parent;
|
||||
|
||||
public int ItemID { get; }
|
||||
|
||||
public override string Caption => m_Type == null ? "bad type" : m_Type.Name;
|
||||
|
||||
public override void OnClick(Mobile from, int page, int index, Gump gump)
|
||||
{
|
||||
if (m_Type == null)
|
||||
{
|
||||
from.SendMessage("That is an invalid type name.");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gump is XmlAddGump xmladdgump)
|
||||
{
|
||||
//Commands.Handle(from, String.Format("{0}Add {1}", Commands.CommandPrefix, m_Type.Name));
|
||||
if (xmladdgump.defs?.NameList != null && index >= 0 && index < xmladdgump.defs.NameList.Length)
|
||||
{
|
||||
xmladdgump.defs.NameList[index] = m_Type.Name;
|
||||
XmlAddGump.Refresh(from, true);
|
||||
}
|
||||
from.SendGump(new XmlCategorizedAddGump(from, m_Parent, page, index, xmladdgump));
|
||||
}
|
||||
else if (gump is XmlSpawnerGump spawnerGump)
|
||||
{
|
||||
XmlSpawner m_Spawner = spawnerGump.m_Spawner;
|
||||
|
||||
if (m_Spawner != null)
|
||||
{
|
||||
XmlSpawnerGump xg = m_Spawner.SpawnerGump;
|
||||
|
||||
if (xg != null)
|
||||
{
|
||||
xg.Rentry = new XmlSpawnerGump.ReplacementEntry
|
||||
{
|
||||
Typename = m_Type.Name,
|
||||
Index = index,
|
||||
Color = 0x1436
|
||||
};
|
||||
|
||||
Timer.DelayCall(TimeSpan.Zero, XmlSpawnerGump.RefreshSpawnerGumps, from);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public XmlAddCAGObject(XmlAddCAGCategory parent, XmlReader xml)
|
||||
{
|
||||
m_Parent = parent;
|
||||
|
||||
if (xml.MoveToAttribute("type"))
|
||||
{
|
||||
m_Type = AssemblyHandler.FindTypeByFullName(xml.Value, false);
|
||||
}
|
||||
|
||||
if (xml.MoveToAttribute("gfx"))
|
||||
{
|
||||
ItemID = XmlConvert.ToInt32(xml.Value);
|
||||
}
|
||||
|
||||
if (xml.MoveToAttribute("hue"))
|
||||
{
|
||||
XmlConvert.ToInt32(xml.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class XmlAddCAGCategory : XmlAddCAGNode
|
||||
{
|
||||
private readonly string m_Title;
|
||||
|
||||
public XmlAddCAGNode[] Nodes { get; }
|
||||
|
||||
public XmlAddCAGCategory Parent { get; }
|
||||
|
||||
public override string Caption => m_Title;
|
||||
|
||||
public override void OnClick(Mobile from, int page, int index, Gump gump)
|
||||
{
|
||||
from.SendGump(new XmlCategorizedAddGump(from, this, 0, index, gump));
|
||||
}
|
||||
|
||||
private XmlAddCAGCategory()
|
||||
{
|
||||
m_Title = "no data";
|
||||
Nodes = new XmlAddCAGNode[0];
|
||||
}
|
||||
|
||||
public XmlAddCAGCategory(XmlAddCAGCategory parent, XmlReader xml)
|
||||
{
|
||||
Parent = parent;
|
||||
|
||||
if (xml.MoveToAttribute("title"))
|
||||
{
|
||||
m_Title = xml.Value == "Add Menu" ? "XmlAdd Menu" : xml.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Title = "empty";
|
||||
}
|
||||
|
||||
if (m_Title == "Docked")
|
||||
{
|
||||
m_Title = "Docked 2";
|
||||
}
|
||||
|
||||
if (xml.IsEmptyElement)
|
||||
{
|
||||
Nodes = new XmlAddCAGNode[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
ArrayList nodes = new ArrayList();
|
||||
|
||||
try
|
||||
{
|
||||
while (xml.Read() && xml.NodeType != XmlNodeType.EndElement)
|
||||
{
|
||||
|
||||
if (xml.NodeType == XmlNodeType.Element && xml.Name == "object")
|
||||
{
|
||||
nodes.Add(new XmlAddCAGObject(this, xml));
|
||||
}
|
||||
else if (xml.NodeType == XmlNodeType.Element && xml.Name == "category")
|
||||
{
|
||||
if (!xml.IsEmptyElement)
|
||||
{
|
||||
nodes.Add(new XmlAddCAGCategory(this, xml));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
xml.Skip();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("XmlCategorizedAddGump: Corrupted Data/objects.xml file detected. Not all XmlCAG objects loaded. {0}", ex);
|
||||
}
|
||||
|
||||
Nodes = (XmlAddCAGNode[])nodes.ToArray(typeof(XmlAddCAGNode));
|
||||
}
|
||||
}
|
||||
|
||||
private static XmlAddCAGCategory m_Root;
|
||||
public static XmlAddCAGCategory Root => m_Root ?? (m_Root = Load("Data/objects.xml"));
|
||||
|
||||
public static XmlAddCAGCategory Load(string path)
|
||||
{
|
||||
if (File.Exists(path))
|
||||
{
|
||||
XmlTextReader xml = new XmlTextReader(path)
|
||||
{
|
||||
WhitespaceHandling = WhitespaceHandling.None
|
||||
};
|
||||
|
||||
while (xml.Read())
|
||||
{
|
||||
if (xml.Name == "category" && xml.NodeType == XmlNodeType.Element)
|
||||
{
|
||||
XmlAddCAGCategory cat = new XmlAddCAGCategory(null, xml);
|
||||
|
||||
xml.Close();
|
||||
|
||||
return cat;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new XmlAddCAGCategory();
|
||||
}
|
||||
}
|
||||
|
||||
public class XmlCategorizedAddGump : Gump
|
||||
{
|
||||
public static bool OldStyle = PropsConfig.OldStyle;
|
||||
|
||||
public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX;
|
||||
public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY;
|
||||
|
||||
public static readonly int TextHue = PropsConfig.TextHue;
|
||||
public static readonly int TextOffsetX = PropsConfig.TextOffsetX;
|
||||
|
||||
public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID;
|
||||
public static readonly int HeaderGumpID = PropsConfig.HeaderGumpID;
|
||||
public static readonly int EntryGumpID = PropsConfig.EntryGumpID;
|
||||
public static readonly int BackGumpID = PropsConfig.BackGumpID;
|
||||
public static readonly int SetGumpID = PropsConfig.SetGumpID;
|
||||
|
||||
public static readonly int SetWidth = PropsConfig.SetWidth;
|
||||
public static readonly int SetOffsetX = PropsConfig.SetOffsetX, SetOffsetY = PropsConfig.SetOffsetY /*+ (((EntryHeight - 20) / 2) / 2)*/;
|
||||
public static readonly int SetButtonID1 = PropsConfig.SetButtonID1;
|
||||
public static readonly int SetButtonID2 = PropsConfig.SetButtonID2;
|
||||
|
||||
public static readonly int PrevWidth = PropsConfig.PrevWidth;
|
||||
public static readonly int PrevOffsetX = PropsConfig.PrevOffsetX, PrevOffsetY = PropsConfig.PrevOffsetY /*+ (((EntryHeight - 20) / 2) / 2)*/;
|
||||
public static readonly int PrevButtonID1 = PropsConfig.PrevButtonID1;
|
||||
public static readonly int PrevButtonID2 = PropsConfig.PrevButtonID2;
|
||||
|
||||
public static readonly int NextWidth = PropsConfig.NextWidth;
|
||||
public static readonly int NextOffsetX = PropsConfig.NextOffsetX, NextOffsetY = PropsConfig.NextOffsetY /*+ (((EntryHeight - 20) / 2) / 2)*/;
|
||||
public static readonly int NextButtonID1 = PropsConfig.NextButtonID1;
|
||||
public static readonly int NextButtonID2 = PropsConfig.NextButtonID2;
|
||||
|
||||
public static readonly int OffsetSize = PropsConfig.OffsetSize;
|
||||
|
||||
public static readonly int EntryHeight = 24;
|
||||
public static readonly int BorderSize = PropsConfig.BorderSize;
|
||||
|
||||
private static readonly bool PrevLabel = false, NextLabel = false;
|
||||
|
||||
private static readonly int PrevLabelOffsetX = PrevWidth + 1;
|
||||
private const int PrevLabelOffsetY = 0;
|
||||
|
||||
private const int NextLabelOffsetX = -29;
|
||||
private const int NextLabelOffsetY = 0;
|
||||
|
||||
private const int EntryWidth = 180;
|
||||
private const int EntryCount = 15;
|
||||
|
||||
private static readonly int TotalWidth = OffsetSize + EntryWidth + OffsetSize + SetWidth + OffsetSize;
|
||||
|
||||
private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize;
|
||||
private readonly Mobile m_Owner;
|
||||
private readonly XmlAddCAGCategory m_Category;
|
||||
private int m_Page;
|
||||
|
||||
private readonly int m_Index;
|
||||
private readonly Gump m_Gump;
|
||||
|
||||
public XmlCategorizedAddGump(Mobile owner, int index, Gump gump) : this(owner, XmlAddCAGCategory.Root, 0, index, gump)
|
||||
{
|
||||
}
|
||||
|
||||
public XmlCategorizedAddGump(Mobile owner, XmlAddCAGCategory category, int page, int index, Gump gump) : base(GumpOffsetX, GumpOffsetY)
|
||||
{
|
||||
if (category == null)
|
||||
{
|
||||
category = XmlAddCAGCategory.Root;
|
||||
page = 0;
|
||||
}
|
||||
|
||||
owner.CloseGump<WhoGump>();
|
||||
|
||||
m_Owner = owner;
|
||||
m_Category = category;
|
||||
|
||||
m_Index = index;
|
||||
m_Gump = gump;
|
||||
|
||||
if (gump is XmlAddGump xmladdgump)
|
||||
{
|
||||
if (xmladdgump.defs != null)
|
||||
{
|
||||
xmladdgump.defs.CurrentCategory = category;
|
||||
xmladdgump.defs.CurrentCategoryPage = page;
|
||||
}
|
||||
}
|
||||
|
||||
Initialize(page);
|
||||
}
|
||||
|
||||
public void Initialize(int page)
|
||||
{
|
||||
m_Page = page;
|
||||
|
||||
XmlAddCAGNode[] nodes = m_Category.Nodes;
|
||||
|
||||
int count = nodes.Length - page * EntryCount;
|
||||
|
||||
if (count < 0)
|
||||
{
|
||||
count = 0;
|
||||
}
|
||||
else if (count > EntryCount)
|
||||
{
|
||||
count = EntryCount;
|
||||
}
|
||||
|
||||
int totalHeight = OffsetSize + (EntryHeight + OffsetSize) * (count + 1);
|
||||
|
||||
AddPage(0);
|
||||
|
||||
AddBackground(0, 0, BackWidth, BorderSize + totalHeight + BorderSize, BackGumpID);
|
||||
AddImageTiled(BorderSize, BorderSize, TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), totalHeight, OffsetGumpID);
|
||||
|
||||
int x = BorderSize + OffsetSize;
|
||||
int y = BorderSize + OffsetSize;
|
||||
|
||||
if (OldStyle)
|
||||
{
|
||||
AddImageTiled(x, y, TotalWidth - OffsetSize * 3 - SetWidth, EntryHeight, HeaderGumpID);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddImageTiled(x, y, PrevWidth, EntryHeight, HeaderGumpID);
|
||||
}
|
||||
|
||||
if (m_Category.Parent != null)
|
||||
{
|
||||
AddButton(x + PrevOffsetX, y + PrevOffsetY, PrevButtonID1, PrevButtonID2, 1);
|
||||
|
||||
if (PrevLabel)
|
||||
{
|
||||
AddLabel(x + PrevLabelOffsetX, y + PrevLabelOffsetY, TextHue, "Previous");
|
||||
}
|
||||
}
|
||||
|
||||
x += PrevWidth + OffsetSize;
|
||||
|
||||
int emptyWidth = TotalWidth - PrevWidth * 2 - NextWidth - OffsetSize * 5 - (OldStyle ? SetWidth + OffsetSize : 0);
|
||||
|
||||
if (!OldStyle)
|
||||
{
|
||||
AddImageTiled(x - (OldStyle ? OffsetSize : 0), y, emptyWidth + (OldStyle ? OffsetSize * 2 : 0), EntryHeight, EntryGumpID);
|
||||
}
|
||||
|
||||
AddHtml(x + TextOffsetX, y + (EntryHeight - 20) / 2, emptyWidth - TextOffsetX, EntryHeight,
|
||||
$"<center>{m_Category.Caption}</center>");
|
||||
|
||||
x += emptyWidth + OffsetSize;
|
||||
|
||||
if (OldStyle)
|
||||
{
|
||||
AddImageTiled(x, y, TotalWidth - OffsetSize * 3 - SetWidth, EntryHeight, HeaderGumpID);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddImageTiled(x, y, PrevWidth, EntryHeight, HeaderGumpID);
|
||||
}
|
||||
|
||||
if (page > 0)
|
||||
{
|
||||
AddButton(x + PrevOffsetX, y + PrevOffsetY, PrevButtonID1, PrevButtonID2, 2);
|
||||
|
||||
if (PrevLabel)
|
||||
{
|
||||
AddLabel(x + PrevLabelOffsetX, y + PrevLabelOffsetY, TextHue, "Previous");
|
||||
}
|
||||
}
|
||||
|
||||
x += PrevWidth + OffsetSize;
|
||||
|
||||
if (!OldStyle)
|
||||
{
|
||||
AddImageTiled(x, y, NextWidth, EntryHeight, HeaderGumpID);
|
||||
}
|
||||
|
||||
if ((page + 1) * EntryCount < nodes.Length)
|
||||
{
|
||||
AddButton(x + NextOffsetX, y + NextOffsetY, NextButtonID1, NextButtonID2, 3, GumpButtonType.Reply, 1);
|
||||
|
||||
if (NextLabel)
|
||||
{
|
||||
AddLabel(x + NextLabelOffsetX, y + NextLabelOffsetY, TextHue, "Next");
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0, index = page * EntryCount; i < EntryCount && index < nodes.Length; ++i, ++index)
|
||||
{
|
||||
x = BorderSize + OffsetSize;
|
||||
y += EntryHeight + OffsetSize;
|
||||
|
||||
XmlAddCAGNode node = nodes[index];
|
||||
|
||||
AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID);
|
||||
AddLabelCropped(x + TextOffsetX, y + (EntryHeight - 20) / 2, EntryWidth - TextOffsetX, EntryHeight, TextHue, node.Caption);
|
||||
|
||||
x += EntryWidth + OffsetSize;
|
||||
|
||||
if (SetGumpID != 0)
|
||||
{
|
||||
AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID);
|
||||
}
|
||||
|
||||
AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, i + 4);
|
||||
|
||||
if (node is XmlAddCAGObject obj)
|
||||
{
|
||||
int itemID = obj.ItemID;
|
||||
|
||||
Rectangle2D bounds = ItemBounds.Table[itemID];
|
||||
|
||||
if (itemID != 1 && bounds.Height < EntryHeight * 2)
|
||||
{
|
||||
if (bounds.Height < EntryHeight)
|
||||
{
|
||||
AddItem(x - OffsetSize - 22 - i % 2 * 44 - bounds.Width / 2 - bounds.X, y + EntryHeight / 2 - bounds.Height / 2 - bounds.Y, itemID);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddItem(x - OffsetSize - 22 - i % 2 * 44 - bounds.Width / 2 - bounds.X, y + EntryHeight - 1 - bounds.Height - bounds.Y, itemID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnResponse(NetState state, RelayInfo info)
|
||||
{
|
||||
Mobile from = m_Owner;
|
||||
|
||||
switch (info.ButtonID)
|
||||
{
|
||||
case 0: // Closed
|
||||
{
|
||||
return;
|
||||
}
|
||||
case 1: // Up
|
||||
{
|
||||
if (m_Category.Parent != null)
|
||||
{
|
||||
int index = Array.IndexOf(m_Category.Parent.Nodes, m_Category) / EntryCount;
|
||||
|
||||
if (index < 0)
|
||||
{
|
||||
index = 0;
|
||||
}
|
||||
|
||||
from.SendGump(new XmlCategorizedAddGump(from, m_Category.Parent, index, m_Index, m_Gump));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 2: // Previous
|
||||
{
|
||||
if (m_Page > 0)
|
||||
{
|
||||
from.SendGump(new XmlCategorizedAddGump(from, m_Category, m_Page - 1, m_Index, m_Gump));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 3: // Next
|
||||
{
|
||||
if ((m_Page + 1) * EntryCount < m_Category.Nodes.Length)
|
||||
{
|
||||
from.SendGump(new XmlCategorizedAddGump(from, m_Category, m_Page + 1, m_Index, m_Gump));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
int index = m_Page * EntryCount + (info.ButtonID - 4);
|
||||
|
||||
if (index >= 0 && index < m_Category.Nodes.Length)
|
||||
{
|
||||
m_Category.Nodes[index].OnClick(from, m_Page, m_Index, m_Gump);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1420
Projects/UOContent/Engines/XMLSpawner/XmlUtils/XmlEdit.cs
Normal file
1420
Projects/UOContent/Engines/XMLSpawner/XmlUtils/XmlEdit.cs
Normal file
File diff suppressed because it is too large
Load diff
2367
Projects/UOContent/Engines/XMLSpawner/XmlUtils/XmlFind.cs
Normal file
2367
Projects/UOContent/Engines/XMLSpawner/XmlUtils/XmlFind.cs
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,266 @@
|
|||
using Server.Mobiles;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Server.Gumps;
|
||||
|
||||
public class XmlPartialCategorizedAddGump : Gump
|
||||
{
|
||||
private readonly string m_SearchString;
|
||||
private readonly ArrayList m_SearchResults;
|
||||
private readonly int m_Page;
|
||||
private readonly Gump m_Gump;
|
||||
private readonly int m_EntryIndex;
|
||||
private readonly XmlSpawner m_Spawner;
|
||||
|
||||
public XmlPartialCategorizedAddGump(Mobile from, string searchString, int page, ArrayList searchResults, bool explicitSearch, int entryindex, Gump gump) : base(50, 50)
|
||||
{
|
||||
if (gump is XmlSpawnerGump spawnerGump)
|
||||
{
|
||||
// keep track of the spawner for xmlspawnergumps
|
||||
m_Spawner = spawnerGump.m_Spawner;
|
||||
}
|
||||
|
||||
// keep track of the gump
|
||||
m_Gump = gump;
|
||||
|
||||
|
||||
m_SearchString = searchString;
|
||||
m_SearchResults = searchResults;
|
||||
m_Page = page;
|
||||
|
||||
m_EntryIndex = entryindex;
|
||||
|
||||
from.CloseGump<XmlPartialCategorizedAddGump>();
|
||||
|
||||
AddPage(0);
|
||||
|
||||
AddBackground(0, 0, 420, 280, 5054);
|
||||
|
||||
AddImageTiled(10, 10, 400, 20, 2624);
|
||||
AddAlphaRegion(10, 10, 400, 20);
|
||||
AddImageTiled(41, 11, 184, 18, 0xBBC);
|
||||
AddImageTiled(42, 12, 182, 16, 2624);
|
||||
AddAlphaRegion(42, 12, 182, 16);
|
||||
|
||||
AddButton(10, 9, 4011, 4013, 1);
|
||||
AddTextEntry(44, 10, 180, 20, 0x480, 0, searchString);
|
||||
|
||||
AddHtmlLocalized(230, 10, 100, 20, 3010005, 0x7FFF);
|
||||
|
||||
AddImageTiled(10, 40, 400, 200, 2624);
|
||||
AddAlphaRegion(10, 40, 400, 200);
|
||||
|
||||
if (searchResults.Count > 0)
|
||||
{
|
||||
for (int i = page * 10; i < (page + 1) * 10 && i < searchResults.Count; ++i)
|
||||
{
|
||||
int index = i % 10;
|
||||
|
||||
SearchEntry se = (SearchEntry)searchResults[i];
|
||||
|
||||
string labelstr = se.EntryType.Name;
|
||||
|
||||
if (se.Parameters.Length > 0)
|
||||
{
|
||||
for (int j = 0; j < se.Parameters.Length; j++)
|
||||
{
|
||||
labelstr += $", {se.Parameters[j].Name}";
|
||||
}
|
||||
}
|
||||
|
||||
AddLabel(44, 39 + index * 20, 0x480, labelstr);
|
||||
AddButton(10, 39 + index * 20, 4023, 4025, 4 + i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddLabel(15, 44, 0x480, explicitSearch ? "Nothing matched your search terms." : "No results to display.");
|
||||
}
|
||||
|
||||
AddImageTiled(10, 250, 400, 20, 2624);
|
||||
AddAlphaRegion(10, 250, 400, 20);
|
||||
|
||||
if (m_Page > 0)
|
||||
{
|
||||
AddButton(10, 249, 4014, 4016, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddImage(10, 249, 4014);
|
||||
}
|
||||
|
||||
AddHtmlLocalized(44, 250, 170, 20, 1061028, m_Page > 0 ? 0x7FFF : 0x5EF7); // Previous page
|
||||
|
||||
if ((m_Page + 1) * 10 < searchResults.Count)
|
||||
{
|
||||
AddButton(210, 249, 4005, 4007, 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddImage(210, 249, 4005);
|
||||
}
|
||||
|
||||
AddHtmlLocalized(244, 250, 170, 20, 1061027, (m_Page + 1) * 10 < searchResults.Count ? 0x7FFF : 0x5EF7); // Next page
|
||||
}
|
||||
|
||||
private static readonly Type typeofItem = typeof(Item), typeofMobile = typeof(Mobile);
|
||||
|
||||
private class SearchEntry
|
||||
{
|
||||
public Type EntryType;
|
||||
public ParameterInfo[] Parameters;
|
||||
}
|
||||
private static void Match(string match, IReadOnlyList<Type> types, IList results)
|
||||
{
|
||||
if (match.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
match = match.ToLower();
|
||||
|
||||
for (int i = 0; i < types.Count; ++i)
|
||||
{
|
||||
Type t = types[i];
|
||||
|
||||
if ((typeofMobile.IsAssignableFrom(t) || typeofItem.IsAssignableFrom(t)) && t.Name.ToLower().IndexOf(match) >= 0 && !results.Contains(t))
|
||||
{
|
||||
ConstructorInfo[] ctors = t.GetConstructors();
|
||||
|
||||
for (int j = 0; j < ctors.Length; ++j)
|
||||
{
|
||||
if (/*ctors[j].GetParameters().Length == 0 && */ ctors[j].IsDefined(typeof(ConstructibleAttribute), false))
|
||||
{
|
||||
SearchEntry s = new SearchEntry
|
||||
{
|
||||
EntryType = t,
|
||||
Parameters = ctors[j].GetParameters()
|
||||
};
|
||||
//results.Add(t);
|
||||
results.Add(s);
|
||||
//break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static ArrayList Match(string match)
|
||||
{
|
||||
ArrayList results = new ArrayList();
|
||||
Type[] types;
|
||||
|
||||
Assembly[] asms = AssemblyHandler.Assemblies;
|
||||
|
||||
for (int i = 0; i < asms.Length; ++i)
|
||||
{
|
||||
types = AssemblyHandler.GetTypeCache(asms[i]).Types;
|
||||
Match(match, types, results);
|
||||
}
|
||||
|
||||
types = AssemblyHandler.GetTypeCache(Core.Assembly).Types;
|
||||
Match(match, types, results);
|
||||
|
||||
results.Sort(new TypeNameComparer());
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private class TypeNameComparer : IComparer
|
||||
{
|
||||
public int Compare(object x, object y)
|
||||
{
|
||||
SearchEntry a = x as SearchEntry;
|
||||
SearchEntry b = y as SearchEntry;
|
||||
|
||||
return a.EntryType.Name.CompareTo(b.EntryType.Name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public override void OnResponse(Network.NetState sender, RelayInfo info)
|
||||
{
|
||||
Mobile from = sender.Mobile;
|
||||
|
||||
switch (info.ButtonID)
|
||||
{
|
||||
case 1: // Search
|
||||
{
|
||||
TextRelay te = info.GetTextEntry(0);
|
||||
string match = te == null ? "" : te.Text.Trim();
|
||||
|
||||
if (match.Length < 3)
|
||||
{
|
||||
from.SendMessage("Invalid search string.");
|
||||
from.SendGump(new XmlPartialCategorizedAddGump(from, match, m_Page, m_SearchResults, false, m_EntryIndex, m_Gump));
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendGump(new XmlPartialCategorizedAddGump(from, match, 0, Match(match), true, m_EntryIndex, m_Gump));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 2: // Previous page
|
||||
{
|
||||
if (m_Page > 0)
|
||||
{
|
||||
from.SendGump(new XmlPartialCategorizedAddGump(from, m_SearchString, m_Page - 1, m_SearchResults, true, m_EntryIndex, m_Gump));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 3: // Next page
|
||||
{
|
||||
if ((m_Page + 1) * 10 < m_SearchResults.Count)
|
||||
{
|
||||
from.SendGump(new XmlPartialCategorizedAddGump(from, m_SearchString, m_Page + 1, m_SearchResults, true, m_EntryIndex, m_Gump));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
int index = info.ButtonID - 4;
|
||||
|
||||
if (index >= 0 && index < m_SearchResults.Count)
|
||||
{
|
||||
Type type = ((SearchEntry)m_SearchResults[index]).EntryType;
|
||||
|
||||
if (m_Gump is XmlAddGump mXmlAddGump && type != null)
|
||||
{
|
||||
if (mXmlAddGump.defs?.NameList != null && m_EntryIndex >= 0 && m_EntryIndex < mXmlAddGump.defs.NameList.Length)
|
||||
{
|
||||
mXmlAddGump.defs.NameList[m_EntryIndex] = type.Name;
|
||||
XmlAddGump.Refresh(from, true);
|
||||
}
|
||||
}
|
||||
else if (m_Spawner != null && type != null)
|
||||
{
|
||||
XmlSpawnerGump xg = m_Spawner.SpawnerGump;
|
||||
|
||||
if (xg != null)
|
||||
{
|
||||
|
||||
xg.Rentry = new XmlSpawnerGump.ReplacementEntry
|
||||
{
|
||||
Typename = type.Name,
|
||||
Index = m_EntryIndex,
|
||||
Color = 0x1436
|
||||
};
|
||||
|
||||
Timer.DelayCall(TimeSpan.Zero, XmlSpawnerGump.RefreshSpawnerGumps, from);
|
||||
//from.CloseGump<XmlSpawnerGump>();
|
||||
//from.SendGump(new XmlSpawnerGump(xg.m_Spawner, xg.X, xg.Y, xg.m_ShowGump, xg.xoffset, xg.page, xg.Rentry));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue