first commit

This commit is contained in:
Beyhan Oğur
2026-09-03 04:45:36 +03:00
commit d5f52cc3d3
1038 changed files with 169579 additions and 0 deletions
@@ -0,0 +1,340 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using ClassicAssist.Shared;
using ClassicAssist.Misc;
using ClassicAssist.UO.Data;
using ClassicAssist.UO.Network;
using ClassicAssist.UO.Network.Packets;
using ClassicAssist.UO.Objects;
using Newtonsoft.Json;
using UOC = ClassicAssist.Shared.UO.Commands;
namespace ClassicAssist.Data.Abilities
{
public enum AbilityType
{
None,
Primary,
Secondary
}
public class AbilitiesManager
{
private static readonly int[] _potionTypes = { 0xf06, 0xf07, 0xf08, 0xf09, 0xf0b, 0xf0c, 0xf0d };
private static AbilitiesManager _instance;
private static readonly object _lock = new object();
private static List<WeaponData> _weaponData;
private AbilitiesManager()
{
if ( _weaponData == null )
{
LoadWeaponData( Engine.StartupPath ?? Environment.CurrentDirectory );
}
PlayerMobile.LayerChangedEvent += OnLayerChangedEvent;
}
public AbilityType Enabled { get; set; }
public bool IsPrimaryEnabled => Enabled == AbilityType.Primary;
public bool IsSecondaryEnabled => Enabled == AbilityType.Secondary;
private void OnLayerChangedEvent( Layer layer, int serial )
{
if ( layer != Layer.OneHanded && layer != Layer.TwoHanded )
{
return;
}
AbilitiesManager manager = GetInstance();
manager.ResendGump( manager.Enabled );
}
public void SetAbility( AbilityType abilityType )
{
if ( Engine.Player == null )
{
return;
}
switch ( abilityType )
{
case AbilityType.Primary when !IsPrimaryEnabled:
Enabled = AbilityType.Primary;
break;
case AbilityType.Secondary when !IsSecondaryEnabled:
Enabled = AbilityType.Secondary;
break;
default:
Enabled = AbilityType.None;
break;
}
int twoHandSerial = Engine.Player.GetLayer( Layer.TwoHanded );
Item twoHandItem = Engine.Items.GetItem( twoHandSerial );
if ( twoHandItem != null )
{
WeaponData wd =
( _weaponData ?? throw new InvalidOperationException() ).FirstOrDefault( d =>
d.Graphic == twoHandItem.ID );
if ( wd != null )
{
UOC.SetWeaponAbility( abilityType == AbilityType.Primary ? wd.Primary : wd.Secondary );
ResendGump( wd.Primary, wd.Secondary, abilityType );
return;
}
}
int oneHandSerial = Engine.Player.GetLayer( Layer.OneHanded );
Item oneHandItem = Engine.Items.GetItem( oneHandSerial );
if ( oneHandItem != null )
{
WeaponData wd =
( _weaponData ?? throw new InvalidOperationException() ).FirstOrDefault( d =>
d.Graphic == oneHandItem.ID );
if ( wd != null )
{
UOC.SetWeaponAbility( abilityType == AbilityType.Primary ? wd.Primary : wd.Secondary );
ResendGump( wd.Primary, wd.Secondary, abilityType );
return;
}
}
// Fists etc
ResendGump( 5, 11, abilityType );
UOC.SetWeaponAbility( abilityType == AbilityType.Primary ? 5 : 11 );
}
public void ResendGump( AbilityType abilityType )
{
if ( Engine.Player == null )
{
return;
}
int twoHandSerial = Engine.Player.GetLayer( Layer.TwoHanded );
Item twoHandItem = Engine.Items.GetItem( twoHandSerial );
if ( twoHandItem != null )
{
WeaponData wd =
( _weaponData ?? throw new InvalidOperationException() ).FirstOrDefault( d =>
d.Graphic == twoHandItem.ID );
if ( wd != null )
{
ResendGump( wd.Primary, wd.Secondary, abilityType );
return;
}
}
int oneHandSerial = Engine.Player.GetLayer( Layer.OneHanded );
Item oneHandItem = Engine.Items.GetItem( oneHandSerial );
if ( oneHandItem != null )
{
WeaponData wd =
( _weaponData ?? throw new InvalidOperationException() ).FirstOrDefault( d =>
d.Graphic == oneHandItem.ID );
if ( wd != null )
{
ResendGump( wd.Primary, wd.Secondary, abilityType );
return;
}
}
ResendGump( 5, 11, abilityType );
}
private static void ResendGump( int primaryId, int secondaryId, AbilityType abilityType )
{
if ( !Options.CurrentOptions.AbilitiesGump )
{
return;
}
//TODO
//WeaponAbilitiesGump gump = new WeaponAbilitiesGump( primaryId, abilityType == AbilityType.Primary,
// secondaryId, abilityType == AbilityType.Secondary );
//gump.SendGump();
}
public static AbilitiesManager GetInstance()
{
// ReSharper disable once InvertIf
if ( _instance == null )
{
lock ( _lock )
{
if ( _instance != null )
{
return _instance;
}
_instance = new AbilitiesManager();
return _instance;
}
}
return _instance;
}
internal WeaponData GetWeaponData( int id )
{
return _weaponData?.FirstOrDefault( w => w.Graphic == id );
}
private static void LoadWeaponData( string basePath )
{
string dataPath = Path.Combine( basePath, "Data" );
_weaponData = JsonConvert
.DeserializeObject<WeaponData[]>( File.ReadAllText( Path.Combine( dataPath, "Weapons.json" ) ) )
.ToList();
}
public void CheckAbility( int abilityIndex )
{
int twoHandSerial = Engine.Player.GetLayer( Layer.TwoHanded );
Item twoHandItem = Engine.Items.GetItem( twoHandSerial );
AbilityType abilityType = AbilityType.None;
if ( twoHandItem != null )
{
WeaponData wd =
( _weaponData ?? throw new InvalidOperationException() ).FirstOrDefault( d =>
d.Graphic == twoHandItem.ID );
if ( wd != null )
{
if ( wd.Primary == abilityIndex )
{
abilityType = AbilityType.Primary;
}
else if ( wd.Secondary == abilityIndex )
{
abilityType = AbilityType.Secondary;
}
ResendGump( wd.Primary, wd.Secondary, abilityType );
return;
}
}
int oneHandSerial = Engine.Player.GetLayer( Layer.OneHanded );
Item oneHandItem = Engine.Items.GetItem( oneHandSerial );
if ( oneHandItem != null )
{
WeaponData wd =
( _weaponData ?? throw new InvalidOperationException() ).FirstOrDefault( d =>
d.Graphic == oneHandItem.ID );
if ( wd != null )
{
if ( wd.Primary == abilityIndex )
{
abilityType = AbilityType.Primary;
}
else if ( wd.Secondary == abilityIndex )
{
abilityType = AbilityType.Secondary;
}
ResendGump( wd.Primary, wd.Secondary, abilityType );
return;
}
}
if ( abilityIndex == 5 )
{
abilityType = AbilityType.Primary;
}
else if ( abilityIndex == 11 )
{
abilityType = AbilityType.Secondary;
}
ResendGump( 5, 11, abilityType );
}
public bool CheckHands( int serial )
{
if ( !Options.CurrentOptions.CheckHandsPotions )
{
return false;
}
Item item = Engine.Items?.GetItem( serial );
if ( item == null || !_potionTypes.Contains( item.ID ) )
{
return false;
}
// Explosion / Conflagaration pot doesn't need hand free
if ( item.ID == 0xf0d && item.Hue == 0 || item.ID == 0xf06 && item.Hue == 1161 )
{
return false;
}
Item leftHand = Engine.Player?.Equipment.FirstOrDefault( i => i.Layer == Layer.TwoHanded );
Item rightHand = Engine.Player?.Equipment.FirstOrDefault( i => i.Layer == Layer.OneHanded );
if ( leftHand == null && rightHand != null )
{
//OSI crossbow in OneHanded layer??
leftHand = rightHand;
rightHand = null;
}
WeaponData leftHandWD = null;
if ( leftHand != null )
{
leftHandWD = GetWeaponData( leftHand.ID );
}
if ( ( !( leftHandWD?.Twohanded ?? false ) && leftHand?.Properties != null &&
!( leftHand.Properties?.Any( p => p.Cliloc == 1061171 /* Two-Handed Weapon */ ) ?? false ) ||
leftHand?.Properties != null &&
!( leftHand.Properties?.All( p => p.Cliloc != 1072792 /* Balanced */ ) ?? false ) ) &&
( rightHand == null || leftHand == null ) )
{
return false;
}
if ( leftHand == null )
{
return false;
}
ActionPacketQueue.EnqueueDragDrop( leftHand.Serial, 1, Engine.Player.GetLayer( Layer.Backpack ),
QueuePriority.High );
ActionPacketQueue.EnqueueActionPacket( new UseObject( serial ), QueuePriority.High );
ActionPacketQueue.EnqueueActionPackets(
new BasePacket[]
{
new DragItem( leftHand.Serial, 1 ),
new EquipRequest( leftHand.Serial, leftHand.Layer, (int) Engine.Player?.Serial )
}, QueuePriority.High );
return true;
}
}
}
@@ -0,0 +1,11 @@
namespace ClassicAssist.Data.Abilities
{
internal class WeaponData
{
public int Graphic { get; set; }
public string Name { get; set; }
public int Primary { get; set; }
public int Secondary { get; set; }
public bool Twohanded { get; set; }
}
}
@@ -0,0 +1,327 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using ClassicAssist.Shared;
using ClassicAssist.UI.Misc;
using ClassicAssist.UO.Objects;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace ClassicAssist.Data
{
public static class AssistantOptions
{
public delegate void dProfileChanged( string profile );
private const string DEFAULT_BACKUP_PATH = "Backup";
private static readonly Dictionary<int, string> _linkedProfiles = new Dictionary<int, string>();
public static string[] Assemblies { get; set; }
public static bool AutoBackupProfiles { get; set; }
public static int AutoBackupProfilesDays { get; set; }
public static string AutoBackupProfilesDirectory { get; set; }
public static DateTime AutoBackupProfilesLast { get; set; }
public static Language LanguageOverride { get; set; }
public static string LastProfile { get; set; }
public static Dictionary<string, string> SavedPasswords { get; set; } = new Dictionary<string, string>();
public static bool SavePasswords { get; set; }
public static bool SavePasswordsOnlyBlank { get; set; }
public static string SessionId { get; set; }
public static Version UpdateGumpVersion { get; set; }
public static string UserId { get; set; }
public static double WindowHeight { get; set; } = 500;
public static double WindowWidth { get; set; } = 625;
public static event EventHandler SavedPasswordsChanged;
public static event EventHandler OptionsLoaded;
public static void Save()
{
JObject json = new JObject
{
{ "LanguageOverride", LanguageOverride.ToString() },
{ "LastProfile", LastProfile },
{ "UpdateGumpVersion", UpdateGumpVersion?.ToString() ?? "0.0.0.0" },
{ "AutoBackupProfiles", AutoBackupProfiles },
{ "AutoBackupProfilesDays", AutoBackupProfilesDays },
{ "AutoBackupProfilesDirectory", AutoBackupProfilesDirectory },
{ "AutoBackupProfilesLast", AutoBackupProfilesLast },
{ "SavePasswords", SavePasswords },
{ "SavePasswordsOnlyBlank", SavePasswordsOnlyBlank },
{ "UserId", UserId },
#if !DEVELOP
{ "WindowWidth", WindowWidth },
{ "WindowHeight", WindowHeight },
#endif
};
JArray linkedProfilesArray = new JArray();
foreach ( JObject linkedObj in _linkedProfiles.Select( profile =>
new JObject { { "Serial", profile.Key }, { "Profile", profile.Value } } ) )
{
linkedProfilesArray.Add( linkedObj );
}
json.Add( "Profiles", linkedProfilesArray );
JArray savedPasswordsArray = new JArray();
foreach ( KeyValuePair<string, string> kvp in SavedPasswords )
{
savedPasswordsArray.Add( new JObject
{
{ "Username", kvp.Key }, { "Password", Crypter.Encrypt( kvp.Value ) }
} );
}
json.Add( "SavedPasswords", savedPasswordsArray );
JArray assembliesArray = new JArray();
foreach ( string assembly in Assemblies ?? new string[0] )
{
assembliesArray.Add( assembly );
}
json.Add( "Assemblies", assembliesArray );
File.WriteAllText( Path.Combine( Engine.StartupPath ?? Environment.CurrentDirectory, "Assistant.json" ),
json.ToString( Formatting.Indented ) );
}
public static void Load()
{
Engine.PlayerInitializedEvent += PlayerInitialized;
string configPath = Path.Combine( Engine.StartupPath ?? Environment.CurrentDirectory, "Assistant.json" );
if ( !File.Exists( configPath ) )
{
LastProfile = Options.DEFAULT_SETTINGS_FILENAME;
UserId = Guid.NewGuid().ToString();
SessionId = Guid.NewGuid().ToString();
return;
}
JObject json = JObject.Parse( File.ReadAllText( configPath ) );
LanguageOverride = json?["LanguageOverride"]?.ToObject<Language>() ?? Language.Default;
LastProfile = json?["LastProfile"]?.ToObject<string>() ?? Options.DEFAULT_SETTINGS_FILENAME;
UpdateGumpVersion = json?["UpdateGumpVersion"]?.ToObject<Version>() ?? new Version();
AutoBackupProfiles = json?["AutoBackupProfiles"]?.ToObject<bool>() ?? true;
AutoBackupProfilesDays = json?["AutoBackupProfilesDays"]?.ToObject<int>() ?? 7;
AutoBackupProfilesDirectory =
json?["AutoBackupProfilesDirectory"]?.ToObject<string>() ?? DEFAULT_BACKUP_PATH;
AutoBackupProfilesLast = json?["AutoBackupProfilesLast"]?.ToObject<DateTime>() ?? default;
SavePasswords = json?["SavePasswords"]?.ToObject<bool>() ?? false;
SavePasswordsOnlyBlank = json?["SavePasswordsOnlyBlank"]?.ToObject<bool>() ?? false;
UserId = json?["UserId"]?.ToObject<string>() ?? Guid.NewGuid().ToString();
WindowWidth = json?["WindowWidth"]?.ToObject<int>() ?? 625;
WindowHeight = json?["WindowHeight"]?.ToObject<int>() ?? 500;
Assemblies = json?["Assemblies"]?.ToObject<string[]>() ?? new string[0];
SessionId = Guid.NewGuid().ToString();
if ( json?["Profiles"] != null )
{
foreach ( JToken token in json["Profiles"] )
{
_linkedProfiles.Add( token["Serial"].ToObject<int>(), token["Profile"].ToObject<string>() );
}
}
if ( json?["SavedPasswords"] != null )
{
foreach ( JToken token in json["SavedPasswords"] )
{
SavedPasswords.Add( token["Username"].ToObject<string>(),
Crypter.Decrypt( token["Password"].ToObject<string>() ) );
}
OnPasswordsChanged();
}
SetLanguage( LanguageOverride );
if ( DateTime.Now - AutoBackupProfilesLast >= TimeSpan.FromDays( AutoBackupProfilesDays ) )
{
BackupProfiles();
}
foreach ( string assembly in Assemblies )
{
try
{
Assembly asm = Assembly.LoadFile( assembly );
IEnumerable<MethodInfo> initializeMethods = asm.GetTypes()
.Where( e => e.IsClass && e.IsPublic && e.GetMethod( "Initialize",
BindingFlags.Public | BindingFlags.Static, null, Type.EmptyTypes, null ) !=
null ).Select( e => e.GetMethod( "Initialize",
BindingFlags.Public | BindingFlags.Static, null, Type.EmptyTypes, null ) );
foreach ( MethodInfo initializeMethod in initializeMethods )
{
initializeMethod?.Invoke( null, null );
}
}
catch ( Exception )
{
// ignored
}
}
OptionsLoaded?.Invoke( null, EventArgs.Empty );
}
public static void OnPasswordsChanged()
{
SavedPasswordsChanged?.Invoke( null, new PropertyChangedEventArgs( nameof( SavedPasswords ) ) );
}
private static void BackupProfiles()
{
string profileDirectory = Path.Combine( Engine.StartupPath ?? Environment.CurrentDirectory, "Profiles" );
if ( !Directory.Exists( profileDirectory ) )
{
return;
}
IEnumerable<string> files = Directory.EnumerateFiles( profileDirectory ).ToList();
if ( !files.Any() )
{
return;
}
string outputPath = AutoBackupProfilesDirectory;
if ( string.IsNullOrEmpty( outputPath ) )
{
outputPath = DEFAULT_BACKUP_PATH;
}
bool rooted = Path.IsPathRooted( AutoBackupProfilesDirectory );
if ( !rooted )
{
outputPath = Path.Combine( Engine.StartupPath ?? Environment.CurrentDirectory,
AutoBackupProfilesDirectory );
}
if ( !Directory.Exists( outputPath ) )
{
Directory.CreateDirectory( outputPath );
}
try
{
foreach ( string file in files )
{
string outputFile = Path.Combine( outputPath,
Path.GetFileName( file ) ?? throw new InvalidOperationException() );
File.Copy( file, outputFile, true );
}
}
catch ( Exception )
{
// We tried
}
AutoBackupProfilesLast = DateTime.Now;
}
public static event dProfileChanged ProfileChangedEvent;
private static void PlayerInitialized( PlayerMobile player )
{
if ( !_linkedProfiles.ContainsKey( player.Serial ) )
{
return;
}
string profile = _linkedProfiles[player.Serial];
Engine.Dispatcher.Invoke( () =>
{
Options.Save( Options.CurrentOptions );
Options.CurrentOptions = new Options { Name = profile };
Options.Load( profile, Options.CurrentOptions );
ProfileChangedEvent?.Invoke( profile );
} );
}
public static void SetLanguage( Language language )
{
CultureInfo locale = CultureInfo.CurrentCulture;
switch ( language )
{
case Language.English:
locale = new CultureInfo( "en-US" );
break;
case Language.Korean:
locale = new CultureInfo( "ko-KR" );
break;
case Language.Chinese:
locale = new CultureInfo( "zh" );
break;
case Language.Italian:
locale = new CultureInfo( "it-IT" );
break;
case Language.Polish:
locale = new CultureInfo( "pl-PL" );
break;
case Language.Default:
break;
default:
throw new ArgumentOutOfRangeException();
}
CultureInfo.DefaultThreadCurrentUICulture = locale;
CultureInfo.DefaultThreadCurrentUICulture = locale;
CultureInfo.CurrentCulture = locale;
CultureInfo.CurrentUICulture = locale;
}
public static void SetLinkedProfile( int serial, string profile )
{
if ( _linkedProfiles.ContainsKey( serial ) )
{
_linkedProfiles.Remove( serial );
}
_linkedProfiles.Add( serial, profile );
}
public static string GetLinkedProfile( int serial )
{
return _linkedProfiles.ContainsKey( serial ) ? _linkedProfiles[serial] : null;
}
public static void RemoveLinkedProfile( int serial )
{
if ( _linkedProfiles.ContainsKey( serial ) )
{
_linkedProfiles.Remove( serial );
}
}
public static void OnWindowLoaded()
{
if ( LastProfile == null )
{
LastProfile = Options.DEFAULT_SETTINGS_FILENAME;
}
Options.Load( LastProfile, Options.CurrentOptions );
ProfileChangedEvent?.Invoke( LastProfile );
}
}
}
@@ -0,0 +1,47 @@
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;
using ClassicAssist.Annotations;
namespace ClassicAssist.Data.Autoloot
{
public class AutolootConstraintEntry : INotifyPropertyChanged
{
private AutolootOperator _operator = AutolootOperator.Equal;
private PropertyEntry _property;
private int _value;
public AutolootOperator Operator
{
get => _operator;
set => SetProperty( ref _operator, value );
}
public PropertyEntry Property
{
get => _property;
set => SetProperty( ref _property, value );
}
public int Value
{
get => _value;
set => SetProperty( ref _value, value );
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged( [CallerMemberName] string propertyName = null )
{
PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( propertyName ) );
}
// ReSharper disable once RedundantAssignment
public virtual void SetProperty<T>( ref T obj, T value, [CallerMemberName] string propertyName = "" )
{
obj = value;
OnPropertyChanged( propertyName );
}
}
}
@@ -0,0 +1,84 @@
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;
using ClassicAssist.Annotations;
namespace ClassicAssist.Data.Autoloot
{
public class AutolootEntry : INotifyPropertyChanged
{
private bool _autoloot = true;
private ObservableCollection<AutolootConstraintEntry> _constraints =
new ObservableCollection<AutolootConstraintEntry>();
private bool _enabled = true;
private int _id;
private string _name;
private bool _rehue;
private int _rehueHue = 1153;
public bool Autoloot
{
get => _autoloot;
set => SetProperty( ref _autoloot, value );
}
public ObservableCollection<AutolootConstraintEntry> Constraints
{
get => _constraints;
set => SetProperty( ref _constraints, value );
}
public bool Enabled
{
get => _enabled;
set => SetProperty( ref _enabled, value );
}
public int ID
{
get => _id;
set => SetProperty( ref _id, value );
}
public string Name
{
get => _name;
set => SetProperty( ref _name, value );
}
public bool Rehue
{
get => _rehue;
set => SetProperty( ref _rehue, value );
}
public int RehueHue
{
get => _rehueHue;
set => SetProperty( ref _rehueHue, value );
}
public event PropertyChangedEventHandler PropertyChanged;
public override string ToString()
{
return $"{Name} - 0x{ID:x}";
}
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged( [CallerMemberName] string propertyName = null )
{
PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( propertyName ) );
}
// ReSharper disable once RedundantAssignment
public virtual void SetProperty<T>( ref T obj, T value, [CallerMemberName] string propertyName = "" )
{
obj = value;
OnPropertyChanged( propertyName );
}
}
}
@@ -0,0 +1,120 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using ClassicAssist.UO.Objects;
namespace ClassicAssist.Data.Autoloot
{
public static class AutolootHelpers
{
public static Action<int> SetAutolootContainer { get; set; }
public static IEnumerable<Item> AutolootFilter( IEnumerable<Item> items, AutolootEntry entry )
{
return items == null
? null
: ( from item in items
where entry.ID == -1 || item.ID == entry.ID
let predicates = ConstraintsToPredicates( entry.Constraints )
where !predicates.Any() || CheckPredicates( item, predicates )
select item ).ToList();
}
private static bool CheckPredicates( Item item, IEnumerable<Predicate<Item>> predicates )
{
return predicates.All( predicate => predicate( item ) );
}
public static IEnumerable<Predicate<Item>> ConstraintsToPredicates(
IEnumerable<AutolootConstraintEntry> constraints )
{
List<Predicate<Item>> predicates = new List<Predicate<Item>>();
foreach ( AutolootConstraintEntry constraint in constraints )
{
switch ( constraint.Property.ConstraintType )
{
case PropertyType.Properties:
if ( constraint.Operator != AutolootOperator.NotPresent )
{
predicates.Add( i => i.Properties != null && constraint.Property.Clilocs.Any( cliloc =>
i.Properties.Any( p => MatchProperty( p, cliloc,
constraint.Property, constraint.Operator,
constraint.Value ) ) ) );
}
else
{
predicates.Add( i =>
i.Properties != null && !constraint.Property.Clilocs.Any( cliloc =>
i.Properties.Any( p => p.Cliloc == cliloc ) ) );
}
break;
case PropertyType.Object:
predicates.Add( i =>
ItemHasObjectProperty( i, constraint.Property.Name ) && Operation( constraint.Operator,
GetItemObjectPropertyValue<int>( i, constraint.Property.Name ), constraint.Value ) );
break;
default:
throw new ArgumentOutOfRangeException();
}
}
return predicates;
}
public static bool ItemHasObjectProperty( Item item, string propertyName )
{
PropertyInfo propertyInfo = item.GetType().GetProperty( propertyName );
if ( propertyInfo == null )
{
return false;
}
return true;
}
public static T GetItemObjectPropertyValue<T>( Item item, string propertyName )
{
PropertyInfo propertyInfo = item.GetType().GetProperty( propertyName );
if ( propertyInfo == null )
{
return default;
}
T val = (T) propertyInfo.GetValue( item );
return val;
}
public static bool Operation( AutolootOperator @operator, int x, int y )
{
switch ( @operator )
{
case AutolootOperator.GreaterThan:
return x >= y;
case AutolootOperator.LessThan:
return x <= y;
case AutolootOperator.Equal:
return x == y;
case AutolootOperator.NotEqual:
return x != y;
default:
throw new ArgumentOutOfRangeException( nameof( @operator ), @operator, null );
}
}
public static bool MatchProperty( Property property, int cliloc, PropertyEntry constraint,
AutolootOperator @operator, int value )
{
return property.Cliloc == cliloc && ( constraint.ClilocIndex == -1 || Operation( @operator,
int.Parse( property.Arguments[constraint.ClilocIndex] ),
value ) );
}
}
}
@@ -0,0 +1,52 @@
#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;
using System.Collections.Generic;
namespace ClassicAssist.Data.Autoloot
{
public class AutolootManager
{
private static AutolootManager _instance;
private static readonly object _lock = new object();
public Func<List<AutolootEntry>> GetEntries { get; set; } = () => new List<AutolootEntry>();
public static AutolootManager GetInstance()
{
// ReSharper disable once InvertIf
if ( _instance == null )
{
lock ( _lock )
{
if ( _instance != null )
{
return _instance;
}
_instance = new AutolootManager();
return _instance;
}
}
return _instance;
}
}
}
@@ -0,0 +1,24 @@
using System.ComponentModel;
using ClassicAssist.UI.Misc;
namespace ClassicAssist.Data.Autoloot
{
[TypeConverter( typeof( EnumDescriptionTypeConverter ) )]
public enum AutolootOperator
{
[Description( "==" )]
Equal,
[Description( "!=" )]
NotEqual,
[Description( ">=" )]
GreaterThan,
[Description( "<=" )]
LessThan,
[Description( "X" )]
NotPresent
}
}
@@ -0,0 +1,77 @@
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;
using ClassicAssist.Annotations;
namespace ClassicAssist.Data.Autoloot
{
public class PropertyEntry : INotifyPropertyChanged, IComparable<PropertyEntry>
{
private int _clilocIndex;
private int[] _clilocs;
private PropertyType _constraintType;
private string _name;
public int ClilocIndex
{
get => _clilocIndex;
set => SetProperty( ref _clilocIndex, value );
}
public int[] Clilocs
{
get => _clilocs;
set => SetProperty( ref _clilocs, value );
}
public PropertyType ConstraintType
{
get => _constraintType;
set => SetProperty( ref _constraintType, value );
}
public string Name
{
get => _name;
set => SetProperty( ref _name, value );
}
public int CompareTo( PropertyEntry other )
{
if ( ReferenceEquals( this, other ) )
{
return 0;
}
if ( ReferenceEquals( null, other ) )
{
return 1;
}
int nameComparison = string.Compare( _name, other._name, StringComparison.InvariantCultureIgnoreCase );
return nameComparison;
}
public event PropertyChangedEventHandler PropertyChanged;
public override string ToString()
{
return Name;
}
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged( [CallerMemberName] string propertyName = null )
{
PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( propertyName ) );
}
// ReSharper disable once RedundantAssignment
public virtual void SetProperty<T>( ref T obj, T value, [CallerMemberName] string propertyName = "" )
{
obj = value;
OnPropertyChanged( propertyName );
}
}
}
@@ -0,0 +1,8 @@
namespace ClassicAssist.Data.Autoloot
{
public enum PropertyType
{
Properties,
Object
}
}
+97
View File
@@ -0,0 +1,97 @@
[
{
"BodyType": 1,
"Graphic": 400,
"Name": "Human Male"
},
{
"BodyType": 1,
"Graphic": 401,
"Name": "Human Female"
},
{
"BodyType": 1,
"Graphic": 605,
"Name": "Elf Male"
},
{
"BodyType": 1,
"Graphic": 606,
"Name": "Elf Female"
},
{
"BodyType": 1,
"Graphic": 666,
"Name": "Gargoyle Male"
},
{
"BodyType": 1,
"Graphic": 667,
"Name": "Gargoyle Female"
},
{
"BodyType": 2,
"Graphic": 746,
"Name": "Horrific Beast"
},
{
"BodyType": 2,
"Graphic": 748,
"Name": "Wraith Male"
},
{
"BodyType": 2,
"Graphic": 747,
"Name": "Wraith Female"
},
{
"BodyType": 2,
"Graphic": 749,
"Name": "Lich"
},
{
"BodyType": 2,
"Graphic": 744,
"Name": "Vampire Male"
},
{
"BodyType": 2,
"Graphic": 745,
"Name": "Vampire Female"
},
{
"BodyType": 2,
"Graphic": 220,
"Name": "Llama"
},
{
"BodyType": 2,
"Graphic": 25,
"Name": "Wolf"
},
{
"BodyType": 2,
"Graphic": 770,
"Name": "Ethereal Voyage"
},
{
"BodyType": 2,
"Graphic": 285,
"Name": "Reaper Form"
},
{
"BodyType": 2,
"Graphic": 705,
"Name": "Stone Form"
},
{
"BodyType": 2,
"Graphic": 183,
"Name": "Tribal Male"
},
{
"BodyType": 2,
"Graphic": 184,
"Name": "Tribal Female"
}
]
+698
View File
@@ -0,0 +1,698 @@
[
{
"ID": 1001,
"Name": "Dismount Prevention"
},
{
"ID": 1002,
"Name": "No Rearm"
},
{
"ID": 1005,
"Name": "Night Sight"
},
{
"ID": 1006,
"Name": "Death Strike"
},
{
"ID": 1007,
"Name": "Evil Omen"
},
{
"ID": 1008,
"Name": "Honored Debuff"
},
{
"ID": 1009,
"Name": "Achieve Perfection"
},
{
"ID": 1010,
"Name": "Divine Fury"
},
{
"ID": 1011,
"Name": "Enemy Of One"
},
{
"ID": 1012,
"Name": "Hiding"
},
{
"ID": 1013,
"Name": "Active Meditation"
},
{
"ID": 1014,
"Name": "BloodOathCaster"
},
{
"ID": 1015,
"Name": "Blood Oath"
},
{
"ID": 1016,
"Name": "Corpse Skin"
},
{
"ID": 1017,
"Name": "Mindrot"
},
{
"ID": 1018,
"Name": "Pain Spike"
},
{
"ID": 1019,
"Name": "Strangle"
},
{
"ID": 1020,
"Name": "Gift Of Renewal"
},
{
"ID": 1021,
"Name": "Attune Weapon"
},
{
"ID": 1022,
"Name": "Thunderstorm"
},
{
"ID": 1023,
"Name": "Essence Of Wind"
},
{
"ID": 1024,
"Name": "Ethereal Voyage"
},
{
"ID": 1025,
"Name": "Gift Of Life"
},
{
"ID": 1026,
"Name": "Arcane Empowerment"
},
{
"ID": 1027,
"Name": "Mortal Strike"
},
{
"ID": 1028,
"Name": "Reactive Armor"
},
{
"ID": 1029,
"Name": "Protection"
},
{
"ID": 1030,
"Name": "Arch Protection"
},
{
"ID": 1031,
"Name": "Magic Reflection"
},
{
"ID": 1032,
"Name": "Incognito"
},
{
"ID": 1033,
"Name": "Disguised"
},
{
"ID": 1034,
"Name": "Animal Form"
},
{
"ID": 1035,
"Name": "Polymorph"
},
{
"ID": 1036,
"Name": "Invisibility"
},
{
"ID": 1037,
"Name": "Paralyze"
},
{
"ID": 1038,
"Name": "Poison"
},
{
"ID": 1039,
"Name": "Bleed"
},
{
"ID": 1040,
"Name": "Clumsy"
},
{
"ID": 1041,
"Name": "FeebleMind"
},
{
"ID": 1042,
"Name": "Weaken"
},
{
"ID": 1043,
"Name": "Curse"
},
{
"ID": 1044,
"Name": "Mass Curse"
},
{
"ID": 1045,
"Name": "Agility"
},
{
"ID": 1046,
"Name": "Cunning"
},
{
"ID": 1047,
"Name": "Strength"
},
{
"ID": 1048,
"Name": "Bless"
},
{
"ID": 1049,
"Name": "Sleep"
},
{
"ID": 1050,
"Name": "Stone Form"
},
{
"ID": 1051,
"Name": "Spell Plague"
},
{
"ID": 1052,
"Name": "Berserk"
},
{
"ID": 1053,
"Name": "Mass Sleep"
},
{
"ID": 1054,
"Name": "Fly"
},
{
"ID": 1055,
"Name": "Inspire"
},
{
"ID": 1056,
"Name": "Invigorate"
},
{
"ID": 1057,
"Name": "Resilience"
},
{
"ID": 1058,
"Name": "Perseverance"
},
{
"ID": 1059,
"Name": "Tribulation Target"
},
{
"ID": 1060,
"Name": "Despair Target"
},
{
"ID": 1062,
"Name": "Fish Pie"
},
{
"ID": 1063,
"Name": "Hit Lower Attack"
},
{
"ID": 1064,
"Name": "Hit Lower Defense"
},
{
"ID": 1065,
"Name": "Dual Wield"
},
{
"ID": 1066,
"Name": "Block"
},
{
"ID": 1067,
"Name": "Defense Mastery"
},
{
"ID": 1068,
"Name": "Despair Caster"
},
{
"ID": 1069,
"Name": "Healing"
},
{
"ID": 1070,
"Name": "Spell Focusing Buff"
},
{
"ID": 1071,
"Name": "Spell Focusing Debuff"
},
{
"ID": 1072,
"Name": "Rage Focusing Debuff"
},
{
"ID": 1073,
"Name": "Rage Focusing Buff"
},
{
"ID": 1074,
"Name": "Warding"
},
{
"ID": 1075,
"Name": "Tribulation Caster"
},
{
"ID": 1076,
"Name": "Force Arrow"
},
{
"ID": 1077,
"Name": "Disarm"
},
{
"ID": 1078,
"Name": "Surge"
},
{
"ID": 1079,
"Name": "Feint"
},
{
"ID": 1080,
"Name": "Talon Strike"
},
{
"ID": 1081,
"Name": "Psychic Attack"
},
{
"ID": 1082,
"Name": "Consecrate Weapon"
},
{
"ID": 1083,
"Name": "Grapes Of Wrath"
},
{
"ID": 1084,
"Name": "Enemy Of One Debuff"
},
{
"ID": 1085,
"Name": "Horrific Beast"
},
{
"ID": 1086,
"Name": "Lich Form"
},
{
"ID": 1087,
"Name": "Vampiric Embrace"
},
{
"ID": 1088,
"Name": "Curse Weapon"
},
{
"ID": 1089,
"Name": "Reaper Form"
},
{
"ID": 1090,
"Name": "Immolating Weapon"
},
{
"ID": 1091,
"Name": "Enchant"
},
{
"ID": 1092,
"Name": "Honorable Execution"
},
{
"ID": 1093,
"Name": "Confidence"
},
{
"ID": 1094,
"Name": "Evasion"
},
{
"ID": 1095,
"Name": "Counter Attack"
},
{
"ID": 1096,
"Name": "Lightning Strike"
},
{
"ID": 1097,
"Name": "Momentum Strike"
},
{
"ID": 1098,
"Name": "Orange Petals"
},
{
"ID": 1099,
"Name": "Rose Of Trinsic"
},
{
"ID": 1100,
"Name": "Poison Immunity"
},
{
"ID": 1101,
"Name": "Veterinary"
},
{
"ID": 1102,
"Name": "Perfection"
},
{
"ID": 1103,
"Name": "Honored"
},
{
"ID": 1104,
"Name": "Mana Phase"
},
{
"ID": 1105,
"Name": "Fan Dancer Fan Fire"
},
{
"ID": 1106,
"Name": "Rage"
},
{
"ID": 1107,
"Name": "Webbing"
},
{
"ID": 1108,
"Name": "Medusa Stone"
},
{
"ID": 1109,
"Name": "True Fear"
},
{
"ID": 1110,
"Name": "Aura Of Nausea"
},
{
"ID": 1111,
"Name": "Howl Of Cacophony"
},
{
"ID": 1112,
"Name": "Gaze Despair"
},
{
"ID": 1113,
"Name": "Hiryu Physical Resistance"
},
{
"ID": 1114,
"Name": "Rune Beetle Corruption"
},
{
"ID": 1115,
"Name": "Bloodworm Anemia"
},
{
"ID": 1116,
"Name": "Rotworm Blood Disease"
},
{
"ID": 1117,
"Name": "Skill Use Delay"
},
{
"ID": 1118,
"Name": "Faction Stat Loss"
},
{
"ID": 1119,
"Name": "Heat Of Battle Status"
},
{
"ID": 1120,
"Name": "Criminal Status"
},
{
"ID": 1121,
"Name": "Armor Pierce"
},
{
"ID": 1122,
"Name": "Splintering Effect"
},
{
"ID": 1123,
"Name": "Swing Speed Debuff"
},
{
"ID": 1124,
"Name": "Wraith Form"
},
{
"ID": 1126,
"Name": "City Trade Deal"
},
{
"ID": 1127,
"Name": "Humility Debuff"
},
{
"ID": 1128,
"Name": "Spirituality"
},
{
"ID": 1129,
"Name": "Humility"
},
{
"ID": 1130,
"Name": "Rampage"
},
{
"ID": 1131,
"Name": "Stagger"
},
{
"ID": 1132,
"Name": "Toughness"
},
{
"ID": 1133,
"Name": "Thrust"
},
{
"ID": 1134,
"Name": "Pierce"
},
{
"ID": 1135,
"Name": "Playing The Odds"
},
{
"ID": 1136,
"Name": "Focused Eye"
},
{
"ID": 1137,
"Name": "Onslaught"
},
{
"ID": 1138,
"Name": "Elemental Fury"
},
{
"ID": 1139,
"Name": "Elemental Fury Debuff"
},
{
"ID": 1140,
"Name": "Called Shot"
},
{
"ID": 1141,
"Name": "Knockout"
},
{
"ID": 1142,
"Name": "Saving Throw"
},
{
"ID": 1143,
"Name": "Conduit"
},
{
"ID": 1144,
"Name": "Ethereal Burst"
},
{
"ID": 1145,
"Name": "Mystic Weapon"
},
{
"ID": 1146,
"Name": "Mana Shield"
},
{
"ID": 1147,
"Name": "Anticipate Hit"
},
{
"ID": 1148,
"Name": "Warcry"
},
{
"ID": 1149,
"Name": "Shadow"
},
{
"ID": 1150,
"Name": "White Tiger Form"
},
{
"ID": 1151,
"Name": "Bodyguard"
},
{
"ID": 1152,
"Name": "Heightened Senses"
},
{
"ID": 1153,
"Name": "Tolerance"
},
{
"ID": 1154,
"Name": "Death Ray"
},
{
"ID": 1155,
"Name": "Death Ray Debuff"
},
{
"ID": 1156,
"Name": "Intuition"
},
{
"ID": 1157,
"Name": "Enchanted Summoning"
},
{
"ID": 1158,
"Name": "Shield Bash"
},
{
"ID": 1159,
"Name": "Whispering"
},
{
"ID": 1160,
"Name": "Combat Training"
},
{
"ID": 1161,
"Name": "Injected Strike Debuff"
},
{
"ID": 1162,
"Name": "Injected Strike"
},
{
"ID": 1163,
"Name": "Unknown Tomato"
},
{
"ID": 1164,
"Name": "Playing The Odds Debuff"
},
{
"ID": 1165,
"Name": "Dragon Turtle Debuff"
},
{
"ID": 1166,
"Name": "Boarding"
},
{
"ID": 1167,
"Name": "Potency"
},
{
"ID": 1168,
"Name": "Thrust Debuff"
},
{
"ID": 1169,
"Name": "Fists Of Fury"
},
{
"ID": 1170,
"Name": "Barrab Hemolymph Concentrate"
},
{
"ID": 1171,
"Name": "Jukari Burn Poiltice"
},
{
"ID": 1172,
"Name": "Kurak Ambushers Essence"
},
{
"ID": 1173,
"Name": "Barako Draft Of Might"
},
{
"ID": 1174,
"Name": "Urali Trance Tonic"
},
{
"ID": 1175,
"Name": "Sakkhra Prophylaxis"
},
{
"ID": 1186,
"Name": "Caddellite Infused"
},
{
"ID": 1187,
"Name": "Potion Glorious Fortune"
},
{
"ID": 1188,
"Name": "Mystical Polymorph Totem"
}
]
@@ -0,0 +1,8 @@
namespace ClassicAssist.Data.BuffIcons
{
public class BuffIconData
{
public int ID { get; set; }
public string Name { get; set; }
}
}
@@ -0,0 +1,133 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using ClassicAssist.Shared;
using ClassicAssist.Shared.Resources;
using ClassicAssist.UO.Network;
using Newtonsoft.Json;
using UOC = ClassicAssist.Shared.UO.Commands;
namespace ClassicAssist.Data.BuffIcons
{
public class BuffIconManager
{
private static BuffIconManager _instance;
private static readonly object _lock = new object();
private readonly List<BuffIconData> _buffIconData;
private bool[] _enabledIds;
private DateTime[] _expireTimes;
private BuffIconManager()
{
string dataPath = Path.Combine( Engine.StartupPath ?? Environment.CurrentDirectory, "Data" );
_buffIconData = JsonConvert
.DeserializeObject<BuffIconData[]>( File.ReadAllText( Path.Combine( dataPath, "BuffIcons.json" ) ) )
.ToList();
_enabledIds = new bool[short.MaxValue];
_expireTimes = new DateTime[short.MaxValue];
IncomingPacketHandlers.BufficonEnabledDisabledEvent += SetID;
Engine.PlayerInitializedEvent += p => Clear();
}
private void Clear()
{
_enabledIds = new bool[short.MaxValue];
_expireTimes = new DateTime[short.MaxValue];
}
private void SetID( int type, bool enabled, int duration )
{
_enabledIds[type] = enabled;
_expireTimes[type] = DateTime.Now.AddSeconds( duration );
}
public bool BuffExists( string name )
{
name = name.ToLower();
BuffIconData data = _buffIconData.FirstOrDefault( bd => bd.Name.ToLower().Equals( name ) );
if ( data != null )
{
return _enabledIds[data.ID];
}
UOC.SystemMessage( Strings.Unknown_buff_name___ );
return false;
}
public double BuffTime( string name )
{
name = name.ToLower();
BuffIconData data = _buffIconData.FirstOrDefault( bd => bd.Name.ToLower().Equals( name ) );
if ( data == null )
{
UOC.SystemMessage( Strings.Unknown_buff_name___ );
return 0;
}
if ( !BuffExists( name ) )
{
return 0;
}
if ( _expireTimes[data.ID] < DateTime.Now )
{
return 0;
}
return ( _expireTimes[data.ID] - DateTime.Now ).TotalMilliseconds;
}
public string[] GetEnabledNames()
{
List<int> enabled = new List<int>();
for ( int i = 0; i < _enabledIds.Length; i++ )
{
if ( _enabledIds[i] )
{
enabled.Add( i );
}
}
return enabled.Select( GetDataByID ).Select( data => data?.Name ).ToArray();
}
public BuffIconData GetDataByName( string name )
{
return _buffIconData.FirstOrDefault( i => i.Name == name );
}
public BuffIconData GetDataByID( int id )
{
return _buffIconData.FirstOrDefault( i => i.ID == id );
}
public static BuffIconManager GetInstance()
{
// ReSharper disable once InvertIf
if ( _instance == null )
{
lock ( _lock )
{
if ( _instance != null )
{
return _instance;
}
_instance = new BuffIconManager();
return _instance;
}
}
return _instance;
}
}
}
@@ -0,0 +1,190 @@
#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.Generic;
using System.Collections.ObjectModel;
using System.Text.RegularExpressions;
using ClassicAssist.UO.Data;
namespace ClassicAssist.Data.Chat
{
public class ChatManager
{
public delegate void dChannelCreated( string channel );
public delegate void dChannelRemoved( string channel );
public delegate void dChatMessage( string username, string channel, string message );
public delegate void dClearUsers();
public delegate void dJoinedChatChannel( string channel );
public delegate void dLeftChatChannel( string channel );
public delegate void dUserJoined( string username, string channel );
public delegate void dUserLeft( string username, string channel );
private static readonly object _instanceLock = new object();
private static ChatManager _instance;
public List<string> Channels { get; set; } = new List<string>();
public string CurrentChannel { get; set; }
public ObservableCollection<ChatMessage> Messages { get; set; } = new ObservableCollection<ChatMessage>();
public List<string> Users { get; set; } = new List<string>();
public event dJoinedChatChannel JoinedChatChannelEvent;
public event dLeftChatChannel LeftChatChannelEvent;
public event dChannelCreated ChannelCreatedEvent;
public event dChannelRemoved ChannelRemovedEvent;
public event dChatMessage ChatMessageEvent;
public event dUserJoined UserJoinedEvent;
public event dUserLeft UserLeftEvent;
public event dClearUsers ClearUsersEvent;
public static ChatManager GetInstance()
{
// ReSharper disable once InvertIf
if ( _instance == null )
{
lock ( _instanceLock )
{
if ( _instance == null )
{
_instance = new ChatManager();
}
}
}
return _instance;
}
public void OnChatPacket( PacketReader reader )
{
int messageNum = reader.ReadInt16();
reader.ReadString( 4 ); // Language
byte[] packet = reader.GetData();
switch ( messageNum )
{
case 0x25:
{
int messageType = reader.ReadInt16();
string username = reader.ReadUnicodeString();
string message = reader.ReadUnicodeString();
Match matches = Regex.Match( message, "{(.*)}\\s+(.*)" );
if ( matches.Success )
{
string channel = matches.Groups[1].Value;
string text = matches.Groups[2].Value;
Messages.Add( new ChatMessage { Username = username, Channel = channel, Text = text } );
ChatMessageEvent?.Invoke( username, channel, text );
}
break;
}
case 0x3e8:
{
string channel = reader.ReadUnicodeString();
if ( !Channels.Contains( channel ) )
{
Channels.Add( channel );
ChannelCreatedEvent?.Invoke( channel );
}
break;
}
case 0x3e9:
{
string channel = reader.ReadUnicodeString();
if ( Channels.Contains( channel ) )
{
Channels.Remove( channel );
ChannelRemovedEvent?.Invoke( channel );
}
break;
}
case 0x3ee:
{
reader.ReadInt16();
string userName = reader.ReadUnicodeString();
if ( !Users.Contains( userName ) )
{
Users.Add( userName );
UserJoinedEvent?.Invoke( userName, string.Empty );
}
break;
}
case 0x3ef:
{
string userName = reader.ReadUnicodeString();
if ( Users.Contains( userName ) )
{
Users.Remove( userName );
UserLeftEvent?.Invoke( userName, string.Empty );
}
break;
}
case 0x3f1:
{
CurrentChannel = reader.ReadUnicodeString();
JoinedChatChannelEvent?.Invoke( CurrentChannel );
break;
}
case 0x3f0:
{
Users.Clear();
ClearUsersEvent?.Invoke();
break;
}
case 0x3f4:
{
LeftChatChannelEvent?.Invoke( CurrentChannel );
CurrentChannel = null;
break;
}
// ReSharper disable once RedundantEmptySwitchSection
default:
break;
}
}
}
}
@@ -0,0 +1,36 @@
#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.Data.Chat
{
public class ChatMessage
{
public string Channel { get; set; }
//TODO2
//public SolidColorBrush Colour { get; set; }
public string Text { get; set; }
public string Username { get; set; }
public override string ToString()
{
return $"{Username}: {Text}";
}
}
}
@@ -0,0 +1,47 @@
#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;
namespace ClassicAssist.Data.Chat
{
public class ChatUser : IComparable<ChatUser>
{
//TODO2
//public SolidColorBrush Colour { get; set; }
public string Username { get; set; }
public int CompareTo( ChatUser other )
{
if ( ReferenceEquals( this, other ) )
{
return 0;
}
return ReferenceEquals( null, other )
? 1
: string.Compare( Username, other.Username, StringComparison.Ordinal );
}
public override string ToString()
{
return Username;
}
}
}
@@ -0,0 +1,212 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ClassicAssist.Shared;
using ClassicAssist.Data.Macros.Commands;
using ClassicAssist.Shared.Resources;
using ClassicAssist.UO.Data;
using ClassicAssist.UO.Objects;
using UOC = ClassicAssist.Shared.UO.Commands;
// ReSharper disable UnusedVariable
namespace ClassicAssist.Data.Commands
{
public class CommandsManager
{
private static Dictionary<string, Func<string[], bool>> _commands;
private static readonly byte[] _speechPacketIDs = { 0xAD, 0x03 };
public static void Initialize()
{
_commands = new Dictionary<string, Func<string[], bool>>
{
{ "help", OnHelp },
{ "where", OnSendLocation },
{ "addfriend", OnAddFriend },
{ "removefriend", OnRemoveFriend },
{ "info", OnInfo },
{ "resync", OnResync },
{ "hide", OnHide }
};
}
private static bool OnHide( string[] arg )
{
Task.Run( async () =>
{
int serial = await UOC.GetTargeSerialAsync();
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Cannot_find_item___ );
return;
}
UOC.RemoveObject( serial );
} );
return true;
}
private static bool OnResync( string[] arg )
{
MainCommands.Resync();
return true;
}
private static bool OnInfo( string[] arg )
{
//TODO
//Task.Run( async () => await UOC.InspectObjectAsync() );
return true;
}
private static bool OnRemoveFriend( string[] args )
{
if ( args.Length != 0 )
{
return false;
}
Task.Run( () => MobileCommands.RemoveFriend() );
return true;
}
private static bool OnAddFriend( string[] args )
{
if ( args.Length != 0 )
{
return false;
}
Task.Run( () => MobileCommands.AddFriend() );
return true;
}
private static bool OnHelp( string[] args )
{
if ( args.Length != 0 )
{
return false;
}
string[] commands = _commands.Select( kvp => kvp.Key ).ToArray();
UOC.SystemMessage( $"{Strings.Commands_} {string.Join( " ", commands )}" );
return true;
}
public static bool IsSpeechPacket( byte packetId )
{
return _speechPacketIDs?.Contains( packetId ) ?? false;
}
private static bool OnSendLocation( string[] args )
{
if ( Engine.Player == null )
{
return false;
}
PlayerMobile player = Engine.Player;
if ( args?.Length != 0 )
{
return false;
}
UOC.SystemMessage( $"{Strings.Current_Location_} {player.X}, {player.Y}, {player.Map}" );
UOC.SystemMessage( $"Region: {Regions.Regions.GetRegion( Engine.Player )}" );
return true;
}
public static bool CheckCommand( byte[] data, int length )
{
string text = null;
if ( data[0] == 0xAD )
{
text = ParseUnicodeSpeech( data, data.Length );
}
else if ( data[0] == 0x03 )
{
text = ParseAsciiSpeech( data, data.Length );
}
if ( string.IsNullOrEmpty( text ) || text[0] != Options.CurrentOptions.CommandPrefix )
{
return false;
}
string[] args = text.Remove( 0, 1 ).Split( ' ' );
return _commands.ContainsKey( args[0] ) && _commands[args[0]].Invoke( args.Skip( 1 ).ToArray() );
}
private static string ParseAsciiSpeech( byte[] data, int length )
{
PacketReader reader = new PacketReader( data, length, false );
int messageType = reader.ReadByte();
int hue = reader.ReadInt16();
int font = reader.ReadInt16();
string text = reader.ReadString();
return text.Trim();
}
internal static string ParseUnicodeSpeech( byte[] data, int length )
{
PacketReader reader = new PacketReader( data, length, false );
int messageType = reader.ReadByte();
int hue = reader.ReadInt16();
int font = reader.ReadInt16();
string lang = reader.ReadString( 4 );
string text;
// skip keywords
if ( ( messageType & 0xC0 ) != 0 )
{
//https://github.com/runuo/runuo/blob/master/Server/Network/PacketHandlers.cs
int count = ( reader.ReadInt16() & 0xFFF0 ) >> 4;
if ( count < 0 || count > 50 )
{
return null;
}
for ( int i = 0; i < count; ++i )
{
if ( ( i & 1 ) == 0 )
{
reader.ReadByte();
}
else
{
reader.ReadInt16();
}
}
text = reader.ReadString();
}
else
{
text = reader.ReadUnicodeString();
}
return text.Trim();
}
}
}
@@ -0,0 +1,68 @@
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using ClassicAssist.Shared;
using ClassicAssist.Annotations;
using ClassicAssist.UO.Objects;
namespace ClassicAssist.Data.Counters
{
public class CountersAgentEntry : INotifyPropertyChanged
{
private int _color;
private int _count;
public int Color
{
get => _color;
set
{
SetProperty( ref _color, value );
Recount();
}
}
public int Count
{
get => _count;
set => SetProperty( ref _count, value );
}
public int Graphic { get; set; }
public string Name { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
public void Recount()
{
if ( Engine.Player == null )
{
return;
}
if ( Engine.Player.Backpack?.Container == null )
{
Count = 0;
return;
}
Item[] matches =
Engine.Player.Backpack.Container.SelectEntities( i =>
i.ID == Graphic && ( Color == -1 || Color == i.Hue ) );
Count = matches?.Sum( i => i.Count ) ?? 0;
}
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged( [CallerMemberName] string propertyName = null )
{
PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( propertyName ) );
}
public void SetProperty<T>( ref T obj, T value, [CallerMemberName] string propertyName = "" )
{
obj = value;
OnPropertyChanged( propertyName );
}
}
}
@@ -0,0 +1,129 @@
using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using ClassicAssist.Shared;
using ClassicAssist.Annotations;
using ClassicAssist.UO.Data;
using ClassicAssist.UO.Network;
using ClassicAssist.UO.Objects;
namespace ClassicAssist.Data.Counters
{
public class CountersManager : INotifyPropertyChanged
{
private static CountersManager _instance;
private static readonly object _instanceLock = new object();
private ObservableCollection<CountersAgentEntry> _items = new ObservableCollection<CountersAgentEntry>();
private bool _listening;
private CountersManager()
{
Items.CollectionChanged += OnCollectionChanged;
IncomingPacketHandlers.ContainerContentsEvent += OnContainerContentsEvent;
IncomingPacketHandlers.NewWorldItemEvent += OnNewWorldItemEvent;
Engine.DisconnectedEvent += () =>
{
if ( Engine.Player != null )
{
Engine.Player.Backpack.Container.CollectionChanged -= OnBackpackContentsChanged;
}
_listening = false;
};
}
public ObservableCollection<CountersAgentEntry> Items
{
get => _items;
set => SetProperty( ref _items, value );
}
public Action RecountAll { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
private void OnNewWorldItemEvent( Item item )
{
RecountAll?.Invoke();
}
private void OnContainerContentsEvent( int serial, ItemCollection container )
{
if ( Engine.Player == null )
{
return;
}
if ( Engine.Player.Backpack?.Container == null )
{
return;
}
if ( !Engine.Items.GetItem( serial, out Item item ) )
{
return;
}
if ( item.Owner == Engine.Player.Serial && item.Layer == Layer.Backpack && !_listening )
{
Engine.Player.Backpack.Container.CollectionChanged += OnBackpackContentsChanged;
RecountAll?.Invoke();
_listening = true;
return;
}
if ( item.IsDescendantOf( Engine.Player.Backpack.Serial ) )
{
// Is child item of backpack
RecountAll?.Invoke();
}
}
private void OnBackpackContentsChanged( int totalcount, bool added, Item[] items )
{
RecountAll?.Invoke();
}
private void OnCollectionChanged( object sender, NotifyCollectionChangedEventArgs e )
{
OnPropertyChanged( nameof( Items ) );
}
public static CountersManager GetInstance()
{
// ReSharper disable once InvertIf
if ( _instance == null )
{
lock ( _instanceLock )
{
if ( _instance == null )
{
_instance = new CountersManager();
}
}
}
return _instance;
}
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged( [CallerMemberName] string propertyName = null )
{
PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( propertyName ) );
}
// ReSharper disable once RedundantAssignment
public void SetProperty<T>( ref T obj, T value, [CallerMemberName] string propertyName = "" )
{
obj = value;
OnPropertyChanged( propertyName );
}
}
}
+125
View File
@@ -0,0 +1,125 @@
#region license
// Copyright (C) 2020 ClassicUO Development Community on Github
//
// This project is an alternative client for the game Ultima Online.
// The goal of this is to develop a lightweight client considering
// new technologies.
//
// 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;
using System.Text;
namespace ClassicAssist.Data
{
internal static class Crypter
{
public static string Encrypt( string source )
{
byte[] buff = Encoding.ASCII.GetBytes( source );
int kidx = 0;
string key = CalculateKey();
if ( key == string.Empty )
{
return string.Empty;
}
StringBuilder sb = new StringBuilder( source.Length * 2 + 2 );
sb.Append( "1+" );
for ( int i = 0; i < buff.Length; i++ )
{
sb.AppendFormat( "{0:X2}", (byte) ( buff[i] ^ (byte) key[kidx++] ) );
if ( kidx >= key.Length )
{
kidx = 0;
}
}
return sb.ToString();
}
public static string Decrypt( string source )
{
byte[] buff;
if ( source.Length > 2 && source[0] == '1' && source[1] == '+' )
{
buff = new byte[( source.Length - 2 ) >> 1];
string key = CalculateKey();
if ( key == string.Empty )
{
return string.Empty;
}
int kidx = 0;
for ( int i = 2; i < source.Length; i += 2 )
{
byte c;
try
{
c = Convert.ToByte( source.Substring( i, 2 ), 16 );
}
catch
{
continue;
}
buff[( i - 2 ) >> 1] = (byte) ( c ^ (byte) key[kidx++] );
if ( kidx >= key.Length )
{
kidx = 0;
}
}
}
else
{
byte key = (byte) ( source.Length >> 1 );
buff = new byte[key];
for ( int i = 0; i < source.Length; i += 2 )
{
byte c;
try
{
c = Convert.ToByte( source.Substring( i, 2 ), 16 );
}
catch
{
continue;
}
buff[i >> 1] = (byte) ( c ^ key++ );
}
}
return Encoding.ASCII.GetString( buff );
}
private static string CalculateKey()
{
return Environment.MachineName;
}
}
}
@@ -0,0 +1,180 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using ClassicAssist.Shared;
using ClassicAssist.Data.Hotkeys;
using ClassicAssist.Misc;
using ClassicAssist.UO.Network;
using ClassicAssist.UO.Objects;
using UOC = ClassicAssist.Shared.UO.Commands;
namespace ClassicAssist.Data.Dress
{
/*
* Future tip to self, this is HotkeyEntry so it doesn't try to add it to hotkey commands
*/
public class DressAgentEntry : HotkeyEntry
{
private List<DressAgentItem> _items;
private int _undressContainer;
public List<DressAgentItem> Items
{
get => _items;
set => SetProperty( ref _items, value );
}
public int UndressContainer
{
get => _undressContainer;
set => SetProperty( ref _undressContainer, value );
}
public override string ToString()
{
return Name;
}
public void AddOrReplaceDressItem( Item item )
{
List<DressAgentItem> list = Items.ToList();
DressAgentItem existingItem = Items.FirstOrDefault( i => i.Layer == item.Layer );
if ( existingItem != null )
{
list.Remove( existingItem );
}
list.Add( new DressAgentItem
{
Serial = item.Serial, Layer = item.Layer, Type = DressAgentItemType.Serial, ID = item.ID
} );
Items = list;
}
public async Task Dress( bool moveConflicting = true )
{
PlayerMobile player = Engine.Player;
if ( player == null )
{
return;
}
int container = DressManager.GetInstance().GetUndressContainer( UndressContainer );
if ( container == 0 || container == -1 )
{
return;
}
if ( DressManager.GetInstance().UseUO3DPackets )
{
//TODO DressAgentItemType.ID
if ( moveConflicting )
{
int[] conflictingLayers = Engine.Player.GetEquippedItems()
.Where( i => Items.Any( ii => i.Layer == ii.Layer && i.Serial != ii.Serial ) )
.Select( l => (int) l.Layer ).ToArray();
if ( conflictingLayers.Length > 0 )
{
UOC.UO3DUnequipItems( conflictingLayers );
Thread.Sleep( Options.CurrentOptions.ActionDelayMS );
}
}
int[] dressItems = Items.Select( i => i.Serial ).ToArray();
UOC.UO3DEquipItems( dressItems );
}
else
{
await Task.Run( async () =>
{
foreach ( DressAgentItem dai in Items )
{
Item item = Engine.Items.GetItem( dai.Serial );
if ( item == null && dai.Type == DressAgentItemType.Serial )
{
continue;
}
int currentInLayer = Engine.Player?.GetLayer( dai.Layer ) ?? 0;
if ( currentInLayer == item?.Serial )
{
continue;
}
if ( currentInLayer != 0 && moveConflicting && container != -1 )
{
await ActionPacketQueue.EnqueueDragDrop( currentInLayer, 1, container,
QueuePriority.Medium );
currentInLayer = 0;
}
if ( currentInLayer != 0 )
{
continue;
}
switch ( dai.Type )
{
case DressAgentItemType.Serial:
await UOC.EquipItem( item, dai.Layer );
break;
case DressAgentItemType.ID:
await UOC.EquipType( dai.ID, dai.Layer );
break;
default:
throw new ArgumentOutOfRangeException();
}
}
} );
}
}
public async Task Undress()
{
if ( Engine.Player == null )
{
return;
}
int container = DressManager.GetInstance().GetUndressContainer( UndressContainer );
if ( container == 0 || container == -1 )
{
return;
}
IEnumerable<int> serials = Items.Select( dai => dai.Serial );
if ( DressManager.GetInstance().UseUO3DPackets )
{
int[] layers = Engine.Player.GetEquippedItems().Where( i => serials.Contains( i.Serial ) )
.Select( i => (int) i.Layer ).ToArray();
UOC.UO3DUnequipItems( layers );
}
else
{
IEnumerable<Item> itemsToUnequip =
Engine.Player.GetEquippedItems().Where( i => serials.Contains( i.Serial ) );
foreach ( Item item in itemsToUnequip )
{
await ActionPacketQueue.EnqueueDragDrop( item.Serial, 1, container, QueuePriority.Medium );
}
}
}
}
}
@@ -0,0 +1,81 @@
using System.ComponentModel;
using System.Runtime.CompilerServices;
using ClassicAssist.Annotations;
using ClassicAssist.Shared.Resources;
using ClassicAssist.UO.Data;
namespace ClassicAssist.Data.Dress
{
public class DressAgentItem : INotifyPropertyChanged
{
private int _id = -1;
private Layer _layer;
private string _name;
private int _serial;
private DressAgentItemType _type = DressAgentItemType.Serial;
public DressAgentItem()
{
PropertyChanged += ( sender, args ) =>
{
// Set the name when the Type changes...
if ( args.PropertyName == nameof( Type ) )
{
Name = Type == DressAgentItemType.ID
? $"{Layer}: {Strings.Type}: 0x{ID:x4}"
: $"{Layer}: 0x{Serial:x8}";
}
};
}
public int ID
{
get => _id;
set => SetProperty( ref _id, value );
}
public Layer Layer
{
get => _layer;
set => SetProperty( ref _layer, value );
}
public string Name
{
get => _name;
set => SetProperty( ref _name, value );
}
public int Serial
{
get => _serial;
set => SetProperty( ref _serial, value );
}
public DressAgentItemType Type
{
get => _type;
set => SetProperty( ref _type, value );
}
public event PropertyChangedEventHandler PropertyChanged;
// ReSharper disable once RedundantAssignment
public void SetProperty<T>( ref T field, T value, [CallerMemberName] string propertyName = null )
{
field = value;
OnPropertyChanged( propertyName );
}
public override string ToString()
{
return Name;
}
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged( [CallerMemberName] string propertyName = null )
{
PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( propertyName ) );
}
}
}
@@ -0,0 +1,27 @@
#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.Data.Dress
{
public enum DressAgentItemType
{
Serial,
ID
}
}
@@ -0,0 +1,191 @@
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using ClassicAssist.Annotations;
using ClassicAssist.Misc;
using ClassicAssist.Shared;
using ClassicAssist.UI.Misc;
using ClassicAssist.UO.Data;
using ClassicAssist.UO.Network;
using ClassicAssist.UO.Objects;
namespace ClassicAssist.Data.Dress
{
public class DressManager : INotifyPropertyChanged
{
private static DressManager _instance;
private static readonly object _instanceLock = new object();
private readonly Layer[] _validLayers =
{
Layer.Arms, Layer.Bracelet, Layer.Cloak, Layer.Earrings, Layer.Gloves, Layer.Helm, Layer.InnerLegs,
Layer.InnerTorso, Layer.MiddleTorso, Layer.Neck, Layer.OneHanded, Layer.OuterLegs, Layer.OuterTorso,
Layer.Pants, Layer.Ring, Layer.Shirt, Layer.Shoes, Layer.Talisman, Layer.TwoHanded, Layer.Waist
};
private ObservableCollectionEx<DressAgentEntry> _items = new ObservableCollectionEx<DressAgentEntry>();
private DressAgentEntry _temporaryDress;
private bool _useUo3DPackets;
private DressManager()
{
Items.CollectionChanged += OnCollectionChanged;
}
public bool IsDressing { get; set; }
public ObservableCollectionEx<DressAgentEntry> Items
{
get => _items;
set => SetProperty( ref _items, value );
}
public DressAgentEntry TemporaryDress
{
get => _temporaryDress;
set => SetProperty( ref _temporaryDress, value );
}
public bool UseUO3DPackets
{
get => _useUo3DPackets;
set => SetProperty( ref _useUo3DPackets, value );
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnCollectionChanged( object sender, NotifyCollectionChangedEventArgs e )
{
OnPropertyChanged( nameof( Items ) );
}
public static DressManager GetInstance()
{
// ReSharper disable once InvertIf
if ( _instance == null )
{
lock ( _instanceLock )
{
if ( _instance == null )
{
_instance = new DressManager();
}
}
}
return _instance;
}
// ReSharper disable once RedundantAssignment
public void SetProperty<T>( ref T obj, T value, [CallerMemberName] string propertyName = "" )
{
obj = value;
OnPropertyChanged( propertyName );
}
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged( [CallerMemberName] string propertyName = null )
{
PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( propertyName ) );
}
public async Task UndressAll( CancellationToken cancellationToken = default )
{
try
{
IsDressing = true;
PlayerMobile player = Engine.Player;
if ( player == null )
{
return;
}
int backpack = player.Backpack.Serial;
if ( backpack == 0 || backpack == -1 )
{
return;
}
if ( _useUo3DPackets )
{
int[] layers = player.GetEquippedItems().Where( i => IsValidLayer( i.Layer ) )
.Select( i => (int) i.Layer ).ToArray();
Shared.UO.Commands.UO3DUnequipItems( layers );
}
else
{
int[] items = player.GetEquippedItems().Where( i => IsValidLayer( i.Layer ) )
.Select( i => i.Serial ).ToArray();
foreach ( int item in items )
{
if ( cancellationToken.IsCancellationRequested )
{
return;
}
await ActionPacketQueue.EnqueueDragDrop( item, 1, backpack, QueuePriority.Medium );
}
}
}
finally
{
IsDressing = false;
}
}
public bool IsValidLayer( Layer layer )
{
return _validLayers.Any( l => l == layer );
}
public int GetUndressContainer( int undressContainer )
{
int container = undressContainer;
if ( container != 0 && ( Engine.Items.GetItem( container )?.Distance ?? byte.MaxValue ) > 3 ||
container == 0 )
{
container = Engine.Player?.Backpack?.Serial ?? 0;
}
return container;
}
public void ImportItems( DressAgentEntry dae )
{
PlayerMobile player = Engine.Player;
List<DressAgentItem> items = player.GetEquippedItems().Where( i => IsValidLayer( i.Layer ) ).Select( i =>
new DressAgentItem
{
Serial = i.Serial, Layer = i.Layer, ID = i.ID, Type = DressAgentItemType.Serial
} )
.ToList();
dae.Items = items;
}
public async Task DressAllItems( DressAgentEntry dae, bool moveConflictingItems )
{
try
{
IsDressing = true;
await dae.Dress( moveConflictingItems );
}
finally
{
IsDressing = false;
}
}
}
}
+24
View File
@@ -0,0 +1,24 @@
#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.Data
{
public interface IExtension
{
void Initialize();
}
}
@@ -0,0 +1,53 @@
#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.Linq;
using ClassicAssist.UO.Network.PacketFilter;
namespace ClassicAssist.Data.Filters
{
[FilterOptions( Name = "Bards Music", DefaultEnabled = true )]
public class BardsMusicFilter : DynamicFilterEntry
{
private static readonly int[] _bardsMusic = { 0x38, 0x39, 0x43, 0x44, 0x45, 0x46, 0x4C, 0x4D, 0x52, 0x53 };
private static bool _isEnabled;
protected override void OnChanged( bool enabled )
{
_isEnabled = enabled;
}
public override bool CheckPacket( ref byte[] packet, ref int length, PacketDirection direction )
{
if ( packet == null || !_isEnabled )
{
return false;
}
if ( packet[0] != 0x54 || direction != PacketDirection.Incoming )
{
return false;
}
int soundId = ( packet[2] << 8 ) | packet[3];
return _bardsMusic.Contains( soundId );
}
}
}
@@ -0,0 +1,112 @@
using System.Collections.Generic;
using System.Linq;
using ClassicAssist.Shared;
using ClassicAssist.Shared.Resources;
using ClassicAssist.UO.Data;
using ClassicAssist.UO.Network.Packets;
using Newtonsoft.Json.Linq;
namespace ClassicAssist.Data.Filters
{
[FilterOptions( Name = "Cliloc Filter", DefaultEnabled = false )]
public class ClilocFilter : FilterEntry, IConfigurableFilter
{
public static Dictionary<int, string> Filters { get; set; } = new Dictionary<int, string>();
public static bool IsEnabled { get; set; }
public void Configure()
{
//TODO
//ClilocFilterConfigureWindow window =
// new ClilocFilterConfigureWindow { Topmost = Options.CurrentOptions.AlwaysOnTop };
//window.ShowDialog();
}
public void Deserialize( JToken token )
{
if ( token?["Filters"] == null )
{
return;
}
foreach ( JToken filterToken in token["Filters"] )
{
int key = filterToken["Key"].ToObject<int>();
string val = filterToken["Value"]?.ToObject<string>();
if ( !Filters.ContainsKey( key ) )
{
Filters.Add( key, val );
}
}
}
public JObject Serialize()
{
JArray itemsArray = new JArray();
foreach ( KeyValuePair<int, string> kvp in Filters )
{
itemsArray.Add( new JObject { { "Key", kvp.Key }, { "Value", kvp.Value } } );
}
return new JObject { { "Filters", itemsArray } };
}
public void ResetOptions()
{
Filters.Clear();
}
protected override void OnChanged( bool enabled )
{
IsEnabled = enabled;
}
public static bool CheckMessage( JournalEntry journalEntry )
{
if ( !IsEnabled || journalEntry.Cliloc == 0 )
{
return false;
}
if ( Filters.All( f => f.Key != journalEntry.Cliloc ) )
{
return false;
}
KeyValuePair<int, string> match = Filters.FirstOrDefault( f => f.Key == journalEntry.Cliloc );
Engine.SendPacketToClient( new UnicodeText( journalEntry.Serial, journalEntry.ID, journalEntry.SpeechType,
journalEntry.SpeechHue, journalEntry.SpeechFont, Strings.UO_LOCALE, journalEntry.Name, match.Value ) );
return true;
}
public static bool CheckMessageAffix( JournalEntry journalEntry, MessageAffixType affixType, string affix )
{
if ( !IsEnabled || journalEntry.Cliloc == 0 )
{
return false;
}
if ( Filters.All( f => f.Key != journalEntry.Cliloc ) )
{
return false;
}
KeyValuePair<int, string> match = Filters.FirstOrDefault( f => f.Key == journalEntry.Cliloc );
string text = affixType.HasFlag( MessageAffixType.Prepend )
? $"{affix}{match.Value}"
: $"{match.Value}{affix}";
Engine.SendPacketToClient( new UnicodeText( journalEntry.Serial, journalEntry.ID, JournalSpeech.Say,
journalEntry.SpeechHue, journalEntry.SpeechFont, Strings.UO_LOCALE, journalEntry.Name, text ) );
return true;
}
}
}
@@ -0,0 +1,44 @@
#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;
using System.Collections.Generic;
using ClassicAssist.UO.Network.PacketFilter;
namespace ClassicAssist.Data.Filters
{
public abstract class DynamicFilterEntry : FilterEntry
{
protected DynamicFilterEntry()
{
Filters.Add( this );
}
public static List<DynamicFilterEntry> Filters { get; set; } = new List<DynamicFilterEntry>();
protected override void OnChanged( bool enabled )
{
}
public virtual bool CheckPacket( ref byte[] packet, ref int length, PacketDirection direction )
{
throw new NotImplementedException();
}
}
}
@@ -0,0 +1,81 @@
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using ClassicAssist.Shared.Resources;
namespace ClassicAssist.Data.Filters
{
public abstract class FilterEntry : INotifyPropertyChanged
{
private bool _enabled;
private bool _isConfigurable;
private string _name;
protected FilterEntry()
{
Action = OnChanged;
FilterOptionsAttribute a =
(FilterOptionsAttribute) Attribute.GetCustomAttribute( GetType(), typeof( FilterOptionsAttribute ) );
if ( a == null )
{
return;
}
string resourceName = Strings.ResourceManager.GetString( a.Name );
if ( string.IsNullOrEmpty( resourceName ) )
{
throw new InvalidOperationException( $"No localized text for filter: {a.Name}" );
}
Name = string.IsNullOrEmpty( resourceName ) ? a.Name : resourceName;
Enabled = a.DefaultEnabled;
IsConfigurable = typeof( IConfigurableFilter ).IsAssignableFrom( GetType() );
}
public Action<bool> Action { get; set; }
public bool Enabled
{
get => _enabled;
set
{
SetProperty( ref _enabled, value );
Action?.Invoke( value );
}
}
public bool IsConfigurable
{
get => _isConfigurable;
set => SetProperty( ref _isConfigurable, value );
}
public string Name
{
get => _name;
set => SetProperty( ref _name, value );
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnChanged( bool enabled )
{
throw new NotImplementedException();
}
protected virtual void OnPropertyChanged( [CallerMemberName] string propertyName = null )
{
PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( propertyName ) );
}
// ReSharper disable once RedundantAssignment
public void SetProperty<T>( ref T field, T value, [CallerMemberName] string propertyName = null )
{
field = value;
OnPropertyChanged( propertyName );
}
}
}
@@ -0,0 +1,10 @@
using System;
namespace ClassicAssist.Data.Filters
{
public class FilterOptionsAttribute : Attribute
{
public bool DefaultEnabled { get; set; }
public string Name { get; set; }
}
}
@@ -0,0 +1,12 @@
using Newtonsoft.Json.Linq;
namespace ClassicAssist.Data.Filters
{
public interface IConfigurableFilter
{
void Configure();
void Deserialize( JToken token );
JObject Serialize();
void ResetOptions();
}
}
@@ -0,0 +1,25 @@
using ClassicAssist.UO.Network.PacketFilter;
namespace ClassicAssist.Data.Filters
{
[FilterOptions( Name = "Light Level", DefaultEnabled = true )]
public class LightLevelFilter : DynamicFilterEntry
{
public override bool CheckPacket( ref byte[] packet, ref int length, PacketDirection direction )
{
if ( packet[0] == 0x4E && Enabled )
{
return true;
}
if ( packet[0] != 0x4F || !Enabled )
{
return false;
}
packet[1] = (byte) Options.CurrentOptions.LightLevel;
return false;
}
}
}
@@ -0,0 +1,161 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ClassicAssist.UO.Data;
using Newtonsoft.Json.Linq;
namespace ClassicAssist.Data.Filters
{
[FilterOptions( Name = "Repeated Messages", DefaultEnabled = false )]
public class RepeatedMessagesFilter : FilterEntry, IConfigurableFilter
{
public static MessageFilterOptions FilterOptions { get; set; } = new MessageFilterOptions();
public static bool IsEnabled { get; set; }
private static List<RepeatedMessageEntry> RepeatedMessageEntries { get; } = new List<RepeatedMessageEntry>();
public void Configure()
{
//TODO
//RepeatedMessagesFilterConfigureWindow window = new RepeatedMessagesFilterConfigureWindow( FilterOptions );
//window.ShowDialog();
}
public void Deserialize( JToken token )
{
if ( token == null )
{
return;
}
try
{
FilterOptions = new MessageFilterOptions
{
SendToJournal = token["SendToJournal"]?.ToObject<bool>() ?? false,
MessageLimit = token["MessageLimit"]?.ToObject<int>() ?? 5,
TimeLimit = token["TimeLimit"]?.ToObject<int>() ?? 5,
BlockedTime = token["BlockedTime"]?.ToObject<int>() ?? 5
};
}
catch ( Exception )
{
FilterOptions = new MessageFilterOptions();
}
}
public JObject Serialize()
{
return new JObject
{
{ "SendToJournal", FilterOptions.SendToJournal },
{ "MessageLimit", FilterOptions.MessageLimit },
{ "TimeLimit", FilterOptions.TimeLimit },
{ "BlockedTime", FilterOptions.BlockedTime }
};
}
public void ResetOptions()
{
FilterOptions = new MessageFilterOptions();
}
protected override void OnChanged( bool enabled )
{
IsEnabled = enabled;
}
public static bool CheckMessage( JournalEntry journalEntry )
{
if ( !IsEnabled )
{
return false;
}
if ( journalEntry.SpeechType != JournalSpeech.System &&
( journalEntry.Name != "System" || journalEntry.Serial != -1 ) )
{
return false;
}
if ( FilterOptions.MessageLimit == 0 )
{
return true;
}
RepeatedMessageEntry entry = RepeatedMessageEntries.FirstOrDefault( e => e.Message == journalEntry.Text );
if ( entry != null && entry.Blocked && entry.Expires < DateTime.Now )
{
RepeatedMessageEntries.Remove( entry );
}
if ( entry != null && entry.Blocked && entry.Expires > DateTime.Now )
{
return true;
}
if ( RepeatedMessageEntries.All( e => e.Message != journalEntry.Text ) )
{
RepeatedMessageEntries.Add( new RepeatedMessageEntry
{
FirstReceived = DateTime.Now,
LastReceived = DateTime.Now,
Count = 1,
Message = journalEntry.Text
} );
return false;
}
entry = RepeatedMessageEntries.FirstOrDefault( e => e.Message == journalEntry.Text );
if ( entry == null )
{
return false;
}
if ( entry.LastReceived < DateTime.Now - TimeSpan.FromSeconds( FilterOptions.TimeLimit ) )
{
RepeatedMessageEntries.Remove( entry );
return false;
}
if ( entry.Count < FilterOptions.MessageLimit )
{
entry.Count++;
entry.LastReceived = DateTime.Now;
return false;
}
if ( Options.CurrentOptions.Debug )
{
Shared.UO.Commands.SystemMessage( $"Filtering message: {journalEntry.Text}" );
}
entry.Blocked = true;
entry.Expires = DateTime.Now + TimeSpan.FromSeconds( FilterOptions.BlockedTime );
return true;
}
internal class RepeatedMessageEntry
{
public bool Blocked { get; set; }
public int Count { get; set; }
public DateTime Expires { get; set; } = DateTime.Now;
public DateTime FirstReceived { get; set; }
public DateTime LastReceived { get; set; }
public string Message { get; set; }
}
public class MessageFilterOptions
{
public int BlockedTime { get; set; } = 5;
public int MessageLimit { get; set; } = 5;
public bool SendToJournal { get; set; }
public int TimeLimit { get; set; } = 5;
}
}
}
@@ -0,0 +1,46 @@
using ClassicAssist.Shared;
using ClassicAssist.UO.Data;
using ClassicAssist.UO.Network.PacketFilter;
namespace ClassicAssist.Data.Filters
{
[FilterOptions( Name = "Seasons", DefaultEnabled = false )]
public class SeasonFilter : FilterEntry
{
private readonly byte[] _desolationSeason = { 0xBC, 0x04, 0x00 };
private readonly byte[] _standardSeason = { 0xBC, 0x00, 0x00 };
protected override void OnChanged( bool enabled )
{
PacketFilterInfo pfi = new PacketFilterInfo( 0xBC, OnSeasonChange );
if ( enabled )
{
Engine.AddReceiveFilter( pfi );
if ( Engine.Player != null && Engine.Player.Map == Map.Felucca )
{
Engine.SendPacketToClient( _desolationSeason, _desolationSeason.Length );
return;
}
Engine.SendPacketToClient( _standardSeason, _standardSeason.Length );
}
else
{
Engine.RemoveReceiveFilter( pfi );
}
}
private void OnSeasonChange( byte[] arg1, PacketFilterInfo arg2 )
{
if ( Engine.Player != null && Engine.Player.Map == Map.Felucca )
{
Engine.SendPacketToClient( _desolationSeason, _desolationSeason.Length );
return;
}
Engine.SendPacketToClient( _standardSeason, _standardSeason.Length );
}
}
}
@@ -0,0 +1,30 @@
using ClassicAssist.Shared;
using ClassicAssist.UO.Network.PacketFilter;
namespace ClassicAssist.Data.Filters
{
[FilterOptions( Name = "Weather", DefaultEnabled = true )]
public class WeatherFilter : FilterEntry
{
private static void OnWeatherPacket( byte[] arg1, PacketFilterInfo arg2 )
{
byte[] packet = { 0x65, 0xFF, 0x00, 0x00 };
Engine.SendPacketToClient( packet, packet.Length );
}
protected override void OnChanged( bool enabled )
{
PacketFilterInfo pfi = new PacketFilterInfo( 0x65, null, OnWeatherPacket );
if ( enabled )
{
Engine.AddReceiveFilter( pfi );
}
else
{
Engine.RemoveReceiveFilter( pfi );
}
}
}
}
@@ -0,0 +1,33 @@
namespace ClassicAssist.Data.Friends
{
public class FriendEntry
{
public string Name { get; set; }
public int Serial { get; set; }
public override string ToString()
{
return $"{Name}: 0x{Serial:x}";
}
public override bool Equals( object obj )
{
if ( !( obj is FriendEntry fe ) )
{
return false;
}
return Equals( fe );
}
protected bool Equals( FriendEntry other )
{
return Serial == other.Serial;
}
public override int GetHashCode()
{
return Serial.GetHashCode();
}
}
}
@@ -0,0 +1,52 @@
using System.Linq;
using ClassicAssist.Shared;
using ClassicAssist.Data.Macros.Commands;
using ClassicAssist.Shared.Resources;
using ClassicAssist.UO.Network.Packets;
using ClassicAssist.UO.Objects;
using UOC = ClassicAssist.Shared.UO.Commands;
namespace ClassicAssist.Data.Hotkeys.Commands
{
[HotkeyCommand( Name = "Bandage Self" )]
public class BandageSelf : HotkeyCommand
{
private const int TIMEOUT = 5000;
private readonly int[] _bandageTypes = { 0xe21 };
public override void Execute()
{
PlayerMobile player = Engine.Player;
if ( player == null )
{
UOC.SystemMessage( Strings.Error__No_Player );
return;
}
Item backpack = player.Backpack;
if ( backpack == null )
{
UOC.SystemMessage( Strings.Error__Cannot_find_player_backpack );
return;
}
Item bandage = backpack.Container?.SelectEntity( i => _bandageTypes.Contains( i.ID ) );
if ( bandage == null )
{
UOC.SystemMessage( Strings.Error__Cannot_find_type );
return;
}
ObjectCommands.UseObject( bandage.Serial );
bool result = UOC.WaitForTarget( TIMEOUT );
if ( result )
{
Engine.SendPacketToServer( new Target( -1, player, true ) );
}
}
}
}
@@ -0,0 +1,36 @@
#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 ClassicAssist.Shared;
using ClassicAssist.UO.Network.Packets;
namespace ClassicAssist.Data.Hotkeys.Commands
{
[HotkeyCommand( Name = "Cast Last Spell" )]
public class CastLastSpell : HotkeyCommand
{
public override void Execute()
{
if ( Engine.LastSpellID != 0 )
{
Engine.SendPacketToServer( new CastSpell( Engine.LastSpellID ) );
}
}
}
}
@@ -0,0 +1,13 @@
using ClassicAssist.UO.Network;
namespace ClassicAssist.Data.Hotkeys.Commands
{
[HotkeyCommand( Name = "Clear Object Queue" )]
public class ClearObjectQueue : HotkeyCommand
{
public override void Execute()
{
ActionPacketQueue.Clear();
}
}
}
@@ -0,0 +1,150 @@
using ClassicAssist.Shared;
using ClassicAssist.Data.Macros.Commands;
using ClassicAssist.UO.Data;
namespace ClassicAssist.Data.Hotkeys.Commands
{
[HotkeyCommand( Category = "Consume", Name = "Cure Potion" )]
public class UseCurePotion : HotkeyCommand
{
public override void Execute()
{
ObjectCommands.UseType( 0xf07, 0, Engine.Player.GetLayer( Layer.Backpack ) );
}
}
[HotkeyCommand( Category = "Consume", Name = "Heal Potion" )]
public class UseHealPotion : HotkeyCommand
{
public override void Execute()
{
ObjectCommands.UseType( 0xf0c, 0, Engine.Player.GetLayer( Layer.Backpack ) );
}
}
[HotkeyCommand( Category = "Consume", Name = "Refresh Potion" )]
public class UseRefreshPotion : HotkeyCommand
{
public override void Execute()
{
ObjectCommands.UseType( 0xf0b, 0, Engine.Player.GetLayer( Layer.Backpack ) );
}
}
[HotkeyCommand( Category = "Consume", Name = "Strength Potion" )]
public class UseStrengthPotion : HotkeyCommand
{
public override void Execute()
{
ObjectCommands.UseType( 0xf09, 0, Engine.Player.GetLayer( Layer.Backpack ) );
}
}
[HotkeyCommand( Category = "Consume", Name = "Agility Potion" )]
public class UseAgilityPotion : HotkeyCommand
{
public override void Execute()
{
ObjectCommands.UseType( 0xf08, 0, Engine.Player.GetLayer( Layer.Backpack ) );
}
}
[HotkeyCommand( Category = "Consume", Name = "Explosion Potion" )]
public class UseExplosionPotion : HotkeyCommand
{
public override void Execute()
{
ObjectCommands.UseType( 0xf0d, 0, Engine.Player.GetLayer( Layer.Backpack ) );
}
}
[HotkeyCommand( Category = "Consume", Name = "Invisibility Potion" )]
public class UseInvisibilityPotion : HotkeyCommand
{
public override void Execute()
{
ObjectCommands.UseType( 0xf06, 306, Engine.Player.GetLayer( Layer.Backpack ) );
}
}
[HotkeyCommand( Category = "Consume", Name = "Confusion Blast Potion" )]
public class UseConfusionBlastPotion : HotkeyCommand
{
public override void Execute()
{
ObjectCommands.UseType( 0xf06, 1165, Engine.Player.GetLayer( Layer.Backpack ) );
}
}
[HotkeyCommand( Category = "Consume", Name = "Conflagration Potion" )]
public class UseConflagPotion : HotkeyCommand
{
public override void Execute()
{
ObjectCommands.UseType( 0xf06, 1161, Engine.Player.GetLayer( Layer.Backpack ) );
}
}
[HotkeyCommand( Category = "Consume", Name = "Smoke Bomb" )]
public class UseSmokeBomb : HotkeyCommand
{
public override void Execute()
{
ObjectCommands.UseType( 0x2808, 0, Engine.Player.GetLayer( Layer.Backpack ) );
}
}
[HotkeyCommand( Category = "Consume", Name = "Grapes of Wrath" )]
public class UseGrapesOfWrath : HotkeyCommand
{
public override void Execute()
{
ObjectCommands.UseType( 0x2fd7, 1154, Engine.Player.GetLayer( Layer.Backpack ) );
}
}
[HotkeyCommand( Category = "Consume", Name = "Fruit Bowl" )]
public class UseFruitBowl : HotkeyCommand
{
public override void Execute()
{
ObjectCommands.UseType( 0x2d4f, 0, Engine.Player.GetLayer( Layer.Backpack ) );
}
}
[HotkeyCommand( Category = "Consume", Name = "Enchanted Apple" )]
public class UseEnchantedApple : HotkeyCommand
{
public override void Execute()
{
ObjectCommands.UseType( 0x2fd8, 1160, Engine.Player.GetLayer( Layer.Backpack ) );
}
}
[HotkeyCommand( Category = "Consume", Name = "Trinsic Rose Petal" )]
public class UseTrinsicPetal : HotkeyCommand
{
public override void Execute()
{
ObjectCommands.UseType( 0x1021, 14, Engine.Player.GetLayer( Layer.Backpack ) );
}
}
[HotkeyCommand( Category = "Consume", Name = "Orange Petal" )]
public class UseOrangePetal : HotkeyCommand
{
public override void Execute()
{
ObjectCommands.UseType( 0x1021, 43, Engine.Player.GetLayer( Layer.Backpack ) );
}
}
[HotkeyCommand( Category = "Consume", Name = "Bola" )]
public class UseBolaCommand : HotkeyCommand
{
public override void Execute()
{
ObjectCommands.UseType( 0x26ac, 0, Engine.Player.GetLayer( Layer.Backpack ) );
}
}
}
@@ -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
using ClassicAssist.Shared;
using ClassicAssist.UO.Network.Packets;
namespace ClassicAssist.Data.Hotkeys.Commands
{
[HotkeyCommand( Name = "Drop Holding Object" )]
public class DropHoldingObject : HotkeyCommand
{
public override void Execute()
{
if ( Engine.Player != null && Engine.Player.Holding != 0 )
{
Engine.SendPacketToServer( new DropItem( Engine.Player.Holding, Engine.Player.Backpack.Serial, -1, -1,
0 ) );
}
}
}
}
@@ -0,0 +1,13 @@
using ClassicAssist.Data.Macros.Commands;
namespace ClassicAssist.Data.Hotkeys.Commands
{
[HotkeyCommand( Name = "Equip Last Weapon (Quick Weapon Switch)", Tooltip = "Requires Server Support" )]
public class EquipLastWeapon : HotkeyCommand
{
public override void Execute()
{
ActionCommands.EquipLastWeapon();
}
}
}
@@ -0,0 +1,22 @@
using ClassicAssist.Data.Macros.Commands;
namespace ClassicAssist.Data.Hotkeys.Commands
{
[HotkeyCommand( Name = "Add Friend", Category = "Friends" )]
public class AddFriend : HotkeyCommand
{
public override void Execute()
{
MobileCommands.AddFriend();
}
}
[HotkeyCommand( Name = "Remove Friend", Category = "Friends" )]
public class RemoveFriend : HotkeyCommand
{
public override void Execute()
{
MobileCommands.RemoveFriend();
}
}
}
@@ -0,0 +1,68 @@
using System;
using System.Threading.Tasks;
using ClassicAssist.Shared.Resources;
namespace ClassicAssist.Data.Hotkeys.Commands
{
public class HotkeyCommand : HotkeyEntry, IComparable<HotkeyCommand>
{
private string _tooltip;
public HotkeyCommand()
{
HotkeyCommandAttribute a =
(HotkeyCommandAttribute) Attribute.GetCustomAttribute( GetType(), typeof( HotkeyCommandAttribute ) );
if ( a != null )
{
// if the attribute exists, the Name must be localizable.
string hotkeyName = Strings.ResourceManager.GetString(
a.Name ?? throw new ArgumentNullException( $"No localizable string for {a.Name}" ) );
string tooltipName = Strings.ResourceManager.GetString(
a.Tooltip ?? throw new ArgumentNullException( $"No localizable string for {a.Tooltip}" ) );
base.Name = string.IsNullOrEmpty( hotkeyName ) ? a.Name : hotkeyName;
Tooltip = string.IsNullOrEmpty( tooltipName ) ? a.Tooltip : tooltipName;
}
Action = hs => Task.Run( Execute );
}
public string Tooltip
{
get => _tooltip;
set => SetProperty( ref _tooltip, value );
}
public int CompareTo( HotkeyCommand other )
{
return string.Compare( Name, other.Name, StringComparison.Ordinal );
}
public virtual void Execute()
{
throw new NotImplementedException();
}
public override string ToString()
{
return Name;
}
public override bool Equals( object obj )
{
if ( !( obj is HotkeyCommand hkc ) )
{
return false;
}
return Name == hkc.Name;
}
public override int GetHashCode()
{
return Name.GetHashCode();
}
}
}
@@ -0,0 +1,11 @@
using System;
namespace ClassicAssist.Data.Hotkeys.Commands
{
public class HotkeyCommandAttribute : Attribute
{
public string Category { get; set; } = "";
public string Name { get; set; }
public string Tooltip { get; set; } = "";
}
}
@@ -0,0 +1,57 @@
using ClassicAssist.Shared;
using ClassicAssist.Misc;
using ClassicAssist.UO.Data;
using ClassicAssist.UO.Network;
using ClassicAssist.UO.Network.Packets;
using ClassicAssist.UO.Objects;
namespace ClassicAssist.Data.Hotkeys.Commands
{
[HotkeyCommand( Name = "Interrupt Spell" )]
public class InterruptSpellCommand : HotkeyCommand
{
public override void Execute()
{
PlayerMobile player = Engine.Player;
if ( player == null )
{
return;
}
Layer[] layerPriority =
{
Layer.Shirt, Layer.Shoes, Layer.Pants, Layer.Helm, Layer.Gloves, Layer.Ring, Layer.Neck,
Layer.Waist, Layer.InnerTorso, Layer.Bracelet, Layer.MiddleTorso, Layer.Earrings, Layer.Arms,
Layer.Cloak, Layer.OuterTorso, Layer.OuterLegs, Layer.InnerLegs, Layer.TwoHanded, Layer.OneHanded
};
Layer selectedLayer = Layer.Invalid;
int serial = 0;
foreach ( Layer layer in layerPriority )
{
serial = player.GetLayer( layer );
if ( serial == 0 )
{
continue;
}
selectedLayer = layer;
break;
}
if ( selectedLayer == Layer.Invalid )
{
return;
}
ActionPacketQueue.EnqueueActionPackets(
new BasePacket[]
{
new DragItem( serial, 1 ), new EquipRequest( serial, selectedLayer, player.Serial )
}, QueuePriority.High );
}
}
}
@@ -0,0 +1,31 @@
using ClassicAssist.Data.Macros.Commands;
namespace ClassicAssist.Data.Hotkeys.Commands
{
[HotkeyCommand( Category = "Movement", Name = "Toggle Force Walk" )]
public class ToggleForceWalk : HotkeyCommand
{
public override void Execute()
{
MovementCommands.ToggleForceWalk();
}
}
[HotkeyCommand( Category = "Movement", Name = "Force Walk On" )]
public class SetForceWalkOn : HotkeyCommand
{
public override void Execute()
{
MovementCommands.SetForceWalk( true );
}
}
[HotkeyCommand( Category = "Movement", Name = "Force Walk Off" )]
public class SetForceWalkOff : HotkeyCommand
{
public override void Execute()
{
MovementCommands.SetForceWalk( false );
}
}
}
@@ -0,0 +1,13 @@
using UOC = ClassicAssist.Shared.UO.Commands;
namespace ClassicAssist.Data.Hotkeys.Commands
{
[HotkeyCommand( Name = "Resync" )]
public class Resync : HotkeyCommand
{
public override void Execute()
{
UOC.Resync();
}
}
}
@@ -0,0 +1,15 @@
using ClassicAssist.Data.Macros;
namespace ClassicAssist.Data.Hotkeys.Commands
{
[HotkeyCommand( Name = "Stop All Macros",
Tooltip = "Stops all running macros including background and autostart macros." )]
public class StopAllMacros : HotkeyCommand
{
public override void Execute()
{
MacroManager manager = MacroManager.GetInstance();
manager.StopAll();
}
}
}
@@ -0,0 +1,14 @@
using ClassicAssist.Data.Macros;
namespace ClassicAssist.Data.Hotkeys.Commands
{
[HotkeyCommand( Name = "Stop Current Macro" )]
public class StopCurrentMacro : HotkeyCommand
{
public override void Execute()
{
MacroManager manager = MacroManager.GetInstance();
manager.Stop();
}
}
}
@@ -0,0 +1,102 @@
#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 ClassicAssist.Data.Targeting;
namespace ClassicAssist.Data.Hotkeys.Commands
{
public class TargetAcquisitionEnemy
{
[HotkeyCommand( Name = "Get Next Friend", Category = "Target Acquisition - Enemy" )]
public class GetNextFriend : HotkeyCommand
{
public override void Execute()
{
TargetManager.GetInstance().GetEnemy( TargetNotoriety.Friend, TargetBodyType.Any, TargetDistance.Next );
}
}
[HotkeyCommand( Name = "Get Next Innocent", Category = "Target Acquisition - Enemy" )]
public class GetNextInnocent : HotkeyCommand
{
public override void Execute()
{
TargetManager.GetInstance()
.GetEnemy( TargetNotoriety.Innocent, TargetBodyType.Any, TargetDistance.Closest );
}
}
[HotkeyCommand( Name = "Get Next Gray", Category = "Target Acquisition - Enemy" )]
public class GetNextGray : HotkeyCommand
{
public override void Execute()
{
TargetManager.GetInstance().GetEnemy( TargetNotoriety.Gray, TargetBodyType.Any, TargetDistance.Next );
}
}
[HotkeyCommand( Name = "Get Next Criminal", Category = "Target Acquisition - Enemy" )]
public class GetNextCriminal : HotkeyCommand
{
public override void Execute()
{
TargetManager.GetInstance()
.GetEnemy( TargetNotoriety.Criminal, TargetBodyType.Any, TargetDistance.Next );
}
}
[HotkeyCommand( Name = "Get Next Gray / Criminal", Category = "Target Acquisition - Enemy" )]
public class GetNextGrayCriminal : HotkeyCommand
{
public override void Execute()
{
TargetManager.GetInstance().GetEnemy( TargetNotoriety.Gray | TargetNotoriety.Criminal,
TargetBodyType.Any, TargetDistance.Next );
}
}
[HotkeyCommand( Name = "Get Next Enemy", Category = "Target Acquisition - Enemy" )]
public class GetNextEnemy : HotkeyCommand
{
public override void Execute()
{
TargetManager.GetInstance().GetEnemy( TargetNotoriety.Enemy, TargetBodyType.Any, TargetDistance.Next );
}
}
[HotkeyCommand( Name = "Get Next Murderer", Category = "Target Acquisition - Enemy" )]
public class GetNextMurderer : HotkeyCommand
{
public override void Execute()
{
TargetManager.GetInstance()
.GetEnemy( TargetNotoriety.Murderer, TargetBodyType.Any, TargetDistance.Next );
}
}
[HotkeyCommand( Name = "Get Next Any", Category = "Target Acquisition - Enemy" )]
public class GetNextAny : HotkeyCommand
{
public override void Execute()
{
TargetManager.GetInstance().GetEnemy( TargetNotoriety.Any, TargetBodyType.Any, TargetDistance.Next );
}
}
}
}
@@ -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 ClassicAssist.Data.Targeting;
namespace ClassicAssist.Data.Hotkeys.Commands
{
public class TargetAcquisitionFriend
{
[HotkeyCommand( Name = "Get Next Friend", Category = "Target Acquisition - Friend" )]
public class GetNextFriend : HotkeyCommand
{
public override void Execute()
{
TargetManager.GetInstance()
.GetFriend( TargetNotoriety.Friend, TargetBodyType.Any, TargetDistance.Next );
}
}
[HotkeyCommand( Name = "Get Next Innocent", Category = "Target Acquisition - Friend" )]
public class GetNextInnocent : HotkeyCommand
{
public override void Execute()
{
TargetManager.GetInstance()
.GetFriend( TargetNotoriety.Innocent, TargetBodyType.Any, TargetDistance.Closest );
}
}
[HotkeyCommand( Name = "Get Next Gray", Category = "Target Acquisition - Friend" )]
public class GetNextGray : HotkeyCommand
{
public override void Execute()
{
TargetManager.GetInstance().GetFriend( TargetNotoriety.Gray, TargetBodyType.Any, TargetDistance.Next );
}
}
[HotkeyCommand( Name = "Get Next Criminal", Category = "Target Acquisition - Friend" )]
public class GetNextCriminal : HotkeyCommand
{
public override void Execute()
{
TargetManager.GetInstance()
.GetFriend( TargetNotoriety.Criminal, TargetBodyType.Any, TargetDistance.Next );
}
}
[HotkeyCommand( Name = "Get Next Gray / Criminal", Category = "Target Acquisition - Friend" )]
public class GetNextGrayCriminal : HotkeyCommand
{
public override void Execute()
{
TargetManager.GetInstance().GetFriend( TargetNotoriety.Gray | TargetNotoriety.Criminal,
TargetBodyType.Any, TargetDistance.Next );
}
}
[HotkeyCommand( Name = "Get Next Enemy", Category = "Target Acquisition - Friend" )]
public class GetNextEnemy : HotkeyCommand
{
public override void Execute()
{
TargetManager.GetInstance().GetFriend( TargetNotoriety.Enemy, TargetBodyType.Any, TargetDistance.Next );
}
}
[HotkeyCommand( Name = "Get Next Murderer", Category = "Target Acquisition - Friend" )]
public class GetNextMurderer : HotkeyCommand
{
public override void Execute()
{
TargetManager.GetInstance()
.GetFriend( TargetNotoriety.Murderer, TargetBodyType.Any, TargetDistance.Next );
}
}
[HotkeyCommand( Name = "Get Next Any", Category = "Target Acquisition - Friend" )]
public class GetNextAny : HotkeyCommand
{
public override void Execute()
{
TargetManager.GetInstance().GetFriend( TargetNotoriety.Any, TargetBodyType.Any, TargetDistance.Next );
}
}
}
}
@@ -0,0 +1,202 @@
using ClassicAssist.Shared;
using ClassicAssist.Data.Macros.Commands;
using ClassicAssist.Data.Targeting;
using ClassicAssist.Shared.Resources;
using ClassicAssist.UO;
using ClassicAssist.UO.Data;
using ClassicAssist.UO.Network.Packets;
using ClassicAssist.UO.Objects;
using UOC = ClassicAssist.Shared.UO.Commands;
namespace ClassicAssist.Data.Hotkeys.Commands
{
public class Targeting
{
[HotkeyCommand( Name = "Set Enemy", Category = "Targeting" )]
public class SetEnemyCommand : HotkeyCommand
{
public override void Execute()
{
TargetManager manager = TargetManager.GetInstance();
Entity mobile = manager.PromptTarget();
if ( mobile == null )
{
return;
}
manager.SetEnemy( mobile );
Engine.SendPacketToServer( new LookRequest( mobile.Serial ) );
}
}
[HotkeyCommand( Name = "Set Friend", Category = "Targeting" )]
public class SetFriendCommand : HotkeyCommand
{
public override void Execute()
{
TargetManager manager = TargetManager.GetInstance();
Entity mobile = manager.PromptTarget();
if ( mobile == null )
{
return;
}
manager.SetFriend( mobile );
Engine.SendPacketToServer( new LookRequest( mobile.Serial ) );
}
}
[HotkeyCommand( Name = "Set Last Target", Category = "Targeting" )]
public class SetLastTargetCommand : HotkeyCommand
{
public override void Execute()
{
TargetManager manager = TargetManager.GetInstance();
Entity entity = manager.PromptTarget();
if ( entity == null )
{
return;
}
manager.SetLastTarget( entity );
if ( UOMath.IsMobile( entity.Serial ) )
{
Engine.SendPacketToServer( new LookRequest( entity.Serial ) );
}
}
}
[HotkeyCommand( Name = "Target Enemy", Category = "Targeting" )]
public class TargetEnemyCommand : HotkeyCommand
{
public override void Execute()
{
TargetCommands.Target( "enemy", Options.CurrentOptions.RangeCheckLastTarget,
Options.CurrentOptions.QueueLastTarget );
}
}
[HotkeyCommand( Name = "Target Last", Category = "Targeting" )]
public class TargetLastCommand : HotkeyCommand
{
public override void Execute()
{
if ( Options.CurrentOptions.SmartTargetOption == SmartTargetOption.None )
{
TargetCommands.Target( "last", Options.CurrentOptions.RangeCheckLastTarget,
Options.CurrentOptions.QueueLastTarget );
}
else
{
if ( Engine.TargetExists )
{
if ( Options.CurrentOptions.SmartTargetOption.HasFlag( SmartTargetOption.Friend ) &&
Engine.TargetFlags == TargetFlags.Beneficial && AliasCommands.FindAlias( "friend" ) )
{
TargetCommands.Target( "friend", Options.CurrentOptions.RangeCheckLastTarget,
Options.CurrentOptions.QueueLastTarget );
return;
}
if ( Options.CurrentOptions.SmartTargetOption.HasFlag( SmartTargetOption.Enemy ) &&
Engine.TargetFlags == TargetFlags.Harmful && AliasCommands.FindAlias( "enemy" ) )
{
TargetCommands.Target( "enemy", Options.CurrentOptions.RangeCheckLastTarget,
Options.CurrentOptions.QueueLastTarget );
return;
}
}
TargetCommands.Target( "last", Options.CurrentOptions.RangeCheckLastTarget,
Options.CurrentOptions.QueueLastTarget );
}
}
}
[HotkeyCommand( Name = "Target Friend", Category = "Targeting" )]
public class TargetFriendCommand : HotkeyCommand
{
public override void Execute()
{
TargetCommands.Target( "friend", Options.CurrentOptions.RangeCheckLastTarget,
Options.CurrentOptions.QueueLastTarget );
}
}
[HotkeyCommand( Name = "Target Self", Category = "Targeting" )]
public class TargetSelfCommand : HotkeyCommand
{
public override void Execute()
{
TargetCommands.Target( "self", Options.CurrentOptions.RangeCheckLastTarget,
Options.CurrentOptions.QueueLastTarget );
}
}
[HotkeyCommand( Name = "Clear Target Queue", Category = "Targeting" )]
public class ClearTargetQueueCommand : HotkeyCommand
{
public override void Execute()
{
TargetCommands.ClearTargetQueue();
}
}
[HotkeyCommand( Name = "Attack Last", Category = "Targeting" )]
public class AttackLastCommand : HotkeyCommand
{
public override void Execute()
{
ActionCommands.Attack( "last" );
}
}
[HotkeyCommand( Name = "Attack Enemy", Category = "Targeting" )]
public class AttackEnemyCommand : HotkeyCommand
{
public override void Execute()
{
ActionCommands.Attack( "enemy" );
}
}
[HotkeyCommand( Name = "Show Next Target In Queue", Category = "Targeting" )]
public class ShowNextTargetQueue : HotkeyCommand
{
public override void Execute()
{
if ( !Options.CurrentOptions.QueueLastTarget )
{
UOC.SystemMessage( Strings.Target_queue_is_not_enabled___ );
return;
}
object nextTarget = Engine.LastTargetQueue.Peek();
switch ( nextTarget )
{
case string targetAlias:
MsgCommands.HeadMsg( string.Format( Strings.Next_Target___0_, targetAlias ),
Engine.Player?.Serial );
break;
case int targetSerial:
{
Mobile entity = Engine.Mobiles.GetMobile( targetSerial );
MsgCommands.HeadMsg(
string.Format( Strings.Next_Target___0_,
$"0x{targetSerial:x} - {entity?.Name ?? "Unknown"}" ), Engine.Player?.Serial );
break;
}
}
}
}
}
}
@@ -0,0 +1,18 @@
using ClassicAssist.Data.Macros.Commands;
namespace ClassicAssist.Data.Hotkeys.Commands
{
[HotkeyCommand( Name = "Toggle hotkeys" )]
public sealed class ToggleHotkeys : HotkeyCommand
{
public ToggleHotkeys()
{
Disableable = false;
}
public override void Execute()
{
MainCommands.Hotkeys();
}
}
}
@@ -0,0 +1,32 @@
#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 ClassicAssist.Data.Macros.Commands;
namespace ClassicAssist.Data.Hotkeys.Commands
{
[HotkeyCommand( Name = "Toggle mounted" )]
public class ToggleMounted : HotkeyCommand
{
public override void Execute()
{
ActionCommands.ToggleMounted();
}
}
}
@@ -0,0 +1,50 @@
using ClassicAssist.Shared;
using ClassicAssist.Data.Macros.Commands;
using ClassicAssist.Shared.Resources;
using ClassicAssist.UO.Data;
using ClassicAssist.UO.Objects;
using UOC = ClassicAssist.Shared.UO.Commands;
namespace ClassicAssist.Data.Hotkeys.Commands
{
public static class UseHands
{
public static void UseHand( Layer layer )
{
PlayerMobile player = Engine.Player;
if ( player == null )
{
return;
}
int serial = player.GetLayer( layer );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_layer_value___ );
return;
}
ObjectCommands.UseObject( serial );
}
[HotkeyCommand( Name = "Use Left Hand" )]
public class UseLeftHand : HotkeyCommand
{
public override void Execute()
{
UseHand( Layer.OneHanded );
}
}
[HotkeyCommand( Name = "Use Right Hand" )]
public class UseRightHand : HotkeyCommand
{
public override void Execute()
{
UseHand( Layer.TwoHanded );
}
}
}
}
@@ -0,0 +1,19 @@
using ClassicAssist.Shared;
using ClassicAssist.Data.Macros.Commands;
namespace ClassicAssist.Data.Hotkeys.Commands
{
[HotkeyCommand( Name = "Use Last Object" )]
public class UseLastObject : HotkeyCommand
{
public override void Execute()
{
int serial = Engine.Player?.LastObjectSerial ?? 0;
if ( serial != 0 )
{
ObjectCommands.UseObject( serial );
}
}
}
}
@@ -0,0 +1,31 @@
using ClassicAssist.Data.Macros.Commands;
namespace ClassicAssist.Data.Hotkeys.Commands
{
[HotkeyCommand( Name = "WarMode On" )]
public class WarModeOnCommand : HotkeyCommand
{
public override void Execute()
{
MainCommands.WarMode( "on" );
}
}
[HotkeyCommand( Name = "WarMode Off" )]
public class WarModeOffCommand : HotkeyCommand
{
public override void Execute()
{
MainCommands.WarMode( "off" );
}
}
[HotkeyCommand( Name = "WarMode Toggle" )]
public class WarModeCommand : HotkeyCommand
{
public override void Execute()
{
MainCommands.WarMode();
}
}
}
@@ -0,0 +1,87 @@
using ClassicAssist.Shared;
using ClassicAssist.Data.Macros.Commands;
using ClassicAssist.UO.Network.Packets;
namespace ClassicAssist.Data.Hotkeys.Commands
{
[HotkeyCommand( Category = "Abilities", Name = "Set Primary Ability" )]
public class SetPrimaryAbility : HotkeyCommand
{
public override void Execute()
{
AbilitiesCommands.SetAbility( "primary", "on" );
}
}
[HotkeyCommand( Category = "Abilities", Name = "Unset Primary Ability" )]
public class UnsetPrimaryAbility : HotkeyCommand
{
public override void Execute()
{
AbilitiesCommands.SetAbility( "primary", "off" );
}
}
[HotkeyCommand( Category = "Abilities", Name = "Set Secondary Ability" )]
public class SetSecondaryAbility : HotkeyCommand
{
public override void Execute()
{
AbilitiesCommands.SetAbility( "secondary", "on" );
}
}
[HotkeyCommand( Category = "Abilities", Name = "Unset Secondary Ability" )]
public class UnsetSecondaryAbility : HotkeyCommand
{
public override void Execute()
{
AbilitiesCommands.SetAbility( "secondary", "off" );
}
}
[HotkeyCommand( Category = "Abilities", Name = "Toggle Primary Ability" )]
public class TogglePrimaryAbility : HotkeyCommand
{
public override void Execute()
{
AbilitiesCommands.SetAbility( "primary" );
}
}
[HotkeyCommand( Category = "Abilities", Name = "Toggle Secondary Ability" )]
public class ToggleSecondaryAbility : HotkeyCommand
{
public override void Execute()
{
AbilitiesCommands.SetAbility( "secondary" );
}
}
[HotkeyCommand( Category = "Abilities", Name = "Clear Weapon Ability" )]
public class ClearWeaponAbility : HotkeyCommand
{
public override void Execute()
{
AbilitiesCommands.ClearAbility();
}
}
[HotkeyCommand( Category = "Abilities", Name = "Stun" )]
public class StunAbility : HotkeyCommand
{
public override void Execute()
{
Engine.SendPacketToServer( new StunRequest() );
}
}
[HotkeyCommand( Category = "Abilities", Name = "Disarm" )]
public class DisarmAbility : HotkeyCommand
{
public override void Execute()
{
Engine.SendPacketToServer( new DisarmRequest() );
}
}
}
@@ -0,0 +1,14 @@
namespace ClassicAssist.Data.Hotkeys
{
public class HotkeyChangedEventArgs
{
public HotkeyChangedEventArgs( ShortcutKeys oldValue, ShortcutKeys newValue )
{
OldValue = oldValue;
NewValue = newValue;
}
public ShortcutKeys NewValue { get; set; }
public ShortcutKeys OldValue { get; set; }
}
}
@@ -0,0 +1,134 @@
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using ClassicAssist.Annotations;
using ClassicAssist.UI.Misc;
using Newtonsoft.Json;
namespace ClassicAssist.Data.Hotkeys
{
public abstract class HotkeyEntry : INotifyPropertyChanged, IComparable<HotkeyEntry>
{
public delegate void HotkeyChangedEventHandler( object sender, HotkeyChangedEventArgs e );
private readonly object _childrenLock = new object();
private ObservableCollectionEx<HotkeyEntry> _children = new ObservableCollectionEx<HotkeyEntry>();
private ShortcutKeys _hotkey = new ShortcutKeys();
private bool _isCategory;
private string _name;
private bool _passToUo = true;
[JsonIgnore]
public Action<HotkeyEntry> Action { get; set; }
[JsonIgnore]
public ObservableCollectionEx<HotkeyEntry> Children
{
get
{
lock ( _childrenLock )
{
return _children;
}
}
set
{
lock ( _childrenLock )
{
SetProperty( ref _children, value );
}
}
}
public virtual bool Disableable { get; set; } = true;
public ShortcutKeys Hotkey
{
get => _hotkey;
set
{
if ( !Equals( value, ShortcutKeys.Default ) )
{
HotkeyManager manager = HotkeyManager.GetInstance();
manager.ClearPreviousHotkey( value );
}
SetProperty( ref _hotkey, value );
OnPropertyChanged( nameof(Image) );
HotkeyChanged?.Invoke( this, new HotkeyChangedEventArgs( _hotkey, value ) );
}
}
[JsonIgnore]
public string Image => Equals( Hotkey, ShortcutKeys.Default ) ? "red-circle.png" : "green-circle.png";
public bool IsCategory
{
get => _isCategory;
set => SetProperty( ref _isCategory, value );
}
public virtual string Name
{
get => _name;
set => SetProperty( ref _name, value );
}
public bool PassToUO
{
get => _passToUo;
set => SetProperty( ref _passToUo, value );
}
public int CompareTo( HotkeyEntry other )
{
if ( ReferenceEquals( this, other ) )
{
return 0;
}
if ( ReferenceEquals( null, other ) )
{
return 1;
}
int isCategoryComparison = _isCategory.CompareTo( other._isCategory );
if ( isCategoryComparison != 0 )
{
return isCategoryComparison;
}
return string.Compare( _name, other._name, StringComparison.Ordinal );
}
public event HotkeyChangedEventHandler HotkeyChanged;
public override string ToString()
{
return Name;
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged( [CallerMemberName] string propertyName = null )
{
PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( propertyName ) );
}
// ReSharper disable once RedundantAssignment
public void SetProperty<T>( ref T field, T value, [CallerMemberName] string propertyName = null )
{
field = value;
OnPropertyChanged( propertyName );
}
#endregion
}
}
@@ -0,0 +1,303 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using ClassicAssist.Annotations;
using ClassicAssist.Data.Hotkeys.Commands;
using ClassicAssist.Data.Macros.Commands;
using ClassicAssist.Misc;
using ClassicAssist.UI.Misc;
using static ClassicAssist.Misc.SDLKeys;
namespace ClassicAssist.Data.Hotkeys
{
public class KeyState
{
[DllImport("SDL2.dll", EntryPoint = "SDL_GetKeyboardState", CallingConvention = CallingConvention.Cdecl)]
private static unsafe extern byte* GetKeyboardState(out int numKeys);
public static unsafe bool GetKeyState(SDL_Scancode scanCode)
{
var result = GetKeyboardState(out int numKeys);
int code = (int) scanCode;
return code < numKeys && result[(int)code] == 1;
}
}
public class HotkeyManager : INotifyPropertyChanged
{
private static HotkeyManager _instance;
private static readonly object _instanceLock = new object();
private readonly object _lock = new object();
private readonly Key[] _modifierKeys =
{
Key.LeftCtrl, Key.RightCtrl, Key.LeftShift, Key.RightShift, Key.LeftAlt, Key.RightAlt
};
private readonly List<Key> _modifiers = new List<Key>();
private bool _enabled = true;
private ObservableCollectionEx<HotkeyCommand> _items = new ObservableCollectionEx<HotkeyCommand>();
private HotkeyManager()
{
}
public Action ClearAllHotkeys { get; set; }
public bool Enabled
{
get => _enabled;
set => SetProperty( ref _enabled, value );
}
public ObservableCollectionEx<HotkeyCommand> Items
{
get => _items;
set => SetProperty( ref _items, value );
}
public event PropertyChangedEventHandler PropertyChanged;
public void AddCategory( HotkeyCommand item, IComparer<HotkeyEntry> comparer = null )
{
if ( Items.Contains( item ) )
{
Items.Remove( item );
}
if ( comparer == null )
{
comparer = Comparer<HotkeyEntry>.Default;
}
int i = 0;
while ( i < Items.Count && comparer.Compare( Items[i], item ) < 0 )
{
i++;
}
Items.Insert( i, item );
}
public void ClearPreviousHotkey( ShortcutKeys keys )
{
foreach ( HotkeyCommand hotkeyEntry in Items )
{
if ( hotkeyEntry.Children == null )
{
continue;
}
foreach ( HotkeyEntry hotkeyEntryChild in hotkeyEntry.Children )
{
if ( Equals( hotkeyEntryChild.Hotkey, keys ) )
{
hotkeyEntryChild.Hotkey = ShortcutKeys.Default;
}
}
}
}
public static HotkeyManager GetInstance()
{
// ReSharper disable once InvertIf
if ( _instance == null )
{
lock ( _instanceLock )
{
if ( _instance == null )
{
_instance = new HotkeyManager();
}
}
}
return _instance;
}
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged( [CallerMemberName] string propertyName = null )
{
PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( propertyName ) );
}
// ReSharper disable once RedundantAssignment
public void SetProperty<T>( ref T obj, T value, [CallerMemberName] string propertyName = "" )
{
obj = value;
OnPropertyChanged( propertyName );
}
public bool OnHotkeyPressed( Key keys )
{
lock ( _lock )
{
bool filter = false;
if ( _modifierKeys.Contains( keys ) )
{
_modifiers.Clear();
_modifiers.Add( keys );
return false;
}
Key modifier = Key.None;
if ( _modifiers.Count > 0 )
{
modifier = _modifiers[0];
}
bool down = KeyState.GetKeyState(KeysToSDLScancode(modifier));
if ( !down )
{
modifier = Key.None;
}
// Sanity check
if ( keys == Key.None )
{
return false;
}
foreach ( HotkeyCommand hke in Items )
{
if ( hke.Children == null )
{
continue;
}
try
{
IEnumerable<HotkeyEntry> hotkeyEntries = hke.Children.Where( t =>
t.Hotkey.Modifier == modifier && t.Hotkey.Key == keys &&
t.Hotkey.Mouse == MouseOptions.None );
foreach ( HotkeyEntry hks in hotkeyEntries )
{
if ( hks.Disableable && !Enabled )
{
continue;
}
filter = !hks.PassToUO;
AliasCommands.SetDefaultAliases();
Task.Run( () => hks.Action.Invoke( hks ) );
break;
}
}
catch ( InvalidOperationException )
{
// When spamming keys
}
}
return filter;
}
}
private SDL_Scancode KeysToSDLScancode(Key modifier )
{
//TODO Enter keys / find better way
switch ( modifier )
{
case Key.LeftAlt:
return SDL_Scancode.SDL_SCANCODE_LALT;
case Key.Right:
return SDL_Scancode.SDL_SCANCODE_RIGHT;
case Key.LeftCtrl:
return SDL_Scancode.SDL_SCANCODE_LCTRL;
case Key.RightCtrl:
return SDL_Scancode.SDL_SCANCODE_RCTRL;
case Key.LeftShift:
return SDL_Scancode.SDL_SCANCODE_LSHIFT;
case Key.RightShift:
return SDL_Scancode.SDL_SCANCODE_RSHIFT;
}
return 0;
}
public void OnMouseAction( MouseOptions mouse )
{
// Sanity check
if ( mouse == MouseOptions.None )
{
return;
}
lock ( _lock )
{
foreach ( HotkeyCommand hke in Items )
{
if ( hke.Children == null )
{
continue;
}
try
{
Key modifier = Key.None;
//Key modifier = _modifierKeys.FirstOrDefault( key =>
// Engine.Dispatcher.Invoke( () => Keyboard.IsKeyDown( key ) ) );
IEnumerable<HotkeyEntry> hotkeyEntries = hke.Children.Where( t =>
t.Hotkey.Modifier == modifier && t.Hotkey.Key == Key.None && t.Hotkey.Mouse == mouse );
foreach ( HotkeyEntry hks in hotkeyEntries )
{
if ( hks.Disableable && !Enabled )
{
continue;
}
AliasCommands.SetDefaultAliases();
Task.Run( () => hks.Action.Invoke( hks ) );
break;
}
}
catch ( InvalidOperationException )
{
// When spamming wheel
}
}
}
}
public void ClearItems()
{
foreach ( HotkeyEntry entry in Items )
{
ClearHotkeys( entry );
}
Items.Clear();
}
private void ClearHotkeys( HotkeyEntry entry )
{
entry.Hotkey = ShortcutKeys.Default;
if ( !entry.IsCategory )
{
return;
}
foreach ( HotkeyEntry hotkeyEntry in entry.Children )
{
ClearHotkeys( hotkeyEntry );
}
}
}
}
@@ -0,0 +1,97 @@
using System;
using ClassicAssist.Misc;
using Newtonsoft.Json.Linq;
namespace ClassicAssist.Data.Hotkeys
{
public enum MouseOptions
{
LeftButton,
MiddleButton,
RightButton,
XButton1,
XButton2,
MouseWheelDown,
MouseWheelUp,
None
}
public class ShortcutKeys
{
public ShortcutKeys()
{
}
public ShortcutKeys( Key modifier, Key key )
{
Modifier = modifier;
Key = key;
}
public ShortcutKeys( JToken token )
{
if ( token == null )
{
return;
}
Key = token["Keys"]?.ToObject<Key>() ?? Key.None;
Modifier = token["Modifier"]?.ToObject<Key>() ?? Key.None;
Mouse = token["Mouse"]?.ToObject<MouseOptions>() ?? MouseOptions.None;
}
public static ShortcutKeys Default => new ShortcutKeys( Key.None, Key.None ) { Mouse = MouseOptions.None };
public Key Key { get; set; } = Key.None;
public Key Modifier { get; set; } = Key.None;
public MouseOptions Mouse { get; set; } = MouseOptions.None;
public Keys[] ToArray()
{
//TODO
//Keys modifier = (Keys) KeyInterop.VirtualKeyFromKey( Modifier );
//Keys key = (Keys) KeyInterop.VirtualKeyFromKey( Key );
//if ( modifier == Keys.LControlKey || modifier == Keys.RControlKey )
//{
// modifier = Keys.ControlKey;
//}
//return modifier == Keys.None ? new[] { key } : new[] { modifier, key };
throw new NotImplementedException();
}
public override string ToString()
{
if ( Mouse != MouseOptions.None )
{
return Modifier != Key.None ? $"{Modifier} + {Mouse}" : Mouse.ToString();
}
return Modifier != Key.None ? $"{Modifier} + {Key}" : Key.ToString();
}
public override bool Equals( object obj )
{
return obj is ShortcutKeys keys && Key == keys.Key && Modifier == keys.Modifier && Mouse == keys.Mouse;
}
public override int GetHashCode()
{
int hashCode = 572187996;
hashCode = hashCode * -1521134295 + Key.GetHashCode();
hashCode = hashCode * -1521134295 + Modifier.GetHashCode();
hashCode = hashCode * -1521134295 + Mouse.GetHashCode();
return hashCode;
}
public JObject ToJObject()
{
JObject keys = new JObject
{
{ "Keys", (int) Key }, { "Modifier", (int) Modifier }, { "Mouse", (int) Mouse }
};
return keys;
}
}
}
+18
View File
@@ -0,0 +1,18 @@
using ClassicAssist.UO.Data;
namespace ClassicAssist.Data
{
public sealed class JournalEntry
{
public string[] Arguments { get; internal set; }
public int Cliloc { get; internal set; }
public int ID { get; internal set; }
public string Name { get; internal set; }
public int Serial { get; internal set; }
public int SpeechFont { get; internal set; }
public int SpeechHue { get; internal set; }
public string SpeechLanguage { get; internal set; }
public JournalSpeech SpeechType { get; internal set; }
public string Text { get; internal set; }
}
}
+12
View File
@@ -0,0 +1,12 @@
namespace ClassicAssist.Data
{
public enum Language
{
Default,
English,
Korean,
Chinese,
Italian,
Polish
}
}
@@ -0,0 +1,155 @@
using ClassicAssist.Shared;
using ClassicAssist.Data.Abilities;
using ClassicAssist.Shared.Resources;
using ClassicAssist.UO.Data;
using ClassicAssist.UO.Network.Packets;
using ClassicAssist.UO.Objects;
using UOC = ClassicAssist.Shared.UO.Commands;
namespace ClassicAssist.Data.Macros.Commands
{
public static class AbilitiesCommands
{
[CommandsDisplay( Category = nameof( Strings.Abilities ) )]
public static void ClearAbility()
{
AbilitiesManager manager = AbilitiesManager.GetInstance();
if ( manager.IsPrimaryEnabled )
{
manager.SetAbility( AbilityType.Primary );
}
else if ( manager.IsSecondaryEnabled )
{
manager.SetAbility( AbilityType.Secondary );
}
}
[CommandsDisplay( Category = nameof( Strings.Abilities ),
Parameters = new[] { nameof( ParameterType.Ability ), nameof( ParameterType.OnOff ) } )]
public static void SetAbility( string ability, string onOff = "toggle" )
{
AbilitiesManager manager = AbilitiesManager.GetInstance();
if ( ability.ToLower().Equals( "stun" ) )
{
Engine.SendPacketToServer( new StunRequest() );
return;
}
if ( ability.ToLower().Equals( "disarm" ) )
{
Engine.SendPacketToServer( new DisarmRequest() );
return;
}
bool primary;
switch ( ability.ToLower() )
{
case "primary":
primary = true;
break;
default:
primary = false;
break;
}
string onOffNormalized = onOff.Trim().ToLower();
if ( onOffNormalized != "toggle" )
{
switch ( onOffNormalized )
{
case "on":
{
if ( primary && manager.IsPrimaryEnabled || !primary && manager.IsSecondaryEnabled )
{
if ( !MacroManager.QuietMode )
{
UOC.SystemMessage( Strings.Ability_already_set___, 0x3F );
}
return;
}
break;
}
case "off":
{
if ( primary && !manager.IsPrimaryEnabled || !primary && !manager.IsSecondaryEnabled )
{
if ( !MacroManager.QuietMode )
{
UOC.SystemMessage( Strings.Ability_not_set___, 0x3F );
}
return;
}
break;
}
}
}
UOC.SystemMessage( string.Format( Strings.Setting_ability___0_____, ability ), 0x3F );
manager.SetAbility( primary ? AbilityType.Primary : AbilityType.Secondary );
}
[CommandsDisplay( Category = nameof( Strings.Abilities ) )]
public static void Fly()
{
PlayerMobile player = Engine.Player;
if ( player == null )
{
return;
}
if ( !player.Status.HasFlag( MobileStatus.Flying ) )
{
UOC.ToggleGargoyleFlying();
}
}
[CommandsDisplay( Category = nameof( Strings.Abilities ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static bool Flying( object obj )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return false;
}
Mobile mobile = Engine.Mobiles.GetMobile( serial );
if ( mobile == null )
{
// TODO better message
UOC.SystemMessage( Strings.Cannot_find_item___ );
return false;
}
return mobile.Status.HasFlag( MobileStatus.Flying );
}
[CommandsDisplay( Category = nameof( Strings.Abilities ) )]
public static void Land()
{
PlayerMobile player = Engine.Player;
if ( player == null )
{
return;
}
if ( player.Status.HasFlag( MobileStatus.Flying ) )
{
UOC.ToggleGargoyleFlying();
}
}
}
}
@@ -0,0 +1,553 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using ClassicAssist.Shared;
using ClassicAssist.Data.Regions;
using ClassicAssist.Misc;
using ClassicAssist.Shared.Resources;
using ClassicAssist.UO;
using ClassicAssist.UO.Data;
using ClassicAssist.UO.Network;
using ClassicAssist.UO.Network.PacketFilter;
using ClassicAssist.UO.Network.Packets;
using ClassicAssist.UO.Objects;
using UOC = ClassicAssist.Shared.UO.Commands;
namespace ClassicAssist.Data.Macros.Commands
{
public static class ActionCommands
{
public static UseOnceList UseOnceList { get; set; } = new UseOnceList();
[CommandsDisplay( Category = nameof( Strings.Actions ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ), nameof( ParameterType.Timeout ) } )]
public static bool WaitForContents( object obj, int timeout = 5000 )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return false;
}
return UOC.WaitForContainerContents( serial, timeout );
}
[CommandsDisplay( Category = nameof( Strings.Actions ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static int Contents( object obj )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return 0;
}
Item container = Engine.Items.GetItem( serial );
if ( container?.Container != null )
{
return container.Container.GetTotalItemCount();
}
UOC.SystemMessage( Strings.Invalid_container___ );
return 0;
}
[CommandsDisplay( Category = nameof( Strings.Actions ) )]
public static void EquipLastWeapon()
{
Engine.SendPacketToServer( new EquipLastWeapon() );
}
[CommandsDisplay( Category = nameof( Strings.Actions ),
Parameters = new[] { nameof( ParameterType.ItemID ), nameof( ParameterType.Hue ) } )]
public static bool UseOnce( int graphic, int hue = -1 )
{
//TODO hue?
if ( Engine.Player?.Backpack?.Container == null )
{
return false;
}
Item backpack = Engine.Player.Backpack;
Item match = backpack.Container.SelectEntity( i =>
i.ID == graphic && !UseOnceList.Contains( i.Serial ) && ( hue == -1 || hue == i.Hue ) );
if ( match == null )
{
UOC.SystemMessage( Strings.UseOnce__Cannot_find_type___ );
return false;
}
UseOnceList.Add( match );
ObjectCommands.UseObject( match.Serial );
return true;
}
[CommandsDisplay( Category = nameof( Strings.Actions ) )]
public static void ClearUseOnce()
{
UseOnceList?.Clear();
UOC.SystemMessage( Strings.UseOnce_cleared___ );
}
[CommandsDisplay( Category = nameof( Strings.Actions ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static void Attack( object obj )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return;
}
if ( Options.CurrentOptions.PreventAttackingInnocentsInGuardzone )
{
Mobile mobile = Engine.Mobiles.GetMobile( serial );
if ( mobile != null && mobile.Notoriety == Notoriety.Innocent &&
mobile.GetRegion().Attributes.HasFlag( RegionAttributes.Guarded ) )
{
UOC.SystemMessage( Strings.Attack_request_blocked___ );
return;
}
}
Engine.SendPacketToClient( new ChangeCombatant( serial ) );
Engine.SendPacketToServer( new AttackRequest( serial ) );
}
[CommandsDisplay( Category = nameof( Strings.Actions ),
Parameters = new[] { nameof( ParameterType.LeftRightBoth ) } )]
public static void ClearHands( string hand = "both" )
{
hand = hand.ToLower();
List<Layer> unequipLayers = new List<Layer>();
switch ( hand )
{
case "left":
unequipLayers.Add( Layer.OneHanded );
break;
case "right":
unequipLayers.Add( Layer.TwoHanded );
break;
case "both":
unequipLayers.Add( Layer.OneHanded );
unequipLayers.Add( Layer.TwoHanded );
break;
default:
throw new ArgumentOutOfRangeException( nameof( hand ) );
}
PlayerMobile player = Engine.Player;
List<int> serials = unequipLayers.Select( unequipLayer => Engine.Player.GetLayer( unequipLayer ) )
.Where( serial => serial != 0 ).ToList();
foreach ( int serial in serials )
{
ActionPacketQueue.EnqueueDragDrop( serial, 1, player.Backpack?.Serial ?? 0 );
}
}
[CommandsDisplay( Category = nameof( Strings.Actions ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static void ClickObject( object obj )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return;
}
Engine.SendPacketToServer( new LookRequest( serial ) );
}
[CommandsDisplay( Category = nameof( Strings.Actions ) )]
public static void ToggleMounted()
{
PlayerMobile player = Engine.Player;
if ( player == null )
{
return;
}
if ( player.IsMounted )
{
ObjectCommands.UseObject( player.Serial );
return;
}
if ( !AliasCommands.FindAlias( "mount" ) )
{
int serial = UOC.GetTargeSerialAsync( Strings.Target_new_mount___ ).Result;
if ( serial == -1 )
{
UOC.SystemMessage( Strings.Invalid_mount___ );
return;
}
AliasCommands.SetAlias( "mount", serial );
}
int mountSerial = AliasCommands.GetAlias( "mount" );
ObjectCommands.UseObject( mountSerial );
}
[CommandsDisplay( Category = nameof( Strings.Actions ),
Parameters = new[]
{
nameof( ParameterType.SerialOrAlias ), nameof( ParameterType.ItemID ),
nameof( ParameterType.Amount ), nameof( ParameterType.Hue )
} )]
public static void Feed( object obj, int graphic, int amount = 1, int hue = -1 )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return;
}
if ( Engine.Player?.Backpack == null )
{
UOC.SystemMessage( Strings.Error__Cannot_find_player_backpack );
return;
}
Item foodItem =
Engine.Player.Backpack?.Container.SelectEntity( i => i.ID == graphic && ( hue == -1 || i.Hue == hue ) );
if ( foodItem == null )
{
UOC.SystemMessage( Strings.Cannot_find_item___ );
return;
}
ActionPacketQueue.EnqueueDragDrop( foodItem.Serial, amount, serial );
}
[CommandsDisplay( Category = nameof( Strings.Actions ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ), nameof( ParameterType.Name ) } )]
public static void Rename( object obj, string name )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return;
}
UOC.RenameRequest( serial, name );
}
[CommandsDisplay( Category = nameof( Strings.Actions ),
Parameters = new[] { nameof( ParameterType.ShowType ) } )]
[CommandsDisplayStringSeeAlso( new[] { nameof( ShowNamesType ) } )]
public static void ShowNames( string showType )
{
const int MAX_DISTANCE = 32;
const int corpseType = 0x2006;
ShowNamesType enumValue = Utility.GetEnumValueByName<ShowNamesType>( showType );
switch ( enumValue )
{
case ShowNamesType.Mobiles:
Mobile[] mobiles = Engine.Mobiles.SelectEntities( m => m.Distance < MAX_DISTANCE );
if ( mobiles == null )
{
return;
}
foreach ( Mobile mobile in mobiles )
{
Engine.SendPacketToServer( new LookRequest( mobile.Serial ) );
}
break;
case ShowNamesType.Corpses:
Item[] corpses = Engine.Items.SelectEntities( i =>
UOMath.Distance( i.X, i.Y, Engine.Player.X, Engine.Player.Y ) < MAX_DISTANCE &&
i.ID == corpseType );
if ( corpses == null )
{
return;
}
foreach ( Item corpse in corpses )
{
Engine.SendPacketToServer( new LookRequest( corpse.Serial ) );
}
break;
}
}
[CommandsDisplay( Category = nameof( Strings.Actions ),
Parameters = new[] { nameof( ParameterType.ItemID ), nameof( ParameterType.Layer ) } )]
[CommandsDisplayStringSeeAlso( new[] { null, nameof( Layer ) } )]
public static void EquipType( int id, object layer )
{
Layer layerValue = Layer.Invalid;
switch ( layer )
{
case string s:
layerValue = Utility.GetEnumValueByName<Layer>( s );
break;
case int i:
layerValue = (Layer) i;
break;
case Layer l:
layerValue = l;
break;
}
if ( layerValue == Layer.Invalid )
{
UOC.SystemMessage( Strings.Invalid_layer_value___ );
return;
}
UOC.EquipType( id, layerValue );
}
[CommandsDisplay( Category = nameof( Strings.Actions ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ), nameof( ParameterType.Layer ) } )]
[CommandsDisplayStringSeeAlso( new[] { null, nameof( Layer ) } )]
public static void EquipItem( object obj, object layer )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return;
}
Layer layerValue = Layer.Invalid;
switch ( layer )
{
case string s:
layerValue = Utility.GetEnumValueByName<Layer>( s );
break;
case int i:
layerValue = (Layer) i;
break;
case Layer l:
layerValue = l;
break;
}
if ( layerValue == Layer.Invalid )
{
UOC.SystemMessage( Strings.Invalid_layer_value___ );
return;
}
Item item = Engine.Items.GetItem( serial );
if ( item == null )
{
UOC.SystemMessage( Strings.Cannot_find_item___ );
return;
}
UOC.EquipItem( item, layerValue );
}
[CommandsDisplay( Category = nameof( Strings.Actions ),
Parameters = new[] { nameof( ParameterType.Layer ), nameof( ParameterType.SerialOrAlias ) } )]
[CommandsDisplayStringSeeAlso( new[] { nameof( Layer ), null } )]
public static bool FindLayer( object layer, object obj = null )
{
if ( obj == null )
{
obj = "self";
}
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return false;
}
Layer layerValue = Layer.Invalid;
switch ( layer )
{
case string s:
layerValue = Utility.GetEnumValueByName<Layer>( s );
break;
case int i:
layerValue = (Layer) i;
break;
case Layer l:
layerValue = l;
break;
}
if ( layerValue == Layer.Invalid )
{
UOC.SystemMessage( Strings.Invalid_layer_value___ );
return false;
}
if ( !UOMath.IsMobile( serial ) )
{
UOC.SystemMessage( Strings.Cannot_find_item___ );
return false;
}
Mobile mobile = Engine.Mobiles.GetMobile( serial );
int layerSerial = mobile?.GetLayer( layerValue ) ?? 0;
if ( layerSerial == 0 )
{
AliasCommands.UnsetAlias( "found" );
return false;
}
AliasCommands.SetMacroAlias( "found", layerSerial );
if ( MacroManager.QuietMode )
{
return true;
}
UOC.SystemMessage( string.Format( Strings.Object___0___updated___, "found" ) );
return true;
}
[CommandsDisplay( Category = nameof( Strings.Actions ) )]
public static long Ping()
{
Random random = new Random();
byte value = (byte) random.Next( 1, byte.MaxValue );
Stopwatch sw = new Stopwatch();
sw.Start();
PacketWaitEntry we = Engine.PacketWaitEntries.Add(
new PacketFilterInfo( 0x73, new[] { new PacketFilterCondition( 1, new[] { value }, 1 ) } ),
PacketDirection.Incoming, true );
Engine.SendPacketToServer( new Ping( value ) );
bool result = we.Lock.WaitOne( 5000 );
sw.Stop();
if ( result )
{
return sw.ElapsedMilliseconds;
}
return -1;
}
[CommandsDisplay( Category = nameof( Strings.Actions ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ), nameof( ParameterType.ContextMenuIndex ) } )]
public static void ContextMenu( object obj, int entry )
{
if ( obj == null )
{
obj = "self";
}
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return;
}
Engine.SendPacketToServer( new ContextMenuRequest( serial ) );
Thread.Sleep( 400 );
Engine.SendPacketToServer( new ContextMenuClick( serial, entry ) );
}
[CommandsDisplay( Category = nameof( Strings.Actions ),
Parameters = new[]
{
nameof( ParameterType.SerialOrAlias ), nameof( ParameterType.ContextMenuIndex ),
nameof( ParameterType.Timeout )
} )]
public static bool WaitForContext( object obj, int entry, int timeout )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return false;
}
AutoResetEvent are = new AutoResetEvent( false );
PacketFilterInfo pfi = new PacketFilterInfo( 0xBF,
new[]
{
PacketFilterConditions.ShortAtPositionCondition( 0x14, 3 ),
PacketFilterConditions.IntAtPositionCondition( serial, 7 )
}, ( bytes, info ) =>
{
Engine.SendPacketToServer( new ContextMenuClick( serial, entry ) );
are.Set();
} );
Engine.AddReceiveFilter( pfi );
Engine.SendPacketToServer( new ContextMenuRequest( serial ) );
try
{
bool result = are.WaitOne( timeout );
return result;
}
finally
{
Engine.RemoveReceiveFilter( pfi );
}
}
private enum ShowNamesType
{
Mobiles,
Corpses
}
}
}
@@ -0,0 +1,104 @@
using System.Linq;
using ClassicAssist.Data.Autoloot;
using ClassicAssist.Data.Counters;
using ClassicAssist.Data.Dress;
using ClassicAssist.Shared.Resources;
using UOC = ClassicAssist.Shared.UO.Commands;
namespace ClassicAssist.Data.Macros.Commands
{
public static class AgentCommands
{
[CommandsDisplay( Category = nameof( Strings.Agents ),
Parameters = new[] { nameof( ParameterType.AgentEntryName ) } )]
public static void Dress( string name = null )
{
DressManager manager = DressManager.GetInstance();
DressAgentEntry dressAgentEntry;
if ( string.IsNullOrEmpty( name ) )
{
if ( manager.TemporaryDress == null )
{
UOC.SystemMessage( Strings.No_temporary_dress_layout_configured___ );
return;
}
dressAgentEntry = manager.TemporaryDress;
}
else
{
dressAgentEntry = manager.Items.FirstOrDefault( dae => dae.Name == name );
}
if ( dressAgentEntry == null )
{
UOC.SystemMessage( string.Format( Strings.Unknown_dress_agent___0___, name ) );
return;
}
dressAgentEntry.Action( dressAgentEntry );
}
[CommandsDisplay( Category = nameof( Strings.Agents ),
Parameters = new[] { nameof( ParameterType.AgentEntryName ) } )]
public static void Undress( string name )
{
DressManager manager = DressManager.GetInstance();
DressAgentEntry dressAgentEntry = manager.Items.FirstOrDefault( dae => dae.Name == name );
if ( dressAgentEntry == null )
{
UOC.SystemMessage( string.Format( Strings.Unknown_dress_agent___0___, name ) );
return;
}
dressAgentEntry.Undress().Wait();
}
[CommandsDisplay( Category = nameof( Strings.Agents ) )]
public static bool Dressing()
{
DressManager manager = DressManager.GetInstance();
return manager.IsDressing;
}
[CommandsDisplay( Category = nameof( Strings.Agents ) )]
public static void DressConfig()
{
DressManager manager = DressManager.GetInstance();
manager.TemporaryDress = new DressAgentEntry();
manager.TemporaryDress.Action = async hks => await manager.DressAllItems( manager.TemporaryDress, false );
manager.ImportItems( manager.TemporaryDress );
}
[CommandsDisplay( Category = nameof( Strings.Agents ),
Parameters = new[] { nameof( ParameterType.AgentEntryName ) } )]
public static int Counter( string name )
{
CountersManager manager = CountersManager.GetInstance();
CountersAgentEntry entry = manager.Items.FirstOrDefault( cae => cae.Name.ToLower() == name.ToLower() );
if ( entry != null )
{
return entry.Count;
}
UOC.SystemMessage( Strings.Invalid_counter_agent_name___ );
return 0;
}
[CommandsDisplay( Category = nameof( Strings.Agents ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static void SetAutolootContainer( object obj )
{
int serial = AliasCommands.ResolveSerial( obj );
AutolootHelpers.SetAutolootContainer?.Invoke( serial );
}
}
}
@@ -0,0 +1,190 @@
using System.Collections.Generic;
using ClassicAssist.Shared;
using ClassicAssist.Shared.Resources;
using ClassicAssist.UO;
using ClassicAssist.UO.Data;
using ClassicAssist.UO.Objects;
using UOC = ClassicAssist.Shared.UO.Commands;
namespace ClassicAssist.Data.Macros.Commands
{
public static class AliasCommands
{
public static Dictionary<string, int> _aliases = new Dictionary<string, int>();
internal static void SetDefaultAliases()
{
PlayerMobile player = Engine.Player;
if ( player == null )
{
return;
}
SetAlias( "bank", player.GetLayer( Layer.Bank ) );
SetAlias( "backpack", player.GetLayer( Layer.Backpack ) );
SetAlias( "self", player.Serial );
}
internal static int ResolveSerial( object obj )
{
int serial;
switch ( obj )
{
case string str:
serial = GetAlias( str );
if ( serial == -1 && !MacroManager.QuietMode )
{
UOC.SystemMessage( string.Format( Strings.Unknown_alias___0___, str ) );
}
break;
case int i:
serial = i;
break;
case uint i:
serial = (int) i;
break;
case Entity i:
serial = i.Serial;
break;
case null:
serial = Engine.Player == null ? 0 : Engine.Player.Serial;
break;
default:
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return -1;
}
return serial;
}
[CommandsDisplay( Category = nameof( Strings.Aliases ),
Parameters = new[] { nameof( ParameterType.AliasName ), nameof( ParameterType.SerialOrAlias ) } )]
public static void SetAlias( string aliasName, object obj )
{
aliasName = aliasName.ToLower();
int value = ResolveSerial( obj );
if ( _aliases.ContainsKey( aliasName ) )
{
_aliases[aliasName] = value;
}
else
{
_aliases.Add( aliasName, value );
}
}
[CommandsDisplay( Category = nameof( Strings.Aliases ),
Parameters = new[] { nameof( ParameterType.AliasName ), nameof( ParameterType.SerialOrAlias ) } )]
public static void SetMacroAlias( string aliasName, object obj )
{
aliasName = aliasName.ToLower();
int value = ResolveSerial( obj );
MacroEntry macro = MacroManager.GetInstance().GetCurrentMacro();
if ( macro == null )
{
SetAlias( aliasName, obj );
return;
}
if ( macro.Aliases.ContainsKey( aliasName ) )
{
macro.Aliases[aliasName] = value;
}
else
{
macro.Aliases.Add( aliasName, value );
}
}
[CommandsDisplay( Category = nameof( Strings.Aliases ),
Parameters = new[] { nameof( ParameterType.AliasName ) } )]
public static void UnsetAlias( string aliasName )
{
aliasName = aliasName.ToLower();
MacroEntry macro = MacroManager.GetInstance().GetCurrentMacro();
if ( macro != null )
{
if ( macro.Aliases.ContainsKey( aliasName ) )
{
macro.Aliases.Remove( aliasName );
}
}
if ( _aliases.ContainsKey( aliasName ) )
{
_aliases.Remove( aliasName );
}
}
[CommandsDisplay( Category = nameof( Strings.Aliases ),
Parameters = new[] { nameof( ParameterType.AliasName ) } )]
public static int GetAlias( string aliasName )
{
aliasName = aliasName.ToLower();
MacroEntry macro = MacroManager.GetInstance().GetCurrentMacro();
if ( macro != null )
{
if ( macro.Aliases.ContainsKey( aliasName ) )
{
return macro.Aliases[aliasName];
}
}
if ( _aliases.ContainsKey( aliasName ) )
{
return _aliases[aliasName];
}
return -1;
}
public static Dictionary<string, int> GetAllAliases()
{
return _aliases;
}
[CommandsDisplay( Category = nameof( Strings.Aliases ),
Parameters = new[] { nameof( ParameterType.AliasName ) } )]
public static int PromptAlias( string aliasName )
{
int serial = UOC.GetTargeSerialAsync( string.Format( Strings.Target_object___0_____, aliasName ) ).Result;
SetAlias( aliasName, serial );
return serial;
}
[CommandsDisplay( Category = nameof( Strings.Aliases ),
Parameters = new[] { nameof( ParameterType.AliasName ) } )]
public static bool FindAlias( string aliasName )
{
aliasName = aliasName.ToLower();
int serial;
if ( ( serial = GetAlias( aliasName ) ) == -1 )
{
return false;
}
if ( UOMath.IsMobile( serial ) )
{
return Engine.Mobiles.GetMobile( serial ) != null;
}
return Engine.Items.GetItem( serial ) != null;
}
}
}
@@ -0,0 +1,64 @@
using System.Linq;
using ClassicAssist.Shared;
using ClassicAssist.Shared.Resources;
using ClassicAssist.UO.Network.PacketFilter;
using ClassicAssist.UO.Network.Packets;
using ClassicAssist.UO.Objects;
using static ClassicAssist.Shared.UO.Commands;
namespace ClassicAssist.Data.Macros.Commands
{
public static class ConsumeCommands
{
private const int TIMEOUT = 5000;
private static readonly int[] _bandageTypes = { 0xe21 };
[CommandsDisplay( Category = nameof( Strings.Actions ) )]
public static bool BandageSelf()
{
PlayerMobile player = Engine.Player;
if ( player == null )
{
SystemMessage( Strings.Error__No_Player );
return false;
}
Item backpack = player.Backpack;
if ( backpack == null )
{
SystemMessage( Strings.Error__Cannot_find_player_backpack );
return false;
}
Item bandage = backpack.Container?.SelectEntity( i => _bandageTypes.Contains( i.ID ) );
if ( bandage == null )
{
SystemMessage( Strings.Error__Cannot_find_type );
return false;
}
ObjectCommands.UseObject( bandage.Serial );
PacketWaitEntry we = Engine.PacketWaitEntries.Add( new PacketFilterInfo( 0x6C ), PacketDirection.Incoming );
bool result = we.Lock.WaitOne( TIMEOUT );
if ( !result )
{
SystemMessage( Strings.Target_timeout___ );
return false;
}
byte[] packet = we.Packet;
int senderSerial = ( packet[2] << 24 ) | ( packet[3] << 16 ) | ( packet[4] << 8 ) | packet[5];
Engine.SendPacketToServer( new Target( senderSerial, player, true ) );
return true;
}
}
}
@@ -0,0 +1,10 @@
namespace ClassicAssist.Data.Macros.Commands
{
public static class DummyCommands
{
public static int Dummy( int a, int b )
{
return a + b;
}
}
}
@@ -0,0 +1,297 @@
using System.Reflection;
using ClassicAssist.Shared;
using ClassicAssist.Data.BuffIcons;
using ClassicAssist.Data.SpecialMoves;
using ClassicAssist.Shared.Resources;
using ClassicAssist.UO;
using ClassicAssist.UO.Data;
using ClassicAssist.UO.Objects;
using UOC = ClassicAssist.Shared.UO.Commands;
namespace ClassicAssist.Data.Macros.Commands
{
public static class EntityCommands
{
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static int Distance( object obj = null )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return 0;
}
Entity entity = Engine.Items.GetItem( serial ) ?? (Entity) Engine.Mobiles.GetMobile( serial );
return entity?.Distance ?? int.MaxValue;
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ), nameof( ParameterType.Distance ) } )]
public static bool InRange( object obj, int distance )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return false;
}
Entity entity = Engine.Items.GetItem( serial ) ?? (Entity) Engine.Mobiles.GetMobile( serial );
if ( entity != null )
{
return entity.Distance < distance;
}
return false;
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static int Hue( object obj = null )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return 0;
}
Entity entity = UOMath.IsMobile( serial )
? Engine.Mobiles.GetMobile( serial )
: Engine.Items.GetItem( serial ) as Entity;
if ( entity != null )
{
return entity.Hue;
}
if ( !MacroManager.QuietMode )
{
UOC.SystemMessage( Strings.Entity_not_found___ );
}
return 0;
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static int Graphic( object obj = null )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return 0;
}
Entity entity = UOMath.IsMobile( serial )
? Engine.Mobiles.GetMobile( serial )
: Engine.Items.GetItem( serial ) as Entity;
if ( entity != null )
{
return entity.ID;
}
if ( !MacroManager.QuietMode )
{
UOC.SystemMessage( Strings.Entity_not_found___ );
}
return 0;
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static int X( object obj = null )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return 0;
}
Entity entity = UOMath.IsMobile( serial )
? Engine.Mobiles.GetMobile( serial )
: Engine.Items.GetItem( serial ) as Entity;
if ( entity != null )
{
return entity.X;
}
if ( !MacroManager.QuietMode )
{
UOC.SystemMessage( Strings.Entity_not_found___ );
}
return 0;
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static int Y( object obj = null )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return 0;
}
Entity entity = UOMath.IsMobile( serial )
? Engine.Mobiles.GetMobile( serial )
: Engine.Items.GetItem( serial ) as Entity;
if ( entity != null )
{
return entity.Y;
}
if ( !MacroManager.QuietMode )
{
UOC.SystemMessage( Strings.Entity_not_found___ );
}
return 0;
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static int Z( object obj = null )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return 0;
}
Entity entity = UOMath.IsMobile( serial )
? Engine.Mobiles.GetMobile( serial )
: Engine.Items.GetItem( serial ) as Entity;
if ( entity != null )
{
return entity.Z;
}
if ( !MacroManager.QuietMode )
{
UOC.SystemMessage( Strings.Entity_not_found___ );
}
return 0;
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.BuffName ) } )]
public static bool BuffExists( string name )
{
return BuffIconManager.GetInstance().BuffExists( name );
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.BuffName ) } )]
public static double BuffTime( string name )
{
return BuffIconManager.GetInstance().BuffTime( name );
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SpecialMoveName ) } )]
public static bool SpecialMoveExists( string name )
{
return SpecialMovesManager.GetInstance().SpecialMoveExists( name );
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static string DirectionTo( object obj )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
return Direction.Invalid.ToString();
}
Entity entity = UOMath.IsMobile( serial )
? Engine.Mobiles.GetMobile( serial )
: Engine.Items.GetItem( serial ) as Entity;
if ( entity == null )
{
return Direction.Invalid.ToString();
}
return UOMath.MapDirection( Engine.Player.X, Engine.Player.Y, entity.X, entity.Y ).ToString();
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static string Name( object obj = null )
{
return GetEntityProperty<string>( obj, nameof( Entity.Name ) )?.Trim() ?? string.Empty;
}
private static T GetEntityProperty<T>( object obj, string propertyName )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial <= 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return default;
}
Entity entity = UOMath.IsMobile( serial )
? Engine.Mobiles.GetMobile( serial )
: (Entity) Engine.Items.GetItem( serial );
if ( entity == null )
{
UOC.SystemMessage( Strings.Entity_not_found___ );
return default;
}
PropertyInfo property = entity.GetType().GetProperty( propertyName );
if ( property == null )
{
return default;
}
T val = (T) property.GetValue( entity );
return val;
}
[CommandsDisplay( Category = nameof( Strings.Main ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static void HideEntity( object obj )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Cannot_find_item___ );
return;
}
UOC.RemoveObject( serial );
}
}
}
@@ -0,0 +1,122 @@
using System.Linq;
using ClassicAssist.Shared;
using ClassicAssist.Shared.Resources;
using ClassicAssist.UO.Network.Packets;
using ClassicAssist.UO.Objects.Gumps;
using UOC = ClassicAssist.Shared.UO.Commands;
namespace ClassicAssist.Data.Macros.Commands
{
public static class GumpCommands
{
[CommandsDisplay( Category = nameof( Strings.Gumps ),
Parameters = new[] { nameof( ParameterType.ItemID ), nameof( ParameterType.Timeout ) } )]
public static bool WaitForGump( uint gumpId = 0, int timeout = 30000 )
{
bool result = UOC.WaitForGump( gumpId, timeout );
if ( !result )
{
UOC.SystemMessage( Strings.Timeout___ );
}
return result;
}
[CommandsDisplay( Category = nameof( Strings.Gumps ),
Parameters = new[]
{
nameof( ParameterType.ItemID ), nameof( ParameterType.GumpButtonIndex ),
nameof( ParameterType.IntegerValue )
} )]
public static void ReplyGump( uint gumpId, int buttonId, int[] switches = null )
{
UOC.GumpButtonClick( gumpId, buttonId, switches );
}
[CommandsDisplay( Category = nameof( Strings.Gumps ) )]
public static bool GumpExists( uint gumpId )
{
return Engine.GumpList.ContainsKey( gumpId );
}
[CommandsDisplay( Category = nameof( Strings.Gumps ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ), nameof( ParameterType.String ) } )]
public static bool InGump( uint gumpId, string text )
{
if ( Engine.Gumps.GetGump( gumpId, out Gump gump ) )
{
return gump.GumpElements.Any( ge => ge.Text != null && ge.Text.ToLower().Contains( text.ToLower() ) );
}
UOC.SystemMessage( Strings.Invalid_gump___ );
return false;
}
[CommandsDisplay( Category = nameof( Strings.Gumps ), Parameters = new[] { nameof( ParameterType.Serial ) } )]
public static void CloseGump( int serial )
{
if ( Engine.Gumps.FindGump( serial, out Gump gump ) )
{
gump.CloseGump();
}
}
[CommandsDisplay( Category = nameof( Strings.Gumps ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static void OpenVirtueGump( object obj = null )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Mobile_not_found___ );
return;
}
Engine.SendPacketToServer( new GumpButtonClick( 0x1CD, Engine.Player.Serial, 1, new[] { serial } ) );
}
[CommandsDisplay( Category = nameof( Strings.Gumps ) )]
public static void OpenGuildGump()
{
Engine.SendPacketToServer( new GuildButtonRequest() );
}
[CommandsDisplay( Category = nameof( Strings.Gumps ) )]
public static void OpenQuestsGump()
{
Engine.SendPacketToServer( new QuestsButtonRequest() );
}
//[CommandsDisplay( Category = nameof( Strings.Gumps ) )]
//public static bool ConfirmPrompt( string message, bool closable = false )
//{
// return ConfirmPromptGump.ConfirmPrompt( message, closable );
//}
//public static int SendCustomGump( Gump gump )
//{
// PacketFilterInfo pfi = new PacketFilterInfo( 0xB1,
// new[] { PacketFilterConditions.IntAtPositionCondition( (int) gump.ID, 7 ) } );
// Engine.AddSendFilter( pfi );
// gump.SendGump();
// PacketWaitEntry we = Engine.PacketWaitEntries.Add( pfi, PacketDirection.Outgoing, true, true );
// we.Lock.WaitOne();
// if ( we.Packet == null )
// {
// return -1;
// }
// PacketReader reader = new PacketReader( we.Packet, we.Packet.Length, false );
// reader.ReadInt32();
// reader.ReadInt32();
// int buttonId = reader.ReadInt32();
// return buttonId;
//}
}
}
@@ -0,0 +1,85 @@
using System;
using System.Linq;
using System.Threading;
using ClassicAssist.Shared;
using ClassicAssist.Shared.Resources;
using ClassicAssist.UO.Data;
using ClassicAssist.UO.Network;
namespace ClassicAssist.Data.Macros.Commands
{
public static class JournalCommands
{
[CommandsDisplay( Category = nameof( Strings.Journal ) )]
public static bool InJournal( string text, string author = "", int hue = -1 )
{
bool match;
if ( author.ToLower().Equals( "system" ) )
{
match = Engine.Journal.GetBuffer().Any( je =>
je.Text.ToLower().Contains( text.ToLower() ) &&
( je.SpeechType == JournalSpeech.System || je.Name == "System" ) &&
( hue == -1 || je.SpeechHue == hue ) );
}
else
{
match = Engine.Journal.GetBuffer().Any( je =>
je.Text.ToLower().Contains( text.ToLower() ) &&
( string.IsNullOrEmpty( author ) || string.Equals( je.Name, author,
StringComparison.CurrentCultureIgnoreCase ) ) && ( hue == -1 || je.SpeechHue == hue ) );
}
return match;
}
[CommandsDisplay( Category = nameof( Strings.Journal ) )]
public static void ClearJournal()
{
Engine.Journal.Clear();
}
[CommandsDisplay( Category = nameof( Strings.Journal ) )]
public static bool WaitForJournal( string text, int timeout, string author = "" )
{
AutoResetEvent are = new AutoResetEvent( false );
void OnIncomingPacketHandlersOnJournalEntryAddedEvent( JournalEntry je )
{
bool match;
if ( author.ToLower().Equals( "system" ) )
{
match = je.Text.ToLower().Contains( text.ToLower() ) &&
( je.SpeechType == JournalSpeech.System || je.Name == "System" );
}
else
{
match = je.Text.ToLower().Contains( text.ToLower() ) &&
( string.IsNullOrEmpty( author ) || string.Equals( je.Name, author,
StringComparison.CurrentCultureIgnoreCase ) );
}
if ( match )
{
are.Set();
}
}
IncomingPacketHandlers.JournalEntryAddedEvent += OnIncomingPacketHandlersOnJournalEntryAddedEvent;
bool result;
try
{
result = are.WaitOne( timeout );
}
finally
{
IncomingPacketHandlers.JournalEntryAddedEvent -= OnIncomingPacketHandlersOnJournalEntryAddedEvent;
}
return result;
}
}
}
@@ -0,0 +1,83 @@
using System.Collections.Generic;
using System.Linq;
using ClassicAssist.Shared.Resources;
namespace ClassicAssist.Data.Macros.Commands
{
public static class ListCommands
{
private static readonly Dictionary<string, List<int>> _lists = new Dictionary<string, List<int>>();
[CommandsDisplay( Category = nameof( Strings.Lists ), Parameters = new[] { nameof( ParameterType.ListName ) } )]
public static void CreateList( string listName )
{
if ( ListExists( listName ) )
{
RemoveList( listName );
}
_lists.Add( listName, new List<int>() );
}
[CommandsDisplay( Category = nameof( Strings.Lists ), Parameters = new[] { nameof( ParameterType.ListName ) } )]
public static bool ListExists( string listName )
{
return _lists.ContainsKey( listName );
}
[CommandsDisplay( Category = nameof( Strings.Lists ), Parameters = new[] { nameof( ParameterType.ListName ) } )]
public static int List( string listName )
{
return ListExists( listName ) ? _lists[listName].Count : 0;
}
[CommandsDisplay( Category = nameof( Strings.Lists ),
Parameters = new[] { nameof( ParameterType.ListName ), nameof( ParameterType.IntegerValue ) } )]
public static void PushList( string listName, int value )
{
if ( !ListExists( listName ) )
{
CreateList( listName );
}
_lists[listName].Add( value );
}
[CommandsDisplay( Category = nameof( Strings.Lists ), Parameters = new[] { nameof( ParameterType.ListName ) } )]
public static int[] GetList( string listName )
{
return _lists[listName].ToArray();
}
[CommandsDisplay( Category = nameof( Strings.Lists ), Parameters = new[] { nameof( ParameterType.ListName ) } )]
public static void RemoveList( string listName )
{
_lists.Remove( listName );
}
public static Dictionary<string, List<int>> GetAllLists()
{
return _lists;
}
[CommandsDisplay( Category = nameof( Strings.Lists ), Parameters = new[] { nameof( ParameterType.ListName ) } )]
public static void ClearList( string listName )
{
if ( !_lists.ContainsKey( listName ) )
{
return;
}
_lists[listName].Clear();
}
[CommandsDisplay( Category = nameof( Strings.Lists ),
Parameters = new[] { nameof( ParameterType.ListName ), nameof( ParameterType.IntegerValue ) } )]
public static bool InList( string listName, int value )
{
int[] list;
return ( list = GetList( listName ) ) != null && list.Contains( value );
}
}
}
@@ -0,0 +1,56 @@
using System.Linq;
using System.Threading.Tasks;
using ClassicAssist.Shared.Resources;
using UOC = ClassicAssist.Shared.UO.Commands;
namespace ClassicAssist.Data.Macros.Commands
{
public static class MacroCommands
{
[CommandsDisplay( Category = nameof( Strings.Macros ),
Parameters = new[] { nameof( ParameterType.MacroName ) } )]
public static void PlayMacro( string name )
{
MacroManager manager = MacroManager.GetInstance();
MacroEntry macro = manager.Items.FirstOrDefault( m => m.Name == name );
if ( macro == null )
{
UOC.SystemMessage( Strings.Unknown_macro___ );
return;
}
Task.Run( () => macro.Action( macro ) );
}
[CommandsDisplay( Category = nameof( Strings.Macros ), Parameters = new[] { nameof( ParameterType.String ) } )]
public static void Stop( string name = null )
{
MacroManager.GetInstance().Stop( name );
}
[CommandsDisplay( Category = nameof( Strings.Macros ) )]
public static void StopAll()
{
MacroManager.GetInstance().StopAll();
}
[CommandsDisplay( Category = nameof( Strings.Macros ) )]
public static void Replay()
{
MacroManager manager = MacroManager.GetInstance();
MacroEntry current = manager?.GetCurrentMacro();
if ( current?.Action == null )
{
return;
}
manager.Replay = true;
Task.Run( () => current.Action( current ) );
}
}
}
@@ -0,0 +1,191 @@
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows;
using ClassicAssist.Shared;
using ClassicAssist.Data.Hotkeys;
using ClassicAssist.Misc;
using ClassicAssist.Shared.Resources;
using ClassicAssist.UO;
using ClassicAssist.UO.Data;
using ClassicAssist.UO.Network.Packets;
using ClassicAssist.UO.Objects;
using UOC = ClassicAssist.Shared.UO.Commands;
namespace ClassicAssist.Data.Macros.Commands
{
public static class MainCommands
{
[CommandsDisplay( Category = nameof( Strings.Main ), Parameters = new[] { nameof( ParameterType.OnOff ) } )]
public static void SetQuietMode( bool onOff )
{
MacroManager.QuietMode = onOff;
}
[CommandsDisplay( Category = nameof( Strings.Main ), Parameters = new[] { nameof( ParameterType.String ) } )]
[CommandsDisplayStringSeeAlso( new[] { nameof( Virtues ) } )]
public static void InvokeVirtue( string virtue )
{
Virtues v = Utility.GetEnumValueByName<Virtues>( virtue );
if ( v == Virtues.None )
{
return;
}
Engine.SendPacketToServer( new InvokeVirtue( v ) );
}
[CommandsDisplay( Category = nameof( Strings.Main ) )]
public static void Resync()
{
UOC.Resync();
}
[CommandsDisplay( Category = nameof( Strings.Main ), Parameters = new[] { nameof( ParameterType.Timeout ) } )]
public static void Pause( int milliseconds )
{
Thread.Sleep( milliseconds );
}
[CommandsDisplay( Category = nameof( Strings.Main ),
Parameters = new[] { nameof( ParameterType.String ), nameof( ParameterType.Hue ) } )]
public static void SysMessage( string text, int hue = 0x03b2 )
{
UOC.SystemMessage( text, hue );
}
[CommandsDisplay( Category = nameof( Strings.Main ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static void Info( object obj = null )
{
int serial = 0;
if ( obj == null )
{
serial = UOC.GetTargeSerialAsync( Strings.Target_object___ ).Result;
if ( serial == 0 )
{
return;
}
}
serial = AliasCommands.ResolveSerial( serial != 0 ? serial : obj );
if ( serial == 0 )
{
return;
}
Entity entity = UOMath.IsMobile( serial )
? Engine.Mobiles.GetMobile( serial )
: (Entity) Engine.Items.GetItem( serial );
if ( entity == null )
{
UOC.SystemMessage( Strings.Cannot_find_item___ );
return;
}
Thread t = new Thread( () =>
{
//TODO Window
//ObjectInspectorWindow window =
// new ObjectInspectorWindow { DataContext = new ObjectInspectorViewModel( entity ) };
//window.ShowDialog();
} )
{ IsBackground = true };
t.SetApartmentState( ApartmentState.STA );
t.Start();
}
[CommandsDisplay( Category = nameof( Strings.Main ) )]
public static void Hotkeys()
{
HotkeyManager manager = HotkeyManager.GetInstance();
manager.Enabled = !manager.Enabled;
UOC.SystemMessage( manager.Enabled ? Strings.Hotkeys_enabled___ : Strings.Hotkeys_disabled___,
manager.Enabled ? 0x3F : 36 );
}
[CommandsDisplay( Category = nameof( Strings.Main ), Parameters = new[] { nameof( ParameterType.OnOff ) } )]
public static void WarMode( string onOff = "toggle" )
{
if ( Engine.Player == null )
{
return;
}
string onOffNormalized = onOff.Trim().ToLower();
if ( onOffNormalized != "toggle" )
{
switch ( onOffNormalized )
{
case "on" when Engine.Player.Status.HasFlag( MobileStatus.WarMode ):
case "off" when !Engine.Player.Status.HasFlag( MobileStatus.WarMode ):
return;
}
}
Engine.SendPacketToServer( Engine.Player.Status.HasFlag( MobileStatus.WarMode )
? new WarMode( false )
: new WarMode( true ) );
}
//[CommandsDisplay( Category = nameof( Strings.Main ),
// Parameters = new[] { nameof( ParameterType.String ), nameof( ParameterType.String ) } )]
//public static void MessageBox( string title, string body )
//{
// System.Windows.MessageBox.Show( body, title, MessageBoxButton.OK, MessageBoxImage.Information );
//}
//[CommandsDisplay( Category = nameof( Strings.Main ) )]
//public static void PlaySound( object param )
//{
// switch ( param )
// {
// case int id:
// Engine.SendPacketToClient( new PlaySound( id ) );
// break;
// case string soundFile:
// {
// string fullPath = Path.Combine( Engine.StartupPath, "Sounds", soundFile );
// if ( !File.Exists( fullPath ) )
// {
// UOC.SystemMessage( Strings.Cannot_find_sound_file___ );
// return;
// }
// SoundPlayer soundPlayer = new SoundPlayer( fullPath );
// soundPlayer.PlaySync();
// break;
// }
// }
//}
[CommandsDisplay( Category = nameof( Strings.Main ) )]
public static bool Playing()
{
MacroManager manager = MacroManager.GetInstance();
return manager.CurrentMacro != null && ( manager.CurrentMacro.IsRunning || manager.Replay );
}
[CommandsDisplay( Category = nameof( Strings.Main ), Parameters = new[] { nameof( ParameterType.MacroName ) } )]
public static bool Playing( string macroName )
{
MacroManager manager = MacroManager.GetInstance();
MacroEntry macro = manager.Items.FirstOrDefault( m => m.Name.Equals( macroName ) );
return macro != null && ( macro.IsRunning || manager.Replay );
}
}
}
@@ -0,0 +1,93 @@
#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.Linq;
using ClassicAssist.Shared;
using ClassicAssist.Shared.Resources;
using ClassicAssist.UO.Network.Packets;
using ClassicAssist.UO.Objects;
using UOC = ClassicAssist.Shared.UO.Commands;
namespace ClassicAssist.Data.Macros.Commands
{
public static class MenuCommands
{
[CommandsDisplay( Category = nameof( Strings.Menus ),
Parameters = new[] { nameof( ParameterType.ItemID ), nameof( ParameterType.Timeout ) } )]
public static bool WaitForMenu( int gumpId = 0, int timeout = 30000 )
{
bool result = UOC.WaitForMenu( gumpId, timeout );
if ( !result )
{
UOC.SystemMessage( Strings.Timeout___ );
}
return result;
}
[CommandsDisplay( Category = nameof( Strings.Menus ),
Parameters = new[]
{
nameof( ParameterType.ItemID ), nameof( ParameterType.GumpButtonIndex ),
nameof( ParameterType.ItemID ), nameof( ParameterType.Hue )
} )]
public static void ReplyMenu( int gumpId, int buttonId, int itemId = 0, int hue = 0 )
{
Engine.SendPacketToServer( new MenuButtonClick( gumpId, -1, buttonId, itemId, hue ) );
Engine.SendPacketToClient( new CloseClientGump( (uint) gumpId ) );
}
[CommandsDisplay( Category = nameof( Strings.Menu ), Parameters = new[] { nameof( ParameterType.ItemID ) } )]
public static void CloseMenu( int gumpId )
{
if ( Engine.Menus.GetMenu( gumpId, out Menu menu ) )
{
Engine.SendPacketToServer( new MenuButtonClick( gumpId, menu.Serial, 0 ) );
}
Engine.SendPacketToClient( new CloseClientGump( (uint) gumpId ) );
}
[CommandsDisplay( Category = nameof( Strings.Menus ),
Parameters = new[] { nameof( ParameterType.ItemID ), nameof( ParameterType.String ) } )]
public static bool InMenu( int gumpId, string text )
{
text = text.ToLower();
if ( !Engine.Menus.GetMenu( gumpId, out Menu menu ) )
{
return false;
}
if ( menu.Title.ToLower().Contains( text ) )
{
return true;
}
return menu.Entries.Any( l => l.Title.ToLower().Contains( text ) );
}
[CommandsDisplay( Category = nameof( Strings.Menus ) )]
public static bool MenuExists( int gumpId )
{
return Engine.Menus.GetMenu( gumpId, out _ );
}
}
}
@@ -0,0 +1,390 @@
using System.Linq;
using System.Reflection;
using ClassicAssist.Shared;
using ClassicAssist.Data.Friends;
using ClassicAssist.Shared.Resources;
using ClassicAssist.UO.Data;
using ClassicAssist.UO.Objects;
using UOC = ClassicAssist.Shared.UO.Commands;
namespace ClassicAssist.Data.Macros.Commands
{
public static class MobileCommands
{
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static bool InFriendList( object obj )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial != 0 )
{
bool result = Options.CurrentOptions.Friends.Any( fe => fe.Serial == serial );
if ( result )
{
return true;
}
if ( Options.CurrentOptions.IncludePartyMembersInFriends )
{
result = Engine.Player?.Party?.Contains( serial ) ?? false;
}
return result;
}
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return false;
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static int AddFriend( object obj = null )
{
int serial = obj != null
? AliasCommands.ResolveSerial( obj )
: UOC.GetTargeSerialAsync( Strings.Target_new_friend___ ).Result;
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return 0;
}
Mobile m = Engine.Mobiles.GetMobile( serial );
if ( m == null )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return 0;
}
FriendEntry fe = new FriendEntry { Name = m.Name?.Trim(), Serial = m.Serial };
if ( !Options.CurrentOptions.Friends.Contains( fe ) )
{
Engine.Dispatcher?.Invoke( () =>
{
Options.CurrentOptions.Friends.Add( fe );
if ( Options.CurrentOptions.RehueFriends )
{
MainCommands.Resync();
}
} );
}
return m.Serial;
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static void RemoveFriend( object obj = null )
{
int serial = obj != null
? AliasCommands.ResolveSerial( obj )
: UOC.GetTargeSerialAsync( Strings.Target_friend_to_remove___ ).Result;
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return;
}
FriendEntry entry = Options.CurrentOptions.Friends.FirstOrDefault( i => i.Serial == serial );
if ( entry == null )
{
return;
}
Engine.Dispatcher?.Invoke( () =>
{
bool result = Options.CurrentOptions.Friends.Remove( entry );
if ( !Options.CurrentOptions.RehueFriends )
{
return;
}
Engine.RehueList.Remove( serial );
MainCommands.Resync();
return;
} );
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static bool Dead( object obj = null )
{
return GetMobileProperty<bool>( obj, nameof( Mobile.IsDead ) );
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static bool Hidden( object obj = null )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial <= 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return false;
}
Mobile mobile = Engine.Mobiles.GetMobile( serial );
if ( mobile != null )
{
return mobile.Status.HasFlag( MobileStatus.Hidden );
}
UOC.SystemMessage( Strings.Mobile_not_found___ );
return false;
}
private static T GetMobileProperty<T>( object obj, string propertyName )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial <= 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return default;
}
Mobile mobile = Engine.Mobiles.GetMobile( serial );
if ( mobile == null )
{
UOC.SystemMessage( Strings.Mobile_not_found___ );
return default;
}
PropertyInfo property = mobile.GetType().GetProperty( propertyName );
if ( property == null )
{
return default;
}
T val = (T) property.GetValue( mobile );
return val;
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static int MaxMana( object obj = null )
{
return GetMobileProperty<int>( obj, nameof( Mobile.ManaMax ) );
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static int MaxStam( object obj = null )
{
return GetMobileProperty<int>( obj, nameof( Mobile.StaminaMax ) );
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static int Hits( object obj = null )
{
return GetMobileProperty<int>( obj, nameof( Mobile.Hits ) );
}
[CommandsDisplay( Category = nameof( Strings.Entity ) )]
public static int Str()
{
return GetMobileProperty<int>( "self", nameof( PlayerMobile.Strength ) );
}
[CommandsDisplay( Category = nameof( Strings.Entity ) )]
public static int Dex()
{
return GetMobileProperty<int>( "self", nameof( PlayerMobile.Dex ) );
}
[CommandsDisplay( Category = nameof( Strings.Entity ) )]
public static int Int()
{
return GetMobileProperty<int>( "self", nameof( PlayerMobile.Int ) );
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static int MaxHits( object obj = null )
{
return GetMobileProperty<int>( obj, nameof( Mobile.HitsMax ) );
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static int DiffHits( object obj = null )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial <= 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return 0;
}
Mobile mobile = Engine.Mobiles.GetMobile( serial );
if ( mobile != null )
{
return mobile.HitsMax - mobile.Hits;
}
UOC.SystemMessage( Strings.Mobile_not_found___ );
return 0;
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static int Stam( object obj = null )
{
return GetMobileProperty<int>( obj, nameof( Mobile.Stamina ) );
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static int Mana( object obj = null )
{
return GetMobileProperty<int>( obj, nameof( Mobile.Mana ) );
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static bool War( object obj )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial != 0 )
{
return Engine.Mobiles.GetMobile( serial )?.Status.HasFlag( MobileStatus.WarMode ) ?? false;
}
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return false;
}
[CommandsDisplay( Category = nameof( Strings.Entity ) )]
public static int Followers()
{
return Engine.Player?.Followers ?? 0;
}
[CommandsDisplay( Category = nameof( Strings.Entity ) )]
public static int MaxFollowers()
{
return Engine.Player?.FollowersMax ?? 0;
}
[CommandsDisplay( Category = nameof( Strings.Entity ) )]
public static int Weight()
{
return Engine.Player?.Weight ?? 0;
}
[CommandsDisplay( Category = nameof( Strings.Entity ) )]
public static int MaxWeight()
{
return Engine.Player?.WeightMax ?? 0;
}
[CommandsDisplay( Category = nameof( Strings.Entity ) )]
public static int DiffWeight()
{
PlayerMobile player = Engine.Player;
if ( player == null )
{
return 0;
}
return player.WeightMax - player.Weight;
}
[CommandsDisplay( Category = nameof( Strings.Entity ) )]
public static int Gold()
{
return Engine.Player?.Gold ?? 0;
}
[CommandsDisplay( Category = nameof( Strings.Entity ) )]
public static int Luck()
{
return Engine.Player?.Luck ?? 0;
}
[CommandsDisplay( Category = nameof( Strings.Entity ) )]
public static int TithingPoints()
{
return Engine.Player?.TithingPoints ?? 0;
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static bool Poisoned( object obj )
{
return GetMobileProperty<bool>( obj, nameof( Mobile.IsPoisoned ) );
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static bool YellowHits( object obj )
{
return GetMobileProperty<bool>( obj, nameof( Mobile.IsYellowHits ) );
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static bool Paralyzed( object obj )
{
return GetMobileProperty<bool>( obj, nameof( Mobile.IsFrozen ) );
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static bool Mounted( object obj )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return false;
}
Mobile mobile = Engine.Mobiles.GetMobile( serial );
if ( mobile != null )
{
return mobile.IsMounted;
}
UOC.SystemMessage( Strings.Mobile_not_found___ );
return false;
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static bool InParty( object obj )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial != 0 )
{
return Engine.Player?.Party != null && Engine.Player.Party.Contains( serial );
}
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return false;
}
}
}
@@ -0,0 +1,136 @@
using System;
using ClassicAssist.Misc;
using ClassicAssist.Shared.Resources;
using ClassicAssist.Shared;
using ClassicAssist.UO;
using ClassicAssist.UO.Data;
using ClassicAssist.UO.Network.PacketFilter;
using ClassicAssist.UO.Network.Packets;
using ClassicAssist.UO.Objects;
using UOC = ClassicAssist.Shared.UO.Commands;
namespace ClassicAssist.Data.Macros.Commands
{
public static class MovementCommands
{
private const int MOVEMENT_TIMEOUT = 500;
private const int PATHFIND_MAX_DISTANCE = 32;
private static bool _forceWalk;
[CommandsDisplay( Category = nameof( Strings.Movement ),
Parameters = new[] { nameof( ParameterType.Direction ) } )]
public static bool Walk( string direction )
{
return Move( direction, false );
}
[CommandsDisplay( Category = nameof( Strings.Movement ) )]
public static void SetForceWalk( bool force )
{
UOC.SetForceWalk( force );
UOC.SystemMessage( force ? Strings.Force_Walk_On : Strings.Force_Walk_Off );
}
[CommandsDisplay( Category = nameof( Strings.Movement ) )]
public static void ToggleForceWalk()
{
_forceWalk = !_forceWalk;
UOC.SetForceWalk( _forceWalk );
UOC.SystemMessage( _forceWalk ? Strings.Force_Walk_On : Strings.Force_Walk_Off );
}
[CommandsDisplay( Category = nameof( Strings.Movement ),
Parameters = new[] { nameof( ParameterType.Direction ) } )]
[CommandsDisplayStringSeeAlso( new[] { nameof( Direction ) } )]
public static void Turn( string direction )
{
Direction directionEnum = Utility.GetEnumValueByName<Direction>( direction );
if ( Engine.Player.Direction == directionEnum )
{
return;
}
Engine.Move( directionEnum, false );
UOC.WaitForIncomingPacket( new PacketFilterInfo( 22 ), MOVEMENT_TIMEOUT );
}
[CommandsDisplay( Category = nameof( Strings.Movement ),
Parameters = new[] { nameof( ParameterType.Direction ) } )]
[CommandsDisplayStringSeeAlso( new[] { nameof( Direction ) } )]
public static bool Run( string direction )
{
return Move( direction, true );
}
private static bool Move( string direction, bool run )
{
Direction directionEnum = Utility.GetEnumValueByName<Direction>( direction );
if ( directionEnum == Direction.Invalid )
{
return false;
}
try
{
bool result = Engine.Move( directionEnum, run );
UOC.WaitForIncomingPacket( new PacketFilterInfo( 22 ), MOVEMENT_TIMEOUT );
return result;
}
catch ( IndexOutOfRangeException )
{
}
return false;
}
[CommandsDisplay( Category = nameof( Strings.Movement ),
Parameters = new[]
{
nameof( ParameterType.XCoordinate ), nameof( ParameterType.YCoordinate ),
nameof( ParameterType.ZCoordinate )
} )]
public static void Pathfind( int x, int y, int z )
{
int distance = Math.Max( Math.Abs( x - Engine.Player?.X ?? x ), Math.Abs( y - Engine.Player?.Y ?? y ) );
if ( distance > PATHFIND_MAX_DISTANCE )
{
UOC.SystemMessage( Strings.Maximum_distance_exceeded_ );
return;
}
Engine.SendPacketToClient( new Pathfind( x, y, z ) );
}
[CommandsDisplay( Category = nameof( Strings.Movement ),
Parameters = new[]
{
nameof( ParameterType.SerialOrAlias )
} )]
public static void Pathfind( object obj )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Entity_not_found___ );
return;
}
Entity entity = UOMath.IsMobile( serial )
? (Entity) Engine.Mobiles.GetMobile( serial )
: Engine.Items.GetItem( serial );
if ( entity == null )
{
UOC.SystemMessage( Strings.Entity_not_found___ );
return;
}
Pathfind( entity.X, entity.Y, entity.Z );
}
}
}
@@ -0,0 +1,116 @@
using ClassicAssist.Shared;
using ClassicAssist.Shared.Resources;
using ClassicAssist.UO.Data;
using ClassicAssist.UO.Network.PacketFilter;
using ClassicAssist.UO.Network.Packets;
using UOC = ClassicAssist.Shared.UO.Commands;
namespace ClassicAssist.Data.Macros.Commands
{
public static class MsgCommands
{
private const int DEFAULT_SPEAK_HUE = 34;
[CommandsDisplay( Category = nameof( Strings.Messages ),
Parameters = new[] { nameof( ParameterType.String ), nameof( ParameterType.Hue ) } )]
public static void Msg( string message, int hue = DEFAULT_SPEAK_HUE )
{
UOC.Speak( message, hue );
}
[CommandsDisplay( Category = nameof( Strings.Messages ),
Parameters = new[] { nameof( ParameterType.String ) } )]
public static void YellMsg( string message )
{
UOC.Speak( message, DEFAULT_SPEAK_HUE, JournalSpeech.Yell );
}
[CommandsDisplay( Category = nameof( Strings.Messages ),
Parameters = new[] { nameof( ParameterType.String ) } )]
public static void WhisperMsg( string message )
{
UOC.Speak( message, DEFAULT_SPEAK_HUE, JournalSpeech.Whisper );
}
[CommandsDisplay( Category = nameof( Strings.Messages ),
Parameters = new[] { nameof( ParameterType.String ) } )]
public static void EmoteMsg( string message )
{
UOC.Speak( message, DEFAULT_SPEAK_HUE, JournalSpeech.Emote );
}
[CommandsDisplay( Category = nameof( Strings.Messages ),
Parameters = new[] { nameof( ParameterType.String ) } )]
public static void GuildMsg( string message )
{
UOC.Speak( message, DEFAULT_SPEAK_HUE, JournalSpeech.Guild );
}
[CommandsDisplay( Category = nameof( Strings.Messages ),
Parameters = new[] { nameof( ParameterType.String ) } )]
public static void AllyMsg( string message )
{
UOC.Speak( message, DEFAULT_SPEAK_HUE, JournalSpeech.Alliance );
}
[CommandsDisplay( Category = nameof( Strings.Messages ),
Parameters = new[] { nameof( ParameterType.String ) } )]
public static void PartyMsg( string message )
{
UOC.PartyMessage( message );
}
[CommandsDisplay( Category = nameof( Strings.Messages ),
Parameters = new[]
{
nameof( ParameterType.String ), nameof( ParameterType.SerialOrAlias ), nameof( ParameterType.Hue )
} )]
public static void HeadMsg( string message, object obj = null, int hue = DEFAULT_SPEAK_HUE )
{
int serial = AliasCommands.ResolveSerial( obj );
UOC.OverheadMessage( message, hue, serial );
}
[CommandsDisplay( Category = nameof( Strings.Messages ),
Parameters = new[] { nameof( ParameterType.String ) } )]
public static void PromptMsg( string message )
{
Engine.SendPacketToServer( new UnicodePromptResponse( Engine.LastPromptSerial, Engine.LastPromptID,
message ) );
}
[CommandsDisplay( Category = nameof( Strings.Messages ),
Parameters = new[] { nameof( ParameterType.Timeout ) } )]
public static bool WaitForPrompt( int timeout )
{
PacketFilterInfo pfi = new PacketFilterInfo( 0xC2 );
PacketWaitEntry packetWaitEntry = Engine.PacketWaitEntries.Add( pfi, PacketDirection.Incoming, true );
try
{
bool result = packetWaitEntry.Lock.WaitOne( timeout );
return result;
}
finally
{
Engine.PacketWaitEntries.Remove( packetWaitEntry );
}
}
[CommandsDisplay( Category = nameof( Strings.Messages ) )]
public static void CancelPrompt()
{
Engine.SendPacketToServer( new UnicodePromptCancel( Engine.LastPromptSerial, Engine.LastPromptID ) );
}
[CommandsDisplay( Category = nameof( Strings.Messages ),
Parameters = new[] { nameof( ParameterType.String ) } )]
public static void ChatMsg( string message )
{
UOC.ChatMsg( message );
}
}
}
@@ -0,0 +1,81 @@
using ClassicAssist.Shared;
using ClassicAssist.Shared.Resources;
using ClassicAssist.UO.Data;
using ClassicAssist.UO.Objects;
using UOC = ClassicAssist.Shared.UO.Commands;
namespace ClassicAssist.Data.Macros.Commands
{
public static class NotorietyCommands
{
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static bool Criminal( object obj )
{
return CheckNotoriety( obj, Notoriety.Criminal );
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static bool Gray( object obj )
{
return CheckNotoriety( obj, Notoriety.Attackable );
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static bool Ally( object obj )
{
return CheckNotoriety( obj, Notoriety.Ally );
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static bool Enemy( object obj )
{
return CheckNotoriety( obj, Notoriety.Enemy );
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static bool Invulnerable( object obj )
{
return CheckNotoriety( obj, Notoriety.Invulnerable );
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static bool Innocent( object obj )
{
return CheckNotoriety( obj, Notoriety.Innocent );
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static bool Murderer( object obj )
{
return CheckNotoriety( obj, Notoriety.Murderer );
}
private static bool CheckNotoriety( object obj, Notoriety notoriety )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return false;
}
Mobile m = Engine.Mobiles.GetMobile( serial );
if ( m == null )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return false;
}
return m.Notoriety == notoriety;
}
}
}
@@ -0,0 +1,602 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ClassicAssist.Shared;
using ClassicAssist.Data.Abilities;
using ClassicAssist.Misc;
using ClassicAssist.Shared.Resources;
using ClassicAssist.UO;
using ClassicAssist.UO.Data;
using ClassicAssist.UO.Network;
using ClassicAssist.UO.Network.Packets;
using ClassicAssist.UO.Objects;
using UOC = ClassicAssist.Shared.UO.Commands;
namespace ClassicAssist.Data.Macros.Commands
{
public static class ObjectCommands
{
public static List<int> IgnoreList { get; set; } = new List<int>();
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static void IgnoreObject( object obj )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return;
}
if ( !IgnoreList.Contains( serial ) )
{
IgnoreList.Add( serial );
}
}
[CommandsDisplay( Category = nameof( Strings.Entity ) )]
public static void ClearIgnoreList()
{
IgnoreList.Clear();
}
[CommandsDisplay( Category = nameof( Strings.Actions ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static void UseObject( object obj, bool skipQueue = false )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return;
}
ActionPacketQueue.EnqueueActionPacket( new UseObject( serial ),
skipQueue ? QueuePriority.Immediate : QueuePriority.Low );
}
[CommandsDisplay( Category = nameof( Strings.Actions ),
Parameters = new[]
{
nameof( ParameterType.SerialOrAlias ), nameof( ParameterType.Hue ),
nameof( ParameterType.SerialOrAlias )
} )]
public static void UseType( object type, int hue = -1, object container = null )
{
int serial = AliasCommands.ResolveSerial( type );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return;
}
if ( container == null )
{
container = Engine.Player?.Backpack?.Serial;
}
int containerSerial = AliasCommands.ResolveSerial( container );
if ( !Engine.Items.GetItem( containerSerial, out Item containerItem ) )
{
UOC.SystemMessage( Strings.Cannot_find_container___ );
return;
}
Item useItem = hue == -1
? containerItem.Container?.SelectEntity( i => i.ID == serial )
: containerItem.Container?.SelectEntity( i => i.ID == serial && i.Hue == hue );
if ( useItem == null )
{
UOC.SystemMessage( Strings.Cannot_find_item___ );
return;
}
if ( !AbilitiesManager.GetInstance().CheckHands( useItem.Serial ) )
{
Engine.SendPacketToServer( new UseObject( useItem.Serial ) );
}
}
[CommandsDisplay( Category = nameof( Strings.Actions ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ), nameof( ParameterType.SerialOrAlias ) } )]
public static void UseTargetedItem( object item, object target )
{
int serial = AliasCommands.ResolveSerial( item );
int targetSerial = AliasCommands.ResolveSerial( target );
if ( serial == 0 || targetSerial == 0 )
{
UOC.SystemMessage( Strings.Cannot_find_item___ );
return;
}
Engine.SendPacketToServer( new UseTargetedItem( serial, targetSerial ) );
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[]
{
nameof( ParameterType.ItemID ), nameof( ParameterType.SerialOrAlias ), nameof( ParameterType.Hue )
} )]
public static int CountType( int graphic, object source = null, int hue = -1 )
{
if ( source == null )
{
source = "backpack";
}
int sourceSerial = AliasCommands.ResolveSerial( source );
Item countainerItem = Engine.Items.GetItem( sourceSerial );
if ( countainerItem?.Container == null )
{
UOC.SystemMessage( Strings.Invalid_container___ );
return 0;
}
Item[] matches =
countainerItem.Container.SelectEntities( i => i.ID == graphic && ( hue == -1 || i.Hue == hue ) );
return matches?.Sum( i => i.Count ) ?? 0;
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[]
{
nameof( ParameterType.ItemID ), nameof( ParameterType.Hue ), nameof( ParameterType.Range )
} )]
public static int CountTypeGround( int graphic, int hue = -1, int range = -1 )
{
IEnumerable<Item> matches = Engine.Items.Where( i =>
i.ID == graphic && ( hue == -1 || hue == i.ID ) && ( range == -1 || i.Distance <= range ) );
int count = matches.Sum( match => match.Count );
if ( count > 0 )
{
return count;
}
IEnumerable<Mobile> mobileMatches = Engine.Mobiles.Where( i =>
i.ID == graphic && ( hue == -1 || hue == i.ID ) && ( range == -1 || i.Distance <= range ) );
count += mobileMatches.Count();
return count;
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[]
{
nameof( ParameterType.ItemID ), nameof( ParameterType.Range ),
nameof( ParameterType.SerialOrAlias ), nameof( ParameterType.Hue )
} )]
public static bool FindType( int graphic, int range = -1, object findLocation = null, int hue = -1 )
{
int owner = 0;
if ( findLocation != null )
{
owner = AliasCommands.ResolveSerial( findLocation );
}
Entity entity;
bool Predicate( Entity i )
{
return i.ID == graphic && ( hue == -1 || i.Hue == hue ) && !IgnoreList.Contains( i.Serial );
}
if ( owner != 0 )
{
entity = Engine.Items.SelectEntities( i => Predicate( i ) && i.IsDescendantOf( owner, range ) )
?.FirstOrDefault();
}
else
{
entity =
(Entity) Engine.Mobiles
.SelectEntities( i => Predicate( i ) && ( range == -1 || i.Distance < range ) )
?.FirstOrDefault() ?? Engine.Items.SelectEntities( i =>
Predicate( i ) && ( range == -1 || i.Distance < range ) && i.Owner == 0 )?.FirstOrDefault();
}
if ( entity == null )
{
AliasCommands.UnsetAlias( "found" );
return false;
}
AliasCommands.SetMacroAlias( "found", entity.Serial );
if ( MacroManager.QuietMode )
{
return true;
}
UOC.SystemMessage( string.Format( Strings.Object___0___updated___, "found" ) );
return true;
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[]
{
nameof( ParameterType.SerialOrAlias ), nameof( ParameterType.Range ),
nameof( ParameterType.SerialOrAlias )
} )]
public static bool FindObject( object obj, int range = -1, object findLocation = null )
{
int owner = 0;
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return false;
}
if ( findLocation != null )
{
owner = AliasCommands.ResolveSerial( findLocation );
}
Entity entity;
bool Predicate( Entity i )
{
return i.Serial == serial;
}
if ( owner != 0 )
{
entity = Engine.Items.SelectEntities( i => Predicate( i ) && i.IsDescendantOf( owner, range ) )
?.FirstOrDefault();
}
else
{
entity =
(Entity) Engine.Mobiles
.SelectEntities( i => Predicate( i ) && ( range == -1 || i.Distance < range ) )
?.FirstOrDefault() ?? Engine.Items.SelectEntities( i =>
Predicate( i ) && ( range == -1 || i.Distance < range ) && i.Owner == 0 )?.FirstOrDefault();
}
if ( entity == null )
{
AliasCommands.UnsetAlias( "found" );
return false;
}
AliasCommands.SetMacroAlias( "found", entity.Serial );
if ( MacroManager.QuietMode )
{
return true;
}
UOC.SystemMessage( string.Format( Strings.Object___0___updated___, "found" ) );
return true;
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[]
{
nameof( ParameterType.SerialOrAlias ), nameof( ParameterType.SerialOrAlias ),
nameof( ParameterType.Amount ), nameof( ParameterType.XCoordinate ),
nameof( ParameterType.YCoordinate )
} )]
public static void MoveItem( object item, object destination, int amount = -1, int x = -1, int y = -1 )
{
int itemSerial = AliasCommands.ResolveSerial( item );
if ( itemSerial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return;
}
Item itemObj = Engine.Items.GetItem( itemSerial );
if ( itemObj == null )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return;
}
if ( amount == -1 )
{
amount = itemObj.Count;
}
int containerSerial = AliasCommands.ResolveSerial( destination );
if ( containerSerial == 0 )
{
//TODO
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return;
}
ActionPacketQueue.EnqueueDragDrop( itemSerial, amount, containerSerial, QueuePriority.Low, false, true,
false, x, y );
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[]
{
nameof( ParameterType.SerialOrAlias ), nameof( ParameterType.XCoordinateOffset ),
nameof( ParameterType.YCoordinateOffset ), nameof( ParameterType.ZCoordinateOffset ),
nameof( ParameterType.Amount )
} )]
public static void MoveItemOffset( object obj, int xOffset, int yOffset, int zOffset, int amount = -1 )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return;
}
PlayerMobile player = Engine.Player;
if ( player == null )
{
return;
}
int x = player.X + xOffset;
int y = player.Y + yOffset;
int z = player.Z + zOffset;
ActionPacketQueue.EnqueueDragDropGround( serial, amount, x, y, z );
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[]
{
nameof( ParameterType.ItemID ), nameof( ParameterType.SerialOrAlias ),
nameof( ParameterType.XCoordinateOffset ), nameof( ParameterType.YCoordinateOffset ),
nameof( ParameterType.ZCoordinateOffset ), nameof( ParameterType.Amount )
} )]
public static bool MoveTypeOffset( int id, object findLocation, int xOffset, int yOffset, int zOffset,
int amount = -1 )
{
if ( findLocation == null ||
( (string) findLocation ).Equals( "ground", StringComparison.InvariantCultureIgnoreCase ) )
{
UOC.SystemMessage( Strings.Invalid_container___ );
return false;
}
int owner = AliasCommands.ResolveSerial( findLocation );
bool Predicate( Item i )
{
return i.ID == id && i.IsDescendantOf( owner );
}
Item entity = Engine.Items.SelectEntities( Predicate )?.FirstOrDefault();
if ( entity == null )
{
return false;
}
PlayerMobile player = Engine.Player;
if ( player == null )
{
return false;
}
int x = player.X + xOffset;
int y = player.Y + yOffset;
int z = player.Z + zOffset;
ActionPacketQueue.EnqueueDragDropGround( entity.Serial, amount, x, y, z );
return true;
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[]
{
nameof( ParameterType.ItemID ), nameof( ParameterType.SerialOrAlias ),
nameof( ParameterType.SerialOrAlias ), nameof( ParameterType.XCoordinate ),
nameof( ParameterType.YCoordinate ), nameof( ParameterType.ZCoordinate ),
nameof( ParameterType.Hue ), nameof( ParameterType.Amount )
} )]
public static void MoveType( int id, object sourceContainer, object destinationContainer, int x = -1,
int y = -1, int z = 0, int hue = -1, int amount = -1 )
{
int sourceSerial = AliasCommands.ResolveSerial( sourceContainer );
if ( sourceSerial == -1 )
{
UOC.SystemMessage( Strings.Invalid_source_container___ );
return;
}
int destinationSerial;
if ( destinationContainer is int destSerial )
{
destinationSerial = destSerial;
}
else
{
destinationSerial = AliasCommands.ResolveSerial( destinationContainer );
}
Item sourceItem = Engine.Items.GetItem( sourceSerial );
if ( sourceItem == null )
{
UOC.SystemMessage( Strings.Cannot_find_item___ );
return;
}
if ( sourceItem.Container == null )
{
UOC.SystemMessage( Strings.Invalid_container___ );
return;
}
Item entity = sourceItem.Container.SelectEntities( i => i.ID == id && ( hue == -1 || i.Hue == hue ) )
?.FirstOrDefault();
if ( entity == null )
{
return;
}
if ( amount == -1 )
{
amount = entity.Count;
}
if ( amount > entity.Count )
{
amount = entity.Count;
}
if ( destinationSerial == -1 )
{
ActionPacketQueue.EnqueueDragDropGround( entity.Serial, amount, x, y, z );
}
else
{
ActionPacketQueue.EnqueueDragDrop( entity.Serial, amount, destinationSerial );
}
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.Layer ), nameof( ParameterType.SerialOrAlias ) } )]
public static bool UseLayer( object layer, object obj = null )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 || !UOMath.IsMobile( serial ) )
{
UOC.SystemMessage( Strings.Cannot_find_item___ );
return false;
}
Layer layerValue = Layer.Invalid;
switch ( layer )
{
case string s:
layerValue = Utility.GetEnumValueByName<Layer>( s );
break;
case int i:
layerValue = (Layer) i;
break;
case Layer l:
layerValue = l;
break;
}
Mobile mobile = Engine.Mobiles.GetMobile( serial );
if ( mobile == null )
{
UOC.SystemMessage( Strings.Mobile_not_found___ );
return false;
}
int layerSerial = mobile.GetLayer( layerValue );
if ( layerSerial == 0 )
{
UOC.SystemMessage( Strings.Cannot_find_item___ );
return false;
}
UseObject( layerSerial );
return true;
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static bool InIgnoreList( object obj )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial > 0 )
{
return IgnoreList.Contains( serial );
}
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return false;
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ), nameof( ParameterType.Hue ) } )]
public static void Rehue( object obj, int hue )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial > 0 )
{
if ( hue > 0 )
{
Engine.RehueList.Add( serial, hue );
}
else
{
Engine.RehueList.Remove( serial );
}
if ( UOMath.IsMobile( serial ) )
{
Mobile m = Engine.Mobiles.GetMobile( serial );
if ( m == null )
{
return;
}
Engine.SendPacketToClient( new MobileIncoming( m, m.Equipment, hue ) );
}
else
{
Item i = Engine.Items.GetItem( serial );
if ( i == null )
{
return;
}
Engine.RehueList.CheckItem( i );
}
return;
}
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
}
}
}
@@ -0,0 +1,51 @@
using System.Linq;
using ClassicAssist.Data.Organizer;
using ClassicAssist.Shared.Resources;
using UOC = ClassicAssist.Shared.UO.Commands;
namespace ClassicAssist.Data.Macros.Commands
{
public static class OrganizerCommands
{
[CommandsDisplay( Category = nameof( Strings.Agents ) )]
public static bool Organizing()
{
OrganizerManager manager = OrganizerManager.GetInstance();
bool organizing = manager.Items.Any( o => o.IsRunning() );
return organizing;
}
[CommandsDisplay( Category = nameof( Strings.Agents ),
Parameters = new[]
{
nameof( ParameterType.AgentEntryName ), nameof( ParameterType.SerialOrAlias ),
nameof( ParameterType.SerialOrAlias )
} )]
public static void Organizer( string name, object sourceContainer = null, object destinationContainer = null )
{
OrganizerManager manager = OrganizerManager.GetInstance();
OrganizerEntry entry = manager.Items.FirstOrDefault( oa => oa.Name.ToLower().Equals( name.ToLower() ) );
if ( entry == null )
{
UOC.SystemMessage( string.Format( Strings.Organizer___0___not_found___, name ) );
return;
}
if ( sourceContainer != null && destinationContainer != null )
{
int sourceContainerSerial = AliasCommands.ResolveSerial( sourceContainer );
int destinatinContainerSerial = AliasCommands.ResolveSerial( destinationContainer );
manager.Organize( entry, sourceContainerSerial, destinatinContainerSerial ).Wait();
}
else
{
manager.Organize( entry ).Wait();
}
}
}
}
@@ -0,0 +1,107 @@
using System;
using System.Linq;
using ClassicAssist.Shared;
using ClassicAssist.Shared.Resources;
using ClassicAssist.UO.Network.PacketFilter;
using ClassicAssist.UO.Network.Packets;
using ClassicAssist.UO.Objects;
using UOC = ClassicAssist.Shared.UO.Commands;
namespace ClassicAssist.Data.Macros.Commands
{
public static class PropertiesCommands
{
[CommandsDisplay( Category = nameof( Strings.Properties ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ), nameof( ParameterType.Timeout ) } )]
public static bool WaitForProperties( object obj, int timeout )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return false;
}
PacketFilterInfo pfi = new PacketFilterInfo( 0xD6,
new[] { PacketFilterConditions.IntAtPositionCondition( serial, 5 ) } );
PacketWaitEntry we = Engine.PacketWaitEntries.Add( pfi, PacketDirection.Incoming, true );
Engine.SendPacketToServer( new BatchQueryProperties( serial ) );
try
{
bool result = we.Lock.WaitOne( timeout );
return result;
}
finally
{
Engine.PacketWaitEntries.Remove( we );
}
}
[CommandsDisplay( Category = nameof( Strings.Properties ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ), nameof( ParameterType.String ) } )]
public static bool Property( object obj, string value )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return false;
}
Entity entity = (Entity) Engine.Items.GetItem( serial ) ?? Engine.Mobiles.GetMobile( serial );
if ( entity?.Properties != null )
{
return entity.Properties.Any( pe => pe.Text.ToLower().Contains( value.ToLower() ) );
}
UOC.SystemMessage( Strings.Item_properties_null_or_not_loaded___ );
return false;
}
[CommandsDisplay( Category = nameof( Strings.Properties ),
Parameters = new[]
{
nameof( ParameterType.SerialOrAlias ), nameof( ParameterType.String ),
nameof( ParameterType.IntegerValue )
} )]
public static T PropertyValue<T>( object obj, string property, int argument = 0 )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return default;
}
Entity entity = (Entity) Engine.Items.GetItem( serial ) ?? Engine.Mobiles.GetMobile( serial );
if ( entity?.Properties != null )
{
Property p = entity.Properties.FirstOrDefault( pe => pe.Text.ToLower().Contains( property.ToLower() ) );
if ( p == null )
{
return default;
}
if ( p.Arguments[0].Trim().Equals( string.Empty ) )
{
return default;
}
return (T) Convert.ChangeType( p?.Arguments?[argument], typeof( T ) );
}
UOC.SystemMessage( Strings.Item_properties_null_or_not_loaded___ );
return default;
}
}
}
@@ -0,0 +1,40 @@
using ClassicAssist.Shared;
using ClassicAssist.Data.Regions;
using ClassicAssist.Misc;
using ClassicAssist.Shared.Resources;
using ClassicAssist.UO.Objects;
using UOC = ClassicAssist.Shared.UO.Commands;
namespace ClassicAssist.Data.Macros.Commands
{
public static class RegionCommands
{
[CommandsDisplay( Category = nameof( Strings.Actions ),
Parameters = new[] { nameof( ParameterType.String ), nameof( ParameterType.SerialOrAlias ) } )]
[CommandsDisplayStringSeeAlso( new[] { nameof( RegionAttributes ) } )]
public static bool InRegion( string attribute, object obj )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return false;
}
Entity entity = (Entity) Engine.Items.GetItem( serial ) ?? Engine.Mobiles.GetMobile( serial );
if ( entity == null )
{
UOC.SystemMessage( Strings.Cannot_find_item___ );
return false;
}
RegionAttributes attr = Utility.GetEnumValueByName<RegionAttributes>( attribute );
Region region = entity.GetRegion();
return region != null && region.Attributes.HasFlag( attr );
}
}
}
@@ -0,0 +1,109 @@
using System.Collections.Generic;
using System.Linq;
using ClassicAssist.Shared;
using ClassicAssist.Data.Skills;
using ClassicAssist.Misc;
using ClassicAssist.Shared.Resources;
using ClassicAssist.UO.Data;
using ClassicAssist.UO.Network.Packets;
using UOC = ClassicAssist.Shared.UO.Commands;
namespace ClassicAssist.Data.Macros.Commands
{
public static class SkillCommands
{
[CommandsDisplay( Category = nameof( Strings.Skills ),
Parameters = new[] { nameof( ParameterType.SkillName ) } )]
public static void UseSkill( string skill )
{
int id = GetSkillID( skill );
if ( id == -1 )
{
UOC.SystemMessage( string.Format( Strings.Invalid_skill_name___0__, skill ) );
return;
}
Engine.SendPacketToServer( new UseSkill( id ) );
}
private static int GetSkillID( string skill )
{
skill = skill.ToLower().Replace( '_', ' ' );
KeyValuePair<int, SkillData> sk = UO.Data.Skills.GetSkills()
.FirstOrDefault( s => s.Value.Name.ToLower().Equals( skill ) );
if ( sk.Value == null )
{
return -1;
}
return sk.Key;
}
[CommandsDisplay( Category = nameof( Strings.Skills ),
Parameters = new[] { nameof( ParameterType.SkillName ) } )]
public static double Skill( string name )
{
SkillManager manager = SkillManager.GetInstance();
SkillEntry s = manager.Items.FirstOrDefault( se => se.Skill.Name.ToLower().Contains( name.ToLower() ) );
return s?.Value ?? 0;
}
[CommandsDisplay( Category = nameof( Strings.Skills ),
Parameters = new[] { nameof( ParameterType.SkillName ) } )]
public static double SkillCap( string name )
{
SkillManager manager = SkillManager.GetInstance();
SkillEntry s = manager.Items.FirstOrDefault( se => se.Skill.Name.ToLower().Contains( name.ToLower() ) );
return s?.Cap ?? 0;
}
[CommandsDisplay( Category = nameof( Strings.Skills ),
Parameters = new[] { nameof( ParameterType.SkillName ) } )]
public static string SkillState( string name )
{
SkillManager manager = SkillManager.GetInstance();
SkillEntry s = manager.Items.FirstOrDefault( se => se.Skill.Name.ToLower().Contains( name.ToLower() ) );
return s?.LockStatus.ToString().ToLower() ?? "up";
}
[CommandsDisplay( Category = nameof( Strings.Skills ),
Parameters = new[] { nameof( ParameterType.SkillName ), nameof( ParameterType.UpDownLocked ) } )]
[CommandsDisplayStringSeeAlso( new[] { null, nameof( LockStatus ) } )]
public static void SetSkill( string skill, string status )
{
SkillManager manager = SkillManager.GetInstance();
SkillEntry s = manager.Items.FirstOrDefault( se => se.Skill.Name.ToLower().Contains( skill.ToLower() ) );
if ( s == null )
{
UOC.SystemMessage( string.Format( Strings.Invalid_skill_name___0__, skill ) );
return;
}
LockStatus ls = Utility.GetEnumValueByName<LockStatus>( status );
UOC.ChangeSkillLock( s, ls );
}
[CommandsDisplay( Category = nameof( Strings.Skills ),
Parameters = new[] { nameof( ParameterType.String ), nameof( ParameterType.UpDownLocked ) } )]
[CommandsDisplayStringSeeAlso( new[] { nameof( StatType ), nameof( LockStatus ) } )]
public static void SetStatus( string stat, string lockStatus )
{
StatType st = Utility.GetEnumValueByName<StatType>( stat );
LockStatus ls = Utility.GetEnumValueByName<LockStatus>( lockStatus );
UOC.ChangeStatLock( st, ls );
}
}
}
@@ -0,0 +1,84 @@
using System.Diagnostics;
using ClassicAssist.Data.Spells;
using ClassicAssist.Shared.Resources;
using UOC = ClassicAssist.Shared.UO.Commands;
namespace ClassicAssist.Data.Macros.Commands
{
public static class SpellCommands
{
private static readonly SpellManager _manager = SpellManager.GetInstance();
[CommandsDisplay( Category = nameof( Strings.Spells ),
Parameters = new[] { nameof( ParameterType.SpellName ) } )]
public static void Cast( string name )
{
_manager?.CastSpell( name );
}
[CommandsDisplay( Category = nameof( Strings.Spells ),
Parameters = new[] { nameof( ParameterType.SpellName ), nameof( ParameterType.SerialOrAlias ) } )]
public static bool Cast( string name, object obj )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return false;
}
SpellData sd = _manager.GetSpellData( name ) ?? _manager.GetMasteryData( name );
if ( sd == null )
{
UOC.SystemMessage( Strings.Unknown_spell___ );
return false;
}
// Debugging only
Stopwatch sw = new Stopwatch();
sw.Start();
//
_manager.CastSpell( sd.ID );
int index = 0;
bool result;
if ( Options.CurrentOptions.UseExperimentalFizzleDetection )
{
( index, result ) = UOC.WaitForTargetOrFizzle( sd.Timeout + 1000 );
}
else
{
result = TargetCommands.WaitForTarget( sd.Timeout + 500 );
}
if ( index == 0 && !result )
{
UOC.SystemMessage( Strings.Timeout___ );
return false;
}
if ( !result )
{
return false;
}
// Debugging only
sw.Stop();
if ( Options.CurrentOptions.Debug )
{
UOC.SystemMessage(
$"Target received in {sw.ElapsedMilliseconds}ms, Spell data timeout: {sd.Timeout}ms" );
}
//
TargetCommands.Target( serial );
return true;
}
}
}
@@ -0,0 +1,603 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ClassicAssist.Shared;
using ClassicAssist.Data.Regions;
using ClassicAssist.Data.Targeting;
using ClassicAssist.Misc;
using ClassicAssist.Shared.Resources;
using ClassicAssist.UO;
using ClassicAssist.UO.Data;
using ClassicAssist.UO.Network.Packets;
using ClassicAssist.UO.Objects;
using TargetTypeEnum = ClassicAssist.UO.Data.TargetType;
using UOC = ClassicAssist.Shared.UO.Commands;
namespace ClassicAssist.Data.Macros.Commands
{
public static class TargetCommands
{
public enum TargetExistsType
{
Any,
Beneficial,
Harmful,
Neutral
}
public enum TargetResourceType
{
Ore,
Sand,
Wood,
Graves,
Red_Mushrooms
}
private static readonly ushort[] _treeTiles =
{
0x0CCA, 0x0CCB, 0x0CCC, 0x0CCD, 0x0CD0, 0x0CD3, 0x0CD6, 0x0CD8, 0x0CDA, 0x0CDD, 0x0CE0, 0x0CE3, 0x0CE6,
0x0D41, 0x0D42, 0x0D43, 0x0D44, 0x0D57, 0x0D58, 0x0D59, 0x0D5A, 0x0D5B, 0x0D6E, 0x0D6F, 0x0D70, 0x0D71,
0x0D72, 0x0D84, 0x0D85, 0x0D86, 0x0D94, 0x0D98, 0x0D9C, 0x0DA0, 0x0DA4, 0x0DA8, 0x0C9E, 0x0CA8, 0x0CAA,
0x0CAB, 0x0CC9, 0x0CF8, 0x0CFB, 0x0CFE, 0x0D01, 0x12B6, 0x12B7, 0x12B8, 0x12B9, 0x12BA, 0x12BB, 0x12BC,
0x12BD
};
private static readonly ushort[] _caveTiles =
{
1339, 1340, 1341, 1342, 1343, 1344, 1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, 1353, 1354, 1355,
1356, 1357, 1358, 1359, 1361, 1362, 1363
};
[CommandsDisplay( Category = nameof( Strings.Target ) )]
public static void CancelTarget()
{
Engine.SendPacketToServer( new Target( TargetTypeEnum.Object, -1, TargetFlags.Cancel, -1, -1, -1, 0, 0,
true ) );
}
[CommandsDisplay( Category = nameof( Strings.Target ), Parameters = new[] { nameof( ParameterType.Timeout ) } )]
public static bool WaitForTarget( int timeout = 5000 )
{
return UOC.WaitForTarget( timeout );
}
[CommandsDisplay( Category = nameof( Strings.Target ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static void Target( object obj, bool checkRange = false, bool useQueue = false )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
return;
}
if ( checkRange && UOMath.IsMobile( serial ) && Engine.TargetExists )
{
Mobile mobile = Engine.Mobiles.GetMobile( serial );
if ( mobile != null )
{
if ( mobile.Distance > Options.CurrentOptions.RangeCheckLastTargetAmount )
{
UOC.SystemMessage( Strings.Target_out_of_range__try_again___ );
UOC.ResendTargetToClient();
return;
}
}
else
{
UOC.SystemMessage( Strings.Target_out_of_range__try_again___ );
UOC.ResendTargetToClient();
return;
}
}
if ( Options.CurrentOptions.PreventTargetingInnocentsInGuardzone && Engine.TargetExists )
{
Mobile mobile = Engine.Mobiles.GetMobile( serial );
if ( mobile != null && mobile.Notoriety == Notoriety.Innocent &&
mobile.Serial != Engine.Player?.Serial && Engine.TargetFlags == TargetFlags.Harmful &&
mobile.GetRegion().Attributes.HasFlag( RegionAttributes.Guarded ) )
{
UOC.SystemMessage( Strings.Target_blocked____try_again___ );
UOC.ResendTargetToClient();
return;
}
}
if ( useQueue && !Engine.TargetExists )
{
MsgCommands.HeadMsg( Strings.Target_Queued, Engine.Player?.Serial );
Engine.LastTargetQueue.Enqueue( obj );
return;
}
Engine.SendPacketToServer( new Target( TargetTypeEnum.Object, -1, TargetFlags.None, serial, -1, -1, -1, 0,
true ) );
Engine.TargetExists = false;
}
[CommandsDisplay( Category = nameof( Strings.Target ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ), nameof( ParameterType.String ) } )]
[CommandsDisplayStringSeeAlso( new[] { null, nameof( TargetResourceType ) } )]
public static void TargetByResource( object toolObj, string resourceType )
{
int serial = AliasCommands.ResolveSerial( toolObj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return;
}
try
{
TargetResourceType resourceEnum = Utility.GetEnumValueByName<TargetResourceType>( resourceType );
Engine.SendPacketToServer( new TargetByResource( serial, (int) resourceEnum ) );
}
catch ( InvalidOperationException )
{
}
}
[CommandsDisplay( Category = nameof( Strings.Target ),
Parameters = new[]
{
nameof( ParameterType.SerialOrAlias ), nameof( ParameterType.IntegerValue ),
nameof( ParameterType.Boolean ), nameof( ParameterType.ItemID )
} )]
public static void TargetTileRelative( object obj, int distance, bool reverse = false, int itemID = 0 )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return;
}
Entity entity = Engine.Mobiles.GetMobile( serial );
if ( entity == null )
{
UOC.SystemMessage( Strings.Mobile_not_found___ );
return;
}
int x = entity.X;
int y = entity.Y;
int offsetX = 0;
int offsetY = 0;
// TODO
Direction direction = (Direction) ( (int) entity.Direction & ~0x80 );
switch ( direction )
{
case Direction.North:
offsetY = -1;
break;
case Direction.Northeast:
offsetY = -1;
offsetX = 1;
break;
case Direction.East:
offsetX = 1;
break;
case Direction.Southeast:
offsetX = 1;
offsetY = 1;
break;
case Direction.South:
offsetY = 1;
break;
case Direction.Southwest:
offsetY = 1;
offsetX = -1;
break;
case Direction.West:
offsetX = -1;
break;
case Direction.Northwest:
offsetX = -1;
offsetY = -1;
break;
case Direction.Invalid:
break;
default:
throw new ArgumentOutOfRangeException();
}
int totalOffsetX = offsetX * distance;
int totalOffsetY = offsetY * distance;
if ( reverse )
{
totalOffsetX = -totalOffsetX;
totalOffsetY = -totalOffsetY;
}
int destinationX = x + totalOffsetX;
int destinationY = y + totalOffsetY;
( int surfaceZ, int surfaceID ) =
MapInfo.GetMapSurface( (int) Engine.Player.Map, destinationX, destinationY );
if ( itemID == 0 )
{
itemID = surfaceID;
}
TargetXYZ( destinationX, destinationY, surfaceZ, itemID );
}
[CommandsDisplay( Category = nameof( Strings.Target ),
Parameters = new[]
{
nameof( ParameterType.XCoordinateOffset ), nameof( ParameterType.YCoordinateOffset ),
nameof( ParameterType.YCoordinateOffset ), nameof( ParameterType.ItemID )
} )]
public static void TargetTileOffset( int xOffset, int yOffset, int zOffset, int itemID = 0 )
{
TargetXYZ( Engine.Player.X + xOffset, Engine.Player.Y + yOffset, Engine.Player.Z + zOffset, itemID );
}
[CommandsDisplay( Category = nameof( Strings.Target ),
Parameters = new[]
{
nameof( ParameterType.XCoordinateOffset ), nameof( ParameterType.YCoordinateOffset ),
nameof( ParameterType.YCoordinateOffset ), nameof( ParameterType.ItemID )
} )]
public static void TargetTileOffsetResource( int xOffset, int yOffset, int zOffset, int itemID = 0 )
{
int x = Engine.Player.X + xOffset;
int y = Engine.Player.Y + yOffset;
int z = Engine.Player.Z + zOffset;
if ( itemID == 0 )
{
StaticTile[] staticTiles = Statics.GetStatics( (int) Engine.Player.Map, x, y );
if ( staticTiles != null )
{
StaticTile selectedStatic = staticTiles.FirstOrDefault( i =>
_treeTiles.Contains( i.ID ) || _caveTiles.Contains( i.ID ) ||
i.Flags.HasFlag( TileFlags.Wet ) );
if ( selectedStatic.ID == 0 )
{
selectedStatic = staticTiles.FirstOrDefault();
}
itemID = selectedStatic.ID;
z = selectedStatic.Z;
}
}
TargetXYZ( x, y, z, itemID );
}
[CommandsDisplay( Category = nameof( Strings.Target ),
Parameters = new[]
{
nameof( ParameterType.Empty ), nameof( ParameterType.Empty ), nameof( ParameterType.Empty ),
nameof( ParameterType.Empty )
} )]
[CommandsDisplayStringSeeAlso( new[]
{
nameof( TargetNotoriety ), nameof( TargetBodyType ), nameof( TargetDistance ),
nameof( TargetInfliction )
} )]
public static bool GetEnemy( IEnumerable<string> notorieties, string bodyType = "Any", string distance = "Next",
string infliction = "Any" )
{
TargetNotoriety notoFlags = TargetNotoriety.None;
foreach ( string noto in notorieties )
{
if ( Enum.TryParse( noto, true, out TargetNotoriety flag ) )
{
notoFlags |= flag;
}
}
if ( !Enum.TryParse( bodyType, true, out TargetBodyType bt ) )
{
bt = TargetBodyType.Any;
}
if ( !Enum.TryParse( distance, true, out TargetDistance td ) )
{
td = TargetDistance.Next;
}
if ( !Enum.TryParse( infliction, true, out TargetInfliction ti ) )
{
ti = TargetInfliction.Any;
}
return TargetManager.GetInstance().GetEnemy( notoFlags, bt, td, TargetFriendType.None, ti );
}
[CommandsDisplay( Category = nameof( Strings.Target ),
Parameters = new[]
{
nameof( ParameterType.Empty ), nameof( ParameterType.Empty ), nameof( ParameterType.Empty )
} )]
[CommandsDisplayStringSeeAlso( new[]
{
nameof( TargetDistance ), nameof( TargetInfliction ), nameof( TargetBodyType )
} )]
public static bool GetFriendListOnly( string distance = "Next", string targetInfliction = "Any",
string bodyType = "Any" )
{
if ( !Enum.TryParse( distance, true, out TargetDistance td ) )
{
td = TargetDistance.Next;
}
if ( !Enum.TryParse( targetInfliction, true, out TargetInfliction ti ) )
{
ti = TargetInfliction.Any;
}
if ( !Enum.TryParse( bodyType, true, out TargetBodyType bt ) )
{
bt = TargetBodyType.Any;
}
return TargetManager.GetInstance().GetFriend( TargetNotoriety.Any, bt, td, TargetFriendType.Only, ti );
}
[CommandsDisplay( Category = nameof( Strings.Target ),
Parameters = new[]
{
nameof( ParameterType.Empty ), nameof( ParameterType.Empty ), nameof( ParameterType.Empty ),
nameof( ParameterType.Empty )
} )]
[CommandsDisplayStringSeeAlso( new[]
{
nameof( TargetNotoriety ), nameof( TargetBodyType ), nameof( TargetDistance ),
nameof( TargetInfliction )
} )]
public static bool GetFriend( IEnumerable<string> notorieties, string bodyType = "Any",
string distance = "Next", string infliction = "Any" )
{
TargetNotoriety notoFlags = TargetNotoriety.None;
foreach ( string noto in notorieties )
{
if ( Enum.TryParse( noto, true, out TargetNotoriety flag ) )
{
notoFlags |= flag;
}
}
if ( !Enum.TryParse( bodyType, true, out TargetBodyType bt ) )
{
bt = TargetBodyType.Any;
}
if ( !Enum.TryParse( distance, true, out TargetDistance td ) )
{
td = TargetDistance.Next;
}
if ( !Enum.TryParse( infliction, true, out TargetInfliction ti ) )
{
ti = TargetInfliction.Any;
}
return TargetManager.GetInstance().GetFriend( notoFlags, bt, td, TargetFriendType.Include, ti );
}
[CommandsDisplay( Category = nameof( Strings.Target ),
Parameters = new[] { nameof( ParameterType.BeneficialHarmfulNeutral ) } )]
[CommandsDisplayStringSeeAlso( new[] { nameof( TargetExistsType ) } )]
public static bool TargetExists( string targetExistsType = "Any" )
{
if ( !Enum.TryParse( targetExistsType, out TargetExistsType enumValue ) )
{
enumValue = TargetExistsType.Any;
}
switch ( enumValue )
{
case TargetExistsType.Any:
return Engine.TargetExists;
case TargetExistsType.Beneficial:
return Engine.TargetExists && Engine.TargetFlags == TargetFlags.Beneficial;
case TargetExistsType.Harmful:
return Engine.TargetExists && Engine.TargetFlags == TargetFlags.Harmful;
case TargetExistsType.Neutral:
return Engine.TargetExists && Engine.TargetFlags == TargetFlags.None;
default:
throw new ArgumentOutOfRangeException();
}
}
[CommandsDisplay( Category = nameof( Strings.Target ) )]
public static bool WaitingForTarget()
{
return Engine.WaitingForTarget;
}
[CommandsDisplay( Category = nameof( Strings.Target ) )]
public static void ClearTargetQueue()
{
Engine.LastTargetQueue?.Clear();
UOC.SystemMessage( Strings.Target_queue_cleared___ );
}
[CommandsDisplay( Category = nameof( Strings.Target ),
Parameters = new[]
{
nameof( ParameterType.SerialOrAlias ), nameof( ParameterType.Hue ), nameof( ParameterType.Range )
} )]
public static void TargetType( object obj, int hue = -1, int range = -1 )
{
int id = AliasCommands.ResolveSerial( obj );
if ( id == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return;
}
if ( Engine.Player?.Backpack == null )
{
UOC.SystemMessage( Strings.Error__Cannot_find_player_backpack );
return;
}
Item item = Engine.Items.SelectEntity( i =>
i.ID == id && ( hue == -1 || i.Hue == hue ) &&
i.IsDescendantOf( Engine.Player.Backpack.Serial, range ) );
if ( item == null )
{
UOC.SystemMessage( Strings.Cannot_find_item___ );
return;
}
Target( item.Serial, false, Options.CurrentOptions.QueueLastTarget );
}
[CommandsDisplay( Category = nameof( Strings.Target ),
Parameters = new[]
{
nameof( ParameterType.SerialOrAlias ), nameof( ParameterType.Hue ), nameof( ParameterType.Range )
} )]
public static void TargetGround( object obj, int hue = -1, int range = -1 )
{
int id = AliasCommands.ResolveSerial( obj );
if ( id == 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return;
}
Entity entity =
(Entity) Engine.Items.SelectEntity( i =>
i.ID == id && ( hue == -1 || i.Hue == hue ) && ( range == -1 || i.Distance < range ) ) ??
Engine.Mobiles.SelectEntity( m =>
m.ID == id && ( hue == -1 || m.Hue == hue ) && ( range == -1 || m.Distance < range ) );
if ( entity == null )
{
UOC.SystemMessage( Strings.Cannot_find_item___ );
return;
}
Target( entity.Serial, false, Options.CurrentOptions.QueueLastTarget );
}
[CommandsDisplay( Category = nameof( Strings.Target ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static void SetEnemy( object obj )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial <= 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return;
}
Entity entity = Engine.Items.GetItem( serial ) ?? (Entity) Engine.Mobiles.GetMobile( serial );
if ( entity == null )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return;
}
TargetManager.GetInstance().SetEnemy( entity );
}
[CommandsDisplay( Category = nameof( Strings.Target ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static void SetFriend( object obj )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial <= 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return;
}
Entity entity = Engine.Items.GetItem( serial ) ?? (Entity) Engine.Mobiles.GetMobile( serial );
if ( entity == null )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return;
}
TargetManager.GetInstance().SetFriend( entity );
}
[CommandsDisplay( Category = nameof( Strings.Target ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ) } )]
public static void SetLastTarget( object obj )
{
int serial = AliasCommands.ResolveSerial( obj );
if ( serial <= 0 )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return;
}
Entity entity = Engine.Items.GetItem( serial ) ?? (Entity) Engine.Mobiles.GetMobile( serial );
if ( entity == null )
{
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
return;
}
TargetManager.GetInstance().SetLastTarget( entity );
}
[CommandsDisplay( Category = nameof( Strings.Target ), Parameters = new[] { nameof( ParameterType.Timeout ) } )]
public static bool WaitForTargetOrFizzle( int timeout )
{
( _, bool result ) = UOC.WaitForTargetOrFizzle( timeout );
return result;
}
[CommandsDisplay( Category = nameof( Strings.Target ),
Parameters = new[]
{
nameof( ParameterType.XCoordinate ), nameof( ParameterType.YCoordinate ),
nameof( ParameterType.ZCoordinate ), nameof( ParameterType.ItemID )
} )]
public static void TargetXYZ( int x, int y, int z, int itemID = 0 )
{
Engine.SendPacketToServer( new Target( TargetTypeEnum.Tile, -1, Engine.TargetFlags, 0, x, y, z, itemID,
true ) );
Engine.TargetExists = false;
}
}
}
@@ -0,0 +1,84 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using ClassicAssist.Misc;
using ClassicAssist.Shared.Resources;
using UOC = ClassicAssist.Shared.UO.Commands;
namespace ClassicAssist.Data.Macros.Commands
{
public static class TimerCommands
{
private static readonly ConcurrentDictionary<string, OffsetStopwatch> _timers =
new ConcurrentDictionary<string, OffsetStopwatch>();
[CommandsDisplay( Category = nameof( Strings.Timers ),
Parameters = new[] { nameof( ParameterType.TimerName ) } )]
public static void CreateTimer( string name )
{
OffsetStopwatch timer = new OffsetStopwatch( TimeSpan.Zero );
_timers.AddOrUpdate( name, t => timer, ( t, o ) => timer );
}
[CommandsDisplay( Category = nameof( Strings.Timers ),
Parameters = new[] { nameof( ParameterType.TimerName ) } )]
public static bool TimerExists( string name )
{
return _timers.ContainsKey( name );
}
[CommandsDisplay( Category = nameof( Strings.Timers ),
Parameters = new[] { nameof( ParameterType.TimerName ) } )]
public static void RemoveTimer( string name )
{
if ( _timers.TryGetValue( name, out OffsetStopwatch sw ) )
{
sw?.Stop();
}
_timers.TryRemove( name, out _ );
}
[CommandsDisplay( Category = nameof( Strings.Timers ),
Parameters = new[] { nameof( ParameterType.SerialOrAlias ), nameof( ParameterType.IntegerValue ) } )]
public static void SetTimer( string name, int milliseconds = 0 )
{
if ( !TimerExists( name ) )
{
CreateTimer( name );
}
if ( _timers.TryGetValue( name, out OffsetStopwatch sw ) )
{
sw?.Reset( TimeSpan.FromMilliseconds( milliseconds ) );
}
}
[CommandsDisplay( Category = nameof( Strings.Timers ),
Parameters = new[] { nameof( ParameterType.TimerName ) } )]
public static long Timer( string name )
{
return !_timers.ContainsKey( name ) ? 0 : _timers[name].ElapsedMilliseconds;
}
[CommandsDisplay( Category = nameof( Strings.Timers ),
Parameters = new[] { nameof( ParameterType.TimerName ) } )]
public static void TimerMsg( string name )
{
if ( !_timers.ContainsKey( name ) )
{
UOC.SystemMessage( Strings.Unknown_timer___ );
return;
}
UOC.SystemMessage( _timers[name].ToString() );
}
public static Dictionary<string, OffsetStopwatch> GetAllTimers()
{
return _timers.ToDictionary( t => t.Key, t => t.Value );
}
}
}
@@ -0,0 +1,181 @@
#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;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ClassicAssist.Shared;
using ClassicAssist.Misc;
using ClassicAssist.Shared.Resources;
using ClassicAssist.UO.Data;
using ClassicAssist.UO.Network.PacketFilter;
using ClassicAssist.UO.Network.Packets;
using ClassicAssist.UO.Objects;
using UOC = ClassicAssist.Shared.UO.Commands;
namespace ClassicAssist.Data.Macros.Commands
{
public static class WandCommands
{
public enum WandTypes
{
Clumsy,
Identification,
Heal,
Feeblemind,
Weaken,
Magic_Arrow,
Harm,
Fireball,
Greater_Heal,
Lightning,
Mana_Drain
}
private static readonly Dictionary<WandTypes, int[]> _wandClilocs = new Dictionary<WandTypes, int[]>
{
{ WandTypes.Clumsy, new[] { 3002011, 1017326 } },
{ WandTypes.Identification, new[] { 1044063, 1017350 } },
{ WandTypes.Heal, new[] { 3002014, 1017329 } },
{ WandTypes.Feeblemind, new[] { 3002013, 1017327 } },
{ WandTypes.Weaken, new[] { 3002018, 1017328 } },
{ WandTypes.Magic_Arrow, new[] { 3002015, 1060492 } },
{ WandTypes.Harm, new[] { 3002022, 1017334 } },
{ WandTypes.Fireball, new[] { 3002028, 1060487 } },
{ WandTypes.Greater_Heal, new[] { 3002039, 1017330 } },
{ WandTypes.Lightning, new[] { 3002040, 1060491 } },
{ WandTypes.Mana_Drain, new[] { 3002041, 1017339 } }
};
private static readonly int[] _wandIds = { 0xDF2, 0xDF3, 0xDF4, 0xDF5 };
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[] { nameof( ParameterType.WandName ), nameof( ParameterType.IntegerValue ) } )]
[CommandsDisplayStringSeeAlso( new[] { nameof( WandTypes ) } )]
public static bool EquipWand( string wandName, int minimumCharges = -1 )
{
try
{
WandTypes wandType = Utility.GetEnumValueByName<WandTypes>( wandName );
int containerSerial = AliasCommands.ResolveSerial( "backpack" );
Item[] matches = FindWands( wandType, containerSerial, minimumCharges ).Result;
if ( matches == null )
{
UOC.SystemMessage( Strings.Cannot_find_item___ );
return false;
}
ActionCommands.EquipItem( matches.First().Serial, Layer.OneHanded );
return true;
}
catch ( InvalidOperationException )
{
UOC.SystemMessage( string.Format( Strings.Invalid_skill_name___0__, wandName ) );
}
return false;
}
[CommandsDisplay( Category = nameof( Strings.Entity ),
Parameters = new[]
{
nameof( ParameterType.WandName ), nameof( ParameterType.SerialOrAlias ),
nameof( ParameterType.IntegerValue )
} )]
[CommandsDisplayStringSeeAlso( new[] { nameof( WandTypes ) } )]
public static bool FindWand( string wandName, object containerSource = null, int minimumCharges = -1 )
{
try
{
WandTypes wandType = Utility.GetEnumValueByName<WandTypes>( wandName );
int containerSerial = AliasCommands.ResolveSerial( containerSource );
if ( containerSource == null )
{
containerSerial = -1;
}
Item[] matches = FindWands( wandType, containerSerial, minimumCharges ).Result;
if ( matches == null )
{
UOC.SystemMessage( Strings.Cannot_find_item___ );
return false;
}
AliasCommands.SetMacroAlias( "found", matches.First().Serial );
if ( MacroManager.QuietMode )
{
return true;
}
UOC.SystemMessage( string.Format( Strings.Object___0___updated___, "found" ) );
return true;
}
catch ( InvalidOperationException )
{
UOC.SystemMessage( string.Format( Strings.Invalid_skill_name___0__, wandName ) );
}
return false;
}
private static async Task<Item[]> FindWands( WandTypes wandType, int containerSerial, int minimumCharges )
{
if ( !Engine.Features.HasFlag( FeatureFlags.AOS ) )
{
Item[] allWands = Engine.Items.SelectEntities( i =>
_wandIds.Contains( i.ID ) && ( containerSerial == -1 || i.IsDescendantOf( containerSerial ) ) );
if ( allWands == null )
{
return null;
}
foreach ( Item wand in allWands )
{
Engine.SendPacketToServer( new LookRequest( wand.Serial ) );
await UOC.WaitForIncomingPacketFilterAsync(
new PacketFilterInfo( 0xBF,
new[]
{
PacketFilterConditions.ShortAtPositionCondition( 0x10, 3 ),
PacketFilterConditions.IntAtPositionCondition( wand.Serial, 5 )
} ), 2500 );
}
}
Item[] matches = Engine.Items.SelectEntities( i =>
_wandIds.Contains( i.ID ) && ( containerSerial == -1 || i.IsDescendantOf( containerSerial ) ) &&
i.Properties != null && i.Properties.Any( p =>
_wandClilocs[wandType].Contains( p.Cliloc ) &&
( minimumCharges == -1 || int.Parse( p.Arguments[0] ) >= minimumCharges ) ) );
return matches;
}
}
}
@@ -0,0 +1,61 @@
using System;
using System.Runtime.CompilerServices;
using ClassicAssist.Shared.Resources;
namespace ClassicAssist.Data.Macros
{
public class CommandsDisplayAttribute : Attribute
{
private string _category;
public CommandsDisplayAttribute( [CallerMemberName] string member = "" )
{
string memberName = member.ToUpper();
string description = MacroCommandHelp.ResourceManager.GetString( $"{memberName}_COMMAND_DESCRIPTION" );
if ( string.IsNullOrEmpty( description ) )
{
throw new ArgumentNullException( $"Macro command help not translated: {member}" );
}
Description = description;
string insertText = MacroCommandHelp.ResourceManager.GetString( $"{memberName}_COMMAND_INSERTTEXT" );
if ( string.IsNullOrEmpty( insertText ) )
{
throw new ArgumentNullException( $"Macro command help not translated: {member}" );
}
InsertText = insertText;
string example = MacroCommandHelp.ResourceManager.GetString( $"{memberName}_COMMAND_EXAMPLE" );
Example = string.IsNullOrEmpty( example ) ? insertText : example;
}
public string Category
{
get => _category;
set => SetCategory( value );
}
public string Description { get; set; }
public string Example { get; set; }
public string InsertText { get; set; }
public string[] Parameters { get; set; }
private void SetCategory( string value )
{
string resourceName = Strings.ResourceManager.GetString( value );
if ( string.IsNullOrEmpty( resourceName ) )
{
throw new ArgumentNullException( $"String not translated: {value}" );
}
_category = resourceName;
}
}
}
@@ -0,0 +1,33 @@
#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;
namespace ClassicAssist.Data.Macros
{
public class CommandsDisplayStringSeeAlsoAttribute : Attribute
{
public CommandsDisplayStringSeeAlsoAttribute( string[] enums )
{
Enums = enums;
}
public string[] Enums { get; set; }
}
}
@@ -0,0 +1,179 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ClassicAssist.Data.Hotkeys;
using ClassicAssist.Shared;
using ClassicAssist.Shared.Resources;
using IronPython.Runtime.Operations;
using Microsoft.Scripting;
using Microsoft.Scripting.Runtime;
using Newtonsoft.Json;
namespace ClassicAssist.Data.Macros
{
public class MacroEntry : HotkeyEntry, IComparable<MacroEntry>
{
//private readonly Dispatcher _dispatcher;
private Dictionary<string, int> _aliases = new Dictionary<string, int>();
private bool _doNotAutoInterrupt;
private bool _global;
private bool _isAutostart;
private bool _isBackground;
private bool _isRunning;
private bool _loop;
private string _macro = string.Empty;
private MacroInvoker _macroInvoker = new MacroInvoker();
private string _name;
public MacroEntry()
{
//TODO
//_dispatcher = Dispatcher.CurrentDispatcher;
_macroInvoker.ExceptionEvent += OnExceptionEvent;
_macroInvoker.StoppedEvent += OnStoppedEvent;
}
public Dictionary<string, int> Aliases
{
get => _aliases;
set => SetProperty( ref _aliases, value );
}
public bool DoNotAutoInterrupt
{
get => _doNotAutoInterrupt;
set => SetProperty( ref _doNotAutoInterrupt, value );
}
public bool Global
{
get => _global;
set => SetProperty( ref _global, value );
}
public bool IsAutostart
{
get => _isAutostart;
set => SetProperty( ref _isAutostart, value );
}
public bool IsBackground
{
get => _isBackground;
set => SetProperty( ref _isBackground, value );
}
public bool IsRunning
{
get => _isRunning;
set => SetProperty( ref _isRunning, value );
}
public bool Loop
{
get => _loop;
set => SetProperty( ref _loop, value );
}
public string Macro
{
get => _macro;
set => SetProperty( ref _macro, value );
}
[JsonIgnore]
public MacroInvoker MacroInvoker
{
get => _macroInvoker;
set => SetProperty( ref _macroInvoker, value );
}
public override string Name
{
get => _name;
set => SetName( _name, value );
}
public int CompareTo( MacroEntry other )
{
return string.Compare( Name, other.Name, StringComparison.OrdinalIgnoreCase );
}
private void OnStoppedEvent()
{
Engine.Dispatcher.Invoke( () => IsRunning = false );
if ( IsBackground && !MacroManager.QuietMode )
{
Shared.UO.Commands.SystemMessage( string.Format( Strings.Background_macro___0___stopped___, Name ) );
}
}
public override string ToString()
{
return Name;
}
private void SetName( string name, string value )
{
MacroManager manager = MacroManager.GetInstance();
bool exists = manager.Items.Any( m => m.Name == value && !ReferenceEquals( m, this ) );
if ( exists && name == null )
{
SetName( null, $"{value}-" );
return;
}
if ( exists )
{
//TODO
//MessageBox.Show( Strings.Macro_name_must_be_unique_, Strings.Error );
return;
}
SetProperty( ref _name, value );
}
public void Execute()
{
Engine.Dispatcher.Invoke( () => IsRunning = true );
if ( IsBackground && !MacroManager.QuietMode )
{
Shared.UO.Commands.SystemMessage( string.Format( Strings.Background_macro___0___started___, Name ) );
}
_macroInvoker.Execute( this );
}
public void Stop()
{
if ( IsRunning )
{
_macroInvoker.Stop();
Engine.Dispatcher.Invoke( () => IsRunning = false );
}
}
private static void OnExceptionEvent( Exception exception )
{
Shared.UO.Commands.SystemMessage( string.Format( Strings.Macro_error___0_, exception.Message ) );
if ( exception is SyntaxErrorException syntaxError )
{
Shared.UO.Commands.SystemMessage( $"{Strings.Line_Number}: {syntaxError.RawSpan.Start.Line}" );
}
else
{
DynamicStackFrame sf = PythonOps.GetDynamicStackFrames( exception ).FirstOrDefault();
if ( sf != null )
{
Shared.UO.Commands.SystemMessage( $"{Strings.Line_Number}: {sf.GetFileLineNumber()}" );
}
}
}
}
}
@@ -0,0 +1,265 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using ClassicAssist.Shared;
using ClassicAssist.Data.Macros.Commands;
using ClassicAssist.Shared.Resources;
using ClassicAssist.Shared.UO;
using IronPython.Hosting;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;
namespace ClassicAssist.Data.Macros
{
public class MacroInvoker
{
public delegate void dMacroException( Exception e );
public delegate void dMacroStartStop();
private static readonly ScriptEngine _engine = Python.CreateEngine();
private static Dictionary<string, object> _importCache;
private readonly MemoryStream _memoryStream = new MemoryStream();
private CancellationTokenSource _cancellationToken;
private MacroEntry _macro;
private readonly SystemMessageTextWriter _textWriter = new SystemMessageTextWriter();
public MacroInvoker()
{
ScriptRuntime runtime = _engine.Runtime;
runtime.LoadAssembly( Assembly.GetExecutingAssembly() );
foreach ( string assembly in AssistantOptions.Assemblies ?? new string[0] )
{
try
{
runtime.LoadAssembly( Assembly.LoadFile( assembly ) );
}
catch ( Exception )
{
// ignored
}
}
if ( _importCache == null )
{
_importCache = InitializeImports( _engine );
}
_engine.Runtime.IO.SetOutput( _memoryStream, _textWriter );
_engine.Runtime.IO.SetErrorOutput( _memoryStream, _textWriter );
string modulePath = Path.Combine( Engine.StartupPath ?? Environment.CurrentDirectory, "Modules" );
ICollection<string> searchPaths = _engine.GetSearchPaths();
if ( searchPaths.Contains( modulePath ) )
{
return;
}
searchPaths.Add( modulePath );
_engine.SetSearchPaths( searchPaths );
}
public Exception Exception { get; set; }
public bool IsFaulted { get; set; }
public bool IsRunning => Thread?.IsAlive ?? false;
public Stopwatch StopWatch { get; set; } = new Stopwatch();
public Thread Thread { get; set; }
public event dMacroStartStop StartedEvent;
public event dMacroStartStop StoppedEvent;
public event dMacroException ExceptionEvent;
private static string GetScriptingImports()
{
string prepend = Assembly.GetExecutingAssembly().GetTypes()
.Where( t =>
t.Namespace != null && t.IsPublic && t.IsClass && t.Namespace.EndsWith( "Macros.Commands" ) )
.Aggregate( string.Empty, ( current, t ) => current + $"from {t.FullName} import * \n" );
foreach ( string assemblyName in AssistantOptions.Assemblies ?? new string[0] )
{
try
{
Assembly assembly = Assembly.LoadFile( assemblyName );
prepend += assembly.GetTypes()
.Where( t =>
t.Namespace != null && t.IsPublic && t.IsClass &&
t.Namespace.EndsWith( "Macros.Commands" ) ).Aggregate( string.Empty,
( current, t ) => current + $"from {t.FullName} import * \n" );
}
catch ( Exception )
{
// ignored
}
}
return prepend;
}
public static Dictionary<string, object> InitializeImports( ScriptEngine engine )
{
Dictionary<string, object> dictionary = new Dictionary<string, object>();
ScriptSource importSource =
engine.CreateScriptSourceFromString( GetScriptingImports(), SourceCodeKind.Statements );
CompiledCode importCompiled = importSource.Compile();
ScriptScope importScope = engine.CreateScope( dictionary );
importCompiled.Execute( importScope );
return dictionary;
}
public void Execute( MacroEntry macro )
{
_macro = macro;
if ( Thread != null && Thread.IsAlive )
{
Stop();
}
MainCommands.SetQuietMode( Options.CurrentOptions.DefaultMacroQuietMode );
_cancellationToken = new CancellationTokenSource();
if ( _importCache == null )
{
_importCache = InitializeImports( _engine );
}
ScriptSource source = _engine.CreateScriptSourceFromString( _macro.Macro, SourceCodeKind.Statements );
Dictionary<string, object> importCache = new Dictionary<string, object>( _importCache );
IsFaulted = false;
Thread = new Thread( () =>
{
Thread = Thread.CurrentThread;
try
{
StartedEvent?.Invoke();
AliasCommands.SetDefaultAliases();
ScriptScope macroScope = _engine.CreateScope( importCache );
StopWatch.Reset();
StopWatch.Start();
do
{
_cancellationToken.Token.ThrowIfCancellationRequested();
source.Execute( macroScope );
StopWatch.Stop();
bool willLoop = _macro.Loop && !IsFaulted && !_cancellationToken.IsCancellationRequested;
if ( !willLoop )
{
break;
}
if ( Options.CurrentOptions.Debug )
{
Shared.UO.Commands.SystemMessage( string.Format( Strings.Loop_time___0_, StopWatch.Elapsed ) );
}
int diff = 50 - (int) StopWatch.ElapsedMilliseconds;
if ( diff > 0 )
{
Thread.Sleep( diff );
}
}
while ( _macro.Loop && !IsFaulted );
}
catch ( TaskCanceledException )
{
IsFaulted = true;
}
catch ( ThreadInterruptedException )
{
IsFaulted = true;
}
catch ( ThreadAbortException )
{
IsFaulted = true;
}
catch ( Exception e )
{
IsFaulted = true;
Exception = e;
ExceptionEvent?.Invoke( e );
}
finally
{
StoppedEvent?.Invoke();
MacroManager.GetInstance().OnMacroStopped();
}
} ) { IsBackground = true };
try
{
Thread.Start();
MacroManager.GetInstance().OnMacroStarted();
}
catch ( ThreadStateException )
{
// TODO
}
catch ( ThreadStartException )
{
// TODO
}
}
public void Stop()
{
_cancellationToken?.Cancel();
if ( Thread == null || !Thread.IsAlive )
{
return;
}
try
{
StopWatch.Stop();
int diff = 50 - (int) StopWatch.ElapsedMilliseconds;
if ( diff > 0 )
{
Thread.Sleep( diff );
}
Thread?.Abort();
Thread?.Join( 100 );
MacroManager.GetInstance().Replay = false;
MacroManager.GetInstance().OnMacroStopped();
}
catch ( ThreadStateException e )
{
Shared.UO.Commands.SystemMessage( string.Format( Strings.Macro_error___0_, e.Message ) );
}
}
}
}
@@ -0,0 +1,178 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading;
using ClassicAssist.Shared;
using ClassicAssist.UI.Misc;
using ClassicAssist.UO.Network.PacketFilter;
using ClassicAssist.UO.Network.Packets;
namespace ClassicAssist.Data.Macros
{
public class MacroManager
{
public delegate void dMacroStartStop();
private static readonly object _lock = new object();
private static MacroManager _instance;
private readonly List<IMacroCommandParser> _parsers = new List<IMacroCommandParser>();
public event dMacroStartStop MacroStartedEvent;
public event dMacroStartStop MacroStoppedEvent;
private MacroManager()
{
Engine.PacketReceivedEvent += PacketReceivedEvent;
Engine.PacketSentEvent += PacketSentEvent;
IEnumerable<Type> types = Assembly.GetExecutingAssembly().GetTypes()
.Where( t => t.IsClass && typeof( IMacroCommandParser ).IsAssignableFrom( t ) );
foreach ( Type type in types )
{
IMacroCommandParser t = (IMacroCommandParser) Activator.CreateInstance( type );
_parsers.Add( t );
}
}
public MacroEntry CurrentMacro { get; set; }
public Action<string> InsertDocument { get; set; }
public Func<bool> IsRecording { get; set; }
public ObservableCollectionEx<MacroEntry> Items { get; set; }
public Action<string, string> NewMacro { get; set; }
public static bool QuietMode { get; set; }
public bool Replay { get; set; }
private void PacketSentEvent( byte[] data, int length )
{
if ( !IsRecording() )
{
return;
}
PacketSentReceived( data, length, PacketDirection.Outgoing );
}
private void PacketReceivedEvent( byte[] data, int length )
{
if ( !IsRecording() )
{
return;
}
PacketSentReceived( data, length, PacketDirection.Incoming );
}
private void PacketSentReceived( byte[] data, int length, PacketDirection direction )
{
foreach ( string result in _parsers.Select( parser => parser.Parse( data, length, direction ) )
.Where( result => !string.IsNullOrEmpty( result ) ) )
{
InsertDocument?.Invoke( result );
return;
}
}
public static MacroManager GetInstance()
{
// ReSharper disable once InvertIf
if ( _instance == null )
{
lock ( _lock )
{
if ( _instance != null )
{
return _instance;
}
_instance = new MacroManager();
return _instance;
}
}
return _instance;
}
public void Execute( MacroEntry macro )
{
if ( macro.IsBackground )
{
if ( macro.IsRunning )
{
macro.Stop();
}
else
{
macro.Execute();
}
}
else
{
if ( CurrentMacro != null && CurrentMacro.IsRunning )
{
if ( macro == CurrentMacro && macro.DoNotAutoInterrupt && !Replay )
{
return;
}
CurrentMacro.Stop();
}
CurrentMacro = macro;
CurrentMacro.Execute();
}
}
public void StopAll()
{
foreach ( MacroEntry entry in Items )
{
if ( entry.IsRunning )
{
entry.Stop();
}
}
}
public void Stop( string name = null )
{
if ( string.IsNullOrEmpty( name ) )
{
CurrentMacro?.Stop();
}
else
{
MacroEntry macro = Items.FirstOrDefault( m => m.Name.ToLower().Equals( name.ToLower() ) );
macro?.Stop();
}
}
public void Autostart()
{
foreach ( MacroEntry entry in Items )
{
if ( entry.IsAutostart )
{
Execute( entry );
}
}
}
public MacroEntry GetCurrentMacro()
{
Thread currentThread = Thread.CurrentThread;
return Items?.FirstOrDefault( m => m.MacroInvoker.Thread?.Equals( currentThread ) ?? false );
}
public void OnMacroStarted()
{
MacroStartedEvent?.Invoke();
}
public void OnMacroStopped()
{
MacroStoppedEvent?.Invoke();
}
}
}
@@ -0,0 +1,65 @@
#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.Data.Macros
{
public enum ParameterType
{
Unknown,
Serial,
SerialOrAlias,
Ability,
OnOff,
Timeout,
ItemID,
Hue,
LeftRightBoth,
Amount,
Name,
ShowType,
Layer,
ContextMenuIndex,
AgentEntryName,
AliasName,
Distance,
BuffName,
SpecialMoveName,
GumpButtonIndex,
String,
ListName,
IntegerValue,
MacroName,
Direction,
Range,
XCoordinate,
YCoordinate,
ZCoordinateOffset,
YCoordinateOffset,
XCoordinateOffset,
ZCoordinate,
SkillName,
UpDownLocked,
SpellName,
BeneficialHarmfulNeutral,
TimerName,
WandName,
Empty,
Boolean
}
}
@@ -0,0 +1,41 @@
#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.IO;
using System.Text;
namespace ClassicAssist.Data.Macros
{
public class SystemMessageTextWriter : TextWriter
{
public override Encoding Encoding { get; } = Encoding.Unicode;
public override void Write( string value )
{
value = value.TrimEnd( '\r', '\n' );
if ( string.IsNullOrEmpty( value ) )
{
return;
}
Shared.UO.Commands.SystemMessage( value );
}
}
}
@@ -0,0 +1,71 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using ClassicAssist.Shared;
using ClassicAssist.UO.Network.Packets;
using ClassicAssist.UO.Objects;
namespace ClassicAssist.Data.Macros
{
public class UseOnceList : IEnumerable<int>
{
private readonly List<int> _useOnce = new List<int>();
public IEnumerator<int> GetEnumerator()
{
return _useOnce.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Add( int serial )
{
_useOnce.Add( serial );
Engine.RehueList.Add( serial, 766 );
}
public void Add( Item item )
{
Add( item.Serial );
int backpack = Engine.Player?.Backpack?.Serial ?? -1;
if ( item.IsDescendantOf( backpack ) )
{
Engine.RehueList.CheckItem( item );
}
}
public void Remove( Item item )
{
Engine.RehueList.Remove( item.Serial );
Engine.SendPacketToClient( new ContainerContentUpdate( item.Serial, item.ID, item.Direction, item.Count,
item.X, item.Y, item.Grid, item.Owner, item.Hue ) );
_useOnce.Remove( item.Serial );
}
public bool Contains( int serial )
{
return _useOnce.Any( i => i == serial );
}
public void Clear()
{
// ReSharper disable once ForCanBeConvertedToForeach
for ( int index = 0; index < _useOnce.Count; index++ )
{
int serial = _useOnce[index];
if ( Engine.Items.GetItem( serial, out Item item ) )
{
Remove( item );
}
}
}
}
}

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