first commit
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using ClassicAssist.Shared;
|
||||
using ClassicAssist.Misc;
|
||||
using ClassicAssist.UO.Data;
|
||||
|
||||
namespace ClassicAssist.UO.Objects
|
||||
{
|
||||
public abstract class Entity : IEquatable<Entity>
|
||||
{
|
||||
protected Entity( int serial )
|
||||
{
|
||||
Serial = serial;
|
||||
}
|
||||
|
||||
public Direction Direction { get; set; }
|
||||
|
||||
public virtual int Distance =>
|
||||
Math.Max( Math.Abs( X - Engine.Player?.X ?? X ), Math.Abs( Y - Engine.Player?.Y ?? Y ) );
|
||||
|
||||
public int Hue { get; set; }
|
||||
|
||||
[DisplayFormat( typeof( HexFormatProvider ) )]
|
||||
public virtual int ID { get; set; }
|
||||
|
||||
public virtual string Name { get; set; }
|
||||
|
||||
[DisplayFormat( typeof( PropertyArrayFormatProvider ) )]
|
||||
public Property[] Properties { get; set; }
|
||||
|
||||
[DisplayFormat( typeof( HexFormatProvider ) )]
|
||||
public int Serial { get; }
|
||||
|
||||
public int X { get; set; }
|
||||
public int Y { get; set; }
|
||||
public int Z { get; set; }
|
||||
|
||||
public bool Equals( Entity other )
|
||||
{
|
||||
if ( ReferenceEquals( null, other ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ReferenceEquals( this, other ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return Serial == other.Serial;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
ToString( sb );
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
protected virtual void ToString( StringBuilder sb )
|
||||
{
|
||||
sb.Append( $"Name: {Name}\n" );
|
||||
sb.Append( $"Serial: 0x{Serial:x}\n" );
|
||||
sb.Append( $"ID: 0x{ID:x}\n" );
|
||||
sb.Append( $"Hue: {(uint) Hue}\n" );
|
||||
sb.Append( $"X: {X}, Y: {Y}, Z: {Z}\n" );
|
||||
}
|
||||
|
||||
public override bool Equals( object obj )
|
||||
{
|
||||
if ( ReferenceEquals( null, obj ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ReferenceEquals( this, obj ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( obj.GetType() != GetType() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return Equals( (Entity) obj );
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Serial;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
|
||||
namespace ClassicAssist.UO.Objects
|
||||
{
|
||||
public abstract class EntityCollection<T> where T : Entity
|
||||
{
|
||||
public delegate void dCollectionChanged( int totalCount, bool added, T[] entities );
|
||||
|
||||
protected ConcurrentDictionary<int, T> EntityList;
|
||||
|
||||
protected EntityCollection() : this( short.MaxValue )
|
||||
{
|
||||
}
|
||||
|
||||
protected EntityCollection( int capacity )
|
||||
{
|
||||
EntityList = new ConcurrentDictionary<int, T>( 16, capacity );
|
||||
}
|
||||
|
||||
public T this[ int s ]
|
||||
{
|
||||
get => EntityList.ContainsKey( s ) ? EntityList[s] : null;
|
||||
set => EntityList[s] = value;
|
||||
}
|
||||
|
||||
public virtual bool Add( T entity )
|
||||
{
|
||||
bool changed = EntityList.AddOrUpdate( entity.Serial, entity, ( k, v ) => entity ) != null;
|
||||
|
||||
if ( changed )
|
||||
{
|
||||
OnCollectionChanged( true, new[] { entity } );
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
public virtual bool Add( T[] entities )
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
foreach ( T entity in entities )
|
||||
{
|
||||
if ( EntityList.AddOrUpdate( entity.Serial, entity, ( k, v ) => entity ) == null )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if ( changed )
|
||||
{
|
||||
OnCollectionChanged( true, entities );
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
protected T[] GetEntities()
|
||||
{
|
||||
T[] entityArray = new T[EntityList.Values.Count];
|
||||
EntityList.Values.CopyTo( entityArray, 0 );
|
||||
return entityArray;
|
||||
}
|
||||
|
||||
public virtual bool Remove( T entity )
|
||||
{
|
||||
return Remove( entity.Serial );
|
||||
}
|
||||
|
||||
public virtual bool Remove( int serial )
|
||||
{
|
||||
EntityList.TryRemove( serial, out T val );
|
||||
|
||||
if ( val != null )
|
||||
{
|
||||
OnCollectionChanged( false, new[] { val } );
|
||||
}
|
||||
|
||||
return val != null;
|
||||
}
|
||||
|
||||
public virtual bool Remove( T[] entities )
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
foreach ( T entity in entities )
|
||||
{
|
||||
if ( Remove( entity.Serial ) )
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
internal virtual void Clear()
|
||||
{
|
||||
T[] all = EntityList.Values.ToArray();
|
||||
|
||||
EntityList.Clear();
|
||||
|
||||
OnCollectionChanged( false, all );
|
||||
}
|
||||
|
||||
public event dCollectionChanged CollectionChanged;
|
||||
|
||||
public virtual void OnCollectionChanged( bool added, T[] entities )
|
||||
{
|
||||
CollectionChanged?.Invoke( EntityList.Count, added, entities );
|
||||
}
|
||||
|
||||
public virtual void RemoveByDistance( int maxDistance, int x, int y )
|
||||
{
|
||||
T[] items = SelectEntities( i =>
|
||||
i is Item item && item.Owner == 0 && UOMath.Distance( x, y, item.X, item.Y ) > maxDistance );
|
||||
|
||||
if ( items == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool changed = Remove( items );
|
||||
|
||||
if ( changed )
|
||||
{
|
||||
OnCollectionChanged( false, items );
|
||||
}
|
||||
}
|
||||
|
||||
public virtual T SelectEntity( Func<T, bool> func )
|
||||
{
|
||||
if ( func == null )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
T entity = EntityList.Select( m => m.Value ).FirstOrDefault( func );
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
public virtual T[] SelectEntities( Func<T, bool> func )
|
||||
{
|
||||
return EntityList.Select( m => m.Value ).Where( func ).ToArray();
|
||||
}
|
||||
|
||||
protected T GetEntity( int key )
|
||||
{
|
||||
EntityList.TryGetValue( key, out T val );
|
||||
|
||||
return val;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/* Copyright (C) 2009 Matthew Geyer
|
||||
*
|
||||
* This file is part of UO Machine.
|
||||
*
|
||||
* UO Machine is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* UO Machine is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with UO Machine. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
using ClassicAssist.UO.Objects.Gumps;
|
||||
|
||||
namespace ClassicAssist.UO.Objects
|
||||
{
|
||||
public sealed class GumpCollection
|
||||
{
|
||||
private readonly ConcurrentDictionary<uint, Gump> _dictionary;
|
||||
|
||||
public GumpCollection()
|
||||
{
|
||||
_dictionary = new ConcurrentDictionary<uint, Gump>();
|
||||
}
|
||||
|
||||
public void Add( Gump gump )
|
||||
{
|
||||
bool result = _dictionary.AddOrUpdate( gump.ID, gump, ( k, v ) => gump ) != null;
|
||||
|
||||
if ( result )
|
||||
{
|
||||
OnCollectionChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public bool Remove( uint id, int buttonId = 0 )
|
||||
{
|
||||
bool result = _dictionary.TryRemove( id, out Gump g );
|
||||
|
||||
g?.OnResponse( buttonId, null );
|
||||
|
||||
if ( result )
|
||||
{
|
||||
OnCollectionChanged();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool GetGump( uint id, out Gump gump )
|
||||
{
|
||||
return _dictionary.TryGetValue( id, out gump );
|
||||
}
|
||||
|
||||
public bool FindGump( int serial, out Gump gump )
|
||||
{
|
||||
gump = _dictionary.Values.FirstOrDefault( g => g.Serial == serial );
|
||||
|
||||
return gump != null;
|
||||
}
|
||||
|
||||
public bool GetGumps( out Gump[] gumps )
|
||||
{
|
||||
gumps = null;
|
||||
|
||||
if ( _dictionary.Values.Count == 0 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
gumps = _dictionary.Values.ToArray();
|
||||
|
||||
return gumps.Length > 0;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
int previousCount = _dictionary.Count;
|
||||
|
||||
_dictionary.Clear();
|
||||
|
||||
if ( previousCount > 0 )
|
||||
{
|
||||
OnCollectionChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCollectionChanged()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,891 @@
|
||||
/* Copyright (C) 2009 Matthew Geyer
|
||||
*
|
||||
* This file is part of UO Machine.
|
||||
*
|
||||
* UO Machine is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* UO Machine is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with UO Machine. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using ClassicAssist.Shared;
|
||||
using ClassicAssist.Shared.UO;
|
||||
using ClassicAssist.UO.Data;
|
||||
|
||||
namespace ClassicAssist.UO.Objects.Gumps
|
||||
{
|
||||
public class Gump
|
||||
{
|
||||
private static readonly Random _random = new Random();
|
||||
|
||||
private static readonly byte[] BeginLayout = StringToBuffer( "{ " );
|
||||
private static readonly byte[] EndLayout = StringToBuffer( " }" );
|
||||
|
||||
private static readonly byte[] NoMove = StringToBuffer( "{ nomove }" );
|
||||
private static readonly byte[] NoClose = StringToBuffer( "{ noclose }" );
|
||||
private static readonly byte[] NoDispose = StringToBuffer( "{ nodispose }" );
|
||||
private static readonly byte[] NoResize = StringToBuffer( "{ noresize }" );
|
||||
|
||||
private static readonly byte[] True = StringToBuffer( " 1" );
|
||||
private static readonly byte[] False = StringToBuffer( " 0" );
|
||||
|
||||
private static readonly byte[] BeginTextSeparator = StringToBuffer( " @" );
|
||||
private static readonly byte[] EndTextSeparator = StringToBuffer( "@" );
|
||||
|
||||
public readonly string Layout;
|
||||
public readonly GumpPage[] Pages;
|
||||
|
||||
private List<GumpElement> _elements;
|
||||
private List<string> _strings;
|
||||
public int Serial;
|
||||
public int X;
|
||||
public int Y;
|
||||
|
||||
public Gump( int x, int y, uint id, int serial, string layout, string[] strings, GumpElement[] elements,
|
||||
GumpPage[] pages )
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
ID = id;
|
||||
Serial = serial;
|
||||
Layout = layout;
|
||||
Strings = strings;
|
||||
GumpElements = elements;
|
||||
Pages = pages;
|
||||
|
||||
foreach ( GumpPage gp in pages )
|
||||
{
|
||||
gp.ParentGump = this;
|
||||
}
|
||||
}
|
||||
|
||||
public Gump( int x, int y, int serial = 0, uint id = 0 )
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
|
||||
Serial = serial;
|
||||
ID = id;
|
||||
|
||||
string fullName = GetType().FullName;
|
||||
|
||||
if ( ID == 0 && fullName != null )
|
||||
{
|
||||
ID = (uint) fullName.GetHashCode();
|
||||
}
|
||||
|
||||
if ( Serial == 0 && fullName != null )
|
||||
{
|
||||
uint hashCode = (uint) fullName.GetHashCode();
|
||||
|
||||
hashCode &= 0x0000FFFF;
|
||||
hashCode <<= 8;
|
||||
hashCode |= (uint) 0xFF << 24;
|
||||
|
||||
Serial = (int) ( hashCode + _random.Next( 0, 0xFF ) );
|
||||
}
|
||||
|
||||
_elements = new List<GumpElement>();
|
||||
_strings = new List<string>();
|
||||
}
|
||||
|
||||
public bool Closable { get; set; }
|
||||
|
||||
public bool Disposable { get; set; }
|
||||
|
||||
public GumpElement[] GumpElements
|
||||
{
|
||||
get => _elements.ToArray();
|
||||
set
|
||||
{
|
||||
_elements = new List<GumpElement>();
|
||||
|
||||
for ( int i = 0; i < value.Length; i++ )
|
||||
{
|
||||
_elements.Add( value[i] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public uint ID { get; }
|
||||
|
||||
public bool Movable { get; set; }
|
||||
|
||||
public bool Resizable { get; set; }
|
||||
|
||||
public string[] Strings
|
||||
{
|
||||
get => _strings.ToArray();
|
||||
set
|
||||
{
|
||||
_strings = new List<string>();
|
||||
|
||||
for ( int i = 0; i < value.Length; i++ )
|
||||
{
|
||||
_strings.Add( value[i] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get array of GumpElements which match the specified ElementType from all pages.
|
||||
/// </summary>
|
||||
public GumpElement[] GetElementsByType( ElementType type )
|
||||
{
|
||||
List<GumpElement> elementList = new List<GumpElement>();
|
||||
|
||||
if ( GumpElements != null )
|
||||
{
|
||||
elementList.AddRange( GumpElements.Where( ge => ge.Type == type ) );
|
||||
}
|
||||
|
||||
if ( Pages != null )
|
||||
{
|
||||
elementList.AddRange( from p in Pages from ge in p.GumpElements where ge.Type == type select ge );
|
||||
}
|
||||
|
||||
return elementList.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the GumpElement with the specified ID. Searches all pages/elements.
|
||||
/// </summary>
|
||||
/// <returns>True on success.</returns>
|
||||
public bool GetElementByID( int id, out GumpElement element )
|
||||
{
|
||||
if ( GumpElements != null )
|
||||
{
|
||||
foreach ( GumpElement ge in GumpElements )
|
||||
{
|
||||
if ( ge.ElementID == id )
|
||||
{
|
||||
element = ge;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( Pages != null )
|
||||
{
|
||||
foreach ( GumpPage p in Pages )
|
||||
{
|
||||
foreach ( GumpElement ge in p.GumpElements )
|
||||
{
|
||||
if ( ge.ElementID == id )
|
||||
{
|
||||
element = ge;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
element = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the GumpElement nearest to the specified GumpElement.
|
||||
/// </summary>
|
||||
/// <returns>True on success.</returns>
|
||||
public bool GetNearestElement( GumpElement source, out GumpElement element )
|
||||
{
|
||||
GumpElement nearest = null;
|
||||
double closest = 0;
|
||||
|
||||
if ( source.ParentPage != null )
|
||||
{
|
||||
return source.ParentPage.GetNearestElement( source, out element );
|
||||
}
|
||||
|
||||
foreach ( GumpElement ge in GumpElements )
|
||||
{
|
||||
if ( ge == source )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
double distance = UOMath.Distance( source.X, source.Y, ge.X, ge.Y );
|
||||
|
||||
if ( nearest == null )
|
||||
{
|
||||
closest = distance;
|
||||
nearest = ge;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( distance < closest )
|
||||
{
|
||||
closest = distance;
|
||||
nearest = ge;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
element = nearest;
|
||||
return nearest != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get nearest GumpElement to source, but only if it's ElementType is contained in the include list.
|
||||
/// </summary>
|
||||
/// <param name="source">Source GumpElement</param>
|
||||
/// <param name="includeTypes">Array of ElementTypes which specifies valid GumpElements to search.</param>
|
||||
/// <param name="element">GumpElement (out).</param>
|
||||
/// <returns>True on success.</returns>
|
||||
public bool GetNearestElement( GumpElement source, ElementType[] includeTypes, out GumpElement element )
|
||||
{
|
||||
GumpElement nearest = null;
|
||||
double closest = 0;
|
||||
|
||||
if ( source.ParentPage != null )
|
||||
{
|
||||
return source.ParentPage.GetNearestElement( source, includeTypes, out element );
|
||||
}
|
||||
|
||||
foreach ( GumpElement ge in GumpElements )
|
||||
{
|
||||
if ( ge == source )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
bool found = includeTypes.Any( et => ge.Type == et );
|
||||
|
||||
if ( !found )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
double distance = UOMath.Distance( source.X, source.Y, ge.X, ge.Y );
|
||||
|
||||
if ( nearest == null )
|
||||
{
|
||||
closest = distance;
|
||||
nearest = ge;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( distance < closest )
|
||||
{
|
||||
closest = distance;
|
||||
nearest = ge;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
element = nearest;
|
||||
return nearest != null;
|
||||
}
|
||||
|
||||
public bool GetElementByXY( int x, int y, out GumpElement gumpElement )
|
||||
{
|
||||
gumpElement = null;
|
||||
|
||||
if ( GumpElements == null )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
GumpElement element = GumpElements.FirstOrDefault( m => m.X == x && m.Y == y );
|
||||
|
||||
if ( element != null )
|
||||
{
|
||||
gumpElement = element;
|
||||
}
|
||||
|
||||
return gumpElement != null;
|
||||
}
|
||||
|
||||
public GumpElement GetElementByXY( int x, int y )
|
||||
{
|
||||
return GetElementByXY( x, y, out GumpElement element ) ? element : null;
|
||||
}
|
||||
|
||||
public bool GetElementByCliloc( int cliloc, out GumpElement gumpElement )
|
||||
{
|
||||
gumpElement = null;
|
||||
|
||||
if ( GumpElements == null )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
GumpElement element = GumpElements.FirstOrDefault( m => m.Cliloc == cliloc );
|
||||
|
||||
if ( element != null )
|
||||
{
|
||||
gumpElement = element;
|
||||
}
|
||||
|
||||
return gumpElement != null;
|
||||
}
|
||||
|
||||
public GumpElement GetElementByCliloc( int cliloc )
|
||||
{
|
||||
return GetElementByCliloc( cliloc, out GumpElement element ) ? element : null;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return ID.GetHashCode() ^ Layout?.GetHashCode() ?? 0;
|
||||
}
|
||||
|
||||
public virtual void OnResponse( int buttonID, int[] switches )
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void SendGump()
|
||||
{
|
||||
byte[] bytes = Compile();
|
||||
|
||||
Engine.Gumps.Add( this );
|
||||
Engine.SendPacketToClient( bytes, bytes.Length );
|
||||
}
|
||||
|
||||
public void CloseGump()
|
||||
{
|
||||
Commands.CloseClientGump( ID );
|
||||
}
|
||||
|
||||
public void Add( GumpElement e )
|
||||
{
|
||||
e.ParentGump = this;
|
||||
_elements.Add( e );
|
||||
}
|
||||
|
||||
public void AddPage( int page )
|
||||
{
|
||||
GumpElement ge = new GumpElement { Type = ElementType.page, PageNumber = page };
|
||||
Add( ge );
|
||||
}
|
||||
|
||||
public void AddAlphaRegion( int x, int y, int width, int height )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.checkertrans,
|
||||
X = x,
|
||||
Y = y,
|
||||
Width = width,
|
||||
Height = height
|
||||
};
|
||||
Add( ge );
|
||||
}
|
||||
|
||||
public void AddBackground( int x, int y, int width, int height, int gumpID )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.resizepic,
|
||||
X = x,
|
||||
Y = y,
|
||||
Width = width,
|
||||
Height = height,
|
||||
ElementID = gumpID
|
||||
};
|
||||
Add( ge );
|
||||
}
|
||||
|
||||
public void AddButton( int x, int y, int normalID, int pressedID, int buttonID, GumpButtonType type, int param )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.button,
|
||||
X = x,
|
||||
Y = y,
|
||||
InactiveID = normalID,
|
||||
ActiveID = pressedID,
|
||||
ButtonType = (int) type,
|
||||
ElementID = buttonID,
|
||||
Param = param
|
||||
};
|
||||
Add( ge );
|
||||
}
|
||||
|
||||
public void AddCheck( int x, int y, int inactiveID, int activeID, bool initialState, int switchID )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.checkbox,
|
||||
X = x,
|
||||
Y = y,
|
||||
InactiveID = inactiveID,
|
||||
ActiveID = activeID,
|
||||
InitialState = initialState,
|
||||
ElementID = switchID
|
||||
};
|
||||
Add( ge );
|
||||
}
|
||||
|
||||
public void AddGroup( int group )
|
||||
{
|
||||
GumpElement ge = new GumpElement { Type = ElementType.group, Group = group };
|
||||
Add( ge );
|
||||
}
|
||||
|
||||
public void AddTooltip( int number )
|
||||
{
|
||||
GumpElement ge = new GumpElement { Type = ElementType.tooltip, Cliloc = number };
|
||||
Add( ge );
|
||||
}
|
||||
|
||||
public void AddHtml( int x, int y, int width, int height, string text, bool background, bool scrollbar )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.htmlgump,
|
||||
X = x,
|
||||
Y = y,
|
||||
Width = width,
|
||||
Height = height,
|
||||
Text = text,
|
||||
ScrollBar = scrollbar,
|
||||
Background = background
|
||||
};
|
||||
Add( ge );
|
||||
}
|
||||
|
||||
public void AddHtmlLocalized( int x, int y, int width, int height, int number, bool background, bool scrollbar )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.xmfhtmlgump,
|
||||
X = x,
|
||||
Y = y,
|
||||
Width = width,
|
||||
Height = height,
|
||||
Cliloc = number,
|
||||
Background = background,
|
||||
ScrollBar = scrollbar
|
||||
};
|
||||
Add( ge );
|
||||
}
|
||||
|
||||
public void AddHtmlLocalized( int x, int y, int width, int height, int number, int color, bool background,
|
||||
bool scrollbar )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.xmfhtmlgumpcolor,
|
||||
X = x,
|
||||
Y = y,
|
||||
Width = width,
|
||||
Height = height,
|
||||
Cliloc = number,
|
||||
Hue = color,
|
||||
Background = background,
|
||||
ScrollBar = scrollbar
|
||||
};
|
||||
Add( ge );
|
||||
}
|
||||
|
||||
public void AddHtmlLocalized( int x, int y, int width, int height, int number, string args, int color,
|
||||
bool background, bool scrollbar )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.xmfhtmltok,
|
||||
X = x,
|
||||
Y = y,
|
||||
Width = width,
|
||||
Height = height,
|
||||
Cliloc = number,
|
||||
Args = args,
|
||||
Hue = color,
|
||||
Background = background,
|
||||
ScrollBar = scrollbar
|
||||
};
|
||||
Add( ge );
|
||||
}
|
||||
|
||||
public void AddImage( int x, int y, int gumpID )
|
||||
{
|
||||
AddImage( x, y, gumpID, 0 );
|
||||
}
|
||||
|
||||
public void AddImage( int x, int y, int gumpID, int hue )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.gumppic,
|
||||
X = x,
|
||||
Y = y,
|
||||
ElementID = gumpID,
|
||||
Hue = hue
|
||||
};
|
||||
Add( ge );
|
||||
}
|
||||
|
||||
public void AddImageTiled( int x, int y, int width, int height, int gumpID )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.gumppictiled,
|
||||
X = x,
|
||||
Y = y,
|
||||
Width = width,
|
||||
Height = height,
|
||||
ElementID = gumpID
|
||||
};
|
||||
Add( ge );
|
||||
}
|
||||
|
||||
public void AddImageTiledButton( int x, int y, int normalID, int pressedID, int buttonID, GumpButtonType type,
|
||||
int param, int itemID, int hue, int width, int height )
|
||||
{
|
||||
AddImageTiledButton( x, y, normalID, pressedID, buttonID, type, param, itemID, hue, width, height, -1 );
|
||||
}
|
||||
|
||||
public void AddImageTiledButton( int x, int y, int normalID, int pressedID, int buttonID, GumpButtonType type,
|
||||
int param, int itemID, int hue, int width, int height, int localizedTooltip )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.buttontileart,
|
||||
X = x,
|
||||
Y = y,
|
||||
InactiveID = normalID,
|
||||
ActiveID = pressedID,
|
||||
ElementID = buttonID,
|
||||
ButtonType = (int) type,
|
||||
Param = param,
|
||||
ItemID = itemID,
|
||||
Hue = hue,
|
||||
Height = height,
|
||||
Width = width,
|
||||
Cliloc = localizedTooltip
|
||||
};
|
||||
Add( ge );
|
||||
}
|
||||
|
||||
public void AddItem( int x, int y, int itemID )
|
||||
{
|
||||
GumpElement ge = new GumpElement { Type = ElementType.tilepic, X = x, Y = y, ItemID = itemID };
|
||||
Add( ge );
|
||||
}
|
||||
|
||||
public void AddItem( int x, int y, int itemID, int hue )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.tilepic,
|
||||
X = x,
|
||||
Y = y,
|
||||
ItemID = itemID,
|
||||
Hue = hue
|
||||
};
|
||||
Add( ge );
|
||||
}
|
||||
|
||||
public void AddLabel( int x, int y, int hue, string text )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.text,
|
||||
X = x,
|
||||
Y = y,
|
||||
Hue = hue,
|
||||
Text = text
|
||||
};
|
||||
Add( ge );
|
||||
}
|
||||
|
||||
public void AddLabelCropped( int x, int y, int width, int height, int hue, string text )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.croppedtext,
|
||||
X = x,
|
||||
Y = y,
|
||||
Width = width,
|
||||
Height = height,
|
||||
Hue = hue,
|
||||
Text = text
|
||||
};
|
||||
Add( ge );
|
||||
}
|
||||
|
||||
public void AddRadio( int x, int y, int inactiveID, int activeID, bool initialState, int switchID )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.radio,
|
||||
X = x,
|
||||
Y = y,
|
||||
InactiveID = inactiveID,
|
||||
ActiveID = activeID,
|
||||
InitialState = initialState,
|
||||
ElementID = switchID
|
||||
};
|
||||
Add( ge );
|
||||
}
|
||||
|
||||
public void AddTextEntry( int x, int y, int width, int height, int hue, int entryID, string initialText )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.textentry,
|
||||
X = x,
|
||||
Y = y,
|
||||
Width = width,
|
||||
Height = height,
|
||||
Hue = hue,
|
||||
ElementID = entryID,
|
||||
Text = initialText
|
||||
};
|
||||
Add( ge );
|
||||
}
|
||||
|
||||
public void AddTextEntry( int x, int y, int width, int height, int hue, int entryID, string initialText,
|
||||
int size )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.textentrylimited,
|
||||
X = x,
|
||||
Y = y,
|
||||
Width = width,
|
||||
Height = height,
|
||||
Hue = hue,
|
||||
ElementID = entryID,
|
||||
Text = initialText,
|
||||
Size = size
|
||||
};
|
||||
Add( ge );
|
||||
}
|
||||
|
||||
public void AddItemProperty( int serial )
|
||||
{
|
||||
GumpElement ge = new GumpElement { Type = ElementType.itemproperty, Serial = serial };
|
||||
Add( ge );
|
||||
}
|
||||
|
||||
public int Intern( string value )
|
||||
{
|
||||
int indexOf = _strings.IndexOf( value );
|
||||
|
||||
if ( indexOf >= 0 )
|
||||
{
|
||||
return indexOf;
|
||||
}
|
||||
|
||||
_strings.Add( value );
|
||||
return _strings.Count - 1;
|
||||
}
|
||||
|
||||
internal static byte[] StringToBuffer( string str )
|
||||
{
|
||||
return Encoding.ASCII.GetBytes( str );
|
||||
}
|
||||
|
||||
private byte[] Compile()
|
||||
{
|
||||
IGumpWriter disp = new GumpWriter( this );
|
||||
|
||||
if ( !Movable )
|
||||
{
|
||||
disp.AppendLayout( NoMove );
|
||||
}
|
||||
|
||||
if ( !Closable )
|
||||
{
|
||||
disp.AppendLayout( NoClose );
|
||||
}
|
||||
|
||||
if ( !Disposable )
|
||||
{
|
||||
disp.AppendLayout( NoDispose );
|
||||
}
|
||||
|
||||
if ( !Resizable )
|
||||
{
|
||||
disp.AppendLayout( NoResize );
|
||||
}
|
||||
|
||||
int count = GumpElements.Length;
|
||||
|
||||
for ( int i = 0; i < count; ++i )
|
||||
{
|
||||
GumpElement e = GumpElements[i];
|
||||
|
||||
disp.AppendLayout( BeginLayout );
|
||||
e.AppendTo( disp );
|
||||
disp.AppendLayout( EndLayout );
|
||||
}
|
||||
|
||||
List<string> strings = new List<string>();
|
||||
|
||||
if ( Strings != null )
|
||||
{
|
||||
for ( int i = 0; i < Strings.Length; i++ )
|
||||
{
|
||||
strings.Add( Strings[i] );
|
||||
}
|
||||
}
|
||||
|
||||
disp.WriteStrings( strings );
|
||||
|
||||
disp.Flush();
|
||||
|
||||
return disp.ToArray();
|
||||
}
|
||||
|
||||
internal interface IGumpWriter
|
||||
{
|
||||
int Switches { get; set; }
|
||||
int TextEntries { get; set; }
|
||||
|
||||
void AppendLayout( bool val );
|
||||
void AppendLayout( int val );
|
||||
void AppendLayoutNS( int val );
|
||||
void AppendLayout( string text );
|
||||
void AppendLayout( byte[] buffer );
|
||||
void WriteStrings( List<string> strings );
|
||||
void Flush();
|
||||
byte[] ToArray();
|
||||
}
|
||||
|
||||
internal class GumpWriter : IGumpWriter, IDisposable
|
||||
{
|
||||
private readonly byte[] _buffer = new byte[48];
|
||||
|
||||
private readonly PacketWriter _stream;
|
||||
|
||||
private int m_LayoutLength;
|
||||
private int m_PacketLength;
|
||||
private int m_StringsLength;
|
||||
|
||||
public GumpWriter( Gump g )
|
||||
{
|
||||
_stream = new PacketWriter( 4096 );
|
||||
_buffer[0] = (byte) ' ';
|
||||
_stream.Write( (byte) 0xB0 );
|
||||
_stream.Write( (short) 0 );
|
||||
_stream.Write( g.Serial );
|
||||
_stream.Write( g.ID );
|
||||
_stream.Write( g.X );
|
||||
_stream.Write( g.Y );
|
||||
_stream.Write( (ushort) 0xFFFF );
|
||||
}
|
||||
|
||||
public int Switches { get; set; }
|
||||
public int TextEntries { get; set; }
|
||||
|
||||
public void AppendLayout( byte[] buffer )
|
||||
{
|
||||
int length = buffer.Length;
|
||||
_stream.Write( buffer, 0, length );
|
||||
m_LayoutLength += length;
|
||||
}
|
||||
|
||||
public void AppendLayout( string text )
|
||||
{
|
||||
AppendLayout( BeginTextSeparator );
|
||||
|
||||
int length = text.Length;
|
||||
_stream.WriteAsciiFixed( text, length );
|
||||
m_LayoutLength += length;
|
||||
|
||||
AppendLayout( EndTextSeparator );
|
||||
}
|
||||
|
||||
public void AppendLayout( int val )
|
||||
{
|
||||
string toString = val.ToString();
|
||||
int bytes = Encoding.ASCII.GetBytes( toString, 0, toString.Length, _buffer, 1 ) + 1;
|
||||
|
||||
_stream.Write( _buffer, 0, bytes );
|
||||
m_LayoutLength += bytes;
|
||||
}
|
||||
|
||||
public void AppendLayout( bool val )
|
||||
{
|
||||
AppendLayout( val ? True : False );
|
||||
}
|
||||
|
||||
public void AppendLayoutNS( int val )
|
||||
{
|
||||
string toString = val.ToString();
|
||||
int bytes = Encoding.ASCII.GetBytes( toString, 0, toString.Length, _buffer, 1 );
|
||||
|
||||
_stream.Write( _buffer, 1, bytes );
|
||||
m_LayoutLength += bytes;
|
||||
}
|
||||
|
||||
public void Flush()
|
||||
{
|
||||
int length = 23 + m_LayoutLength + m_StringsLength;
|
||||
_stream.Seek( 1, SeekOrigin.Begin );
|
||||
_stream.Write( (short) length );
|
||||
m_PacketLength = length;
|
||||
}
|
||||
|
||||
public void WriteStrings( List<string> text )
|
||||
{
|
||||
_stream.Seek( 19, SeekOrigin.Begin );
|
||||
_stream.Write( (ushort) m_LayoutLength );
|
||||
_stream.Seek( 0, SeekOrigin.End );
|
||||
|
||||
_stream.Write( (ushort) text.Count );
|
||||
|
||||
for ( int i = 0; i < text.Count; ++i )
|
||||
{
|
||||
string v = text[i] ?? string.Empty;
|
||||
|
||||
int length = (ushort) v.Length;
|
||||
m_StringsLength += length * 2 + 2;
|
||||
|
||||
_stream.Write( (ushort) length );
|
||||
_stream.WriteBigUniFixed( v, length );
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] ToArray()
|
||||
{
|
||||
byte[] packet = new byte[m_PacketLength];
|
||||
Buffer.BlockCopy( _stream.ToArray(), 0, packet, 0, m_PacketLength );
|
||||
return packet;
|
||||
}
|
||||
|
||||
#region IDisposable Support
|
||||
|
||||
private bool disposedValue; // To detect redundant calls
|
||||
|
||||
protected virtual void Dispose( bool disposing )
|
||||
{
|
||||
if ( disposedValue )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( disposing )
|
||||
{
|
||||
_stream.Dispose();
|
||||
}
|
||||
|
||||
disposedValue = true;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose( true );
|
||||
GC.SuppressFinalize( this );
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace ClassicAssist.UO.Objects.Gumps
|
||||
{
|
||||
public enum GumpButtonType
|
||||
{
|
||||
Page = 0,
|
||||
Reply = 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,346 @@
|
||||
/* Copyright (C) 2009 Matthew Geyer
|
||||
*
|
||||
* This file is part of UO Machine.
|
||||
*
|
||||
* UO Machine is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* UO Machine is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with UO Machine. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
using System;
|
||||
|
||||
namespace ClassicAssist.UO.Objects.Gumps
|
||||
{
|
||||
public class GumpElement
|
||||
{
|
||||
private Gump _parentGump;
|
||||
public int ActiveID { get; set; }
|
||||
public string Args { get; set; }
|
||||
public bool Background { get; set; }
|
||||
public int ButtonType { get; set; }
|
||||
public int Cliloc { get; set; }
|
||||
public int ElementID { get; set; }
|
||||
public int Group { get; set; }
|
||||
public int Height { get; set; }
|
||||
public int Hue { get; set; }
|
||||
public int InactiveID { get; set; }
|
||||
public bool InitialState { get; set; }
|
||||
public int ItemID { get; set; }
|
||||
public int PageNumber { get; set; }
|
||||
public int Param { get; set; }
|
||||
|
||||
public Gump ParentGump
|
||||
{
|
||||
get => _parentGump ?? ParentPage?.ParentGump;
|
||||
set => _parentGump = value;
|
||||
}
|
||||
|
||||
public GumpPage ParentPage { get; set; }
|
||||
public bool ScrollBar { get; set; }
|
||||
public int Serial { get; set; }
|
||||
public int Size { get; set; }
|
||||
public string Text { get; set; }
|
||||
public int Tooltip { get; set; }
|
||||
public ElementType Type { get; set; }
|
||||
public int Width { get; set; }
|
||||
public int X { get; set; }
|
||||
public int Y { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Get nearest GumpElement.
|
||||
/// </summary>
|
||||
/// <returns>True on success.</returns>
|
||||
public bool GetNearestElement( out GumpElement element )
|
||||
{
|
||||
if ( ParentPage != null )
|
||||
{
|
||||
return ParentPage.GetNearestElement( this, out element );
|
||||
}
|
||||
|
||||
element = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get nearest GumpElement, but only if it's ElementType is contained in the include list.
|
||||
/// </summary>
|
||||
/// <param name="includeTypes">Array of ElementTypes which specifies valid GumpElements to search.</param>
|
||||
/// <param name="element">GumpElement (out).</param>
|
||||
/// <returns>True on success.</returns>
|
||||
public bool GetNearestElement( ElementType[] includeTypes, out GumpElement element )
|
||||
{
|
||||
if ( ParentPage != null )
|
||||
{
|
||||
return ParentPage.GetNearestElement( this, includeTypes, out element );
|
||||
}
|
||||
|
||||
element = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Click()
|
||||
{
|
||||
Gump g = ParentGump;
|
||||
|
||||
if ( g != null && g.ID != 461 && Type == ElementType.button )
|
||||
{
|
||||
//TODO
|
||||
//Macros.MacroEx.CloseClientGump( g.Client, g.ID );
|
||||
//Macros.MacroEx.GumpButtonClick( g.Client, g.ID, g.Serial, this.ElementID );
|
||||
}
|
||||
}
|
||||
|
||||
internal void AppendTo( Gump.IGumpWriter disp )
|
||||
{
|
||||
switch ( Type )
|
||||
{
|
||||
case ElementType.textentrylimited:
|
||||
{
|
||||
disp.AppendLayout( Gump.StringToBuffer( "textentrylimited" ) );
|
||||
disp.AppendLayout( X );
|
||||
disp.AppendLayout( Y );
|
||||
disp.AppendLayout( Width );
|
||||
disp.AppendLayout( Height );
|
||||
disp.AppendLayout( Hue );
|
||||
disp.AppendLayout( ElementID );
|
||||
disp.AppendLayout( ParentGump.Intern( Text ) );
|
||||
disp.AppendLayout( Size );
|
||||
disp.TextEntries++;
|
||||
break;
|
||||
}
|
||||
case ElementType.textentry:
|
||||
{
|
||||
disp.AppendLayout( Gump.StringToBuffer( "textentry" ) );
|
||||
disp.AppendLayout( X );
|
||||
disp.AppendLayout( Y );
|
||||
disp.AppendLayout( Width );
|
||||
disp.AppendLayout( Height );
|
||||
disp.AppendLayout( Hue );
|
||||
disp.AppendLayout( ElementID );
|
||||
disp.AppendLayout( ParentGump.Intern( Text ) );
|
||||
disp.TextEntries++;
|
||||
break;
|
||||
}
|
||||
case ElementType.radio:
|
||||
{
|
||||
disp.AppendLayout( Gump.StringToBuffer( "radio" ) );
|
||||
disp.AppendLayout( X );
|
||||
disp.AppendLayout( Y );
|
||||
disp.AppendLayout( InactiveID );
|
||||
disp.AppendLayout( ActiveID );
|
||||
disp.AppendLayout( InitialState );
|
||||
disp.AppendLayout( ElementID );
|
||||
disp.Switches++;
|
||||
break;
|
||||
}
|
||||
case ElementType.croppedtext:
|
||||
{
|
||||
disp.AppendLayout( Gump.StringToBuffer( "croppedtext" ) );
|
||||
disp.AppendLayout( X );
|
||||
disp.AppendLayout( Y );
|
||||
disp.AppendLayout( Width );
|
||||
disp.AppendLayout( Height );
|
||||
disp.AppendLayout( Hue );
|
||||
disp.AppendLayout( ParentGump.Intern( Text ) );
|
||||
break;
|
||||
}
|
||||
case ElementType.buttontileart:
|
||||
{
|
||||
disp.AppendLayout( Gump.StringToBuffer( "buttontileart" ) );
|
||||
disp.AppendLayout( X );
|
||||
disp.AppendLayout( Y );
|
||||
disp.AppendLayout( InactiveID );
|
||||
disp.AppendLayout( ActiveID );
|
||||
disp.AppendLayout( ButtonType );
|
||||
disp.AppendLayout( Param );
|
||||
disp.AppendLayout( ElementID );
|
||||
disp.AppendLayout( ItemID );
|
||||
disp.AppendLayout( Hue );
|
||||
disp.AppendLayout( Width );
|
||||
disp.AppendLayout( Height );
|
||||
|
||||
if ( Cliloc != -1 )
|
||||
{
|
||||
disp.AppendLayout( Gump.StringToBuffer( " }{ tooltip" ) );
|
||||
disp.AppendLayout( Cliloc );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ElementType.tilepic:
|
||||
case ElementType.tilepichue:
|
||||
{
|
||||
disp.AppendLayout( Gump.StringToBuffer( Hue == 0 ? "tilepic" : "tilepichue" ) );
|
||||
disp.AppendLayout( X );
|
||||
disp.AppendLayout( Y );
|
||||
disp.AppendLayout( ItemID );
|
||||
|
||||
if ( Hue != 0 )
|
||||
{
|
||||
disp.AppendLayout( Hue );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ElementType.itemproperty:
|
||||
{
|
||||
disp.AppendLayout( Gump.StringToBuffer( "itemproperty" ) );
|
||||
disp.AppendLayout( Serial );
|
||||
break;
|
||||
}
|
||||
case ElementType.gumppictiled:
|
||||
{
|
||||
disp.AppendLayout( Gump.StringToBuffer( "gumppictiled" ) );
|
||||
disp.AppendLayout( X );
|
||||
disp.AppendLayout( Y );
|
||||
disp.AppendLayout( Width );
|
||||
disp.AppendLayout( Height );
|
||||
disp.AppendLayout( ElementID );
|
||||
break;
|
||||
}
|
||||
case ElementType.gumppic:
|
||||
{
|
||||
disp.AppendLayout( Gump.StringToBuffer( "gumppic" ) );
|
||||
disp.AppendLayout( X );
|
||||
disp.AppendLayout( Y );
|
||||
disp.AppendLayout( ElementID );
|
||||
|
||||
if ( Hue != 0 )
|
||||
{
|
||||
disp.AppendLayout( Gump.StringToBuffer( " hue=" ) );
|
||||
disp.AppendLayoutNS( Hue );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ElementType.xmfhtmlgump:
|
||||
{
|
||||
disp.AppendLayout( Gump.StringToBuffer( "xmfhtmlgump" ) );
|
||||
disp.AppendLayout( X );
|
||||
disp.AppendLayout( Y );
|
||||
disp.AppendLayout( Width );
|
||||
disp.AppendLayout( Height );
|
||||
disp.AppendLayout( Cliloc );
|
||||
disp.AppendLayout( Background );
|
||||
disp.AppendLayout( ScrollBar );
|
||||
break;
|
||||
}
|
||||
case ElementType.xmfhtmlgumpcolor:
|
||||
{
|
||||
disp.AppendLayout( Gump.StringToBuffer( "xmfhtmlgumpcolor" ) );
|
||||
disp.AppendLayout( X );
|
||||
disp.AppendLayout( Y );
|
||||
disp.AppendLayout( Width );
|
||||
disp.AppendLayout( Height );
|
||||
disp.AppendLayout( Cliloc );
|
||||
disp.AppendLayout( Background );
|
||||
disp.AppendLayout( ScrollBar );
|
||||
disp.AppendLayout( Hue );
|
||||
break;
|
||||
}
|
||||
case ElementType.xmfhtmltok:
|
||||
{
|
||||
disp.AppendLayout( Gump.StringToBuffer( "xmfhtmltok" ) );
|
||||
disp.AppendLayout( X );
|
||||
disp.AppendLayout( Y );
|
||||
disp.AppendLayout( Width );
|
||||
disp.AppendLayout( Height );
|
||||
disp.AppendLayout( Background );
|
||||
disp.AppendLayout( ScrollBar );
|
||||
disp.AppendLayout( Hue );
|
||||
disp.AppendLayout( Cliloc );
|
||||
disp.AppendLayout( Args );
|
||||
break;
|
||||
}
|
||||
case ElementType.htmlgump:
|
||||
{
|
||||
disp.AppendLayout( Gump.StringToBuffer( "htmlgump" ) );
|
||||
disp.AppendLayout( X );
|
||||
disp.AppendLayout( Y );
|
||||
disp.AppendLayout( Width );
|
||||
disp.AppendLayout( Height );
|
||||
disp.AppendLayout( ParentGump.Intern( Text ) );
|
||||
disp.AppendLayout( Background );
|
||||
disp.AppendLayout( ScrollBar );
|
||||
break;
|
||||
}
|
||||
case ElementType.tooltip:
|
||||
{
|
||||
disp.AppendLayout( Gump.StringToBuffer( "tooltip" ) );
|
||||
disp.AppendLayout( Cliloc );
|
||||
break;
|
||||
}
|
||||
case ElementType.group:
|
||||
{
|
||||
disp.AppendLayout( Gump.StringToBuffer( "group" ) );
|
||||
disp.AppendLayout( Group );
|
||||
break;
|
||||
}
|
||||
case ElementType.resizepic:
|
||||
{
|
||||
disp.AppendLayout( Gump.StringToBuffer( "resizepic" ) );
|
||||
disp.AppendLayout( X );
|
||||
disp.AppendLayout( Y );
|
||||
disp.AppendLayout( ElementID );
|
||||
disp.AppendLayout( Width );
|
||||
disp.AppendLayout( Height );
|
||||
break;
|
||||
}
|
||||
case ElementType.checkertrans:
|
||||
{
|
||||
disp.AppendLayout( Gump.StringToBuffer( "checkertrans" ) );
|
||||
disp.AppendLayout( X );
|
||||
disp.AppendLayout( Y );
|
||||
disp.AppendLayout( Width );
|
||||
disp.AppendLayout( Height );
|
||||
break;
|
||||
}
|
||||
case ElementType.page:
|
||||
{
|
||||
disp.AppendLayout( Gump.StringToBuffer( "page" ) );
|
||||
disp.AppendLayout( PageNumber );
|
||||
break;
|
||||
}
|
||||
case ElementType.button:
|
||||
{
|
||||
disp.AppendLayout( Gump.StringToBuffer( "button" ) );
|
||||
disp.AppendLayout( X );
|
||||
disp.AppendLayout( Y );
|
||||
disp.AppendLayout( InactiveID );
|
||||
disp.AppendLayout( ActiveID );
|
||||
disp.AppendLayout( ButtonType );
|
||||
disp.AppendLayout( Param );
|
||||
disp.AppendLayout( ElementID );
|
||||
break;
|
||||
}
|
||||
case ElementType.text:
|
||||
{
|
||||
disp.AppendLayout( Gump.StringToBuffer( "text" ) );
|
||||
disp.AppendLayout( X );
|
||||
disp.AppendLayout( Y );
|
||||
disp.AppendLayout( Hue );
|
||||
disp.AppendLayout( ParentGump.Intern( Text ) );
|
||||
break;
|
||||
}
|
||||
case ElementType.invalid:
|
||||
break;
|
||||
case ElementType.checkbox:
|
||||
break;
|
||||
case ElementType.kr_xmfhtmlgump:
|
||||
break;
|
||||
case ElementType.mastergump:
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
/* Copyright (C) 2009 Matthew Geyer
|
||||
*
|
||||
* This file is part of UO Machine.
|
||||
*
|
||||
* UO Machine is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* UO Machine is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with UO Machine. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
using System.Linq;
|
||||
|
||||
namespace ClassicAssist.UO.Objects.Gumps
|
||||
{
|
||||
public sealed class GumpPage
|
||||
{
|
||||
public GumpElement[] GumpElements { get; internal set; }
|
||||
public int Page { get; internal set; }
|
||||
public Gump ParentGump { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Get array of GumpElements which match the specified ElementType.
|
||||
/// </summary>
|
||||
public GumpElement[] GetElementsByType( ElementType type )
|
||||
{
|
||||
return GumpElements.Where( ge => ge.Type == type ).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get nearest GumpElement to source, but only if it's ElementType is contained in the include list.
|
||||
/// </summary>
|
||||
/// <param name="source">Source element.</param>
|
||||
/// <param name="includeTypes">Array of ElementTypes which specifies valid GumpElements to search.</param>
|
||||
/// <param name="element">GumpElement (out).</param>
|
||||
/// <returns>True on success.</returns>
|
||||
public bool GetNearestElement( GumpElement source, ElementType[] includeTypes, out GumpElement element )
|
||||
{
|
||||
GumpElement nearest = null;
|
||||
double closest = 0;
|
||||
|
||||
foreach ( GumpElement ge in GumpElements )
|
||||
{
|
||||
if ( ge == source )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
bool found = includeTypes.Any( et => ge.Type == et );
|
||||
|
||||
if ( !found )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
double distance = UOMath.Distance( source.X, source.Y, ge.X, ge.Y );
|
||||
|
||||
if ( nearest == null )
|
||||
{
|
||||
closest = distance;
|
||||
nearest = ge;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !( distance < closest ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
closest = distance;
|
||||
nearest = ge;
|
||||
}
|
||||
}
|
||||
|
||||
element = nearest;
|
||||
return nearest != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get nearest GumpElement from source.
|
||||
/// </summary>
|
||||
/// <returns>True on success.</returns>
|
||||
public bool GetNearestElement( GumpElement source, out GumpElement element )
|
||||
{
|
||||
GumpElement nearest = null;
|
||||
double closest = 0;
|
||||
|
||||
foreach ( GumpElement ge in GumpElements )
|
||||
{
|
||||
if ( ge == source )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
double distance = UOMath.Distance( source.X, source.Y, ge.X, ge.Y );
|
||||
|
||||
if ( nearest == null )
|
||||
{
|
||||
closest = distance;
|
||||
nearest = ge;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !( distance < closest ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
closest = distance;
|
||||
nearest = ge;
|
||||
}
|
||||
}
|
||||
|
||||
element = nearest;
|
||||
return nearest != null;
|
||||
}
|
||||
|
||||
public bool GetElementByXY( int x, int y, out GumpElement gumpElement )
|
||||
{
|
||||
gumpElement = null;
|
||||
|
||||
if ( GumpElements == null )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
GumpElement element = GumpElements.FirstOrDefault( m => m.X == x && m.Y == y );
|
||||
|
||||
if ( element != null )
|
||||
{
|
||||
gumpElement = element;
|
||||
}
|
||||
|
||||
return gumpElement != null;
|
||||
}
|
||||
|
||||
public GumpElement GetElementByXY( int x, int y )
|
||||
{
|
||||
if ( GetElementByXY( x, y, out GumpElement element ) )
|
||||
{
|
||||
return element;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool GetElementByCliloc( int cliloc, out GumpElement gumpElement )
|
||||
{
|
||||
gumpElement = null;
|
||||
|
||||
if ( GumpElements == null )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
GumpElement element = GumpElements.FirstOrDefault( m => m.Cliloc == cliloc );
|
||||
|
||||
if ( element != null )
|
||||
{
|
||||
gumpElement = element;
|
||||
}
|
||||
|
||||
return gumpElement != null;
|
||||
}
|
||||
|
||||
public GumpElement GetElementByCliloc( int cliloc )
|
||||
{
|
||||
return GetElementByCliloc( cliloc, out GumpElement element ) ? element : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,917 @@
|
||||
/* Copyright (C) 2009 Matthew Geyer
|
||||
*
|
||||
* This file is part of UO Machine.
|
||||
*
|
||||
* UO Machine is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* UO Machine is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with UO Machine. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using ClassicAssist.UO.Data;
|
||||
|
||||
namespace ClassicAssist.UO.Objects.Gumps
|
||||
{
|
||||
public static class GumpParser
|
||||
{
|
||||
// Gump command reference: http://docs.polserver.com/pol098/guides.php?guidefile=gumpcmdlist#xmfhtmltok
|
||||
private static void OnError( string elementName, string layout )
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"Error parsing gump element {elementName} in layout:\r\n\r\n{layout}" );
|
||||
}
|
||||
|
||||
private static string[] GetTokens( string input )
|
||||
{
|
||||
//@0@1@ = {"0","1"}
|
||||
if ( input.Contains( "@" ) )
|
||||
{
|
||||
input = input.Trim( '@' );
|
||||
|
||||
if ( input.Contains( "@" ) )
|
||||
{
|
||||
return input.Split( '@' );
|
||||
}
|
||||
|
||||
string[] output = new string[1];
|
||||
output[0] = input;
|
||||
return output;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static bool GetInt( string input, out int output )
|
||||
{
|
||||
if ( input.Contains( "=" ) )
|
||||
{
|
||||
string[] strArray = input.Split( '=' );
|
||||
return int.TryParse( strArray[1].Trim(), out output );
|
||||
}
|
||||
|
||||
output = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Gump Parse( int serial, uint ID, int x, int y, string layout, string[] text )
|
||||
{
|
||||
bool closable = true, movable = true, disposable = true, resizable = true;
|
||||
|
||||
List<GumpPage> pageList = new List<GumpPage>();
|
||||
List<GumpElement> gumpElementList = new List<GumpElement>();
|
||||
GumpElement lastGumpElement = null;
|
||||
GumpPage currentPage = null;
|
||||
|
||||
if ( string.IsNullOrEmpty( layout ) )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
string[] split = layout.Substring( layout.IndexOf( '{' ) ).TrimEnd( '}', ' ' )
|
||||
.Split( new[] { '}' }, StringSplitOptions.RemoveEmptyEntries );
|
||||
|
||||
for ( int i = 0; i < split.Length; i++ )
|
||||
{
|
||||
split[i] = split[i].TrimStart( '{', ' ' ).Trim();
|
||||
string[] formatted = split[i].Split( new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries );
|
||||
|
||||
for ( int j = 0; j < formatted.Length; j++ )
|
||||
{
|
||||
formatted[j] = formatted[j].Trim();
|
||||
}
|
||||
|
||||
switch ( formatted[0] )
|
||||
{
|
||||
case "noclose":
|
||||
closable = false;
|
||||
break;
|
||||
case "nodispose":
|
||||
disposable = false;
|
||||
break;
|
||||
case "nomove":
|
||||
movable = false;
|
||||
break;
|
||||
case "noresize":
|
||||
resizable = false;
|
||||
break;
|
||||
case "kr_button":
|
||||
case "button":
|
||||
try
|
||||
{
|
||||
if ( int.TryParse( formatted[1], out int gbX ) &&
|
||||
int.TryParse( formatted[2], out int gbY ) &&
|
||||
int.TryParse( formatted[3], out int gbNormalID ) &&
|
||||
int.TryParse( formatted[4], out int gbPressedID ) &&
|
||||
int.TryParse( formatted[5], out int gbType ) &&
|
||||
int.TryParse( formatted[6], out int gbParam ) &&
|
||||
int.TryParse( formatted[7], out int gbID ) )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.button,
|
||||
ParentPage = currentPage,
|
||||
X = gbX,
|
||||
Y = gbY,
|
||||
InactiveID = gbNormalID,
|
||||
ActiveID = gbPressedID,
|
||||
ElementID = gbID,
|
||||
ButtonType = gbType,
|
||||
Param = gbParam
|
||||
};
|
||||
gumpElementList.Add( ge );
|
||||
}
|
||||
else
|
||||
{
|
||||
OnError( "button", layout );
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
OnError( "button", layout );
|
||||
}
|
||||
|
||||
break;
|
||||
case "buttontileart":
|
||||
try
|
||||
{
|
||||
if ( int.TryParse( formatted[1], out int btX ) &&
|
||||
int.TryParse( formatted[2], out int btY ) &&
|
||||
int.TryParse( formatted[3], out int btNormalID ) &&
|
||||
int.TryParse( formatted[4], out int btPressedID ) &&
|
||||
int.TryParse( formatted[5], out int btType ) &&
|
||||
int.TryParse( formatted[6], out int btParam ) &&
|
||||
int.TryParse( formatted[7], out int btID ) &&
|
||||
int.TryParse( formatted[8], out int btItemID ) &&
|
||||
int.TryParse( formatted[9], out int btHue ) &&
|
||||
int.TryParse( formatted[10], out int btWidth ) &&
|
||||
int.TryParse( formatted[11], out int btHeight ) )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.buttontileart,
|
||||
ParentPage = currentPage,
|
||||
X = btX,
|
||||
Y = btY,
|
||||
ElementID = btID,
|
||||
ButtonType = btType,
|
||||
Height = btHeight,
|
||||
Width = btWidth,
|
||||
Hue = btHue,
|
||||
ItemID = btItemID,
|
||||
InactiveID = btNormalID,
|
||||
Param = btParam,
|
||||
ActiveID = btPressedID
|
||||
};
|
||||
gumpElementList.Add( ge );
|
||||
lastGumpElement = ge;
|
||||
}
|
||||
else
|
||||
{
|
||||
OnError( "buttontileart", layout );
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
OnError( "buttontileart", layout );
|
||||
}
|
||||
|
||||
break;
|
||||
case "checkertrans":
|
||||
try
|
||||
{
|
||||
if ( int.TryParse( formatted[1], out int ctX ) &&
|
||||
int.TryParse( formatted[2], out int ctY ) &&
|
||||
int.TryParse( formatted[3], out int ctWidth ) &&
|
||||
int.TryParse( formatted[4], out int ctHeight ) )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.checkertrans,
|
||||
ParentPage = currentPage,
|
||||
X = ctX,
|
||||
Y = ctY,
|
||||
Width = ctWidth,
|
||||
Height = ctHeight
|
||||
};
|
||||
gumpElementList.Add( ge );
|
||||
}
|
||||
else
|
||||
{
|
||||
OnError( "checkertrans", layout );
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
OnError( "checkertrans", layout );
|
||||
}
|
||||
|
||||
break;
|
||||
case "croppedtext":
|
||||
try
|
||||
{
|
||||
if ( int.TryParse( formatted[1], out int crX ) &&
|
||||
int.TryParse( formatted[2], out int crY ) &&
|
||||
int.TryParse( formatted[3], out int crWidth ) &&
|
||||
int.TryParse( formatted[4], out int crHeight ) &&
|
||||
int.TryParse( formatted[5], out int crHue ) &&
|
||||
int.TryParse( formatted[6], out int crText ) )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.croppedtext,
|
||||
ParentPage = currentPage,
|
||||
X = crX,
|
||||
Y = crY,
|
||||
Height = crHeight,
|
||||
Width = crWidth,
|
||||
Hue = crHue,
|
||||
Text = text[crText]
|
||||
};
|
||||
gumpElementList.Add( ge );
|
||||
}
|
||||
else
|
||||
{
|
||||
OnError( "croppedtext", layout );
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
OnError( "croppedtext", layout );
|
||||
}
|
||||
|
||||
break;
|
||||
case "checkbox":
|
||||
try
|
||||
{
|
||||
if ( int.TryParse( formatted[1], out int cbX ) &&
|
||||
int.TryParse( formatted[2], out int cbY ) &&
|
||||
int.TryParse( formatted[3], out int cbInactiveID ) &&
|
||||
int.TryParse( formatted[4], out int cbActiveID ) &&
|
||||
int.TryParse( formatted[5], out int cbState ) &&
|
||||
int.TryParse( formatted[6], out int cbID ) )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.checkbox,
|
||||
ParentPage = currentPage,
|
||||
X = cbX,
|
||||
Y = cbY,
|
||||
InactiveID = cbInactiveID,
|
||||
ActiveID = cbActiveID,
|
||||
ElementID = cbID,
|
||||
InitialState = cbState == 1
|
||||
};
|
||||
gumpElementList.Add( ge );
|
||||
}
|
||||
else
|
||||
{
|
||||
OnError( "checkbox", layout );
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
OnError( "checkbox", layout );
|
||||
}
|
||||
|
||||
break;
|
||||
case "page":
|
||||
if ( currentPage == null )
|
||||
{
|
||||
currentPage = new GumpPage();
|
||||
}
|
||||
else
|
||||
{
|
||||
currentPage.GumpElements = gumpElementList.ToArray();
|
||||
pageList.Add( currentPage );
|
||||
currentPage = new GumpPage();
|
||||
gumpElementList = new List<GumpElement>();
|
||||
}
|
||||
|
||||
if ( int.TryParse( formatted[1], out int page ) )
|
||||
{
|
||||
currentPage.Page = page;
|
||||
}
|
||||
else
|
||||
{
|
||||
OnError( "page", layout );
|
||||
}
|
||||
|
||||
break;
|
||||
case "kr_gumppic":
|
||||
case "gumppic":
|
||||
try
|
||||
{
|
||||
if ( int.TryParse( formatted[1], out int gpX ) &&
|
||||
int.TryParse( formatted[2], out int gpY ) &&
|
||||
int.TryParse( formatted[3], out int gpID ) )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.gumppic, ParentPage = currentPage
|
||||
};
|
||||
|
||||
if ( formatted.Length > 4 )
|
||||
{
|
||||
for ( int gp = 4; gp < formatted.Length; gp++ )
|
||||
{
|
||||
if ( formatted[gp].Contains( "hue" ) )
|
||||
{
|
||||
if ( GetInt( formatted[gp], out int gpHue ) )
|
||||
{
|
||||
ge.Hue = gpHue;
|
||||
}
|
||||
else
|
||||
{
|
||||
OnError( "gumppic", layout );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ge.Args = formatted[gp];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ge.X = gpX;
|
||||
ge.Y = gpY;
|
||||
ge.ElementID = gpID;
|
||||
gumpElementList.Add( ge );
|
||||
}
|
||||
else
|
||||
{
|
||||
OnError( "gumppic", layout );
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
OnError( "gumppic", layout );
|
||||
}
|
||||
|
||||
break;
|
||||
case "gumppictiled":
|
||||
try
|
||||
{
|
||||
if ( int.TryParse( formatted[1], out int gtX ) &&
|
||||
int.TryParse( formatted[2], out int gtY ) &&
|
||||
int.TryParse( formatted[3], out int gtWidth ) &&
|
||||
int.TryParse( formatted[4], out int gtHeight ) &&
|
||||
int.TryParse( formatted[5], out int gtID ) )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.gumppictiled,
|
||||
ParentPage = currentPage,
|
||||
X = gtX,
|
||||
Y = gtY,
|
||||
Width = gtWidth,
|
||||
Height = gtHeight,
|
||||
ElementID = gtID
|
||||
};
|
||||
gumpElementList.Add( ge );
|
||||
}
|
||||
else
|
||||
{
|
||||
OnError( "gumppictiled", layout );
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
OnError( "gumppictiled", layout );
|
||||
}
|
||||
|
||||
break;
|
||||
case "kr_xmfhtmlgump":
|
||||
try
|
||||
{
|
||||
if ( int.TryParse( formatted[1], out int xgX ) &&
|
||||
int.TryParse( formatted[2], out int xgY ) &&
|
||||
int.TryParse( formatted[3], out int xgWidth ) &&
|
||||
int.TryParse( formatted[4], out int xgHeight ) &&
|
||||
int.TryParse( formatted[5], out int xgCliloc ) &&
|
||||
int.TryParse( formatted[6], out int xgBackground ) &&
|
||||
int.TryParse( formatted[7], out int xgScrollbar ) )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.kr_xmfhtmlgump,
|
||||
ParentPage = currentPage,
|
||||
X = xgX,
|
||||
Y = xgY,
|
||||
Width = xgWidth,
|
||||
Height = xgHeight,
|
||||
Cliloc = xgCliloc,
|
||||
Background = xgBackground == 1,
|
||||
ScrollBar = xgScrollbar == 1
|
||||
};
|
||||
|
||||
if ( xgCliloc != 0 )
|
||||
{
|
||||
ge.Text = Cliloc.GetProperty( xgCliloc );
|
||||
}
|
||||
|
||||
gumpElementList.Add( ge );
|
||||
}
|
||||
else
|
||||
{
|
||||
OnError( "kr_xmfhtmlgump", layout );
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
OnError( "kr_xmfhtmlgump", layout );
|
||||
}
|
||||
|
||||
break;
|
||||
case "mastergump":
|
||||
try
|
||||
{
|
||||
if ( int.TryParse( formatted[1], out int mgID ) )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.mastergump, ParentPage = currentPage, ElementID = mgID
|
||||
};
|
||||
gumpElementList.Add( ge );
|
||||
}
|
||||
else
|
||||
{
|
||||
OnError( "mastergump", layout );
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
OnError( "mastergump", layout );
|
||||
}
|
||||
|
||||
break;
|
||||
case "radio":
|
||||
try
|
||||
{
|
||||
if ( int.TryParse( formatted[1], out int rX ) && int.TryParse( formatted[2], out int rY ) &&
|
||||
int.TryParse( formatted[3], out int rInactiveID ) &&
|
||||
int.TryParse( formatted[4], out int rActiveID ) &&
|
||||
int.TryParse( formatted[5], out int rState ) &&
|
||||
int.TryParse( formatted[6], out int rID ) )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.radio,
|
||||
ParentPage = currentPage,
|
||||
X = rX,
|
||||
Y = rY,
|
||||
InactiveID = rInactiveID,
|
||||
ActiveID = rActiveID,
|
||||
ElementID = rID,
|
||||
InitialState = rState == 1
|
||||
};
|
||||
gumpElementList.Add( ge );
|
||||
}
|
||||
else
|
||||
{
|
||||
OnError( "radio", layout );
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
OnError( "radio", layout );
|
||||
}
|
||||
|
||||
break;
|
||||
case "resizepic":
|
||||
try
|
||||
{
|
||||
if ( int.TryParse( formatted[1], out int rpX ) &&
|
||||
int.TryParse( formatted[2], out int rpY ) &&
|
||||
int.TryParse( formatted[3], out int rpID ) &&
|
||||
int.TryParse( formatted[4], out int rpWidth ) &&
|
||||
int.TryParse( formatted[5], out int _ ) )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.resizepic,
|
||||
ParentPage = currentPage,
|
||||
X = rpX,
|
||||
Y = rpY,
|
||||
Width = rpWidth,
|
||||
Height = rpWidth,
|
||||
ElementID = rpID
|
||||
};
|
||||
gumpElementList.Add( ge );
|
||||
}
|
||||
else
|
||||
{
|
||||
OnError( "resizepic", layout );
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
OnError( "resizepic", layout );
|
||||
}
|
||||
|
||||
break;
|
||||
case "text":
|
||||
try
|
||||
{
|
||||
if ( int.TryParse( formatted[1], out int tX ) && int.TryParse( formatted[2], out int tY ) &&
|
||||
int.TryParse( formatted[3], out int tHue ) &&
|
||||
int.TryParse( formatted[4], out int tText ) )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.text,
|
||||
ParentPage = currentPage,
|
||||
X = tX,
|
||||
Y = tY,
|
||||
Hue = tHue,
|
||||
Text = text[tText]
|
||||
};
|
||||
gumpElementList.Add( ge );
|
||||
}
|
||||
else
|
||||
{
|
||||
OnError( "text", layout );
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
OnError( "text", layout );
|
||||
}
|
||||
|
||||
break;
|
||||
case "tooltip":
|
||||
try
|
||||
{
|
||||
if ( int.TryParse( formatted[1], out int tooltip ) /* && lastGumpElement != null */ )
|
||||
{
|
||||
if ( lastGumpElement != null )
|
||||
{
|
||||
lastGumpElement.Tooltip = tooltip;
|
||||
lastGumpElement.Text = Cliloc.GetProperty( tooltip );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
OnError( "tooltip", layout );
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
OnError( "tooltip", layout );
|
||||
}
|
||||
|
||||
break;
|
||||
case "htmlgump":
|
||||
try
|
||||
{
|
||||
if ( int.TryParse( formatted[1], out int hgX ) &&
|
||||
int.TryParse( formatted[2], out int hgY ) &&
|
||||
int.TryParse( formatted[3], out int hgWidth ) &&
|
||||
int.TryParse( formatted[4], out int hgHeight ) &&
|
||||
int.TryParse( formatted[5], out int hgText ) &&
|
||||
int.TryParse( formatted[6], out int hgBackground ) &&
|
||||
int.TryParse( formatted[7], out int hgScrollbar ) )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.htmlgump,
|
||||
ParentPage = currentPage,
|
||||
X = hgX,
|
||||
Y = hgY,
|
||||
Width = hgWidth,
|
||||
Height = hgHeight,
|
||||
Text = text[hgText],
|
||||
ScrollBar = hgScrollbar == 1,
|
||||
Background = hgBackground == 1
|
||||
};
|
||||
gumpElementList.Add( ge );
|
||||
}
|
||||
else
|
||||
{
|
||||
OnError( "htmlgump", layout );
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
OnError( "htmlgump", layout );
|
||||
}
|
||||
|
||||
break;
|
||||
case "textentry":
|
||||
try
|
||||
{
|
||||
if ( int.TryParse( formatted[1], out int teX ) &&
|
||||
int.TryParse( formatted[2], out int teY ) &&
|
||||
int.TryParse( formatted[3], out int teWidth ) &&
|
||||
int.TryParse( formatted[4], out int teHeight ) &&
|
||||
int.TryParse( formatted[5], out int teHue ) &&
|
||||
int.TryParse( formatted[6], out int teID ) &&
|
||||
int.TryParse( formatted[7], out int teText ) )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.textentry,
|
||||
ParentPage = currentPage,
|
||||
X = teX,
|
||||
Y = teY,
|
||||
Height = teHeight,
|
||||
Width = teWidth,
|
||||
Hue = teHue,
|
||||
ElementID = teID,
|
||||
Text = text[teText]
|
||||
};
|
||||
gumpElementList.Add( ge );
|
||||
}
|
||||
else
|
||||
{
|
||||
OnError( "textentry", layout );
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
OnError( "textentry", layout );
|
||||
}
|
||||
|
||||
break;
|
||||
case "textentrylimited":
|
||||
try
|
||||
{
|
||||
if ( int.TryParse( formatted[1], out int tlX ) &&
|
||||
int.TryParse( formatted[2], out int tlY ) &&
|
||||
int.TryParse( formatted[3], out int tlWidth ) &&
|
||||
int.TryParse( formatted[4], out int tlHeight ) &&
|
||||
int.TryParse( formatted[5], out int tlHue ) &&
|
||||
int.TryParse( formatted[6], out int tlID ) &&
|
||||
int.TryParse( formatted[7], out int tlText ) &&
|
||||
int.TryParse( formatted[8], out int tlSize ) )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.textentrylimited,
|
||||
ParentPage = currentPage,
|
||||
X = tlX,
|
||||
Y = tlY,
|
||||
Height = tlHeight,
|
||||
Width = tlWidth,
|
||||
Hue = tlHue,
|
||||
ElementID = tlID,
|
||||
Text = text[tlText],
|
||||
Size = tlSize
|
||||
};
|
||||
gumpElementList.Add( ge );
|
||||
}
|
||||
else
|
||||
{
|
||||
OnError( "textentrylimited", layout );
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
OnError( "textentrylimited", layout );
|
||||
}
|
||||
|
||||
break;
|
||||
case "tilepic":
|
||||
try
|
||||
{
|
||||
if ( int.TryParse( formatted[1], out int tpX ) &&
|
||||
int.TryParse( formatted[2], out int tpY ) && int.TryParse(
|
||||
formatted[3].Split( new[] { ',' }, StringSplitOptions.RemoveEmptyEntries )?[0] ??
|
||||
"0", out int tpID ) )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.tilepic,
|
||||
ParentPage = currentPage,
|
||||
X = tpX,
|
||||
Y = tpY,
|
||||
ElementID = tpID
|
||||
};
|
||||
gumpElementList.Add( ge );
|
||||
}
|
||||
else
|
||||
{
|
||||
OnError( "tilepic", layout );
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
OnError( "tilepic", layout );
|
||||
}
|
||||
|
||||
break;
|
||||
case "tilepichue":
|
||||
try
|
||||
{
|
||||
if ( int.TryParse( formatted[1], out int tpX ) &&
|
||||
int.TryParse( formatted[2], out int tpY ) &&
|
||||
int.TryParse( formatted[3], out int tpID ) &&
|
||||
int.TryParse( formatted[4], out int tpHue ) )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.tilepichue,
|
||||
ParentPage = currentPage,
|
||||
X = tpX,
|
||||
Y = tpY,
|
||||
ElementID = tpID,
|
||||
Hue = tpHue
|
||||
};
|
||||
gumpElementList.Add( ge );
|
||||
}
|
||||
else
|
||||
{
|
||||
OnError( "tilepichue", layout );
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
OnError( "tilepichue", layout );
|
||||
}
|
||||
|
||||
break;
|
||||
case "xmfhtmlgump":
|
||||
try
|
||||
{
|
||||
if ( int.TryParse( formatted[1], out int xgX ) &&
|
||||
int.TryParse( formatted[2], out int xgY ) &&
|
||||
int.TryParse( formatted[3], out int xgWidth ) &&
|
||||
int.TryParse( formatted[4], out int xgHeight ) &&
|
||||
int.TryParse( formatted[5], out int xgCliloc ) &&
|
||||
int.TryParse( formatted[6], out int xgBackground ) &&
|
||||
int.TryParse( formatted[7], out int xgScrollbar ) )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.xmfhtmlgump,
|
||||
ParentPage = currentPage,
|
||||
X = xgX,
|
||||
Y = xgY,
|
||||
Width = xgWidth,
|
||||
Height = xgHeight,
|
||||
Cliloc = xgCliloc,
|
||||
Background = xgBackground == 1,
|
||||
ScrollBar = xgScrollbar == 1
|
||||
};
|
||||
|
||||
if ( xgCliloc != 0 )
|
||||
{
|
||||
ge.Text = Cliloc.GetProperty( xgCliloc );
|
||||
}
|
||||
|
||||
gumpElementList.Add( ge );
|
||||
}
|
||||
else
|
||||
{
|
||||
OnError( "xmfhtmlgump", layout );
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
OnError( "xmfhtmlgump", layout );
|
||||
}
|
||||
|
||||
break;
|
||||
case "xmfhtmlgumpcolor":
|
||||
try
|
||||
{
|
||||
if ( int.TryParse( formatted[1], out int xcX ) &&
|
||||
int.TryParse( formatted[2], out int xcY ) &&
|
||||
int.TryParse( formatted[3], out int xcWidth ) &&
|
||||
int.TryParse( formatted[4], out int xcHeight ) &&
|
||||
int.TryParse( formatted[5], out int xcCliloc ) &&
|
||||
int.TryParse( formatted[6], out int xcBackground ) &&
|
||||
int.TryParse( formatted[7], out int xcScrollbar ) &&
|
||||
int.TryParse( formatted[8], out int xcHue ) )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.xmfhtmlgumpcolor,
|
||||
ParentPage = currentPage,
|
||||
X = xcX,
|
||||
Y = xcY,
|
||||
Width = xcWidth,
|
||||
Height = xcHeight,
|
||||
Cliloc = xcCliloc,
|
||||
Background = xcBackground == 1,
|
||||
ScrollBar = xcScrollbar == 1,
|
||||
Hue = xcHue
|
||||
};
|
||||
|
||||
if ( xcCliloc != 0 )
|
||||
{
|
||||
ge.Text = Cliloc.GetProperty( xcCliloc );
|
||||
}
|
||||
|
||||
gumpElementList.Add( ge );
|
||||
}
|
||||
else
|
||||
{
|
||||
OnError( "xmfhtmlgumpcolor", layout );
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
OnError( "xmfhtmlgumpcolor", layout );
|
||||
}
|
||||
|
||||
break;
|
||||
case "xmfhtmltok":
|
||||
try
|
||||
{
|
||||
if ( int.TryParse( formatted[1], out int xtX ) &&
|
||||
int.TryParse( formatted[2], out int xtY ) &&
|
||||
int.TryParse( formatted[3], out int xtWidth ) &&
|
||||
int.TryParse( formatted[4], out int xtHeight ) &&
|
||||
int.TryParse( formatted[5], out int xtBackground ) &&
|
||||
int.TryParse( formatted[6], out int xtScrollbar ) &&
|
||||
int.TryParse( formatted[7], out int xtHue ) &&
|
||||
int.TryParse( formatted[8], out int xtCliloc ) )
|
||||
{
|
||||
GumpElement ge = new GumpElement
|
||||
{
|
||||
Type = ElementType.xmfhtmltok, ParentPage = currentPage
|
||||
};
|
||||
|
||||
string[] args = null;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if ( formatted.Length > 9 )
|
||||
{
|
||||
sb.Append( formatted[9] );
|
||||
|
||||
for ( int a = 10; a < formatted.Length; a++ )
|
||||
{
|
||||
sb.Append( ' ' );
|
||||
sb.Append( formatted[a] );
|
||||
}
|
||||
|
||||
args = GetTokens( sb.ToString() );
|
||||
}
|
||||
|
||||
ge.Text = Cliloc.GetLocalString( xtCliloc, args );
|
||||
ge.Args = args != null ? string.Join( "\t", args ) : string.Empty;
|
||||
ge.X = xtX;
|
||||
ge.Y = xtY;
|
||||
ge.Width = xtWidth;
|
||||
ge.Height = xtHeight;
|
||||
ge.Hue = xtHue;
|
||||
ge.Cliloc = xtCliloc;
|
||||
ge.ScrollBar = xtScrollbar == 1;
|
||||
ge.Background = xtBackground == 1;
|
||||
gumpElementList.Add( ge );
|
||||
}
|
||||
else
|
||||
{
|
||||
OnError( "xmfhtmltok", layout );
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
OnError( "xmfhtmltok", layout );
|
||||
}
|
||||
|
||||
break;
|
||||
case "itemproperty":
|
||||
int itemserial;
|
||||
|
||||
if ( int.TryParse( formatted[1], out itemserial ) )
|
||||
{
|
||||
GumpElement ge = new GumpElement { Type = ElementType.itemproperty, Serial = itemserial };
|
||||
gumpElementList.Add( ge );
|
||||
}
|
||||
|
||||
break;
|
||||
case "echandleinput":
|
||||
//TODO
|
||||
break;
|
||||
//default:
|
||||
// throw new InvalidOperationException(
|
||||
// $"Unknown element \"{formatted[0]}\" in custom gump layout:\r\n\r\n{layout}" );
|
||||
}
|
||||
}
|
||||
|
||||
if ( currentPage != null )
|
||||
{
|
||||
currentPage.GumpElements = gumpElementList.ToArray();
|
||||
pageList.Add( currentPage );
|
||||
}
|
||||
|
||||
Gump g = new Gump( x, y, ID, serial, layout, text, gumpElementList.ToArray(), pageList.ToArray() )
|
||||
{
|
||||
Closable = closable, Disposable = disposable, Movable = movable, Resizable = resizable
|
||||
};
|
||||
|
||||
return g;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/* Copyright (C) 2009 Matthew Geyer
|
||||
*
|
||||
* This file is part of UO Machine.
|
||||
*
|
||||
* UO Machine is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* UO Machine is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with UO Machine. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
namespace ClassicAssist.UO.Objects.Gumps
|
||||
{
|
||||
public enum ElementType : byte
|
||||
{
|
||||
invalid,
|
||||
button,
|
||||
buttontileart,
|
||||
checkbox,
|
||||
checkertrans,
|
||||
croppedtext,
|
||||
gumppic,
|
||||
gumppictiled,
|
||||
htmlgump,
|
||||
kr_xmfhtmlgump,
|
||||
mastergump,
|
||||
radio,
|
||||
resizepic,
|
||||
text,
|
||||
textentry,
|
||||
textentrylimited,
|
||||
tilepic,
|
||||
tilepichue,
|
||||
xmfhtmlgump,
|
||||
xmfhtmlgumpcolor,
|
||||
xmfhtmltok,
|
||||
itemproperty,
|
||||
page,
|
||||
group,
|
||||
tooltip
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using ClassicAssist.Shared;
|
||||
using ClassicAssist.Misc;
|
||||
using ClassicAssist.UO.Data;
|
||||
|
||||
namespace ClassicAssist.UO.Objects
|
||||
{
|
||||
public class Item : Entity
|
||||
{
|
||||
private string _name;
|
||||
|
||||
public Item( int serial ) : base( serial )
|
||||
{
|
||||
}
|
||||
|
||||
public Item( int serial, int containerSerial ) : base( serial )
|
||||
{
|
||||
Owner = containerSerial;
|
||||
}
|
||||
|
||||
public int ArtDataID { get; set; }
|
||||
public ItemCollection Container { get; set; }
|
||||
public int Count { get; set; } = 1;
|
||||
|
||||
public override int Distance
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( Owner == 0 )
|
||||
{
|
||||
return Math.Max( Math.Abs( X - Engine.Player?.X ?? X ), Math.Abs( Y - Engine.Player?.Y ?? Y ) );
|
||||
}
|
||||
|
||||
Entity entity = UOMath.IsMobile( Owner )
|
||||
? (Entity) Engine.Mobiles.GetMobile( Owner )
|
||||
: Engine.Items.GetItem( Owner );
|
||||
|
||||
return entity?.Distance ?? 0;
|
||||
}
|
||||
}
|
||||
|
||||
public int Flags { get; set; }
|
||||
public int Grid { get; set; }
|
||||
public bool IsContainer => Container != null;
|
||||
public Layer Layer { get; set; }
|
||||
public int Light { get; set; }
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get => string.IsNullOrEmpty( _name ) ? TileData.GetStaticTile( ID ).Name : _name;
|
||||
set => _name = value;
|
||||
}
|
||||
|
||||
[DisplayFormat( typeof( HexFormatProvider ) )]
|
||||
public int Owner { get; set; }
|
||||
|
||||
[DisplayFormat( typeof( HexFormatProvider ) )]
|
||||
public int RootOwner
|
||||
{
|
||||
get
|
||||
{
|
||||
int owner = Owner;
|
||||
Item ownerItem;
|
||||
|
||||
while ( ( ownerItem = Engine.Items.GetItem( owner ) )?.Owner != 0 )
|
||||
{
|
||||
if ( ownerItem == null )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
owner = ownerItem.Owner;
|
||||
}
|
||||
|
||||
return owner;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsDescendantOf( int serial, int searchLevel = -1 )
|
||||
{
|
||||
int owner = Owner;
|
||||
int level = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if ( owner == serial )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
level++;
|
||||
|
||||
if ( searchLevel != -1 && level > searchLevel )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
owner = Engine.Items.GetItem( owner )?.Owner ?? 0;
|
||||
}
|
||||
while ( owner != 0 );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override void ToString( StringBuilder sb )
|
||||
{
|
||||
base.ToString( sb );
|
||||
|
||||
if ( Container != null )
|
||||
{
|
||||
sb.AppendLine( Container.ToString() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,374 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ClassicAssist.Shared;
|
||||
|
||||
namespace ClassicAssist.UO.Objects
|
||||
{
|
||||
public sealed class ItemCollection : EntityCollection<Item>, IEnumerable<Item>
|
||||
{
|
||||
public delegate void dContainerContentsChanged( bool added, IEnumerable<Item> items );
|
||||
|
||||
private const int DefaultCapacity = 125;
|
||||
public readonly int Serial;
|
||||
|
||||
public ItemCollection( int serial ) : base( DefaultCapacity )
|
||||
{
|
||||
Serial = serial;
|
||||
}
|
||||
|
||||
public IEnumerator<Item> GetEnumerator()
|
||||
{
|
||||
return EntityList.Values.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public bool FindItem( int id, out Item item )
|
||||
{
|
||||
item = SelectEntity( i => i.ID == id );
|
||||
|
||||
if ( item != null )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
item = null;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool Add( Item entity )
|
||||
{
|
||||
bool added = base.Add( entity );
|
||||
|
||||
if ( added )
|
||||
{
|
||||
OnCollectionChanged( true, true, new[] { entity } );
|
||||
}
|
||||
|
||||
return added;
|
||||
}
|
||||
|
||||
public override bool Add( Item[] entities )
|
||||
{
|
||||
bool added = base.Add( entities );
|
||||
|
||||
if ( added )
|
||||
{
|
||||
OnCollectionChanged( true, true, entities );
|
||||
}
|
||||
|
||||
return added;
|
||||
}
|
||||
|
||||
public bool FindItems( int id, out Item[] items )
|
||||
{
|
||||
items = SelectEntities( i => i.ID == id );
|
||||
|
||||
if ( items != null )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
items = null;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flatten items + subitems into a single array.
|
||||
/// </summary>
|
||||
/// <param name="items">Item array to flatten.</param>
|
||||
/// <returns>Array of flattened items.</returns>
|
||||
public static Item[] GetAllItems( Item[] items )
|
||||
{
|
||||
List<Item> output = new List<Item>();
|
||||
|
||||
for ( int i = 0; i < items.Length; i++ )
|
||||
{
|
||||
output.Add( items[i] );
|
||||
|
||||
if ( items[i].IsContainer )
|
||||
{
|
||||
output.AddRange( GetAllItems( items[i].Container.GetItems() ) );
|
||||
}
|
||||
}
|
||||
|
||||
return output.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get item with specified serial.
|
||||
/// </summary>
|
||||
/// <param name="serial">Serial of item to retrieve.</param>
|
||||
/// <param name="item">Item (out).</param>
|
||||
/// <returns>Null if no match is found.</returns>
|
||||
public bool GetItem( int serial, out Item item )
|
||||
{
|
||||
try
|
||||
{
|
||||
Item match = EntityList.Values.FirstOrDefault( i => i.Serial == serial );
|
||||
|
||||
if ( match != null )
|
||||
{
|
||||
item = match;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
IEnumerable<Item> containers = EntityList.Values.Where( i => i.IsContainer );
|
||||
|
||||
foreach ( Item container in containers )
|
||||
{
|
||||
if ( !container.Container.GetItem( serial, out Item containerMatch ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
item = containerMatch;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch ( Exception )
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
item = null;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public Item GetItem( int serial )
|
||||
{
|
||||
GetItem( serial, out Item item );
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get all items contained within this container.
|
||||
/// </summary>
|
||||
public Item[] GetItems()
|
||||
{
|
||||
Item[] itemArray = new Item[EntityList.Values.Count];
|
||||
EntityList.Values.CopyTo( itemArray, 0 );
|
||||
|
||||
return itemArray;
|
||||
}
|
||||
|
||||
public int GetItemCount()
|
||||
{
|
||||
return EntityList.Count;
|
||||
}
|
||||
|
||||
public int GetTotalItemCount()
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
foreach ( Item item in EntityList.Values )
|
||||
{
|
||||
count++;
|
||||
|
||||
if ( item.IsContainer )
|
||||
{
|
||||
count += item.Container.GetTotalItemCount();
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
public static implicit operator int( ItemCollection i )
|
||||
{
|
||||
return i.Serial;
|
||||
}
|
||||
|
||||
public override bool Remove( Item entity )
|
||||
{
|
||||
bool changed;
|
||||
|
||||
if ( entity.Container == null )
|
||||
{
|
||||
changed = base.Remove( entity );
|
||||
}
|
||||
else
|
||||
{
|
||||
Remove( entity.Container.GetItems() );
|
||||
|
||||
changed = base.Remove( entity );
|
||||
}
|
||||
|
||||
if ( changed )
|
||||
{
|
||||
OnCollectionChanged( true, false, new[] { entity } );
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
public override bool Remove( Item[] entities )
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
if ( entities == null )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ( Item entity in entities )
|
||||
{
|
||||
if ( entity == null )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( entity.Container != null )
|
||||
{
|
||||
Remove( entity.Container.GetItems() );
|
||||
}
|
||||
|
||||
if ( base.Remove( entity ) )
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( changed )
|
||||
{
|
||||
OnCollectionChanged( true, false, entities );
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
public override bool Remove( int serial )
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
Item item = GetItem( serial );
|
||||
|
||||
if ( EntityList.ContainsKey( serial ) )
|
||||
{
|
||||
changed = base.Remove( serial );
|
||||
}
|
||||
else
|
||||
{
|
||||
IEnumerable<Item> containers = EntityList.Values.Where( i => i.IsContainer );
|
||||
|
||||
foreach ( Item container in containers )
|
||||
{
|
||||
if ( container.Container?.GetItem( serial ) == null )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
container.Container.Remove( serial );
|
||||
}
|
||||
}
|
||||
|
||||
if ( changed && item != null )
|
||||
{
|
||||
OnCollectionChanged( true, false, new[] { item } );
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
internal void RemoveByOwner( int serial )
|
||||
{
|
||||
Item[] items = SelectEntities( i => i.Owner == serial );
|
||||
|
||||
if ( items == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Remove( items );
|
||||
}
|
||||
|
||||
public override Item[] SelectEntities( Func<Item, bool> func )
|
||||
{
|
||||
List<Item> itemList = new List<Item>();
|
||||
IEnumerable<Item> ents = EntityList.Select( m => m.Value ).Where( m => func( m ) || m.IsContainer );
|
||||
|
||||
foreach ( Item i in ents )
|
||||
{
|
||||
if ( func( i ) && !itemList.Contains( i ) )
|
||||
{
|
||||
itemList.Add( i );
|
||||
}
|
||||
|
||||
if ( !i.IsContainer )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Item[] result = i.Container.SelectEntities( func );
|
||||
|
||||
if ( result != null )
|
||||
{
|
||||
itemList.AddRange( result );
|
||||
}
|
||||
}
|
||||
|
||||
return itemList.Count > 0 ? itemList.ToArray() : null;
|
||||
}
|
||||
|
||||
public override Item SelectEntity( Func<Item, bool> func )
|
||||
{
|
||||
Item item = base.SelectEntity( func );
|
||||
|
||||
if ( item != null )
|
||||
{
|
||||
return item;
|
||||
}
|
||||
|
||||
IEnumerable<Item> containers = EntityList.Select( i => i.Value ).Where( i => i.Container != null );
|
||||
|
||||
foreach ( Item container in containers )
|
||||
{
|
||||
item = container.Container.SelectEntity( func );
|
||||
|
||||
if ( item != null )
|
||||
{
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void OnCollectionChanged( bool rippleDown, bool added, Item[] items )
|
||||
{
|
||||
OnCollectionChanged( added, items );
|
||||
|
||||
// Ripple down
|
||||
|
||||
if ( !rippleDown )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( Serial == 0 || !Engine.Items.GetItem( Serial, out Item item ) || item.Owner == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( Engine.Items.GetItem( item.Owner, out Item parent ) )
|
||||
{
|
||||
parent.Container?.OnCollectionChanged( false, added, items );
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"ItemCollection: Items: {EntityList.Count}, Total Items: {GetTotalItemCount()}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
#region License
|
||||
|
||||
// Copyright (C) 2020 Reetus
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#endregion
|
||||
|
||||
namespace ClassicAssist.UO.Objects
|
||||
{
|
||||
public class Menu
|
||||
{
|
||||
public MenuEntry[] Entries { get; set; }
|
||||
public int ID { get; set; }
|
||||
public int Serial { get; set; }
|
||||
public string Title { get; set; }
|
||||
}
|
||||
|
||||
public class MenuEntry
|
||||
{
|
||||
public int Hue { get; set; }
|
||||
public int ID { get; set; }
|
||||
public int Index { get; set; }
|
||||
public string Title { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
#region License
|
||||
|
||||
// Copyright (C) 2020 Reetus
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#endregion
|
||||
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
|
||||
namespace ClassicAssist.UO.Objects
|
||||
{
|
||||
public class MenuCollection
|
||||
{
|
||||
public delegate void dCollectionChanged( Menu[] menus );
|
||||
|
||||
private readonly ConcurrentDictionary<int, Menu> _dictionary;
|
||||
|
||||
public MenuCollection()
|
||||
{
|
||||
_dictionary = new ConcurrentDictionary<int, Menu>();
|
||||
}
|
||||
|
||||
public event dCollectionChanged CollectionChangedEvent;
|
||||
|
||||
public void Add( Menu menu )
|
||||
{
|
||||
bool result = _dictionary.AddOrUpdate( menu.ID, menu, ( k, v ) => menu ) != null;
|
||||
|
||||
if ( result )
|
||||
{
|
||||
OnCollectionChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public bool Remove( int id )
|
||||
{
|
||||
bool result = _dictionary.TryRemove( id, out Menu m );
|
||||
|
||||
if ( result )
|
||||
{
|
||||
OnCollectionChanged();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool GetMenu( int id, out Menu menu )
|
||||
{
|
||||
return _dictionary.TryGetValue( id, out menu );
|
||||
}
|
||||
|
||||
public bool FindMenu( int serial, out Menu menu )
|
||||
{
|
||||
menu = _dictionary.Values.FirstOrDefault( g => g.Serial == serial );
|
||||
|
||||
return menu != null;
|
||||
}
|
||||
|
||||
public bool GetMenus( out Menu[] menus )
|
||||
{
|
||||
menus = null;
|
||||
|
||||
if ( _dictionary.Values.Count == 0 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
menus = _dictionary.Values.ToArray();
|
||||
|
||||
return menus.Length > 0;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
int previousCount = _dictionary.Count;
|
||||
|
||||
_dictionary.Clear();
|
||||
|
||||
if ( previousCount > 0 )
|
||||
{
|
||||
OnCollectionChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCollectionChanged()
|
||||
{
|
||||
CollectionChangedEvent?.Invoke( _dictionary.Values.ToArray() );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using ClassicAssist.Shared;
|
||||
using ClassicAssist.Data.Vendors;
|
||||
using ClassicAssist.UO.Data;
|
||||
|
||||
namespace ClassicAssist.UO.Objects
|
||||
{
|
||||
public class Mobile : Entity
|
||||
{
|
||||
public delegate void dMobileStatusUpdated( MobileStatus oldStatus, MobileStatus newStatus );
|
||||
|
||||
private bool _isDead;
|
||||
|
||||
internal int[] _layerArray = new int[(int) Layer.LastValid + 1];
|
||||
private MobileStatus _status;
|
||||
|
||||
public Mobile( int serial ) : base( serial )
|
||||
{
|
||||
Equipment = new ItemCollection( serial );
|
||||
}
|
||||
|
||||
public Item Backpack => Engine.Items.GetItem( GetLayer( Layer.Backpack ) );
|
||||
public ItemCollection Equipment { get; set; }
|
||||
|
||||
public HealthbarColour HealthbarColour { get; set; }
|
||||
|
||||
public int Hits { get; set; }
|
||||
public int HitsMax { get; set; }
|
||||
|
||||
public bool IsDead
|
||||
{
|
||||
get => IsGhostType( ID ) || _isDead;
|
||||
set => _isDead = value;
|
||||
}
|
||||
|
||||
public bool IsFrozen => Status.HasFlag( MobileStatus.Frozen );
|
||||
public bool IsMounted => Mount != null;
|
||||
|
||||
public bool IsPoisoned
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( Engine.ClientVersion != null && Engine.ClientVersion < new Version( 7, 0, 0, 0 ) )
|
||||
{
|
||||
return Status.HasFlag( MobileStatus.Flying ) || HealthbarColour.HasFlag( HealthbarColour.Green );
|
||||
}
|
||||
|
||||
return HealthbarColour.HasFlag( HealthbarColour.Green );
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsRenamable { get; set; }
|
||||
public bool IsYellowHits => HealthbarColour.HasFlag( HealthbarColour.Yellow );
|
||||
|
||||
public int Mana { get; set; }
|
||||
public int ManaMax { get; set; }
|
||||
public Item Mount => Engine.Items.GetItem( GetLayer( Layer.Mount ) );
|
||||
public Notoriety Notoriety { get; set; }
|
||||
|
||||
public int[] Pets { get; set; }
|
||||
public ShopListEntry[] ShopBuy { get; set; }
|
||||
public int Stamina { get; set; }
|
||||
public int StaminaMax { get; set; }
|
||||
|
||||
public MobileStatus Status
|
||||
{
|
||||
get => _status;
|
||||
set
|
||||
{
|
||||
MobileStatusUpdated?.Invoke( _status, value );
|
||||
|
||||
_status = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected static bool IsGhostType( int id )
|
||||
{
|
||||
return id == 0x0192 || id == 0x0193 || id >= 0x025F && id <= 0x0260 || id == 0x2B6 || id == 0x02B7;
|
||||
}
|
||||
|
||||
public event dMobileStatusUpdated MobileStatusUpdated;
|
||||
|
||||
internal virtual void SetLayer( Layer layer, int serial )
|
||||
{
|
||||
if ( (int) layer >= _layerArray.Length )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Interlocked.Exchange( ref _layerArray[(int) layer], serial );
|
||||
}
|
||||
|
||||
public int[] GetAllLayers()
|
||||
{
|
||||
return _layerArray;
|
||||
}
|
||||
|
||||
public int GetLayer( Layer layer )
|
||||
{
|
||||
return (int) layer >= _layerArray.Length ? 0 : Thread.VolatileRead( ref _layerArray[(int) layer] );
|
||||
}
|
||||
|
||||
public Item[] GetEquippedItems()
|
||||
{
|
||||
List<Item> itemList = new List<Item>();
|
||||
|
||||
int[] layerArray = GetAllLayers();
|
||||
|
||||
IEnumerable<int> layers = layerArray.Where( layer => layer != 0 );
|
||||
|
||||
foreach ( int layer in layers )
|
||||
{
|
||||
if ( Engine.Items.GetItem( layer, out Item i ) && i.Layer != Layer.Invalid )
|
||||
{
|
||||
itemList.Add( i );
|
||||
}
|
||||
}
|
||||
|
||||
return itemList.ToArray();
|
||||
}
|
||||
|
||||
protected override void ToString( StringBuilder sb )
|
||||
{
|
||||
base.ToString( sb );
|
||||
sb.Append( $"Flags: {Status}\n" );
|
||||
sb.Append( $"Notoriety: {Notoriety}\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using ClassicAssist.Shared;
|
||||
|
||||
namespace ClassicAssist.UO.Objects
|
||||
{
|
||||
public sealed class MobileCollection : EntityCollection<Mobile>, IEnumerable<Mobile>
|
||||
{
|
||||
private readonly ItemCollection _linkedItemCollection;
|
||||
|
||||
public MobileCollection( ItemCollection linkedItemCollection )
|
||||
{
|
||||
_linkedItemCollection = linkedItemCollection;
|
||||
}
|
||||
|
||||
public IEnumerator<Mobile> GetEnumerator()
|
||||
{
|
||||
return EntityList.Values.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public Mobile GetMobile( int serial )
|
||||
{
|
||||
return serial == Engine.Player?.Serial ? Engine.Player : GetEntity( serial );
|
||||
}
|
||||
|
||||
public bool GetMobile( int serial, out Mobile mobile )
|
||||
{
|
||||
mobile = GetEntity( serial );
|
||||
return mobile != null;
|
||||
}
|
||||
|
||||
public Mobile[] GetMobiles()
|
||||
{
|
||||
return GetEntities();
|
||||
}
|
||||
|
||||
public override void RemoveByDistance( int maxDistance, int x, int y )
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
Mobile[] mobiles = SelectEntities( m =>
|
||||
{
|
||||
double d = UOMath.Distance( x, y, m.X, m.Y );
|
||||
return d > maxDistance;
|
||||
} );
|
||||
|
||||
if ( mobiles == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( Mobile m in mobiles )
|
||||
{
|
||||
Remove( m.Serial );
|
||||
_linkedItemCollection.RemoveByOwner( m.Serial );
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if ( changed )
|
||||
{
|
||||
OnCollectionChanged( false, mobiles );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
|
||||
namespace ClassicAssist.UO.Objects
|
||||
{
|
||||
public class Packet
|
||||
{
|
||||
private readonly byte[] _data;
|
||||
private readonly int _length;
|
||||
|
||||
public Packet( byte[] data, int length )
|
||||
{
|
||||
_data = new byte[length];
|
||||
_length = length;
|
||||
|
||||
Buffer.BlockCopy( data, 0, _data, 0, length );
|
||||
}
|
||||
|
||||
public byte GetPacketID()
|
||||
{
|
||||
return _data?[0] ?? 0;
|
||||
}
|
||||
|
||||
public byte[] GetPacket()
|
||||
{
|
||||
return _data;
|
||||
}
|
||||
|
||||
public int GetLength()
|
||||
{
|
||||
return _length;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
using System.Text;
|
||||
using ClassicAssist.Data.Abilities;
|
||||
using ClassicAssist.Data.Macros.Commands;
|
||||
using ClassicAssist.Misc;
|
||||
using ClassicAssist.UO.Data;
|
||||
|
||||
namespace ClassicAssist.UO.Objects
|
||||
{
|
||||
public class PlayerMobile : Mobile
|
||||
{
|
||||
public delegate void dLastTargetChanged( int serial );
|
||||
|
||||
public delegate void dLayerChanged( Layer layer, int serial );
|
||||
|
||||
private int _enemyTargetSerial;
|
||||
private int _friendTargetSerial;
|
||||
private int _lastTargetSerial;
|
||||
|
||||
public PlayerMobile( int serial ) : base( serial )
|
||||
{
|
||||
}
|
||||
|
||||
public int ColdResistance { get; set; }
|
||||
public int ColdResistanceMax { get; set; }
|
||||
public int Damage { get; set; }
|
||||
public int DamageIncrease { get; set; }
|
||||
public int DamageMax { get; set; }
|
||||
public int DefenseChanceIncrease { get; set; }
|
||||
public int DefenseChanceIncreaseMax { get; set; }
|
||||
|
||||
public int Dex { get; set; }
|
||||
|
||||
[DisplayFormat( typeof( HexFormatProvider ) )]
|
||||
public int EnemyTargetSerial
|
||||
{
|
||||
get => _enemyTargetSerial;
|
||||
set
|
||||
{
|
||||
_enemyTargetSerial = value;
|
||||
AliasCommands.SetAlias( "enemy", value );
|
||||
}
|
||||
}
|
||||
|
||||
public int EnergyResistance { get; set; }
|
||||
public int EnergyResistanceMax { get; set; }
|
||||
public int FasterCasting { get; set; }
|
||||
public int FasterCastRecovery { get; set; }
|
||||
public int FireResistance { get; set; }
|
||||
public int FireResistanceMax { get; set; }
|
||||
public int Followers { get; set; }
|
||||
public int FollowersMax { get; set; }
|
||||
|
||||
[DisplayFormat( typeof( HexFormatProvider ) )]
|
||||
public int FriendTargetSerial
|
||||
{
|
||||
get => _friendTargetSerial;
|
||||
set
|
||||
{
|
||||
_friendTargetSerial = value;
|
||||
AliasCommands.SetAlias( "friend", value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Gold { get; set; }
|
||||
public int HitChanceIncrease { get; set; }
|
||||
public int Holding { get; set; }
|
||||
public int HoldingAmount { get; set; }
|
||||
public int Int { get; set; }
|
||||
|
||||
[DisplayFormat( typeof( HexFormatProvider ) )]
|
||||
public int LastObjectSerial { get; set; }
|
||||
|
||||
[DisplayFormat( typeof( HexFormatProvider ) )]
|
||||
public int LastTargetSerial
|
||||
{
|
||||
get => _lastTargetSerial;
|
||||
set
|
||||
{
|
||||
if ( value == Serial )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_lastTargetSerial = value;
|
||||
AliasCommands.SetAlias( "last", value );
|
||||
LastTargetChangedEvent?.Invoke( value );
|
||||
}
|
||||
}
|
||||
|
||||
public TargetType LastTargetType { get; set; }
|
||||
public int LowerManaCost { get; set; }
|
||||
public int LowerReagentCost { get; set; }
|
||||
public int Luck { get; set; }
|
||||
public Map Map { get; set; }
|
||||
public int[] Party { get; set; }
|
||||
public int PhysicalResistance { get; set; }
|
||||
public int PhysicalResistanceMax { get; set; }
|
||||
public int PoisonResistance { get; set; }
|
||||
public int PoisonResistanceMax { get; set; }
|
||||
public MobileRace Race { get; set; }
|
||||
public int SpellDamageIncrease { get; set; }
|
||||
public int StatCap { get; set; }
|
||||
public int Strength { get; set; }
|
||||
public int SwingSpeedIncrease { get; set; }
|
||||
public int TithingPoints { get; set; }
|
||||
public int Weight { get; set; }
|
||||
public int WeightMax { get; set; }
|
||||
|
||||
public static event dLayerChanged LayerChangedEvent;
|
||||
|
||||
public event dLastTargetChanged LastTargetChangedEvent;
|
||||
|
||||
internal override void SetLayer( Layer layer, int serial )
|
||||
{
|
||||
base.SetLayer( layer, serial );
|
||||
|
||||
LayerChangedEvent?.Invoke( layer, serial );
|
||||
|
||||
if ( layer != Layer.Bank )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AliasCommands.SetAlias( "bank", serial );
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.AppendLine( $"Name: {Name}" );
|
||||
sb.AppendLine( $"Serial: 0x{Serial:x}" );
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
namespace ClassicAssist.UO.Objects
|
||||
{
|
||||
public sealed class Property
|
||||
{
|
||||
/// <summary>
|
||||
/// Array of arguments supplied with this property.
|
||||
/// </summary>
|
||||
public string[] Arguments { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Property number.
|
||||
/// </summary>
|
||||
public int Cliloc { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Entire property decoded to a string.
|
||||
/// </summary>
|
||||
public string Text { get; set; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user