first commit
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
|
||||
</startup>
|
||||
<dllmap dll="SDL2.dll">
|
||||
<dllentry os="linux" dll="lib64/libSDL2-2.0.so.0" />
|
||||
<dllentry os="osx" dll="osx/libSDL2-2.0.0.dylib" />
|
||||
</dllmap>
|
||||
</configuration>
|
||||
@@ -0,0 +1,175 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<RootNamespace>ClassicAssist.Shared</RootNamespace>
|
||||
<UseWPF>false</UseWPF>
|
||||
<Configurations>Debug;Release;Linux</Configurations>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<OutputPath>..\Output</OutputPath>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Linux|AnyCPU'">
|
||||
<OutputPath>..\Output</OutputPath>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Data\Bodies.json" />
|
||||
<None Remove="Data\BuffIcons.json" />
|
||||
<None Remove="Data\Properties.json" />
|
||||
<None Remove="Data\Regions.json" />
|
||||
<None Remove="Data\Spells.json" />
|
||||
<None Remove="Data\Weapons.json" />
|
||||
<None Remove="Resources\Colours.xaml" />
|
||||
<None Remove="Resources\DarkTheme.xaml" />
|
||||
<None Remove="Resources\dialog-error.png" />
|
||||
<None Remove="Resources\dialog-info.png" />
|
||||
<None Remove="Resources\dialog-warn.png" />
|
||||
<None Remove="Resources\Icons.xaml" />
|
||||
<None Remove="Resources\LeftRightIconToggleButton.xaml" />
|
||||
<None Remove="Resources\ResourceDictionary.xaml" />
|
||||
<None Remove="zlib32.dll" />
|
||||
<None Remove="zlib64.dll" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="Data\Bodies.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Data\BuffIcons.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Data\Properties.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Data\Regions.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Data\Spells.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Data\Weapons.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="zlib32.dll">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="zlib64.dll">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources\arrow_down.png" />
|
||||
<EmbeddedResource Include="Resources\arrow_up.png" />
|
||||
<EmbeddedResource Include="Resources\dialog-error.png" />
|
||||
<EmbeddedResource Include="Resources\dialog-info.png" />
|
||||
<EmbeddedResource Include="Resources\dialog-warn.png" />
|
||||
<EmbeddedResource Include="Resources\green-circle.png" />
|
||||
<EmbeddedResource Include="Resources\kiss.wav" />
|
||||
<EmbeddedResource Include="Resources\lock.png" />
|
||||
<EmbeddedResource Include="Resources\python.png" />
|
||||
<EmbeddedResource Include="Resources\red-circle.png" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="IronPython" Version="2.7.10-candidate1" />
|
||||
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="Octokit" Version="0.48.0" />
|
||||
<PackageReference Include="OptimizedPriorityQueue" Version="4.2.0" />
|
||||
<PackageReference Include="reactiveui" Version="11.4.17" />
|
||||
<PackageReference Include="Sentry" Version="2.1.4" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="5.0.0-preview.6.20305.6" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Include="Resources\Colours.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Resources\DarkTheme.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Resources\Icons.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Resources\LeftRightIconToggleButton.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Resources\ResourceDictionary.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="cuoapi">
|
||||
<HintPath>cuoapi.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Resources\MacroCommandHelp.Designer.cs">
|
||||
<DependentUpon>MacroCommandHelp.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
</Compile>
|
||||
<Compile Update="Resources\Strings.Designer.cs">
|
||||
<DependentUpon>Strings.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Resources\MacroCommandHelp.it-IT.resx">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\MacroCommandHelp.resx">
|
||||
<SubType>Designer</SubType>
|
||||
<LastGenOutput>MacroCommandHelp.Designer.cs</LastGenOutput>
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\Strings.en-AU.resx">
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\Strings.en-GB.resx">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\Strings.pl-PL.resx">
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\Strings.resx">
|
||||
<SubType>Designer</SubType>
|
||||
<LastGenOutput>Strings.Designer.cs</LastGenOutput>
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Data\Masteries.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Data\MountID.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<BuildDate>$([System.DateTime]::op_Subtraction($([System.DateTime]::get_Now().get_Date()),$([System.DateTime]::new(2020,7,3))).get_TotalDays())</BuildDate>
|
||||
<Version>0.3.$(BuildDate).0</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Resources\Strings.pl-PL.resx">
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user