diff --git a/Artemis/Artemis/App.config b/Artemis/Artemis/App.config
index 3ccf6e7e5..cedff3614 100644
--- a/Artemis/Artemis/App.config
+++ b/Artemis/Artemis/App.config
@@ -10,7 +10,7 @@
-
+
@@ -30,7 +30,7 @@
-
+
@@ -44,6 +44,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/Artemis/Artemis/Artemis.csproj b/Artemis/Artemis/Artemis.csproj
index 5f0aea86c..5b67a756b 100644
--- a/Artemis/Artemis/Artemis.csproj
+++ b/Artemis/Artemis/Artemis.csproj
@@ -45,6 +45,7 @@
true
true
true
+ 38ead84566f241de8f334abe173b1038
x64
@@ -140,32 +141,23 @@
True
- ..\packages\Caliburn.Micro.Core.3.0.3\lib\net45\Caliburn.Micro.dll
- True
+ ..\packages\Caliburn.Micro.Core.3.1.0\lib\net45\Caliburn.Micro.dll
- ..\packages\Caliburn.Micro.3.0.3\lib\net45\Caliburn.Micro.Platform.dll
- True
+ ..\packages\Caliburn.Micro.3.1.0\lib\net45\Caliburn.Micro.Platform.dll
- ..\packages\Caliburn.Micro.3.0.3\lib\net45\Caliburn.Micro.Platform.Core.dll
- True
-
-
- ..\packages\Castle.Core.4.0.0\lib\net45\Castle.Core.dll
- True
+ ..\packages\Caliburn.Micro.3.1.0\lib\net45\Caliburn.Micro.Platform.Core.dll
..\packages\Colore.5.1.0\lib\net35\Corale.Colore.dll
True
-
- ..\packages\CSCore.1.2.0\lib\net35-client\CSCore.dll
- True
+
+ ..\packages\CSCore.1.2.1.2\lib\net35-client\CSCore.dll
-
- ..\packages\CUE.NET.1.1.3.0\lib\net45\CUE.NET.dll
- True
+
+ ..\packages\CUE.NET.1.1.3.1\lib\net45\CUE.NET.dll
..\packages\DeltaCompressionDotNet.1.1.0\lib\net20\DeltaCompressionDotNet.dll
@@ -179,9 +171,8 @@
..\packages\DeltaCompressionDotNet.1.1.0\lib\net20\DeltaCompressionDotNet.PatchApi.dll
True
-
- ..\packages\DynamicExpresso.Core.1.3.3.5\lib\net40\DynamicExpresso.Core.dll
- True
+
+ ..\packages\DynamicExpresso.Core.1.3.4.7\lib\net40\DynamicExpresso.Core.dll
..\packages\MouseKeyHook.5.4.0\lib\net40\Gma.System.MouseKeyHook.dll
@@ -197,7 +188,6 @@
..\packages\squirrel.windows.1.4.4\lib\Net45\ICSharpCode.SharpZipLib.dll
- True
..\packages\log4net.2.0.8\lib\net45-full\log4net.dll
@@ -205,7 +195,9 @@
..\packages\MahApps.Metro.1.4.3\lib\net45\MahApps.Metro.dll
- True
+
+
+ ..\packages\TaskScheduler.2.6.5\lib\net452\Microsoft.Win32.TaskScheduler.dll
..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.dll
@@ -227,9 +219,8 @@
..\packages\MoonSharp.2.0.0.0\lib\net40-client\MoonSharp.Interpreter.dll
True
-
- ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll
- True
+
+ ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll
..\packages\Ninject.3.2.2.0\lib\net45-full\Ninject.dll
@@ -248,36 +239,42 @@
True
- ..\packages\NLog.4.4.4\lib\net45\NLog.dll
- True
+ ..\packages\NLog.4.4.12\lib\net45\NLog.dll
..\packages\squirrel.windows.1.4.4\lib\Net45\NuGet.Squirrel.dll
- True
+
+
+ ..\packages\Pcap.Net.x64.1.0.4.1\lib\net45\PcapDotNet.Base.dll
+
+
+ ..\packages\Pcap.Net.x64.1.0.4.1\lib\net45\PcapDotNet.Core.dll
+
+
+ ..\packages\Pcap.Net.x64.1.0.4.1\lib\net45\PcapDotNet.Core.Extensions.dll
+
+
+ ..\packages\Pcap.Net.x64.1.0.4.1\lib\net45\PcapDotNet.Packets.dll
..\packages\Process.NET.1.0.8\lib\Process.NET.dll
True
-
- ..\packages\SharpDX.3.1.1\lib\net45\SharpDX.dll
- True
+
+ ..\packages\SharpDX.4.0.1\lib\net45\SharpDX.dll
-
- ..\packages\SharpDX.Direct3D9.3.1.1\lib\net45\SharpDX.Direct3D9.dll
- True
+
+ ..\packages\SharpDX.Direct3D9.4.0.1\lib\net45\SharpDX.Direct3D9.dll
..\packages\Splat.2.0.0\lib\Net45\Splat.dll
True
- ..\packages\SpotifyAPI-NET.2.13.1\lib\SpotifyAPI.dll
- True
+ ..\packages\SpotifyAPI-NET.2.16.1\lib\SpotifyAPI.dll
..\packages\squirrel.windows.1.4.4\lib\Net45\Squirrel.dll
- True
@@ -291,7 +288,6 @@
..\packages\MahApps.Metro.1.4.3\lib\net45\System.Windows.Interactivity.dll
- True
@@ -340,6 +336,7 @@
+
MarkdownDialog.xaml
@@ -384,6 +381,13 @@
AssettoCorsaView.xaml
+
+
+
+ FormulaOne2017View.xaml
+
+
+
@@ -391,6 +395,13 @@
TerrariaView.xaml
+
+
+
+
+
+
+
@@ -470,15 +481,6 @@
UnrealTournamentView.xaml
-
-
-
-
-
-
-
-
-
WoWView.xaml
@@ -486,7 +488,6 @@
-
@@ -573,6 +574,7 @@
+
LuaWindowView.xaml
@@ -801,6 +803,17 @@
Code
+
+
+
+
+
+
+
+
+
+
+
Designer
@@ -880,6 +893,10 @@
MSBuild:Compile
Designer
+
+ MSBuild:Compile
+ Designer
+
Designer
MSBuild:Compile
@@ -1075,6 +1092,13 @@
+
+
+
+
+
+
+
@@ -1096,15 +1120,16 @@
+
-
+
This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
+
+
+
+
+
+ The F1 2017 module requires UDP Telemetry to be enabled in the ingame settings menu.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/FormulaOne2017/FormulaOne2017View.xaml.cs b/Artemis/Artemis/Modules/Games/FormulaOne2017/FormulaOne2017View.xaml.cs
new file mode 100644
index 000000000..0d3e85bcd
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/FormulaOne2017/FormulaOne2017View.xaml.cs
@@ -0,0 +1,12 @@
+using System.Windows.Controls;
+
+namespace Artemis.Modules.Games.FormulaOne2017
+{
+ public partial class FormulaOne2017View : UserControl
+ {
+ public FormulaOne2017View()
+ {
+ InitializeComponent();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/FormulaOne2017/FormulaOne2017ViewModel.cs b/Artemis/Artemis/Modules/Games/FormulaOne2017/FormulaOne2017ViewModel.cs
new file mode 100644
index 000000000..42faf13bd
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/FormulaOne2017/FormulaOne2017ViewModel.cs
@@ -0,0 +1,17 @@
+using Artemis.Managers;
+using Artemis.Modules.Abstract;
+using Ninject;
+
+namespace Artemis.Modules.Games.FormulaOne2017
+{
+ public sealed class FormulaOne2017ViewModel : ModuleViewModel
+ {
+ public FormulaOne2017ViewModel(MainManager mainManager, [Named(nameof(FormulaOne2017Model))] ModuleModel moduleModel,
+ IKernel kernel) : base(mainManager, moduleModel, kernel)
+ {
+ DisplayName = "F1 2017";
+ }
+
+ public override bool UsesProfileEditor => true;
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/Overwatch/OverwatchDataModel.cs b/Artemis/Artemis/Modules/Games/Overwatch/OverwatchDataModel.cs
index d88a3a28e..72895b27d 100644
--- a/Artemis/Artemis/Modules/Games/Overwatch/OverwatchDataModel.cs
+++ b/Artemis/Artemis/Modules/Games/Overwatch/OverwatchDataModel.cs
@@ -48,6 +48,8 @@ namespace Artemis.Modules.Games.Overwatch
Symmetra,
Zenyatta,
Ana,
- Sombra
+ Sombra,
+ Orisa,
+ Doomfist
}
}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/Overwatch/OverwatchModel.cs b/Artemis/Artemis/Modules/Games/Overwatch/OverwatchModel.cs
index 819611cb0..4a216cd99 100644
--- a/Artemis/Artemis/Modules/Games/Overwatch/OverwatchModel.cs
+++ b/Artemis/Artemis/Modules/Games/Overwatch/OverwatchModel.cs
@@ -76,7 +76,9 @@ namespace Artemis.Modules.Games.Overwatch
new CharacterColor {Character = OverwatchCharacter.Symmetra, Color = Color.FromRgb(46, 116, 148)},
new CharacterColor {Character = OverwatchCharacter.Zenyatta, Color = Color.FromRgb(248, 218, 26)},
new CharacterColor {Character = OverwatchCharacter.Ana, Color = Color.FromRgb(16, 36, 87)},
- new CharacterColor {Character = OverwatchCharacter.Sombra, Color = Color.FromRgb(20, 5, 101)}
+ new CharacterColor {Character = OverwatchCharacter.Sombra, Color = Color.FromRgb(20, 5, 101)},
+ new CharacterColor {Character = OverwatchCharacter.Orisa, Color = Color.FromRgb(1,40,0)},
+ new CharacterColor {Character = OverwatchCharacter.Doomfist, Color = Color.FromRgb(33, 3, 1)}
};
}
diff --git a/Artemis/Artemis/Modules/Games/Overwatch/OverwatchView.xaml b/Artemis/Artemis/Modules/Games/Overwatch/OverwatchView.xaml
index 7fa2840a1..60369248f 100644
--- a/Artemis/Artemis/Modules/Games/Overwatch/OverwatchView.xaml
+++ b/Artemis/Artemis/Modules/Games/Overwatch/OverwatchView.xaml
@@ -41,7 +41,7 @@
-
+
diff --git a/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueViewModel.cs b/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueViewModel.cs
index a1f168377..59ef8c499 100644
--- a/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueViewModel.cs
+++ b/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueViewModel.cs
@@ -41,7 +41,7 @@ namespace Artemis.Modules.Games.RocketLeague
}
Updater.GetPointers();
- var version = SettingsProvider.Load().RocketLeague.GameVersion;
+ var version = SettingsProvider.Load().RocketLeague?.GameVersion;
VersionText = $"Requires patch {version}. When a new patch is released Artemis downloads new pointers for the latest version (unless disabled in settings).";
}
}
diff --git a/Artemis/Artemis/Modules/Games/UnrealTournament/Resources/ut-plugin.zip b/Artemis/Artemis/Modules/Games/UnrealTournament/Resources/ut-plugin.zip
index 80d8f3fbc..9973ee615 100644
Binary files a/Artemis/Artemis/Modules/Games/UnrealTournament/Resources/ut-plugin.zip and b/Artemis/Artemis/Modules/Games/UnrealTournament/Resources/ut-plugin.zip differ
diff --git a/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournamentModel.cs b/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournamentModel.cs
index 5a6ba3d87..1fb4f2c8e 100644
--- a/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournamentModel.cs
+++ b/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournamentModel.cs
@@ -47,7 +47,7 @@ namespace Artemis.Modules.Games.UnrealTournament
var gameSettings = (UnrealTournamentSettings) Settings;
// If already propertly set up, don't do anything
if (gameSettings.GameDirectory != null &&
- File.Exists(gameSettings.GameDirectory + "UE4-Win64-Shipping.exe"))
+ File.Exists(gameSettings.GameDirectory + @"\Engine\Binaries\Win64\UE4-Win64-Shipping.exe"))
return;
// Attempt to read the file
@@ -65,7 +65,7 @@ namespace Artemis.Modules.Games.UnrealTournament
// Use backslash in path for consistency
utDir = utDir.Replace('/', '\\');
- if (!File.Exists(utDir + @"\UE4-Win64-Shipping.exe"))
+ if (!File.Exists(utDir + @"\Engine\Binaries\Win64\UE4-Win64-Shipping.exe"))
return;
gameSettings.GameDirectory = utDir;
@@ -78,7 +78,7 @@ namespace Artemis.Modules.Games.UnrealTournament
var gameSettings = (UnrealTournamentSettings) Settings;
var path = gameSettings.GameDirectory;
- if (!File.Exists(path + @"\UE4-Win64-Shipping.exe"))
+ if (!File.Exists(path + @"\Engine\Binaries\Win64\UE4-Win64-Shipping.exe"))
{
_dialogService.ShowErrorMessageBox("Please select a valid Unreal Tournament directory\n\n" +
@"By default Unreal Tournament is in C:\Program Files\Epic Games\UnrealTournament");
diff --git a/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournamentViewModel.cs b/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournamentViewModel.cs
index 3ed9edeee..81f678981 100644
--- a/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournamentViewModel.cs
+++ b/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournamentViewModel.cs
@@ -1,52 +1,52 @@
-using System.Windows.Forms;
-using Artemis.DAL;
-using Artemis.Managers;
-using Artemis.Modules.Abstract;
-using Artemis.Properties;
-using Ninject;
-
-namespace Artemis.Modules.Games.UnrealTournament
-{
- public sealed class UnrealTournamentViewModel : ModuleViewModel
- {
- public UnrealTournamentViewModel(MainManager mainManager,
- [Named(nameof(UnrealTournamentModel))] ModuleModel moduleModel, IKernel kernel)
- : base(mainManager, moduleModel, kernel)
- {
- DisplayName = "Unreal Tournament";
- InstallGif();
- }
-
- public override bool UsesProfileEditor => true;
-
- public void BrowseDirectory()
- {
- var dialog = new FolderBrowserDialog {SelectedPath = ((UnrealTournamentSettings) Settings).GameDirectory};
- var result = dialog.ShowDialog();
- if (result != DialogResult.OK)
- return;
-
- ((UnrealTournamentSettings) Settings).GameDirectory = dialog.SelectedPath;
- ((UnrealTournamentModel) ModuleModel).PlaceFiles();
- Settings.Save();
- NotifyOfPropertyChange(() => Settings);
- }
-
- public void PlaceFiles()
+using System.Windows.Forms;
+using Artemis.DAL;
+using Artemis.Managers;
+using Artemis.Modules.Abstract;
+using Artemis.Properties;
+using Ninject;
+
+namespace Artemis.Modules.Games.UnrealTournament
+{
+ public sealed class UnrealTournamentViewModel : ModuleViewModel
+ {
+ public UnrealTournamentViewModel(MainManager mainManager,
+ [Named(nameof(UnrealTournamentModel))] ModuleModel moduleModel, IKernel kernel)
+ : base(mainManager, moduleModel, kernel)
{
- ((UnrealTournamentModel)ModuleModel).PlaceFiles();
- Settings.Save();
- NotifyOfPropertyChange(() => Settings);
- }
-
- // Installing GIF on editor open to make sure the proper profiles are loaded
- private void InstallGif()
- {
- var gif = Resources.redeemer;
- if (gif == null)
- return;
-
- ProfileProvider.InsertGif("UnrealTournament", "Default", "Redeemer GIF", gif, "redeemer");
- }
- }
+ DisplayName = "Unreal Tournament";
+ InstallGif();
+ }
+
+ public override bool UsesProfileEditor => true;
+
+ public void BrowseDirectory()
+ {
+ var dialog = new FolderBrowserDialog {SelectedPath = ((UnrealTournamentSettings) Settings).GameDirectory};
+ var result = dialog.ShowDialog();
+ if (result != DialogResult.OK)
+ return;
+
+ ((UnrealTournamentSettings) Settings).GameDirectory = dialog.SelectedPath;
+ ((UnrealTournamentModel) ModuleModel).PlaceFiles();
+ Settings.Save();
+ NotifyOfPropertyChange(() => Settings);
+ }
+
+ public void PlaceFiles()
+ {
+ ((UnrealTournamentModel)ModuleModel).PlaceFiles();
+ Settings.Save();
+ NotifyOfPropertyChange(() => Settings);
+ }
+
+ // Installing GIF on editor open to make sure the proper profiles are loaded
+ private void InstallGif()
+ {
+ var gif = Resources.redeemer;
+ if (gif == null)
+ return;
+
+ ProfileProvider.InsertGif("UnrealTournament", "Default", "Redeemer GIF", gif, "redeemer");
+ }
+ }
}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/WoW/Data/Int128.cs b/Artemis/Artemis/Modules/Games/WoW/Data/Int128.cs
deleted file mode 100644
index 4a66ecc0f..000000000
--- a/Artemis/Artemis/Modules/Games/WoW/Data/Int128.cs
+++ /dev/null
@@ -1,2256 +0,0 @@
-using System;
-using System.ComponentModel;
-using System.Globalization;
-using System.IO;
-using System.Runtime.InteropServices;
-using System.Text;
-using Microsoft.SqlServer.Server;
-
-namespace Artemis.Modules.Games.WoW.Data
-{
- namespace WowSharp.Client.Patchables
- {
- ///
- /// Represents a 128-bit signed integer.
- ///
-#if !WINDOWS_PHONE && !SILVERLIGHT
- [Serializable]
-#endif
- [StructLayout(LayoutKind.Sequential)]
- [TypeConverter(typeof(Int128Converter))]
- public struct Int128 : IComparable, IComparable, IEquatable, IConvertible, IFormattable
-#if !WINDOWS_PHONE && !SILVERLIGHT
- , IBinarySerialize
-#endif
- {
- private ulong _hi;
- private ulong _lo;
-
- private const ulong HiNeg = 0x8000000000000000;
-
- ///
- /// Gets a value that represents the number 0 (zero).
- ///
- public static Int128 Zero = GetZero();
-
- ///
- /// Represents the largest possible value of an Int128.
- ///
- public static Int128 MaxValue = GetMaxValue();
-
- ///
- /// Represents the smallest possible value of an Int128.
- ///
- public static Int128 MinValue = GetMinValue();
-
- private static Int128 GetMaxValue()
- {
- return new Int128(long.MaxValue, ulong.MaxValue);
- }
-
- private static Int128 GetMinValue()
- {
- return new Int128(HiNeg, 0);
- }
-
- private static Int128 GetZero()
- {
- return new Int128();
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The value.
- public Int128(byte value)
- {
- _hi = 0;
- _lo = value;
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// if set to true [value].
- public Int128(bool value)
- {
- _hi = 0;
- _lo = (ulong) (value ? 1 : 0);
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The value.
- public Int128(char value)
- {
- _hi = 0;
- _lo = value;
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The value.
- public Int128(decimal value)
- {
- if (value < 0)
- {
- var n = -new Int128(-value);
- _hi = n._hi;
- _lo = n._lo;
- return;
- }
-
- var bits = decimal.GetBits(value);
- _hi = (uint) bits[2];
- _lo = (uint) bits[0] | ((ulong) bits[1] << 32);
-
- var scale = (bits[3] >> 16) & 31;
- if (scale > 0)
- {
- var i = new Int128(_hi, _lo);
- for (var s = 0; s < scale; s++)
- i = i/10;
- _hi = i._hi;
- _lo = i._lo;
- }
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The value.
- public Int128(double value)
- : this((decimal) value)
- {
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The value.
- public Int128(float value)
- : this((decimal) value)
- {
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The value.
- public Int128(short value)
- : this((int) value)
- {
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The value.
- public Int128(int value)
- : this((long) value)
- {
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The value.
- public Int128(long value)
- {
- if (value < 0)
- {
- // long.MinValue = -long.MinValue
- if (value == long.MinValue)
- {
- _hi = HiNeg;
- _lo = HiNeg;
- return;
- }
-
- var n = -new Int128(-value);
- _hi = n._hi;
- _lo = n._lo;
- return;
- }
-
- _hi = 0;
- _lo = (ulong) value;
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The value.
- public Int128(sbyte value)
- : this((long) value)
- {
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The value.
- public Int128(ushort value)
- {
- _hi = 0;
- _lo = value;
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The value.
- public Int128(uint value)
- {
- _hi = 0;
- _lo = value;
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The value.
- public Int128(ulong value)
- {
- _hi = 0;
- _lo = value;
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The value.
- public Int128(Guid value)
- : this(value.ToByteArray())
- {
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The value.
- public Int128(byte[] value)
- {
- if (value == null)
- throw new ArgumentNullException("value");
-
- if (value.Length != 16)
- throw new ArgumentException(null, "value");
-
- _hi = BitConverter.ToUInt64(value, 8);
- _lo = BitConverter.ToUInt64(value, 0);
- }
-
- public Int128(ulong hi, ulong lo)
- {
- _hi = hi;
- _lo = lo;
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The sign.
- /// The ints.
- public Int128(int sign, uint[] ints)
- {
- if (ints == null)
- throw new ArgumentNullException("ints");
-
- var lo = new byte[8];
- var hi = new byte[8];
-
- if (ints.Length > 0)
- {
- Array.Copy(BitConverter.GetBytes(ints[0]), 0, lo, 0, 4);
- if (ints.Length > 1)
- {
- Array.Copy(BitConverter.GetBytes(ints[1]), 0, lo, 4, 4);
- if (ints.Length > 2)
- {
- Array.Copy(BitConverter.GetBytes(ints[2]), 0, hi, 0, 4);
- if (ints.Length > 3)
- Array.Copy(BitConverter.GetBytes(ints[3]), 0, hi, 4, 4);
- }
- }
- }
-
- _lo = BitConverter.ToUInt64(lo, 0);
- _hi = BitConverter.ToUInt64(hi, 0);
-
- if (sign < 0)
- _hi |= HiNeg;
- else
- _hi &= ~HiNeg;
- }
-
- ///
- /// Gets a number that indicates the sign (negative, positive, or zero) of the current Int128 object.
- ///
- /// A number that indicates the sign of the Int128 object
- public int Sign
- {
- get
- {
- if ((_hi == 0) && (_lo == 0))
- return 0;
-
- return (_hi & HiNeg) == 0 ? 1 : -1;
- }
- }
-
- ///
- /// Returns a hash code for this instance.
- ///
- ///
- /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
- ///
- public override int GetHashCode()
- {
- return _hi.GetHashCode() ^ _lo.GetHashCode();
- }
-
- ///
- /// Returns a value indicating whether this instance is equal to a specified object.
- ///
- /// An object to compare with this instance.
- ///
- /// true if obj has the same value as this instance; otherwise, false.
- ///
- public override bool Equals(object obj)
- {
- return base.Equals(obj);
- }
-
- ///
- /// Returns a value indicating whether this instance is equal to a specified Int64 value.
- ///
- /// The obj.
- ///
- /// true if obj has the same value as this instance; otherwise, false.
- ///
- public bool Equals(Int128 obj)
- {
- return (_hi == obj._hi) && (_lo == obj._lo);
- }
-
- ///
- /// Returns a that represents this instance.
- ///
- ///
- /// A that represents this instance.
- ///
- public override string ToString()
- {
- return ToString(null, null);
- }
-
- ///
- /// Returns a that represents this instance.
- ///
- /// The format. Only x, X, g, G, d, D are supported.
- ///
- /// A that represents this instance.
- ///
- public string ToString(string format)
- {
- return ToString(format, null);
- }
-
- ///
- /// Returns a that represents this instance.
- ///
- /// The format. Only x, X, g, G, d, D are supported.
- /// An object that supplies culture-specific formatting information about this instance.
- ///
- /// A that represents this instance.
- ///
- public string ToString(string format, IFormatProvider formatProvider)
- {
- if (formatProvider == null)
- formatProvider = CultureInfo.CurrentCulture;
-
- if (!string.IsNullOrEmpty(format))
- {
- var ch = format[0];
- if ((ch == 'x') || (ch == 'X'))
- {
- int min;
- int.TryParse(format.Substring(1).Trim(), out min);
- return ToHexaString(ch == 'X', min);
- }
-
- if ((ch != 'G') && (ch != 'g') && (ch != 'D') && (ch != 'd'))
- throw new NotSupportedException("Not supported format: " + format);
- }
-
- return ToString((NumberFormatInfo) formatProvider.GetFormat(typeof(NumberFormatInfo)));
- }
-
- private string ToHexaString(bool caps, int min)
- {
- var sb = new StringBuilder();
- var x = caps ? "X" : "x";
- if ((min < 0) || (min > 16) || (_hi != 0))
- {
- sb.Append(min > 16 ? _hi.ToString(x + (min - 16)) : _hi.ToString(x));
- sb.Append(_lo.ToString(x + "16"));
- }
- else
- {
- sb.Append(_lo.ToString(x + min));
- }
- return sb.ToString();
- }
-
- private string ToString(NumberFormatInfo info)
- {
- if (Sign == 0)
- return "0";
-
- var sb = new StringBuilder();
- var ten = new Int128(10);
- var current = this;
- current._hi &= ~HiNeg;
- Int128 r;
- while (true)
- {
- current = DivRem(current, ten, out r);
- if ((r._lo > 0) || (current.Sign != 0) || (sb.Length == 0))
- {
-#if !WINDOWS_PHONE && !SILVERLIGHT
- sb.Insert(0, (char) ('0' + r._lo));
-#else
- sb.Insert(0, new[] { (char)('0' + r._lo) });
-#endif
- }
- if (current.Sign == 0)
- break;
- }
-
- var s = sb.ToString();
- if ((Sign < 0) && (s != "0"))
- return info.NegativeSign + s;
-
- return s;
- }
-
- ///
- /// Returns the for this instance.
- ///
- ///
- /// The enumerated constant that is the of the class or value type that implements
- /// this interface.
- ///
- TypeCode IConvertible.GetTypeCode()
- {
- return TypeCode.Object;
- }
-
- ///
- /// Converts the value of this instance to an equivalent Boolean value using the specified culture-specific formatting
- /// information.
- ///
- ///
- /// An interface implementation that supplies
- /// culture-specific formatting information.
- ///
- ///
- /// A Boolean value equivalent to the value of this instance.
- ///
- bool IConvertible.ToBoolean(IFormatProvider provider)
- {
- return (bool) this;
- }
-
- ///
- /// Converts the value of this instance to an equivalent 8-bit unsigned integer using the specified culture-specific
- /// formatting information.
- ///
- ///
- /// An interface implementation that supplies
- /// culture-specific formatting information.
- ///
- ///
- /// An 8-bit unsigned integer equivalent to the value of this instance.
- ///
- byte IConvertible.ToByte(IFormatProvider provider)
- {
- return (byte) this;
- }
-
- ///
- /// Converts the value of this instance to an equivalent Unicode character using the specified culture-specific
- /// formatting information.
- ///
- ///
- /// An interface implementation that supplies
- /// culture-specific formatting information.
- ///
- ///
- /// A Unicode character equivalent to the value of this instance.
- ///
- char IConvertible.ToChar(IFormatProvider provider)
- {
- return (char) this;
- }
-
- ///
- /// Converts the value of this instance to an equivalent using the specified
- /// culture-specific formatting information.
- ///
- ///
- /// An interface implementation that supplies
- /// culture-specific formatting information.
- ///
- ///
- /// A instance equivalent to the value of this instance.
- ///
- DateTime IConvertible.ToDateTime(IFormatProvider provider)
- {
- throw new InvalidCastException();
- }
-
- ///
- /// Converts the value of this instance to an equivalent number using the specified
- /// culture-specific formatting information.
- ///
- ///
- /// An interface implementation that supplies
- /// culture-specific formatting information.
- ///
- ///
- /// A number equivalent to the value of this instance.
- ///
- decimal IConvertible.ToDecimal(IFormatProvider provider)
- {
- return (decimal) this;
- }
-
- ///
- /// Converts the value of this instance to an equivalent double-precision floating-point number using the specified
- /// culture-specific formatting information.
- ///
- ///
- /// An interface implementation that supplies
- /// culture-specific formatting information.
- ///
- ///
- /// A double-precision floating-point number equivalent to the value of this instance.
- ///
- double IConvertible.ToDouble(IFormatProvider provider)
- {
- return (double) this;
- }
-
- ///
- /// Converts the value of this instance to an equivalent 16-bit signed integer using the specified culture-specific
- /// formatting information.
- ///
- ///
- /// An interface implementation that supplies
- /// culture-specific formatting information.
- ///
- ///
- /// An 16-bit signed integer equivalent to the value of this instance.
- ///
- short IConvertible.ToInt16(IFormatProvider provider)
- {
- return (short) this;
- }
-
- ///
- /// Converts the value of this instance to an equivalent 32-bit signed integer using the specified culture-specific
- /// formatting information.
- ///
- ///
- /// An interface implementation that supplies
- /// culture-specific formatting information.
- ///
- ///
- /// An 32-bit signed integer equivalent to the value of this instance.
- ///
- int IConvertible.ToInt32(IFormatProvider provider)
- {
- return (int) this;
- }
-
- ///
- /// Converts the value of this instance to an equivalent 64-bit signed integer using the specified culture-specific
- /// formatting information.
- ///
- ///
- /// An interface implementation that supplies
- /// culture-specific formatting information.
- ///
- ///
- /// An 64-bit signed integer equivalent to the value of this instance.
- ///
- long IConvertible.ToInt64(IFormatProvider provider)
- {
- return (int) this;
- }
-
- ///
- /// Converts the value of this instance to an equivalent 8-bit signed integer using the specified culture-specific
- /// formatting information.
- ///
- ///
- /// An interface implementation that supplies
- /// culture-specific formatting information.
- ///
- ///
- /// An 8-bit signed integer equivalent to the value of this instance.
- ///
- sbyte IConvertible.ToSByte(IFormatProvider provider)
- {
- return (sbyte) this;
- }
-
- ///
- /// Converts the value of this instance to an equivalent single-precision floating-point number using the specified
- /// culture-specific formatting information.
- ///
- ///
- /// An interface implementation that supplies
- /// culture-specific formatting information.
- ///
- ///
- /// A single-precision floating-point number equivalent to the value of this instance.
- ///
- float IConvertible.ToSingle(IFormatProvider provider)
- {
- return (float) this;
- }
-
- ///
- /// Returns a that represents this instance.
- ///
- /// The provider.
- ///
- /// A that represents this instance.
- ///
- string IConvertible.ToString(IFormatProvider provider)
- {
- return ToString(null, provider);
- }
-
- ///
- /// Converts the numeric value to an equivalent object. The return value indicates whether the conversion succeeded.
- ///
- /// The target conversion type.
- /// An object that supplies culture-specific information about the conversion.
- ///
- /// When this method returns, contains the value that is equivalent to the numeric value, if the
- /// conversion succeeded, or is null if the conversion failed. This parameter is passed uninitialized.
- ///
- /// true if this value was converted successfully; otherwise, false.
- public bool TryConvert(Type conversionType, IFormatProvider provider, out object value)
- {
- if (conversionType == typeof(bool))
- {
- value = (bool) this;
- return true;
- }
-
- if (conversionType == typeof(byte))
- {
- value = (byte) this;
- return true;
- }
-
- if (conversionType == typeof(char))
- {
- value = (char) this;
- return true;
- }
-
- if (conversionType == typeof(decimal))
- {
- value = (decimal) this;
- return true;
- }
-
- if (conversionType == typeof(double))
- {
- value = (double) this;
- return true;
- }
-
- if (conversionType == typeof(short))
- {
- value = (short) this;
- return true;
- }
-
- if (conversionType == typeof(int))
- {
- value = (int) this;
- return true;
- }
-
- if (conversionType == typeof(long))
- {
- value = (long) this;
- return true;
- }
-
- if (conversionType == typeof(sbyte))
- {
- value = (sbyte) this;
- return true;
- }
-
- if (conversionType == typeof(float))
- {
- value = (float) this;
- return true;
- }
-
- if (conversionType == typeof(string))
- {
- value = ToString(null, provider);
- return true;
- }
-
- if (conversionType == typeof(ushort))
- {
- value = (ushort) this;
- return true;
- }
-
- if (conversionType == typeof(uint))
- {
- value = (uint) this;
- return true;
- }
-
- if (conversionType == typeof(ulong))
- {
- value = (ulong) this;
- return true;
- }
-
- if (conversionType == typeof(byte[]))
- {
- value = ToByteArray();
- return true;
- }
-
- if (conversionType == typeof(Guid))
- {
- value = new Guid(ToByteArray());
- return true;
- }
-
- value = null;
- return false;
- }
-
- ///
- /// Converts the string representation of a number to its Int128 equivalent.
- ///
- /// A string that contains a number to convert.
- ///
- /// A value that is equivalent to the number specified in the value parameter.
- ///
- public static Int128 Parse(string value)
- {
- return Parse(value, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
- }
-
- ///
- /// Converts the string representation of a number in a specified style format to its Int128 equivalent.
- ///
- /// A string that contains a number to convert.
- /// A bitwise combination of the enumeration values that specify the permitted format of value.
- ///
- /// A value that is equivalent to the number specified in the value parameter.
- ///
- public static Int128 Parse(string value, NumberStyles style)
- {
- return Parse(value, style, NumberFormatInfo.CurrentInfo);
- }
-
- ///
- /// Converts the string representation of a number in a culture-specific format to its Int128 equivalent.
- ///
- /// A string that contains a number to convert.
- /// An object that provides culture-specific formatting information about value.
- ///
- /// A value that is equivalent to the number specified in the value parameter.
- ///
- public static Int128 Parse(string value, IFormatProvider provider)
- {
- return Parse(value, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
- }
-
- ///
- /// Converts the string representation of a number in a specified style and culture-specific format to its Int128
- /// equivalent.
- ///
- /// A string that contains a number to convert.
- /// A bitwise combination of the enumeration values that specify the permitted format of value.
- /// An object that provides culture-specific formatting information about value.
- /// A value that is equivalent to the number specified in the value parameter.
- public static Int128 Parse(string value, NumberStyles style, IFormatProvider provider)
- {
- Int128 result;
- if (!TryParse(value, style, provider, out result))
- throw new ArgumentException(null, "value");
-
- return result;
- }
-
- ///
- /// Tries to convert the string representation of a number to its Int128 equivalent, and returns a value that indicates
- /// whether the conversion succeeded..
- ///
- /// The string representation of a number.
- ///
- /// When this method returns, contains the Int128 equivalent to the number that is contained in value,
- /// or Int128.Zero if the conversion failed. This parameter is passed uninitialized.
- ///
- ///
- /// true if the value parameter was converted successfully; otherwise, false.
- ///
- public static bool TryParse(string value, out Int128 result)
- {
- return TryParse(value, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
- }
-
- ///
- /// Tries to convert the string representation of a number in a specified style and culture-specific format to its
- /// Int128 equivalent, and returns a value that indicates whether the conversion succeeded..
- ///
- ///
- /// The string representation of a number. The string is interpreted using the style specified by
- /// style.
- ///
- ///
- /// A bitwise combination of enumeration values that indicates the style elements that can be present
- /// in value. A typical value to specify is NumberStyles.Integer.
- ///
- /// An object that supplies culture-specific formatting information about value.
- ///
- /// When this method returns, contains the Int128 equivalent to the number that is contained in value,
- /// or Int128.Zero if the conversion failed. This parameter is passed uninitialized.
- ///
- /// true if the value parameter was converted successfully; otherwise, false.
- public static bool TryParse(string value, NumberStyles style, IFormatProvider provider, out Int128 result)
- {
- result = Zero;
- if (string.IsNullOrEmpty(value))
- return false;
-
- if (value.StartsWith("x", StringComparison.OrdinalIgnoreCase))
- {
- style |= NumberStyles.AllowHexSpecifier;
- value = value.Substring(1);
- }
- else if (value.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
- {
- style |= NumberStyles.AllowHexSpecifier;
- value = value.Substring(2);
- }
-
- if ((style & NumberStyles.AllowHexSpecifier) == NumberStyles.AllowHexSpecifier)
- return TryParseHex(value, out result);
-
- return TryParseNum(value, out result);
- }
-
- private static bool TryParseHex(string value, out Int128 result)
- {
- if (value.Length > 32)
- throw new OverflowException();
-
- result = Zero;
- var hi = false;
- var pos = 0;
- for (var i = value.Length - 1; i >= 0; i--)
- {
- var ch = value[i];
- ulong b;
- if ((ch >= '0') && (ch <= '9'))
- b = (ulong) (ch - '0');
- else if ((ch >= 'A') && (ch <= 'F'))
- b = (ulong) (ch - 'A' + 10);
- else if ((ch >= 'a') && (ch <= 'f'))
- b = (ulong) (ch - 'a' + 10);
- else
- return false;
-
- if (hi)
- {
- result._hi |= b << pos;
- pos += 4;
- }
- else
- {
- result._lo |= b << pos;
- pos += 4;
- if (pos == 64)
- {
- pos = 0;
- hi = true;
- }
- }
- }
- return true;
- }
-
- private static bool TryParseNum(string value, out Int128 result)
- {
- result = Zero;
- foreach (var ch in value)
- {
- byte b;
- if ((ch >= '0') && (ch <= '9'))
- b = (byte) (ch - '0');
- else
- return false;
-
- result = 10*result;
- result += b;
- }
- return true;
- }
-
- ///
- /// Converts the value of this instance to an of the specified
- /// that has an equivalent value, using the specified culture-specific formatting
- /// information.
- ///
- /// The to which the value of this instance is converted.
- ///
- /// An interface implementation that supplies
- /// culture-specific formatting information.
- ///
- ///
- /// An instance of type whose value is equivalent to
- /// the value of this instance.
- ///
- public object ToType(Type conversionType, IFormatProvider provider)
- {
- object value;
- if (TryConvert(conversionType, provider, out value))
- return value;
-
- throw new InvalidCastException();
- }
-
- ///
- /// Converts the value of this instance to an equivalent 16-bit unsigned integer using the specified culture-specific
- /// formatting information.
- ///
- ///
- /// An interface implementation that supplies
- /// culture-specific formatting information.
- ///
- ///
- /// An 16-bit unsigned integer equivalent to the value of this instance.
- ///
- ushort IConvertible.ToUInt16(IFormatProvider provider)
- {
- if (_hi != 0)
- throw new OverflowException();
-
- return Convert.ToUInt16(_lo);
- }
-
- ///
- /// Converts the value of this instance to an equivalent 32-bit unsigned integer using the specified culture-specific
- /// formatting information.
- ///
- ///
- /// An interface implementation that supplies
- /// culture-specific formatting information.
- ///
- ///
- /// An 32-bit unsigned integer equivalent to the value of this instance.
- ///
- uint IConvertible.ToUInt32(IFormatProvider provider)
- {
- if (_hi != 0)
- throw new OverflowException();
-
- return Convert.ToUInt32(_lo);
- }
-
- ///
- /// Converts the value of this instance to an equivalent 64-bit unsigned integer using the specified culture-specific
- /// formatting information.
- ///
- ///
- /// An interface implementation that supplies
- /// culture-specific formatting information.
- ///
- ///
- /// An 64-bit unsigned integer equivalent to the value of this instance.
- ///
- ulong IConvertible.ToUInt64(IFormatProvider provider)
- {
- if (_hi != 0)
- throw new OverflowException();
-
- return _lo;
- }
-
- ///
- /// Compares the current instance with another object of the same type and returns an integer that indicates whether
- /// the current instance precedes, follows, or occurs in the same position in the sort order as the other object.
- ///
- /// An object to compare with this instance.
- ///
- /// A value that indicates the relative order of the objects being compared. The return value has these meanings: Value
- /// Meaning Less than zero This instance is less than . Zero This instance is equal to
- /// . Greater than zero This instance is greater than .
- ///
- ///
- /// is not the same type as this instance.
- ///
- int IComparable.CompareTo(object obj)
- {
- return Compare(this, obj);
- }
-
- ///
- /// Compares two Int128 values and returns an integer that indicates whether the first value is less than, equal to, or
- /// greater than the second value.
- ///
- /// The first value to compare.
- /// The second value to compare.
- /// A signed integer that indicates the relative values of left and right, as shown in the following table.
- public static int Compare(Int128 left, object right)
- {
- if (right is Int128)
- return Compare(left, (Int128) right);
-
- // NOTE: this could be optimized type per type
- if (right is bool)
- return Compare(left, new Int128((bool) right));
-
- if (right is byte)
- return Compare(left, new Int128((byte) right));
-
- if (right is char)
- return Compare(left, new Int128((char) right));
-
- if (right is decimal)
- return Compare(left, new Int128((decimal) right));
-
- if (right is double)
- return Compare(left, new Int128((double) right));
-
- if (right is short)
- return Compare(left, new Int128((short) right));
-
- if (right is int)
- return Compare(left, new Int128((int) right));
-
- if (right is long)
- return Compare(left, new Int128((long) right));
-
- if (right is sbyte)
- return Compare(left, new Int128((sbyte) right));
-
- if (right is float)
- return Compare(left, new Int128((float) right));
-
- if (right is ushort)
- return Compare(left, new Int128((ushort) right));
-
- if (right is uint)
- return Compare(left, new Int128((uint) right));
-
- if (right is ulong)
- return Compare(left, new Int128((ulong) right));
-
- var bytes = right as byte[];
- if ((bytes != null) && (bytes.Length != 16))
- return Compare(left, new Int128(bytes));
-
- if (right is Guid)
- return Compare(left, new Int128((Guid) right));
-
- throw new ArgumentException();
- }
-
- ///
- /// Converts an Int128 value to a byte array.
- ///
- /// The value of the current Int128 object converted to an array of bytes.
- public byte[] ToByteArray()
- {
- var bytes = new byte[16];
- Buffer.BlockCopy(BitConverter.GetBytes(_lo), 0, bytes, 0, 8);
- Buffer.BlockCopy(BitConverter.GetBytes(_hi), 0, bytes, 8, 8);
- return bytes;
- }
-
- ///
- /// Compares two 128-bit signed integer values and returns an integer that indicates whether the first value is less
- /// than, equal to, or greater than the second value.
- ///
- /// The first value to compare.
- /// The second value to compare.
- ///
- /// A signed number indicating the relative values of this instance and value.
- ///
- public static int Compare(Int128 left, Int128 right)
- {
- if (left.Sign < 0)
- {
- if (right.Sign >= 0)
- return -1;
-
- var xhi = left._hi & ~HiNeg;
- var yhi = right._hi & ~HiNeg;
- if (xhi != yhi)
- return -xhi.CompareTo(yhi);
-
- return -left._lo.CompareTo(right._lo);
- }
-
- if (right.Sign < 0)
- return 1;
-
- if (left._hi != right._hi)
- return left._hi.CompareTo(right._hi);
-
- return left._lo.CompareTo(right._lo);
- }
-
- ///
- /// Compares this instance to a specified 128-bit signed integer and returns an indication of their relative values.
- ///
- /// An integer to compare.
- /// A signed number indicating the relative values of this instance and value.
- public int CompareTo(Int128 value)
- {
- return Compare(this, value);
- }
-
- ///
- /// Performs an implicit conversion from to .
- ///
- /// if set to true [value].
- ///
- /// The result of the conversion.
- ///
- public static implicit operator Int128(bool value)
- {
- return new Int128(value);
- }
-
- ///
- /// Performs an implicit conversion from to .
- ///
- /// The value.
- ///
- /// The result of the conversion.
- ///
- public static implicit operator Int128(byte value)
- {
- return new Int128(value);
- }
-
- ///
- /// Performs an implicit conversion from to .
- ///
- /// The value.
- ///
- /// The result of the conversion.
- ///
- public static implicit operator Int128(char value)
- {
- return new Int128(value);
- }
-
- ///
- /// Performs an explicit conversion from to .
- ///
- /// The value.
- ///
- /// The result of the conversion.
- ///
- public static explicit operator Int128(decimal value)
- {
- return new Int128(value);
- }
-
- ///
- /// Performs an explicit conversion from to .
- ///
- /// The value.
- ///
- /// The result of the conversion.
- ///
- public static explicit operator Int128(double value)
- {
- return new Int128(value);
- }
-
- ///
- /// Performs an implicit conversion from to .
- ///
- /// The value.
- ///
- /// The result of the conversion.
- ///
- public static implicit operator Int128(short value)
- {
- return new Int128(value);
- }
-
- ///
- /// Performs an implicit conversion from to .
- ///
- /// The value.
- ///
- /// The result of the conversion.
- ///
- public static implicit operator Int128(int value)
- {
- return new Int128(value);
- }
-
- ///
- /// Performs an implicit conversion from to .
- ///
- /// The value.
- ///
- /// The result of the conversion.
- ///
- public static implicit operator Int128(long value)
- {
- return new Int128(value);
- }
-
- ///
- /// Performs an implicit conversion from to .
- ///
- /// The value.
- ///
- /// The result of the conversion.
- ///
- public static implicit operator Int128(sbyte value)
- {
- return new Int128(value);
- }
-
- ///
- /// Performs an explicit conversion from to .
- ///
- /// The value.
- ///
- /// The result of the conversion.
- ///
- public static explicit operator Int128(float value)
- {
- return new Int128(value);
- }
-
- ///
- /// Performs an implicit conversion from to .
- ///
- /// The value.
- ///
- /// The result of the conversion.
- ///
- public static implicit operator Int128(ushort value)
- {
- return new Int128(value);
- }
-
- ///
- /// Performs an implicit conversion from to .
- ///
- /// The value.
- ///
- /// The result of the conversion.
- ///
- public static implicit operator Int128(uint value)
- {
- return new Int128(value);
- }
-
- ///
- /// Performs an implicit conversion from to .
- ///
- /// The value.
- ///
- /// The result of the conversion.
- ///
- public static implicit operator Int128(ulong value)
- {
- return new Int128(value);
- }
-
- ///
- /// Performs an explicit conversion from to .
- ///
- /// The value.
- ///
- /// The result of the conversion.
- ///
- public static explicit operator bool(Int128 value)
- {
- return value.Sign != 0;
- }
-
- ///
- /// Performs an explicit conversion from to .
- ///
- /// The value.
- ///
- /// The result of the conversion.
- ///
- public static explicit operator byte(Int128 value)
- {
- if (value.Sign == 0)
- return 0;
-
- if ((value.Sign < 0) || (value._lo > 0xFF))
- throw new OverflowException();
-
- return (byte) value._lo;
- }
-
- ///
- /// Performs an explicit conversion from to .
- ///
- /// The value.
- ///
- /// The result of the conversion.
- ///
- public static explicit operator char(Int128 value)
- {
- if (value.Sign == 0)
- return (char) 0;
-
- if ((value.Sign < 0) || (value._lo > 0xFFFF))
- throw new OverflowException();
-
- return (char) (ushort) value._lo;
- }
-
- ///
- /// Performs an explicit conversion from to .
- ///
- /// The value.
- ///
- /// The result of the conversion.
- ///
- public static explicit operator decimal(Int128 value)
- {
- if (value.Sign == 0)
- return 0;
-
- return new decimal((int) (value._lo & 0xFFFFFFFF), (int) (value._lo >> 32),
- (int) (value._hi & 0xFFFFFFFF),
- value.Sign < 0, 0);
- }
-
- ///
- /// Performs an explicit conversion from to .
- ///
- /// The value.
- ///
- /// The result of the conversion.
- ///
- public static explicit operator double(Int128 value)
- {
- if (value.Sign == 0)
- return 0;
-
- double d;
- var nfi = CultureInfo.InvariantCulture.NumberFormat;
- if (!double.TryParse(value.ToString(nfi), NumberStyles.Number, nfi, out d))
- throw new OverflowException();
-
- return d;
- }
-
- ///
- /// Performs an explicit conversion from to .
- ///
- /// The value.
- ///
- /// The result of the conversion.
- ///
- public static explicit operator float(Int128 value)
- {
- if (value.Sign == 0)
- return 0;
-
- float f;
- var nfi = CultureInfo.InvariantCulture.NumberFormat;
- if (!float.TryParse(value.ToString(nfi), NumberStyles.Number, nfi, out f))
- throw new OverflowException();
-
- return f;
- }
-
- ///
- /// Performs an explicit conversion from to .
- ///
- /// The value.
- ///
- /// The result of the conversion.
- ///
- public static explicit operator short(Int128 value)
- {
- if (value.Sign == 0)
- return 0;
-
- if (value._lo > 0x8000)
- throw new OverflowException();
-
- if ((value._lo == 0x8000) && (value.Sign > 0))
- throw new OverflowException();
-
- return (short) ((int) value._lo*value.Sign);
- }
-
- ///
- /// Performs an explicit conversion from to .
- ///
- /// The value.
- ///
- /// The result of the conversion.
- ///
- public static explicit operator int(Int128 value)
- {
- if (value.Sign == 0)
- return 0;
-
- if (value._lo > 0x80000000)
- throw new OverflowException();
-
- if ((value._lo == 0x80000000) && (value.Sign > 0))
- throw new OverflowException();
-
- return (int) value._lo*value.Sign;
- }
-
- ///
- /// Performs an explicit conversion from to .
- ///
- /// The value.
- ///
- /// The result of the conversion.
- ///
- public static explicit operator long(Int128 value)
- {
- if (value.Sign == 0)
- return 0;
-
- if (value._lo > long.MaxValue)
- throw new OverflowException();
-
- return (long) value._lo*value.Sign;
- }
-
- ///
- /// Performs an explicit conversion from to .
- ///
- /// The value.
- ///
- /// The result of the conversion.
- ///
- public static explicit operator uint(Int128 value)
- {
- if (value.Sign == 0)
- return 0;
-
- if ((value.Sign < 0) || (value._lo > uint.MaxValue))
- throw new OverflowException();
-
- return (uint) value._lo;
- }
-
- ///
- /// Performs an explicit conversion from to .
- ///
- /// The value.
- ///
- /// The result of the conversion.
- ///
- public static explicit operator ushort(Int128 value)
- {
- if (value.Sign == 0)
- return 0;
-
- if ((value.Sign < 0) || (value._lo > ushort.MaxValue))
- throw new OverflowException();
-
- return (ushort) value._lo;
- }
-
- ///
- /// Performs an explicit conversion from to .
- ///
- /// The value.
- ///
- /// The result of the conversion.
- ///
- public static explicit operator ulong(Int128 value)
- {
- if ((value.Sign < 0) || (value._hi != 0))
- throw new OverflowException();
-
- return value._lo;
- }
-
- ///
- /// Implements the operator >.
- ///
- /// The x.
- /// The y.
- ///
- /// The result of the operator.
- ///
- public static bool operator >(Int128 left, Int128 right)
- {
- return Compare(left, right) > 0;
- }
-
- ///
- /// Implements the operator <.
- ///
- /// The x.
- /// The y.
- ///
- /// The result of the operator.
- ///
- public static bool operator <(Int128 left, Int128 right)
- {
- return Compare(left, right) < 0;
- }
-
- ///
- /// Implements the operator >=.
- ///
- /// The x.
- /// The y.
- ///
- /// The result of the operator.
- ///
- public static bool operator >=(Int128 left, Int128 right)
- {
- return Compare(left, right) >= 0;
- }
-
- ///
- /// Implements the operator <=.
- ///
- /// The x.
- /// The y.
- ///
- /// The result of the operator.
- ///
- public static bool operator <=(Int128 left, Int128 right)
- {
- return Compare(left, right) <= 0;
- }
-
- ///
- /// Implements the operator !=.
- ///
- /// The x.
- /// The y.
- ///
- /// The result of the operator.
- ///
- public static bool operator !=(Int128 left, Int128 right)
- {
- return Compare(left, right) != 0;
- }
-
- ///
- /// Implements the operator ==.
- ///
- /// The x.
- /// The y.
- ///
- /// The result of the operator.
- ///
- public static bool operator ==(Int128 left, Int128 right)
- {
- return Compare(left, right) == 0;
- }
-
- ///
- /// Implements the operator +.
- ///
- /// The value.
- ///
- /// The result of the operator.
- ///
- public static Int128 operator +(Int128 value)
- {
- return value;
- }
-
- ///
- /// Implements the operator -.
- ///
- /// The value.
- ///
- /// The result of the operator.
- ///
- public static Int128 operator -(Int128 value)
- {
- return Negate(value);
- }
-
- ///
- /// Negates a specified Int128 value.
- ///
- /// The value to negate.
- /// The result of the value parameter multiplied by negative one (-1).
- public static Int128 Negate(Int128 value)
- {
- var neg = value;
- var sign = value.Sign;
- if (sign < 0)
- neg._hi &= ~HiNeg;
- else
- neg._hi |= HiNeg;
- return neg;
- }
-
- ///
- /// Gets the absolute value this object.
- ///
- /// The absolute value.
- public Int128 ToAbs()
- {
- return Abs(this);
- }
-
- ///
- /// Gets the absolute value of an Int128 object.
- ///
- /// A number.
- ///
- /// The absolute value.
- ///
- public static Int128 Abs(Int128 value)
- {
- if (value.Sign < 0)
- return -value;
-
- return value;
- }
-
- ///
- /// Implements the operator +.
- ///
- /// The x.
- /// The y.
- ///
- /// The result of the operator.
- ///
- public static Int128 operator +(Int128 left, Int128 right)
- {
- var add = left;
- add._hi += right._hi;
- add._lo += right._lo;
- if (add._lo < left._lo)
- add._hi++;
- return add;
- }
-
- ///
- /// Implements the operator -.
- ///
- /// The x.
- /// The y.
- ///
- /// The result of the operator.
- ///
- public static Int128 operator -(Int128 left, Int128 right)
- {
- return left + -right;
- }
-
- ///
- /// Adds two Int128 values and returns the result.
- ///
- /// The first value to add.
- /// The second value to add.
- /// The sum of left and right.
- public static Int128 Add(Int128 left, Int128 right)
- {
- return left + right;
- }
-
- ///
- /// Subtracts one Int128 value from another and returns the result.
- ///
- /// The value to subtract from (the minuend).
- /// The value to subtract (the subtrahend).
- /// The result of subtracting right from left.
- public static Int128 Subtract(Int128 left, Int128 right)
- {
- return left - right;
- }
-
- ///
- /// Divides one Int128 value by another and returns the result.
- ///
- /// The value to be divided.
- /// The value to divide by.
- /// The quotient of the division.
- public static Int128 Divide(Int128 dividend, Int128 divisor)
- {
- Int128 integer;
- return DivRem(dividend, divisor, out integer);
- }
-
- ///
- /// Divides one Int128 value by another, returns the result, and returns the remainder in an output parameter.
- ///
- /// The value to be divided.
- /// The value to divide by.
- ///
- /// When this method returns, contains an Int128 value that represents the remainder from the
- /// division. This parameter is passed uninitialized.
- ///
- ///
- /// The quotient of the division.
- ///
- public static Int128 DivRem(Int128 dividend, Int128 divisor, out Int128 remainder)
- {
- if (divisor == 0)
- throw new DivideByZeroException();
-
- uint[] quotient;
- uint[] rem;
- DivRem(dividend.ToUIn32Array(), divisor.ToUIn32Array(), out quotient, out rem);
- remainder = new Int128(1, rem);
- return new Int128(dividend.Sign*divisor.Sign, quotient);
- }
-
- private static void DivRem(uint[] dividend, uint[] divisor, out uint[] quotient, out uint[] remainder)
- {
- const ulong hiBit = 0x100000000;
- var divisorLen = GetLength(divisor);
- var dividendLen = GetLength(dividend);
- if (divisorLen <= 1)
- {
- ulong rem = 0;
- var div = divisor[0];
- quotient = new uint[dividendLen];
- remainder = new uint[1];
- for (var i = dividendLen - 1; i >= 0; i--)
- {
- rem *= hiBit;
- rem += dividend[i];
- var q = rem/div;
- rem -= q*div;
- quotient[i] = (uint) q;
- }
- remainder[0] = (uint) rem;
- return;
- }
-
- if (dividendLen >= divisorLen)
- {
- var shift = GetNormalizeShift(divisor[divisorLen - 1]);
- var normDividend = new uint[dividendLen + 1];
- var normDivisor = new uint[divisorLen];
- Normalize(dividend, dividendLen, normDividend, shift);
- Normalize(divisor, divisorLen, normDivisor, shift);
- quotient = new uint[dividendLen - divisorLen + 1];
- for (var j = dividendLen - divisorLen; j >= 0; j--)
- {
- var dx = hiBit*normDividend[j + divisorLen] + normDividend[j + divisorLen - 1];
- var qj = dx/normDivisor[divisorLen - 1];
- dx -= qj*normDivisor[divisorLen - 1];
- do
- {
- if ((qj < hiBit) &&
- (qj*normDivisor[divisorLen - 2] <= dx*hiBit + normDividend[j + divisorLen - 2]))
- break;
-
- qj -= 1L;
- dx += normDivisor[divisorLen - 1];
- } while (dx < hiBit);
-
- long di = 0;
- long dj;
- var index = 0;
- while (index < divisorLen)
- {
- var dqj = normDivisor[index]*qj;
- dj = normDividend[index + j] - (uint) dqj - di;
- normDividend[index + j] = (uint) dj;
- dqj = dqj >> 32;
- dj = dj >> 32;
- di = (long) dqj - dj;
- index++;
- }
-
- dj = normDividend[j + divisorLen] - di;
- normDividend[j + divisorLen] = (uint) dj;
- quotient[j] = (uint) qj;
-
- if (dj < 0)
- {
- quotient[j]--;
- ulong sum = 0;
- for (index = 0; index < divisorLen; index++)
- {
- sum = normDivisor[index] + normDividend[j + index] + sum;
- normDividend[j + index] = (uint) sum;
- sum = sum >> 32;
- }
- sum += normDividend[j + divisorLen];
- normDividend[j + divisorLen] = (uint) sum;
- }
- }
- remainder = Unnormalize(normDividend, shift);
- return;
- }
-
- quotient = new uint[0];
- remainder = dividend;
- }
-
- private static int GetLength(uint[] uints)
- {
- var index = uints.Length - 1;
- while ((index >= 0) && (uints[index] == 0))
- index--;
- return index + 1;
- }
-
- private static int GetNormalizeShift(uint ui)
- {
- var shift = 0;
- if ((ui & 0xffff0000) == 0)
- {
- ui = ui << 16;
- shift += 16;
- }
-
- if ((ui & 0xff000000) == 0)
- {
- ui = ui << 8;
- shift += 8;
- }
-
- if ((ui & 0xf0000000) == 0)
- {
- ui = ui << 4;
- shift += 4;
- }
-
- if ((ui & 0xc0000000) == 0)
- {
- ui = ui << 2;
- shift += 2;
- }
-
- if ((ui & 0x80000000) == 0)
- shift++;
- return shift;
- }
-
- private static uint[] Unnormalize(uint[] normalized, int shift)
- {
- var len = GetLength(normalized);
- var unormalized = new uint[len];
- if (shift > 0)
- {
- var rshift = 32 - shift;
- uint r = 0;
- for (var i = len - 1; i >= 0; i--)
- {
- unormalized[i] = (normalized[i] >> shift) | r;
- r = normalized[i] << rshift;
- }
- }
- else
- {
- for (var j = 0; j < len; j++)
- unormalized[j] = normalized[j];
- }
- return unormalized;
- }
-
- private static void Normalize(uint[] unormalized, int len, uint[] normalized, int shift)
- {
- int i;
- uint n = 0;
- if (shift > 0)
- {
- var rshift = 32 - shift;
- for (i = 0; i < len; i++)
- {
- normalized[i] = (unormalized[i] << shift) | n;
- n = unormalized[i] >> rshift;
- }
- }
- else
- {
- i = 0;
- while (i < len)
- {
- normalized[i] = unormalized[i];
- i++;
- }
- }
-
- while (i < normalized.Length)
- normalized[i++] = 0;
-
- if (n != 0)
- normalized[len] = n;
- }
-
- ///
- /// Performs integer division on two Int128 values and returns the remainder.
- ///
- /// The value to be divided.
- /// The value to divide by.
- /// The remainder after dividing dividend by divisor.
- public static Int128 Remainder(Int128 dividend, Int128 divisor)
- {
- Int128 remainder;
- DivRem(dividend, divisor, out remainder);
- return remainder;
- }
-
- ///
- /// Implements the operator %.
- ///
- /// The dividend.
- /// The divisor.
- ///
- /// The result of the operator.
- ///
- public static Int128 operator %(Int128 dividend, Int128 divisor)
- {
- return Remainder(dividend, divisor);
- }
-
- ///
- /// Implements the operator /.
- ///
- /// The dividend.
- /// The divisor.
- ///
- /// The result of the operator.
- ///
- public static Int128 operator /(Int128 dividend, Int128 divisor)
- {
- return Divide(dividend, divisor);
- }
-
- ///
- /// Converts an int128 value to an unsigned long array.
- ///
- ///
- /// The value of the current Int128 object converted to an array of unsigned integers.
- ///
- public ulong[] ToUIn64Array()
- {
- return new[] {_hi, _lo};
- }
-
- ///
- /// Converts an int128 value to an unsigned integer array.
- ///
- /// The value of the current Int128 object converted to an array of unsigned integers.
- public uint[] ToUIn32Array()
- {
- var ints = new uint[4];
- var lob = BitConverter.GetBytes(_lo);
- var hib = BitConverter.GetBytes(_hi);
-
- Buffer.BlockCopy(lob, 0, ints, 0, 4);
- Buffer.BlockCopy(lob, 4, ints, 4, 4);
- Buffer.BlockCopy(hib, 0, ints, 8, 4);
- Buffer.BlockCopy(hib, 4, ints, 12, 4);
- return ints;
- }
-
- ///
- /// Returns the product of two Int128 values.
- ///
- /// The first number to multiply.
- /// The second number to multiply.
- /// The product of the left and right parameters.
- public static Int128 Multiply(Int128 left, Int128 right)
- {
- var xInts = left.ToUIn32Array();
- var yInts = right.ToUIn32Array();
- var mulInts = new uint[8];
-
- for (var i = 0; i < xInts.Length; i++)
- {
- var index = i;
- ulong remainder = 0;
- foreach (var yi in yInts)
- {
- remainder = remainder + (ulong) xInts[i]*yi + mulInts[index];
- mulInts[index++] = (uint) remainder;
- remainder = remainder >> 32;
- }
-
- while (remainder != 0)
- {
- remainder += mulInts[index];
- mulInts[index++] = (uint) remainder;
- remainder = remainder >> 32;
- }
- }
- return new Int128(left.Sign*right.Sign, mulInts);
- }
-
- ///
- /// Implements the operator *.
- ///
- /// The x.
- /// The y.
- ///
- /// The result of the operator.
- ///
- public static Int128 operator *(Int128 left, Int128 right)
- {
- return Multiply(left, right);
- }
-
- ///
- /// Implements the operator >>.
- ///
- /// The value.
- /// The shift.
- /// The result of the operator.
- public static Int128 operator >>(Int128 value, int shift)
- {
- if (shift == 0)
- return value;
-
- if (shift < 0)
- return value << -shift;
-
- shift = shift%128;
-
- var shifted = new Int128();
-
- if (shift > 63)
- {
- shifted._lo = value._hi >> (shift - 64);
- shifted._hi = 0;
- }
- else
- {
- shifted._hi = value._hi >> shift;
- shifted._lo = (value._hi << (64 - shift)) | (value._lo >> shift);
- }
- return shifted;
- }
-
- ///
- /// Implements the operator <<.
- ///
- /// The value.
- /// The shift.
- /// The result of the operator.
- public static Int128 operator <<(Int128 value, int shift)
- {
- if (shift == 0)
- return value;
-
- if (shift < 0)
- return value >> -shift;
-
- shift = shift%128;
-
- var shifted = new Int128();
-
- if (shift > 63)
- {
- shifted._hi = value._lo << (shift - 64);
- shifted._lo = 0;
- }
- else
- {
- var ul = value._lo >> (64 - shift);
- shifted._hi = ul | (value._hi << shift);
- shifted._lo = value._lo << shift;
- }
- return shifted;
- }
-
- ///
- /// Implements the operator |.
- ///
- /// The left.
- /// The right.
- /// The result of the operator.
- public static Int128 operator |(Int128 left, Int128 right)
- {
- if (left == 0)
- return right;
-
- if (right == 0)
- return left;
-
- var result = left;
- result._hi |= right._hi;
- result._lo |= right._lo;
- return result;
- }
-
- ///
- /// Implements the operator ~.
- ///
- /// The left.
- /// The right.
- /// The result of the operator.
- public static Int128 operator ~(Int128 value)
- {
- Int128 result = 0;
- result._hi = ~value._hi;
- result._lo = ~value._lo;
- return result;
- }
-
- ///
- /// Implements the operator &.
- ///
- /// The left.
- /// The right.
- /// The result of the operator.
- public static Int128 operator &(Int128 left, Int128 right)
- {
- if ((left == 0) || (right == 0))
- return Zero;
-
- var result = left;
- result._hi &= right._hi;
- result._lo &= right._lo;
- return result;
- }
-
-#if !WINDOWS_PHONE && !SILVERLIGHT
- void IBinarySerialize.Read(BinaryReader reader)
- {
- if (reader == null)
- throw new ArgumentNullException("reader");
-
- _hi = reader.ReadUInt64();
- _lo = reader.ReadUInt64();
- }
-
- void IBinarySerialize.Write(BinaryWriter writer)
- {
- if (writer == null)
- throw new ArgumentNullException("writer");
-
- writer.Write(_hi);
- writer.Write(_lo);
- }
-#endif
-
- ///
- /// Converts a String type to a Int128 type, and vice versa.
- ///
- public class Int128Converter : TypeConverter
- {
- ///
- /// Returns whether this converter can convert an object of the given type to the type of this converter, using the
- /// specified context.
- ///
- /// An that provides a format context.
- /// A that represents the type you want to convert from.
- ///
- /// true if this converter can perform the conversion; otherwise, false.
- ///
- public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
- {
- if (sourceType == typeof(string))
- return true;
-
- return base.CanConvertFrom(context, sourceType);
- }
-
- ///
- /// Converts the given object to the type of this converter, using the specified context and culture information.
- ///
- /// An that provides a format context.
- /// The to use as the current culture.
- /// The to convert.
- ///
- /// An that represents the converted value.
- ///
- ///
- /// The conversion cannot be performed.
- ///
- public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
- {
- if (value != null)
- {
- Int128 i;
- if (TryParse(string.Format("{0}", value), out i))
- return i;
- }
- return new Int128();
- }
-
- ///
- /// Returns whether this converter can convert the object to the specified type, using the specified context.
- ///
- /// An that provides a format context.
- /// A that represents the type you want to convert to.
- ///
- /// true if this converter can perform the conversion; otherwise, false.
- ///
- public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
- {
- if (destinationType == typeof(string))
- return true;
-
- return base.CanConvertTo(context, destinationType);
- }
-
- ///
- /// Converts the given value object to the specified type, using the specified context and culture information.
- ///
- /// An that provides a format context.
- ///
- /// A . If null is passed, the current culture is
- /// assumed.
- ///
- /// The to convert.
- /// The to convert the parameter to.
- ///
- /// An that represents the converted value.
- ///
- ///
- /// The parameter is null.
- ///
- ///
- /// The conversion cannot be performed.
- ///
- public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value,
- Type destinationType)
- {
- if (destinationType == typeof(string))
- return string.Format("{0}", value);
-
- return base.ConvertTo(context, culture, value, destinationType);
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/WoW/Data/WoWEnums.cs b/Artemis/Artemis/Modules/Games/WoW/Data/WoWEnums.cs
deleted file mode 100644
index 24fa676fa..000000000
--- a/Artemis/Artemis/Modules/Games/WoW/Data/WoWEnums.cs
+++ /dev/null
@@ -1,157 +0,0 @@
-namespace Artemis.Modules.Games.WoW.Data
-{
- public static class WoWEnums
- {
- public enum GuidType : byte
- {
- Null = 0,
- Uniq = 1,
- Player = 2,
- Item = 3,
- StaticDoor = 4,
- Transport = 5,
- Conversation = 6,
- Creature = 7,
- Vehicle = 8,
- Pet = 9,
- GameObject = 10,
- DynamicObject = 11,
- AreaTrigger = 12,
- Corpse = 13,
- LootObject = 14,
- SceneObject = 15,
- Scenario = 16,
- AiGroup = 17,
- DynamicDoor = 18,
- ClientActor = 19,
- Vignette = 20,
- CallForHelp = 21,
- AiResource = 22,
- AiLock = 23,
- AiLockTicket = 24,
- ChatChannel = 25,
- Party = 26,
- Guild = 27,
- WowAccount = 28,
- BNetAccount = 29,
- GmTask = 30,
- MobileSession = 31,
- RaidGroup = 32,
- Spell = 33,
- Mail = 34,
- WebObj = 35,
- LfgObject = 36,
- LfgList = 37,
- UserRouter = 38,
- PvpQueueGroup = 39,
- UserClient = 40,
- PetBattle = 41,
- UniqueUserClient = 42,
- BattlePet = 43
- }
-
- public enum ObjectType
- {
- Object = 0,
- Item = 1,
- Container = 2,
- Unit = 3,
- Player = 4,
- GameObject = 5,
- DynamicObject = 6,
- Corpse = 7,
- AreaTrigger = 8,
- SceneObject = 9,
- Conversation = 10
- }
-
- public enum PowerType
- {
- Mana = 0,
- Rage = 1,
- Focus = 2,
- Energy = 3,
- Happiness = 4,
- RunicPower = 5,
- Runes = 6,
- Health = 7,
- Maelstrom = 11,
- Insanity = 13,
- Fury = 17,
- Pain = 18,
- UNKNOWN
- }
-
- public enum Reaction
- {
- Hostile = 1,
- Neutral = 3,
- Friendly = 4
- }
-
- public enum ShapeshiftForm
- {
- Normal = 0,
- Cat = 1,
- TreeOfLife = 2,
- Travel = 3,
- Aqua = 4,
- Bear = 5,
- Ambient = 6,
- Ghoul = 7,
- DireBear = 8,
- CreatureBear = 14,
- CreatureCat = 15,
- GhostWolf = 16,
- BattleStance = 17,
- DefensiveStance = 18,
- BerserkerStance = 19,
- EpicFlightForm = 27,
- Shadow = 28,
- Stealth = 30,
- Moonkin = 31,
- SpiritOfRedemption = 32
- }
-
- public enum WoWClass
- {
- None = 0,
- Warrior = 1,
- Paladin = 2,
- Hunter = 3,
- Rogue = 4,
- Priest = 5,
- DeathKnight = 6,
- Shaman = 7,
- Mage = 8,
- Warlock = 9,
- Druid = 11
- }
-
- public enum WoWRace
- {
- Human = 1,
- Orc = 2,
- Dwarf = 3,
- NightElf = 4,
- Undead = 5,
- Tauren = 6,
- Gnome = 7,
- Troll = 8,
- Goblin = 9,
- BloodElf = 10,
- Draenei = 11,
- FelOrc = 12,
- Naga = 13,
- Broken = 14,
- Skeleton = 15,
- Worgen = 22
- }
-
- public enum WoWType
- {
- Player,
- Npc
- }
- }
-}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/WoW/Data/WoWNameCache.cs b/Artemis/Artemis/Modules/Games/WoW/Data/WoWNameCache.cs
deleted file mode 100644
index 78677f117..000000000
--- a/Artemis/Artemis/Modules/Games/WoW/Data/WoWNameCache.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-using System;
-using System.Text;
-using Process.NET;
-
-namespace Artemis.Modules.Games.WoW.Data
-{
- public class WoWNameCache
- {
- public WoWNameCache(ProcessSharp process, IntPtr baseAddress)
- {
- Process = process;
- CurrentCacheAddress = process.Native.MainModule.BaseAddress + baseAddress.ToInt32();
- }
-
- public ProcessSharp Process { get; set; }
-
- public IntPtr CurrentCacheAddress { get; set; }
-
- public WoWDetails GetNameByGuid(Guid searchGuid)
- {
- var current = Process.Memory.Read(CurrentCacheAddress);
- var index = 0;
- while (current != IntPtr.Zero)
- {
- var guid = Process.Memory.Read(current + 0x20);
- if (guid.Equals(searchGuid))
- {
- var pRace = Process.Memory.Read(current + 0x88);
- var pClass = Process.Memory.Read(current + 0x90);
- var pName = Process.Memory.Read(current + 0x31, Encoding.ASCII, 48);
-
- var name = new WoWDetails(guid, pRace, pClass, WoWEnums.WoWType.Player, pName);
- return name;
- }
-
- if (index > 20000)
- return null;
-
- index++;
- current = Process.Memory.Read(current);
- }
- return null;
- }
- }
-
- public class WoWDetails
- {
- public WoWDetails(Guid guid, int race, int @class, WoWEnums.WoWType type, string name)
- {
- Guid = guid;
- Race = (WoWEnums.WoWRace) race;
- Class = (WoWEnums.WoWClass) @class;
- Type = type;
- Name = name;
- }
-
- public Guid Guid { get; set; }
- public WoWEnums.WoWRace Race { get; set; }
- public WoWEnums.WoWClass Class { get; set; }
- public WoWEnums.WoWType Type { get; set; }
- public string Name { get; set; }
- }
-}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/WoW/Data/WoWObject.cs b/Artemis/Artemis/Modules/Games/WoW/Data/WoWObject.cs
deleted file mode 100644
index a8db9114c..000000000
--- a/Artemis/Artemis/Modules/Games/WoW/Data/WoWObject.cs
+++ /dev/null
@@ -1,73 +0,0 @@
-using System;
-using System.Text;
-using Newtonsoft.Json;
-using Process.NET;
-
-namespace Artemis.Modules.Games.WoW.Data
-{
- public class WoWObject
- {
- private readonly bool _readPointer;
-
- public WoWObject(IProcess process, IntPtr baseAddress, bool readPointer = false)
- {
- Process = process;
- BaseAddress = baseAddress;
- _readPointer = readPointer;
-
- Guid = ReadField(0x00);
- }
-
- [JsonIgnore]
- public IntPtr BaseAddress { get; set; }
-
- [JsonIgnore]
- public IProcess Process { get; set; }
-
- public Guid Guid { get; set; }
-
- [JsonIgnore]
- public WoWStructs.ObjectData Data { get; set; }
-
- public T ReadField(int offset)
- {
- var address = GetAddress();
- if (address == IntPtr.Zero)
- return default(T);
-
- var ptr = Process.Memory.Read(address + 0x10);
- return Process.Memory.Read(ptr + offset);
- }
-
- public T ReadField(Enum offset)
- {
- var address = GetAddress();
- if (address == IntPtr.Zero)
- return default(T);
-
- var ptr = Process.Memory.Read(address + 0x10);
- return Process.Memory.Read(ptr + Convert.ToInt32(offset));
- }
-
- private IntPtr GetAddress()
- {
- return _readPointer
- ? Process.Memory.Read(Process.Native.MainModule.BaseAddress + BaseAddress.ToInt32())
- : BaseAddress;
- }
-
- public WoWDetails GetNpcDetails()
- {
- var address = GetAddress();
- if (address == IntPtr.Zero)
- return null;
-
- var npcCachePtr = Process.Memory.Read(address + 0x1760);
- if (npcCachePtr == IntPtr.Zero)
- return null;
-
- var npcName = Process.Memory.Read(Process.Memory.Read(npcCachePtr + 0x00A0), Encoding.ASCII, 48);
- return new WoWDetails(Guid, 0, 0, WoWEnums.WoWType.Npc, npcName);
- }
- }
-}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/WoW/Data/WoWObjectManager.cs b/Artemis/Artemis/Modules/Games/WoW/Data/WoWObjectManager.cs
deleted file mode 100644
index e47ff61ec..000000000
--- a/Artemis/Artemis/Modules/Games/WoW/Data/WoWObjectManager.cs
+++ /dev/null
@@ -1,92 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Runtime.InteropServices;
-using Process.NET;
-
-namespace Artemis.Modules.Games.WoW.Data
-{
- public class WoWObjectManager
- {
- public WoWObjectManager(IProcess process, IntPtr baseAddress)
- {
- Process = process;
- CurrentManagerAddress = process.Native.MainModule.BaseAddress + baseAddress.ToInt32();
- }
-
- public IProcess Process { get; set; }
-
- public IntPtr CurrentManagerAddress { get; set; }
-
- public Dictionary WoWObjects { get; set; }
-
- public IntPtr GetFirstObject()
- {
- var mgr = GetCurrentManager();
- return mgr.VisibleObjects.m_fulllist.baseClass.m_terminator.m_next;
- }
-
- public WoWStructs.CurrentManager GetCurrentManager()
- {
- return Process.Memory.Read(Process.Memory.Read(CurrentManagerAddress));
- }
-
- public IntPtr GetNextObjectFromCurrent(IntPtr current)
- {
- var mgr = GetCurrentManager();
-
- return Process.Memory.Read(
- current + mgr.VisibleObjects.m_fulllist.baseClass.m_linkoffset + IntPtr.Size);
- }
-
- public void Update()
- {
- WoWObjects.Clear();
- var wowObjects = EnumVisibleObjects();
- foreach (var wowObject in wowObjects)
- WoWObjects[wowObject.Data.Guid] = wowObject;
-
- OnObjectsUpdated(WoWObjects);
- }
-
- public event EventHandler> ObjectsUpdated;
-
- // Loop through the games object list.
- public IEnumerable EnumVisibleObjects()
- {
- var first = GetFirstObject();
- var typeOffset = Marshal.OffsetOf(typeof(WoWStructs.ObjectData), "ObjectType").ToInt32();
-
- while (((first.ToInt64() & 1) == 0) && (first != IntPtr.Zero))
- {
- var type = (WoWEnums.ObjectType) Process.Memory.Read(first + typeOffset);
-
- // Fix below with other object types as added.
- // ReSharper disable once SwitchStatementMissingSomeCases
- switch (type)
- {
- case WoWEnums.ObjectType.Object:
- yield return new WoWObject(Process, first);
- break;
- case WoWEnums.ObjectType.Container:
- break;
- case WoWEnums.ObjectType.Unit:
- yield return new WoWUnit(Process, first);
- break;
- case WoWEnums.ObjectType.Player:
- yield return new WoWPlayer(Process, first, new IntPtr(0x179A6E0));
- break;
- default:
- yield return new WoWObject(Process, first);
- break;
- }
-
- first = GetNextObjectFromCurrent(first);
- }
- }
-
- protected virtual void OnObjectsUpdated(Dictionary e)
- {
- ObjectsUpdated?.Invoke(this, e);
- }
- }
-}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/WoW/Data/WoWOffsets.cs b/Artemis/Artemis/Modules/Games/WoW/Data/WoWOffsets.cs
deleted file mode 100644
index b4037a419..000000000
--- a/Artemis/Artemis/Modules/Games/WoW/Data/WoWOffsets.cs
+++ /dev/null
@@ -1,368 +0,0 @@
-namespace Artemis.Modules.Games.WoW.Data
-{
- internal static class WoWOffsets
- {
- internal enum AreaTriggerData
- {
- OverrideScaleCurve = 0x30, // Size: 0x7, Flags: 0x201
- ExtraScaleCurve = 0x4C, // Size: 0x7, Flags: 0x201
- Caster = 0x68, // Size: 0x4, Flags: 0x1
- Duration = 0x78, // Size: 0x1, Flags: 0x1
- TimeToTarget = 0x7C, // Size: 0x1, Flags: 0x201
- TimeToTargetScale = 0x80, // Size: 0x1, Flags: 0x201
- TimeToTargetExtraScale = 0x84, // Size: 0x1, Flags: 0x201
- SpellId = 0x88, // Size: 0x1, Flags: 0x1
- SpellVisualId = 0x8C, // Size: 0x1, Flags: 0x80
- BoundsRadius2D = 0x90, // Size: 0x1, Flags: 0x280
- DecalPropertiesId = 0x94 // Size: 0x1, Flags: 0x1
- }
-
- internal enum ContainerData
- {
- Slots = 0x150, // Size: 0x90, Flags: 0x1
- NumSlots = 0x390 // Size: 0x1, Flags: 0x1
- }
-
- internal enum ConversationData
- {
- LastLineDuration = 0x30 // Size: 0x1, Flags: 0x80
- }
-
- internal enum CorpseData
- {
- Owner = 0x30, // Size: 0x4, Flags: 0x1
- PartyGuid = 0x40, // Size: 0x4, Flags: 0x1
- DisplayId = 0x50, // Size: 0x1, Flags: 0x1
- Items = 0x54, // Size: 0x13, Flags: 0x1
- SkinId = 0xA0, // Size: 0x1, Flags: 0x1
- FacialHairStyleId = 0xA4, // Size: 0x1, Flags: 0x1
- Flags = 0xA8, // Size: 0x1, Flags: 0x1
- DynamicFlags = 0xAC, // Size: 0x1, Flags: 0x80
- FactionTemplate = 0xB0, // Size: 0x1, Flags: 0x1
- CustomDisplayOption = 0xB4 // Size: 0x1, Flags: 0x1
- }
-
- internal enum DynamicObjectData
- {
- Caster = 0x30, // Size: 0x4, Flags: 0x1
- TypeAndVisualId = 0x40, // Size: 0x1, Flags: 0x80
- SpellId = 0x44, // Size: 0x1, Flags: 0x1
- Radius = 0x48, // Size: 0x1, Flags: 0x1
- CastTime = 0x4C // Size: 0x1, Flags: 0x1
- }
-
- internal enum GameObjectData
- {
- CreatedBy = 0x30, // Size: 0x4, Flags: 0x1
- DisplayId = 0x40, // Size: 0x1, Flags: 0x280
- Flags = 0x44, // Size: 0x1, Flags: 0x201
- ParentRotation = 0x48, // Size: 0x4, Flags: 0x1
- FactionTemplate = 0x58, // Size: 0x1, Flags: 0x1
- Level = 0x5C, // Size: 0x1, Flags: 0x1
- PercentHealth = 0x60, // Size: 0x1, Flags: 0x201
- SpellVisualId = 0x64, // Size: 0x1, Flags: 0x281
- StateSpellVisualId = 0x68, // Size: 0x1, Flags: 0x280
- StateAnimId = 0x6C, // Size: 0x1, Flags: 0x280
- StateAnimKitId = 0x70, // Size: 0x1, Flags: 0x280
- StateWorldEffectId = 0x74 // Size: 0x4, Flags: 0x280
- }
-
- internal enum ItemData
- {
- Owner = 0x30, // Size: 0x4, Flags: 0x1
- ContainedIn = 0x40, // Size: 0x4, Flags: 0x1
- Creator = 0x50, // Size: 0x4, Flags: 0x1
- GiftCreator = 0x60, // Size: 0x4, Flags: 0x1
- StackCount = 0x70, // Size: 0x1, Flags: 0x4
- Expiration = 0x74, // Size: 0x1, Flags: 0x4
- SpellCharges = 0x78, // Size: 0x5, Flags: 0x4
- DynamicFlags = 0x8C, // Size: 0x1, Flags: 0x1
- Enchantment = 0x90, // Size: 0x27, Flags: 0x1
- PropertySeed = 0x12C, // Size: 0x1, Flags: 0x1
- RandomPropertiesId = 0x130, // Size: 0x1, Flags: 0x1
- Durability = 0x134, // Size: 0x1, Flags: 0x4
- MaxDurability = 0x138, // Size: 0x1, Flags: 0x4
- CreatePlayedTime = 0x13C, // Size: 0x1, Flags: 0x1
- ModifiersMask = 0x140, // Size: 0x1, Flags: 0x4
- Context = 0x144, // Size: 0x1, Flags: 0x1
- ArtifactXp = 0x148, // Size: 0x1, Flags: 0x4
- ItemAppearanceModId = 0x14C // Size: 0x1, Flags: 0x4
- }
-
- internal enum KeyBinding
- {
- NumKeyBindings = 0x1700030, // -0x17C0
- First = 0xC8,
- Next = 0xB8,
- Key = 0x30,
- Command = 0x58
- }
-
- internal enum ObjectData
- {
- Guid = 0x0, // Size: 0x4, Flags: 0x1
- Data = 0x10, // Size: 0x4, Flags: 0x1
- Type = 0x20, // Size: 0x1, Flags: 0x1
- EntryId = 0x24, // Size: 0x1, Flags: 0x80
- DynamicFlags = 0x28, // Size: 0x1, Flags: 0x280
- Scale = 0x2C // Size: 0x1, Flags: 0x1
- }
-
- internal enum PlayerData
- {
- DuelArbiter = 0x360, // Size: 0x4, Flags: 0x1
- WowAccount = 0x370, // Size: 0x4, Flags: 0x1
- LootTargetGuid = 0x380, // Size: 0x4, Flags: 0x1
- PlayerFlags = 0x390, // Size: 0x1, Flags: 0x1
- PlayerFlagsEx = 0x394, // Size: 0x1, Flags: 0x1
- GuildRankId = 0x398, // Size: 0x1, Flags: 0x1
- GuildDeleteDate = 0x39C, // Size: 0x1, Flags: 0x1
- GuildLevel = 0x3A0, // Size: 0x1, Flags: 0x1
- HairColorId = 0x3A4, // Size: 0x1, Flags: 0x1
- CustomDisplayOption = 0x3A8, // Size: 0x1, Flags: 0x1
- Inebriation = 0x3AC, // Size: 0x1, Flags: 0x1
- ArenaFaction = 0x3B0, // Size: 0x1, Flags: 0x1
- DuelTeam = 0x3B4, // Size: 0x1, Flags: 0x1
- GuildTimeStamp = 0x3B8, // Size: 0x1, Flags: 0x1
- QuestLog = 0x3BC, // Size: 0x320, Flags: 0x20
- VisibleItems = 0x103C, // Size: 0x26, Flags: 0x1
- PlayerTitle = 0x10D4, // Size: 0x1, Flags: 0x1
- FakeInebriation = 0x10D8, // Size: 0x1, Flags: 0x1
- VirtualPlayerRealm = 0x10DC, // Size: 0x1, Flags: 0x1
- CurrentSpecId = 0x10E0, // Size: 0x1, Flags: 0x1
- TaxiMountAnimKitId = 0x10E4, // Size: 0x1, Flags: 0x1
- AvgItemLevel = 0x10E8, // Size: 0x4, Flags: 0x1
- CurrentBattlePetBreedQuality = 0x10F8, // Size: 0x1, Flags: 0x1
- Prestige = 0x10FC, // Size: 0x1, Flags: 0x1
- HonorLevel = 0x1100, // Size: 0x1, Flags: 0x1
- InvSlots = 0x1104, // Size: 0x2EC, Flags: 0x2
- FarsightObject = 0x1CB4, // Size: 0x4, Flags: 0x2
- SummonedBattlePetGuid = 0x1CC4, // Size: 0x4, Flags: 0x2
- KnownTitles = 0x1CD4, // Size: 0xC, Flags: 0x2
- Coinage = 0x1D04, // Size: 0x2, Flags: 0x2
- Xp = 0x1D0C, // Size: 0x1, Flags: 0x2
- NextLevelXp = 0x1D10, // Size: 0x1, Flags: 0x2
- Skill = 0x1D14, // Size: 0x1C0, Flags: 0x2
- CharacterPoints = 0x2414, // Size: 0x1, Flags: 0x2
- MaxTalentTiers = 0x2418, // Size: 0x1, Flags: 0x2
- TrackCreatureMask = 0x241C, // Size: 0x1, Flags: 0x2
- TrackResourceMask = 0x2420, // Size: 0x1, Flags: 0x2
- MainhandExpertise = 0x2424, // Size: 0x1, Flags: 0x2
- OffhandExpertise = 0x2428, // Size: 0x1, Flags: 0x2
- RangedExpertise = 0x242C, // Size: 0x1, Flags: 0x2
- CombatRatingExpertise = 0x2430, // Size: 0x1, Flags: 0x2
- BlockPercentage = 0x2434, // Size: 0x1, Flags: 0x2
- DodgePercentage = 0x2438, // Size: 0x1, Flags: 0x2
- ParryPercentage = 0x243C, // Size: 0x1, Flags: 0x2
- CritPercentage = 0x2440, // Size: 0x1, Flags: 0x2
- RangedCritPercentage = 0x2444, // Size: 0x1, Flags: 0x2
- OffhandCritPercentage = 0x2448, // Size: 0x1, Flags: 0x2
- SpellCritPercentage = 0x244C, // Size: 0x1, Flags: 0x2
- ShieldBlock = 0x2450, // Size: 0x1, Flags: 0x2
- ShieldBlockCritPercentage = 0x2454, // Size: 0x1, Flags: 0x2
- Mastery = 0x2458, // Size: 0x1, Flags: 0x2
- Speed = 0x245C, // Size: 0x1, Flags: 0x2
- Lifesteal = 0x2460, // Size: 0x1, Flags: 0x2
- Avoidance = 0x2464, // Size: 0x1, Flags: 0x2
- Sturdiness = 0x2468, // Size: 0x1, Flags: 0x2
- Versatility = 0x246C, // Size: 0x1, Flags: 0x2
- VersatilityBonus = 0x2470, // Size: 0x1, Flags: 0x2
- PvpPowerDamage = 0x2474, // Size: 0x1, Flags: 0x2
- PvpPowerHealing = 0x2478, // Size: 0x1, Flags: 0x2
- ExploredZones = 0x247C, // Size: 0x100, Flags: 0x2
- RestInfo = 0x287C, // Size: 0x4, Flags: 0x2
- ModDamageDonePos = 0x288C, // Size: 0x7, Flags: 0x2
- ModDamageDoneNeg = 0x28A8, // Size: 0x7, Flags: 0x2
- ModDamageDonePercent = 0x28C4, // Size: 0x7, Flags: 0x2
- ModHealingDonePos = 0x28E0, // Size: 0x1, Flags: 0x2
- ModHealingPercent = 0x28E4, // Size: 0x1, Flags: 0x2
- ModHealingDonePercent = 0x28E8, // Size: 0x1, Flags: 0x2
- ModPeriodicHealingDonePercent = 0x28EC, // Size: 0x1, Flags: 0x2
- WeaponDmgMultipliers = 0x28F0, // Size: 0x3, Flags: 0x2
- WeaponAtkSpeedMultipliers = 0x28FC, // Size: 0x3, Flags: 0x2
- ModSpellPowerPercent = 0x2908, // Size: 0x1, Flags: 0x2
- ModResiliencePercent = 0x290C, // Size: 0x1, Flags: 0x2
- OverrideSpellPowerByApPercent = 0x2910, // Size: 0x1, Flags: 0x2
- OverrideApBySpellPowerPercent = 0x2914, // Size: 0x1, Flags: 0x2
- ModTargetResistance = 0x2918, // Size: 0x1, Flags: 0x2
- ModTargetPhysicalResistance = 0x291C, // Size: 0x1, Flags: 0x2
- LocalFlags = 0x2920, // Size: 0x1, Flags: 0x2
- NumRespecs = 0x2924, // Size: 0x1, Flags: 0x2
- SelfResSpell = 0x2928, // Size: 0x1, Flags: 0x2
- PvpMedals = 0x292C, // Size: 0x1, Flags: 0x2
- BuybackPrice = 0x2930, // Size: 0xC, Flags: 0x2
- BuybackTimestamp = 0x2960, // Size: 0xC, Flags: 0x2
- YesterdayHonorableKills = 0x2990, // Size: 0x1, Flags: 0x2
- LifetimeHonorableKills = 0x2994, // Size: 0x1, Flags: 0x2
- WatchedFactionIndex = 0x2998, // Size: 0x1, Flags: 0x2
- CombatRatings = 0x299C, // Size: 0x20, Flags: 0x2
- PvpInfo = 0x2A1C, // Size: 0x24, Flags: 0x2
- MaxLevel = 0x2AAC, // Size: 0x1, Flags: 0x2
- ScalingPlayerLevelDelta = 0x2AB0, // Size: 0x1, Flags: 0x2
- MaxCreatureScalingLevel = 0x2AB4, // Size: 0x1, Flags: 0x2
- NoReagentCostMask = 0x2AB8, // Size: 0x4, Flags: 0x2
- PetSpellPower = 0x2AC8, // Size: 0x1, Flags: 0x2
- Researching = 0x2ACC, // Size: 0xA, Flags: 0x2
- ProfessionSkillLine = 0x2AF4, // Size: 0x2, Flags: 0x2
- UiHitModifier = 0x2AFC, // Size: 0x1, Flags: 0x2
- UiSpellHitModifier = 0x2B00, // Size: 0x1, Flags: 0x2
- HomeRealmTimeOffset = 0x2B04, // Size: 0x1, Flags: 0x2
- ModPetHaste = 0x2B08, // Size: 0x1, Flags: 0x2
- OverrideSpellsId = 0x2B0C, // Size: 0x1, Flags: 0x402
- LfgBonusFactionId = 0x2B10, // Size: 0x1, Flags: 0x2
- LootSpecId = 0x2B14, // Size: 0x1, Flags: 0x2
- OverrideZonePvpType = 0x2B18, // Size: 0x1, Flags: 0x402
- BagSlotFlags = 0x2B1C, // Size: 0x4, Flags: 0x2
- BankBagSlotFlags = 0x2B2C, // Size: 0x7, Flags: 0x2
- InsertItemsLeftToRight = 0x2B48, // Size: 0x1, Flags: 0x2
- QuestCompleted = 0x2B4C, // Size: 0x36B, Flags: 0x2
- Honor = 0x38F8, // Size: 0x1, Flags: 0x2
- HonorNextLevel = 0x38FC // Size: 0x1, Flags: 0x2
- }
-
- internal enum SceneObjectData
- {
- ScriptPackageId = 0x30, // Size: 0x1, Flags: 0x1
- RndSeedVal = 0x34, // Size: 0x1, Flags: 0x1
- CreatedBy = 0x38, // Size: 0x4, Flags: 0x1
- SceneType = 0x48 // Size: 0x1, Flags: 0x1
- }
-
- internal enum Unit
- {
- CurrentCastId = 0x1B98,
- CurrentChanneledId = 0x1BB8,
- AuraTable = 0x1D10,
- AuraCount = 0x2390,
- AuraSize = 0x68,
- ClientRace = 0x2670,
- DisplayData = 0x1718
- }
-
- // Note: Invalid possibly!
- internal enum UnitAuras : uint
- {
- AuraCount1 = 0x2390,
- AuraCount2 = 0x1D10,
- AuraTable1 = 0x1D14,
- AuraTable2 = 0x1D18,
- AuraSize = 0x68,
-
- OwnerGuid = 0x40,
- AuraSpellId = 0x50,
- //AuraFlags = 0x54, //Not exactly sure here.
- //AuraLevel = 0x58, //Not exactly sure here.
- AuraStack = 0x59,
- TimeLeft = 0x60,
- //In case I need it:
- DruidEclipse = 0x2694
- }
-
- // Below is all of the World of Warcraft in-game object field offsets.
- // Commenting is not used on purpose and enums below should remain internal.
- internal enum UnitData
- {
- Charm = 0x30, // Size: 0x4, Flags: 0x1
- Summon = 0x40, // Size: 0x4, Flags: 0x1
- Critter = 0x50, // Size: 0x4, Flags: 0x2
- CharmedBy = 0x60, // Size: 0x4, Flags: 0x1
- SummonedBy = 0x70, // Size: 0x4, Flags: 0x1
- CreatedBy = 0x80, // Size: 0x4, Flags: 0x1
- DemonCreator = 0x90, // Size: 0x4, Flags: 0x1
- Target = 0xA0, // Size: 0x4, Flags: 0x1
- BattlePetCompanionGuid = 0xB0, // Size: 0x4, Flags: 0x1
- BattlePetDbid = 0xC0, // Size: 0x2, Flags: 0x1
- ChannelObject = 0xC8, // Size: 0x4, Flags: 0x201
- ChannelSpell = 0xD8, // Size: 0x1, Flags: 0x201
- ChannelSpellXSpellVisual = 0xDC, // Size: 0x1, Flags: 0x201
- SummonedByHomeRealm = 0xE0, // Size: 0x1, Flags: 0x1
- Sex = 0xE4, // Size: 0x1, Flags: 0x1
- DisplayPower = 0xE8, // Size: 0x1, Flags: 0x1
- OverrideDisplayPowerId = 0xEC, // Size: 0x1, Flags: 0x1
- Health = 0xF0, // Size: 0x2, Flags: 0x1
- Power = 0xF8, // Size: 0x6, Flags: 0x401
- TertiaryPower = 0xFC,
- SecondaryPower = 0x100,
- MaxHealth = 0x110, // Size: 0x2, Flags: 0x1
- MaxPower = 0x118, // Size: 0x6, Flags: 0x1
- PowerRegenFlatModifier = 0x130, // Size: 0x6, Flags: 0x46
- PowerRegenInterruptedFlatModifier = 0x148, // Size: 0x6, Flags: 0x46
- Level = 0x160, // Size: 0x1, Flags: 0x1
- EffectiveLevel = 0x164, // Size: 0x1, Flags: 0x1
- ScalingLevelMin = 0x168, // Size: 0x1, Flags: 0x1
- ScalingLevelMax = 0x16C, // Size: 0x1, Flags: 0x1
- ScalingLevelDelta = 0x170, // Size: 0x1, Flags: 0x1
- FactionTemplate = 0x174, // Size: 0x1, Flags: 0x1
- VirtualItems = 0x178, // Size: 0x6, Flags: 0x1
- Flags = 0x190, // Size: 0x1, Flags: 0x201
- Flags2 = 0x194, // Size: 0x1, Flags: 0x201
- Flags3 = 0x198, // Size: 0x1, Flags: 0x201
- AuraState = 0x19C, // Size: 0x1, Flags: 0x1
- AttackRoundBaseTime = 0x1A0, // Size: 0x2, Flags: 0x1
- RangedAttackRoundBaseTime = 0x1A8, // Size: 0x1, Flags: 0x2
- BoundingRadius = 0x1AC, // Size: 0x1, Flags: 0x1
- CombatReach = 0x1B0, // Size: 0x1, Flags: 0x1
- DisplayId = 0x1B4, // Size: 0x1, Flags: 0x280
- NativeDisplayId = 0x1B8, // Size: 0x1, Flags: 0x201
- MountDisplayId = 0x1BC, // Size: 0x1, Flags: 0x201
- MinDamage = 0x1C0, // Size: 0x1, Flags: 0x16
- MaxDamage = 0x1C4, // Size: 0x1, Flags: 0x16
- MinOffHandDamage = 0x1C8, // Size: 0x1, Flags: 0x16
- MaxOffHandDamage = 0x1CC, // Size: 0x1, Flags: 0x16
- AnimTier = 0x1D0, // Size: 0x1, Flags: 0x1
- PetNumber = 0x1D4, // Size: 0x1, Flags: 0x1
- PetNameTimestamp = 0x1D8, // Size: 0x1, Flags: 0x1
- PetExperience = 0x1DC, // Size: 0x1, Flags: 0x4
- PetNextLevelExperience = 0x1E0, // Size: 0x1, Flags: 0x4
- ModCastingSpeed = 0x1E4, // Size: 0x1, Flags: 0x1
- ModSpellHaste = 0x1E8, // Size: 0x1, Flags: 0x1
- ModHaste = 0x1EC, // Size: 0x1, Flags: 0x1
- ModRangedHaste = 0x1F0, // Size: 0x1, Flags: 0x1
- ModHasteRegen = 0x1F4, // Size: 0x1, Flags: 0x1
- ModTimeRate = 0x1F8, // Size: 0x1, Flags: 0x1
- CreatedBySpell = 0x1FC, // Size: 0x1, Flags: 0x1
- NpcFlags = 0x200, // Size: 0x2, Flags: 0x81
- EmoteState = 0x208, // Size: 0x1, Flags: 0x1
- Stats = 0x20C, // Size: 0x4, Flags: 0x6
- StatPosBuff = 0x21C, // Size: 0x4, Flags: 0x6
- StatNegBuff = 0x22C, // Size: 0x4, Flags: 0x6
- Resistances = 0x23C, // Size: 0x7, Flags: 0x16
- ResistanceBuffModsPositive = 0x258, // Size: 0x7, Flags: 0x6
- ResistanceBuffModsNegative = 0x274, // Size: 0x7, Flags: 0x6
- ModBonusArmor = 0x290, // Size: 0x1, Flags: 0x6
- BaseMana = 0x294, // Size: 0x1, Flags: 0x1
- BaseHealth = 0x298, // Size: 0x1, Flags: 0x6
- ShapeshiftForm = 0x29C, // Size: 0x1, Flags: 0x1
- AttackPower = 0x2A0, // Size: 0x1, Flags: 0x6
- AttackPowerModPos = 0x2A4, // Size: 0x1, Flags: 0x6
- AttackPowerModNeg = 0x2A8, // Size: 0x1, Flags: 0x6
- AttackPowerMultiplier = 0x2AC, // Size: 0x1, Flags: 0x6
- RangedAttackPower = 0x2B0, // Size: 0x1, Flags: 0x6
- RangedAttackPowerModPos = 0x2B4, // Size: 0x1, Flags: 0x6
- RangedAttackPowerModNeg = 0x2B8, // Size: 0x1, Flags: 0x6
- RangedAttackPowerMultiplier = 0x2BC, // Size: 0x1, Flags: 0x6
- SetAttackSpeedAura = 0x2C0, // Size: 0x1, Flags: 0x6
- MinRangedDamage = 0x2C4, // Size: 0x1, Flags: 0x6
- MaxRangedDamage = 0x2C8, // Size: 0x1, Flags: 0x6
- PowerCostModifier = 0x2CC, // Size: 0x7, Flags: 0x6
- PowerCostMultiplier = 0x2E8, // Size: 0x7, Flags: 0x6
- MaxHealthModifier = 0x304, // Size: 0x1, Flags: 0x6
- HoverHeight = 0x308, // Size: 0x1, Flags: 0x1
- MinItemLevelCutoff = 0x30C, // Size: 0x1, Flags: 0x1
- MinItemLevel = 0x310, // Size: 0x1, Flags: 0x1
- MaxItemLevel = 0x314, // Size: 0x1, Flags: 0x1
- WildBattlePetLevel = 0x318, // Size: 0x1, Flags: 0x1
- BattlePetCompanionNameTimestamp = 0x31C, // Size: 0x1, Flags: 0x1
- InteractSpellId = 0x320, // Size: 0x1, Flags: 0x1
- StateSpellVisualId = 0x324, // Size: 0x1, Flags: 0x280
- StateAnimId = 0x328, // Size: 0x1, Flags: 0x280
- StateAnimKitId = 0x32C, // Size: 0x1, Flags: 0x280
- StateWorldEffectId = 0x330, // Size: 0x4, Flags: 0x280
- ScaleDuration = 0x340, // Size: 0x1, Flags: 0x1
- LooksLikeMountId = 0x344, // Size: 0x1, Flags: 0x1
- LooksLikeCreatureId = 0x348, // Size: 0x1, Flags: 0x1
- LookAtControllerId = 0x34C, // Size: 0x1, Flags: 0x1
- LookAtControllerTarget = 0x350 // Size: 0x4, Flags: 0x1
- }
- }
-}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/WoW/Data/WoWPlayer.cs b/Artemis/Artemis/Modules/Games/WoW/Data/WoWPlayer.cs
deleted file mode 100644
index b7eba53bb..000000000
--- a/Artemis/Artemis/Modules/Games/WoW/Data/WoWPlayer.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using System;
-using System.Linq;
-using Process.NET;
-
-namespace Artemis.Modules.Games.WoW.Data
-{
- public class WoWPlayer : WoWUnit
- {
- private readonly IntPtr _targetIntPtr;
-
- public WoWPlayer(IProcess process, IntPtr baseAddress, IntPtr targetIntPtr, bool readPointer = false)
- : base(process, baseAddress, readPointer)
- {
- _targetIntPtr = targetIntPtr;
- }
-
- public WoWObject GetTarget(WoWObjectManager manager)
- {
- var targetGuid = Process.Memory.Read(Process.Native.MainModule.BaseAddress + _targetIntPtr.ToInt32());
- return manager.EnumVisibleObjects().FirstOrDefault(o => o.Guid == targetGuid);
- }
- }
-}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/WoW/Data/WoWStructs.cs b/Artemis/Artemis/Modules/Games/WoW/Data/WoWStructs.cs
deleted file mode 100644
index b16179265..000000000
--- a/Artemis/Artemis/Modules/Games/WoW/Data/WoWStructs.cs
+++ /dev/null
@@ -1,181 +0,0 @@
-using System;
-using System.Runtime.InteropServices;
-using Artemis.Modules.Games.WoW.Data.WowSharp.Client.Patchables;
-
-namespace Artemis.Modules.Games.WoW.Data
-{
- public static class WoWStructs
- {
- [StructLayout(LayoutKind.Explicit)]
- public struct ObjectData
- {
- // x32 : x64
- [FieldOffset(0)] private readonly IntPtr vtable; // 0x00 0x00
- [FieldOffset(10)] public IntPtr Descriptors; // 0x04 0x10
- [FieldOffset(18)] private readonly IntPtr unk1; // 0x08 0x18
- [FieldOffset(20)] public int ObjectType; // 0x0C 0x20
- [FieldOffset(24)] private readonly IntPtr unk3; // 0x10 0x24
- [FieldOffset(28)] private readonly IntPtr unk4; // 0x14 0x28
- [FieldOffset(30)] private readonly IntPtr unk5; // 0x18 0x30
- [FieldOffset(38)] private readonly IntPtr unk6; // 0x1C 0x38
- [FieldOffset(40)] private readonly IntPtr unk7; // 0x20 0x40
- [FieldOffset(48)] private readonly IntPtr unk8; // 0x24 0x48
- [FieldOffset(50)] public Guid Guid; // 0x28 0x50
- }
-
- public struct Guid
- {
- private readonly Int128 _mGuid;
-
- public static readonly Guid Zero = new Guid(0);
-
- public Guid(Int128 guid)
- {
- _mGuid = guid;
- }
-
- public override string ToString()
- {
- // ReSharper disable once SwitchStatementMissingSomeCases
- switch (Type)
- {
- case WoWEnums.GuidType.Creature:
- case WoWEnums.GuidType.Vehicle:
- case WoWEnums.GuidType.Pet:
- case WoWEnums.GuidType.GameObject:
- case WoWEnums.GuidType.AreaTrigger:
- case WoWEnums.GuidType.DynamicObject:
- case WoWEnums.GuidType.Corpse:
- case WoWEnums.GuidType.LootObject:
- case WoWEnums.GuidType.SceneObject:
- case WoWEnums.GuidType.Scenario:
- case WoWEnums.GuidType.AiGroup:
- case WoWEnums.GuidType.DynamicDoor:
- case WoWEnums.GuidType.Vignette:
- case WoWEnums.GuidType.Conversation:
- case WoWEnums.GuidType.CallForHelp:
- case WoWEnums.GuidType.AiResource:
- case WoWEnums.GuidType.AiLock:
- case WoWEnums.GuidType.AiLockTicket:
- return $"{Type}-{SubType}-{RealmId}-{MapId}-{ServerId}-{Id}-{CreationBits:X10}";
- case WoWEnums.GuidType.Player:
- return $"{Type}-{RealmId}-{(ulong) (_mGuid >> 64):X8}";
- case WoWEnums.GuidType.Item:
- return $"{Type}-{RealmId}-{(uint) ((_mGuid >> 18) & 0xFFFFFF)}-{(ulong) (_mGuid >> 64):X10}";
- //case GuidType.ClientActor:
- // return String.Format("{0}-{1}-{2}", Type, RealmId, CreationBits);
- //case GuidType.Transport:
- //case GuidType.StaticDoor:
- // return String.Format("{0}-{1}-{2}", Type, RealmId, CreationBits);
- default:
- return $"{Type}-{_mGuid:X32}";
- }
- }
-
- public override bool Equals(object obj)
- {
- if (obj is Guid)
- return _mGuid == ((Guid) obj)._mGuid;
- return false;
- }
-
- public override int GetHashCode()
- {
- return _mGuid.GetHashCode();
- }
-
- public WoWEnums.GuidType Type => (WoWEnums.GuidType) (byte) ((_mGuid >> 58) & 0x3F);
-
- public byte SubType => (byte) ((_mGuid >> 120) & 0x3F);
-
- public ushort RealmId => (ushort) ((_mGuid >> 42) & 0x1FFF);
-
- public ushort ServerId => (ushort) ((_mGuid >> 104) & 0x1FFF);
-
- public ushort MapId => (ushort) ((_mGuid >> 29) & 0x1FFF);
-
- // Creature, Pet, Vehicle
- public uint Id => (uint) ((_mGuid >> 6) & 0x7FFFFF);
-
- public ulong CreationBits => (ulong) ((_mGuid >> 64) & 0xFFFFFFFFFF);
- }
-
- #region Manager
-
- // Region is here due to the large amount of structs-
- // the CurremtManager struct depends on.
- [StructLayout(LayoutKind.Sequential)]
- public struct CurrentManager
- {
- public TsHashTable VisibleObjects; // m_objects
- public TsHashTable LazyCleanupObjects; // m_lazyCleanupObjects
-
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 13)]
- // m_lazyCleanupFifo, m_freeObjects, m_visibleObjects, m_reenabledObjects, whateverObjects...
- public TsExplicitList[] Links; // Links[13] has all objects stored in VisibleObjects it seems
-
-#if !X64
- public int Unknown1; // wtf is that and why x86 only?
-#endif
- public Int128 ActivePlayer;
- public int MapId;
- public IntPtr ClientConnection;
- public IntPtr MovementGlobals;
- public int Unk1;
- }
-
- [StructLayout(LayoutKind.Sequential)]
- public struct Ts
- {
- public IntPtr vtable;
- public uint m_alloc;
- public uint m_count;
- public IntPtr m_data; //TSExplicitList* m_data;
- }
-
- [StructLayout(LayoutKind.Sequential)]
- public struct TsExplicitList
- {
- public TsList baseClass;
- }
-
- [StructLayout(LayoutKind.Sequential)]
- public struct TsFixedArray
- {
- public Ts baseClass;
- }
-
- [StructLayout(LayoutKind.Sequential)]
- public struct TsGrowableArray
- {
- public TsFixedArray baseclass;
- public uint m_chunk;
- }
-
- [StructLayout(LayoutKind.Sequential)]
- public struct TsHashTable
- {
- public IntPtr vtable;
- public TsExplicitList m_fulllist;
- public int m_fullnessIndicator;
- public TsGrowableArray m_slotlistarray;
- public int m_slotmask;
- }
-
- [StructLayout(LayoutKind.Sequential)]
- public struct TsLink
- {
- public IntPtr m_prevlink; //TSLink *m_prevlink
- public IntPtr m_next; // C_OBJECTHASH *m_next
- }
-
- [StructLayout(LayoutKind.Sequential)]
- public struct TsList
- {
- public int m_linkoffset;
- public TsLink m_terminator;
- }
-
- #endregion;
- }
-}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/WoW/Data/WoWUnit.cs b/Artemis/Artemis/Modules/Games/WoW/Data/WoWUnit.cs
deleted file mode 100644
index c0c0f45bd..000000000
--- a/Artemis/Artemis/Modules/Games/WoW/Data/WoWUnit.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-using System;
-using Process.NET;
-using static Artemis.Modules.Games.WoW.Data.WoWEnums;
-using static Artemis.Modules.Games.WoW.Data.WoWOffsets;
-
-namespace Artemis.Modules.Games.WoW.Data
-{
- public class WoWUnit : WoWObject
- {
- public WoWUnit(IProcess process, IntPtr baseAddress, bool readPointer = false)
- : base(process, baseAddress, readPointer)
- {
- }
-
- public int Health => ReadField(UnitData.Health);
- public int MaxHealth => ReadField(UnitData.MaxHealth);
- public int Power => ReadField(UnitData.Power);
- public int SecondaryPower => ReadField(UnitData.SecondaryPower);
- public int TertiaryPower => ReadField(UnitData.TertiaryPower);
- public int MaxPower => ReadField(UnitData.MaxPower);
- public PowerType PowerType => (PowerType) ReadField(UnitData.DisplayPower);
- public int Level => ReadField(UnitData.Level);
-
- public WoWDetails Details { get; set; }
-
- public void UpdateDetails(WoWNameCache nameCache)
- {
- Details = GetNpcDetails() ?? nameCache.GetNameByGuid(Guid);
- }
- }
-}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/WoW/Models/WoWAura.cs b/Artemis/Artemis/Modules/Games/WoW/Models/WoWAura.cs
new file mode 100644
index 000000000..cd08f216b
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/WoW/Models/WoWAura.cs
@@ -0,0 +1,45 @@
+using System;
+using MoonSharp.Interpreter;
+using Newtonsoft.Json.Linq;
+
+namespace Artemis.Modules.Games.WoW.Models
+{
+ [MoonSharpUserData]
+ public class WoWAura
+ {
+ public string Name { get; set; }
+ public int Id { get; set; }
+ public int Stacks { get; set; }
+ public DateTime StartTime { set; get; }
+ public DateTime EndTime { get; set; }
+ public float Progress { get; set; }
+
+ public void ApplyJson(JToken buffJson)
+ {
+ Name = buffJson["n"].Value();
+ Id = buffJson["id"].Value();
+ if (buffJson["c"] != null)
+ Stacks = buffJson["c"].Value();
+
+ if (buffJson["e"] != null)
+ {
+ var expires = buffJson["e"].Value();
+ var tickCount = Environment.TickCount;
+ var timeLeft = expires - tickCount;
+ EndTime = DateTime.Now.AddMilliseconds(timeLeft);
+ }
+ if (buffJson["d"] != null)
+ StartTime = EndTime.AddSeconds(buffJson["d"].Value() * -1);
+ }
+
+ public void UpdateProgress()
+ {
+ var elapsed = DateTime.Now - StartTime;
+ var total = EndTime - StartTime;
+
+ Progress = (float) (elapsed.TotalMilliseconds / total.TotalMilliseconds);
+ if (Progress > 1)
+ Progress = 1;
+ }
+ }
+}
diff --git a/Artemis/Artemis/Modules/Games/WoW/Models/WoWCastBar.cs b/Artemis/Artemis/Modules/Games/WoW/Models/WoWCastBar.cs
new file mode 100644
index 000000000..53cd4bccc
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/WoW/Models/WoWCastBar.cs
@@ -0,0 +1,64 @@
+using System;
+using MoonSharp.Interpreter;
+using Newtonsoft.Json.Linq;
+
+namespace Artemis.Modules.Games.WoW.Models
+{
+ [MoonSharpUserData]
+ public class WoWCastBar
+ {
+ public WoWCastBar()
+ {
+ Spell = new WoWSpell();
+ }
+
+ public WoWSpell Spell { get; set; }
+ public DateTime StartTime { set; get; }
+ public DateTime EndTime { get; set; }
+ public bool NonInterruptible { get; set; }
+ public float Progress { get; set; }
+ public bool IsChannel { get; set; }
+
+ public void ApplyJson(JToken spellJson, bool isChannel)
+ {
+ var castMs = spellJson["e"].Value() - spellJson["s"].Value();
+ var tickCount = Environment.TickCount;
+ var difference = tickCount - spellJson["s"].Value();
+
+ Spell.Name = spellJson["n"].Value();
+ Spell.Id = spellJson["sid"].Value();
+ StartTime = new DateTime(DateTime.Now.Ticks + difference);
+ EndTime = StartTime.AddMilliseconds(castMs);
+ NonInterruptible = spellJson["ni"].Value();
+ IsChannel = isChannel;
+ }
+
+ public void UpdateProgress()
+ {
+ if (Spell.Name == null)
+ return;
+
+ var elapsed = DateTime.Now - StartTime;
+ var total = EndTime - StartTime;
+
+ if (IsChannel)
+ Progress = 1 - (float) (elapsed.TotalMilliseconds / total.TotalMilliseconds);
+ else
+ Progress = (float) (elapsed.TotalMilliseconds / total.TotalMilliseconds);
+
+ if (Progress > 1 || Progress < 0)
+ Clear();
+ }
+
+ public void Clear()
+ {
+ Spell.Name = null;
+ Spell.Id = 0;
+ StartTime = DateTime.MinValue;
+ EndTime = DateTime.MinValue;
+ NonInterruptible = false;
+ Progress = 0;
+ IsChannel = false;
+ }
+ }
+}
diff --git a/Artemis/Artemis/Modules/Games/WoW/Models/WoWEnums.cs b/Artemis/Artemis/Modules/Games/WoW/Models/WoWEnums.cs
new file mode 100644
index 000000000..9a484d508
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/WoW/Models/WoWEnums.cs
@@ -0,0 +1,44 @@
+namespace Artemis.Modules.Games.WoW.Models
+{
+ public enum WoWRace
+ {
+ Human,
+ Orc,
+ Dwarf,
+ NightElf,
+ Undead,
+ Tauren,
+ Gnome,
+ Troll,
+ BloodElf,
+ Draenei,
+ Goblin,
+ Worgen,
+ Pandaren
+ }
+
+ public enum WoWPowerType
+ {
+ Mana = 0,
+ Rage = 1,
+ Focus = 2,
+ Energy = 3,
+ ComboPoints = 4,
+ Runes = 5,
+ RunicPower = 6,
+ SoulShards = 7,
+ LunarPower = 8,
+ HolyPower = 9,
+ AlternatePower = 10,
+ Maelstrom = 11,
+ Chi = 12,
+ Insanity = 13,
+ ArcaneCharges = 16
+ }
+
+ public enum WoWGender
+ {
+ Male,
+ Female
+ }
+}
diff --git a/Artemis/Artemis/Modules/Games/WoW/Models/WoWSpecialization.cs b/Artemis/Artemis/Modules/Games/WoW/Models/WoWSpecialization.cs
new file mode 100644
index 000000000..3582359c8
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/WoW/Models/WoWSpecialization.cs
@@ -0,0 +1,20 @@
+using MoonSharp.Interpreter;
+using Newtonsoft.Json.Linq;
+
+namespace Artemis.Modules.Games.WoW.Models
+{
+ [MoonSharpUserData]
+ public class WoWSpecialization
+ {
+ public string Name { get; set; }
+ public int Id { get; set; }
+ public string Role { get; set; }
+
+ public void ApplyJson(JToken specJson)
+ {
+ Name = specJson["n"].Value();
+ Id = specJson["id"].Value();
+ Role = specJson["r"].Value();
+ }
+ }
+}
diff --git a/Artemis/Artemis/Modules/Games/WoW/Models/WoWSpell.cs b/Artemis/Artemis/Modules/Games/WoW/Models/WoWSpell.cs
new file mode 100644
index 000000000..5b99c5fe1
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/WoW/Models/WoWSpell.cs
@@ -0,0 +1,11 @@
+using MoonSharp.Interpreter;
+
+namespace Artemis.Modules.Games.WoW.Models
+{
+ [MoonSharpUserData]
+ public class WoWSpell
+ {
+ public string Name { get; set; }
+ public int Id { get; set; }
+ }
+}
diff --git a/Artemis/Artemis/Modules/Games/WoW/Models/WoWUnit.cs b/Artemis/Artemis/Modules/Games/WoW/Models/WoWUnit.cs
new file mode 100644
index 000000000..06e93edb5
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/WoW/Models/WoWUnit.cs
@@ -0,0 +1,134 @@
+using System.Collections.Generic;
+using Artemis.Utilities;
+using MoonSharp.Interpreter;
+using Newtonsoft.Json.Linq;
+
+namespace Artemis.Modules.Games.WoW.Models
+{
+ [MoonSharpUserData]
+ public class WoWUnit
+ {
+ private readonly List _currentFrameCasts = new List();
+
+ public WoWUnit()
+ {
+ CastBar = new WoWCastBar();
+ Specialization = new WoWSpecialization();
+
+ Buffs = new List();
+ Debuffs = new List();
+ RecentIntantCasts = new List();
+ }
+
+ public string Name { get; set; }
+ public int Level { get; set; }
+ public int Health { get; set; }
+ public int MaxHealth { get; set; }
+ public int Power { get; set; }
+ public int MaxPower { get; set; }
+ public WoWPowerType PowerType { get; set; }
+ public string Class { get; set; }
+ public WoWRace Race { get; set; }
+ public WoWGender Gender { get; set; }
+
+ public WoWCastBar CastBar { get; set; }
+ public WoWSpecialization Specialization { get; }
+
+ public List Buffs { get; }
+ public List Debuffs { get; }
+ public List RecentIntantCasts { get; }
+
+ public void ApplyJson(JToken json)
+ {
+ if (json["n"] == null)
+ return;
+
+ Name = json["n"].Value();
+ Level = json["l"].Value();
+ Class = json["c"].Value();
+ Gender = json["g"].Value() == 3 ? WoWGender.Female : WoWGender.Male;
+
+ if (json["r"] != null)
+ Race = GeneralHelpers.ParseEnum(json["r"].Value());
+ if (json["s"] != null)
+ Specialization.ApplyJson(json["s"]);
+ }
+
+ public void ApplyStateJson(JToken json)
+ {
+ Health = json["h"].Value();
+ MaxHealth = json["mh"].Value();
+ PowerType = GeneralHelpers.ParseEnum(json["t"].Value().ToString());
+ Power = json["p"].Value();
+ MaxPower = json["mp"].Value();
+ }
+
+ public void ApplyAuraJson(JToken json, bool buffs)
+ {
+ if (buffs)
+ {
+ lock (Buffs)
+ {
+ Buffs.Clear();
+ foreach (var auraJson in json.Children())
+ {
+ var aura = new WoWAura();
+ aura.ApplyJson(auraJson);
+ Buffs.Add(aura);
+ }
+ }
+ }
+ else
+ {
+ lock (Debuffs)
+ {
+ Debuffs.Clear();
+ foreach (var auraJson in json.Children())
+ {
+ var aura = new WoWAura();
+ aura.ApplyJson(auraJson);
+ Debuffs.Add(aura);
+ }
+ }
+ }
+ }
+
+ public void AddInstantCast(WoWSpell spell)
+ {
+ lock (_currentFrameCasts)
+ {
+ _currentFrameCasts.Add(spell);
+ }
+ }
+
+ public void ClearInstantCasts()
+ {
+ lock (_currentFrameCasts)
+ {
+ // Remove all casts that weren't cast in the after the last frame
+ RecentIntantCasts.Clear();
+ RecentIntantCasts.AddRange(_currentFrameCasts);
+
+ // Clear the that were after the last frame so that they are removed next frame when this method is called again
+ _currentFrameCasts.Clear();
+ }
+ }
+
+ public void Update()
+ {
+ CastBar.UpdateProgress();
+ ClearInstantCasts();
+
+ lock (Buffs)
+ {
+ foreach (var buff in Buffs)
+ buff.UpdateProgress();
+ }
+ lock (Debuffs)
+ {
+ foreach (var debuff in Debuffs)
+ debuff.UpdateProgress();
+ }
+ }
+ }
+}
diff --git a/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Artemis.toc b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Artemis.toc
new file mode 100644
index 000000000..824da3279
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Artemis.toc
@@ -0,0 +1,9 @@
+## Interface: 70300
+## Title: Artemis
+## Notes: Transmits ingame data to Artemis
+## Author: SpoinkyNL
+## Version: 1.0.0
+
+embeds.xml
+
+Core.lua
diff --git a/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Core.lua b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Core.lua
new file mode 100644
index 000000000..52a6287e9
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Core.lua
@@ -0,0 +1,398 @@
+Artemis = LibStub("AceAddon-3.0"):NewAddon("Artemis", "AceConsole-3.0", "AceEvent-3.0", "AceTimer-3.0", "AceComm-3.0")
+json = LibStub("json")
+
+-- Hook onto logout because it seems PLAYER_LOGOUT fires on reload as well
+local _Logout = Logout
+
+local debugging = false
+local lastLine = {}
+local channeling = {}
+local unitUpdates = {}
+local lastTransmitMessage
+local lastTransmitTime
+local lastBuffs = "";
+local lastDebuffs = "";
+local prefixCounts = {}
+
+channeling["player"] = false
+channeling["target"] = false
+
+function Artemis:OnEnable()
+ -- Register all the various events that Artemis will want to know about
+ Artemis:RegisterEvent("PLAYER_ENTERING_WORLD")
+ Artemis:RegisterEvent("PLAYER_LEVEL_UP")
+ Artemis:RegisterEvent("PLAYER_FLAGS_CHANGED")
+ Artemis:RegisterEvent("ACHIEVEMENT_EARNED")
+ Artemis:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED")
+ Artemis:RegisterEvent("UNIT_TARGET")
+ Artemis:RegisterEvent("UNIT_HEALTH")
+ Artemis:RegisterEvent("UNIT_POWER")
+ Artemis:RegisterEvent("UNIT_AURA")
+ Artemis:RegisterEvent("UNIT_SPELLCAST_START")
+ Artemis:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED")
+ Artemis:RegisterEvent("UNIT_SPELLCAST_FAILED")
+ Artemis:RegisterEvent("UNIT_SPELLCAST_DELAYED")
+ Artemis:RegisterEvent("UNIT_SPELLCAST_CHANNEL_START")
+ Artemis:RegisterEvent("UNIT_SPELLCAST_CHANNEL_STOP")
+ Artemis:RegisterEvent("UNIT_SPELLCAST_CHANNEL_UPDATE")
+ Artemis:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED")
+ Artemis:RegisterEvent("ZONE_CHANGED")
+ Artemis:RegisterEvent("ZONE_CHANGED_NEW_AREA")
+
+ -- Register the chat command /artemis
+ Artemis:RegisterChatCommand("artemis", "HandleChatCommand")
+
+ -- Create a loop that'll periodically send character data in case of an Artemis restart/late start
+ Artemis:ScheduleRepeatingTimer("PeriodicUpdate", 30)
+end
+
+function Artemis:HandleChatCommand(input)
+ if input == "debug" then
+ debugging = not (debugging)
+ if debugging then
+ Artemis:Print("Debugging enabled.")
+ else
+ Artemis:Print("Debugging disabled.")
+ end
+ end
+ if input == "rc" then
+ prefixCounts = {}
+ Artemis:Print("Reset the send counters.")
+ end
+ if input == nill or input == "" or input == "help" then
+ Artemis:Print("Available chat commands:")
+ Artemis:Printf("|cffb7b7b7/artemis debug|r: Toggle debugging")
+ Artemis:Printf("|cffb7b7b7/artemis rc|r: Reset the debug counters")
+ end
+end
+
+function Artemis:Transmit(prefix, data, prio)
+ local msg = "artemis(".. prefix .. "|" .. json.encode(data) ..")"
+ -- If the message is the same as the previous, make sure it wasn't sent less than 250ms ago
+ if msg == lastTransmitMessage then
+ if not (lastTransmitTime == nil) then
+ local diff = GetTime() - lastTransmitTime;
+ if (diff < 0.25) then
+ return
+ end
+ end
+ end
+
+ lastTransmitTime = GetTime()
+
+ if debugging == true then
+ if prefixCounts[prefix] == nill then
+ prefixCounts[prefix] = 0
+ end
+ prefixCounts[prefix] = prefixCounts[prefix] + 1
+ end
+
+ if debugging == true then
+ Artemis:Printf("Transmitting with prefix |cfffdff71" .. prefix .. "|r (" .. prefixCounts[prefix] .. ").")
+ Artemis:Print(msg)
+ end
+ Artemis:SendCommMessage("(artemis)", msg, "WHISPER", UnitName("player"), prio)
+end
+
+function Artemis:TransmitUnitState(unit, ignoreThrottle)
+ if not ignoreThrottle then
+ if not (unitUpdates[unit] == nil) then
+ local diff = GetTime() - unitUpdates[unit]
+ if (diff < 0.5) then
+ return
+ end
+ end
+ end
+
+ local table = {
+ h = UnitHealth(unit),
+ mh = UnitHealthMax(unit),
+ p = UnitPower(unit),
+ mp = UnitPowerMax(unit),
+ t = UnitPowerType(unit)
+ };
+
+ unitUpdates[unit] = GetTime()
+ Artemis:Transmit(unit .. "State", table)
+end
+
+function Artemis:GetUnitDetails(unit)
+ return {
+ n = UnitName(unit),
+ c = UnitClass(unit),
+ l = UnitLevel(unit),
+ r = UnitRace(unit),
+ g = UnitSex(unit),
+ f = UnitFactionGroup(unit)
+ };
+end
+
+function Artemis:GetPlayerDetails()
+ local details = Artemis:GetUnitDetails("player")
+ local id, name, _, _, role = GetSpecializationInfo(GetSpecialization())
+
+ details.realm = GetRealmName()
+ details.achievementPoints = GetTotalAchievementPoints(false)
+ details.s = {id = id, n = name, r = role}
+
+ return details
+end
+
+function Artemis:GetUnitAuras(unit, filter)
+ local auras = {};
+ for index = 1, 40 do
+ local name, _, _, count, _, duration, expires, caster, _, _, spellID = UnitAura(unit, index, filter);
+ if not (name == nil) then
+ local buffTable = {n = name, id = spellID}
+ -- Leave these values out if they are 0 to save some space
+ if count > 0 then
+ buffTable["c"] = count
+ end
+ if duration > 0 then
+ buffTable["d"] = duration
+ end
+ if expires > 0 then
+ buffTable["e"] = expires
+ end
+ table.insert(auras, buffTable)
+ end
+ end
+ return auras
+end
+
+function Artemis:PeriodicUpdate()
+ -- Don't do this in combat, enough data going out at that time already
+ if InCombatLockdown() then
+ return
+ end
+ Artemis:Transmit("player", Artemis:GetPlayerDetails())
+ Artemis:TransmitUnitState("player", true);
+end
+
+function Artemis:PLAYER_ENTERING_WORLD(...)
+ Artemis:Transmit("player", Artemis:GetPlayerDetails())
+ Artemis:TransmitUnitState("player", true);
+end
+
+function Logout()
+ Artemis:Transmit("gameState", "loggedOut")
+ return _Logout()
+end
+
+function Artemis:PLAYER_LEVEL_UP(...)
+ Artemis:Transmit("player", Artemis:GetPlayerDetails())
+end
+
+function Artemis:PLAYER_FLAGS_CHANGED(...)
+ local _, unitID = ...
+ if unitID == "player" then
+ -- AFK overwrites DND
+ if UnitIsAFK("player") then
+ Artemis:Transmit("gameState", "afk")
+ return
+ end
+ if UnitIsDND("player") then
+ Artemis:Transmit("gameState", "dnd")
+ return
+ end
+ Artemis:Transmit("gameState", "ingame")
+ end
+end
+
+function Artemis:ACHIEVEMENT_EARNED(...)
+ Artemis:Transmit("player", Artemis:GetPlayerDetails())
+end
+
+function Artemis:ACTIVE_TALENT_GROUP_CHANGED(...)
+ Artemis:Transmit("player", Artemis:GetPlayerDetails())
+end
+
+function Artemis:UNIT_TARGET(...)
+ local _, source = ...
+ if not (source == "player") then
+ return
+ end
+
+ local details = Artemis:GetUnitDetails("target")
+ channeling["target"] = false
+
+ Artemis:Transmit("target", details)
+ Artemis:TransmitUnitState("target", true);
+end
+
+function Artemis:UNIT_HEALTH(...)
+ local _, source = ...
+ if not (source == "player") and not (source == "target") then
+ return
+ end
+
+ Artemis:TransmitUnitState(source, false);
+end
+
+function Artemis:UNIT_POWER(...)
+ local _, source = ...
+ if not (source == "player") and not (source == "target") then
+ return
+ end
+
+ Artemis:TransmitUnitState(source, false);
+end
+
+function Artemis:UNIT_AURA(...)
+ local _, source = ...
+ if not (source == "player") then
+ return
+ end
+
+ local buffs = Artemis:GetUnitAuras(source, "PLAYER|HELPFUL")
+ local debuffs = Artemis:GetUnitAuras(source, "PLAYER|HARMFUL")
+
+ local newBuffs = json.encode(buffs)
+ local newDebuffs = json.encode(debuffs)
+
+ if not (lastBuffs == newBuffs) then
+ Artemis:Transmit("buffs", buffs)
+ end
+ if not (lastDebuffs == newDebuffs) then
+ Artemis:Transmit("debuffs", debuffs)
+ end
+
+ lastBuffs = newBuffs
+ lastDebuffs = newDebuffs
+end
+
+-- Detect non-instant spell casts
+function Artemis:UNIT_SPELLCAST_START(...)
+ local _, unitID, spell, rank, lineID, spellID = ...
+ if not (unitID == "player") and not (unitID == "target") then
+ return
+ end
+
+ local name, _, _, _, startTime, endTime, _, _, notInterruptible = UnitCastingInfo(unitID)
+ local table = {uid = unitID, n = name, sid = spellID, s = startTime, e = endTime, ni = notInterruptible}
+ lastLine[unitID] = lineID
+
+ Artemis:Transmit("spellCast", table, "ALERT")
+end
+
+-- Detect instant spell casts
+function Artemis:UNIT_SPELLCAST_SUCCEEDED (...)
+ local _, unitID, spell, rank, lineID, spellID = ...
+ if not (unitID == "player") and not (unitID == "target") then
+ return
+ end
+ if channeling[unitID] == true then
+ return
+ end
+ -- Many spells are irrelevant system spells, don't transmit these
+ if unitID == "player" and not (IsPlayerSpell(spellID)) then
+ return
+ end
+
+ local name, subText, text, texture, startTime, endTime, isTradeSkill, castID, notInterruptible = UnitCastingInfo(unitID)
+ -- Don't trigger on the success of a non instant cast
+ if not (lastLine[unitID] == nil) and lastLine[unitID] == lineID then
+ return
+ end
+
+ -- Set back the last line to what is currently being cast (Fireblast during Fireball per example)
+ if not (name == nil) then
+ lastLine[unitID] = castID
+ else
+ lastLine[unitID] = nil
+ end
+
+ local table = {uid = unitID, n = spell, sid = spellID}
+
+ Artemis:Transmit("instantSpellCast", table, "ALERT")
+end
+
+-- Detect falure of non instant casts
+function Artemis:UNIT_SPELLCAST_FAILED (...)
+ local source, unitID, _, _, lineID = ...
+ if not (unitID == "player") and not (unitID == "target") then
+ return
+ end
+ if lastLine[unitID] == nil or not (lastLine[unitID] == lineID) then
+ return
+ end
+
+ lastLine[unitID] = nil
+
+ Artemis:Transmit("spellCastFailed", unitID, "ALERT")
+end
+
+-- Detect falure of non instant casts
+function Artemis:UNIT_SPELLCAST_DELAYED (...)
+ local _, unitID, spell, rank, lineID, spellID = ...
+ if not (unitID == "player") and not (unitID == "target") then
+ return
+ end
+ local name, _, _, _, startTime, endTime, _, _, notInterruptible = UnitCastingInfo(unitID)
+ local table = {uid = unitID, n = name, sid = spellID, s = startTime, e = endTime, ni = notInterruptible}
+
+ Artemis:Transmit("spellCast", table, "ALERT")
+end
+
+-- Detect cancellation of non instant casts
+function Artemis:UNIT_SPELLCAST_INTERRUPTED (...)
+ local source, unitID, _, _, lineID = ...
+ if not (unitID == "player") and not (unitID == "target") then
+ return
+ end
+ if lastLine[unitID] == nil or not (lastLine[unitID] == lineID) then
+ return
+ end
+
+ lastLine[unitID] = nil
+
+ Artemis:Transmit("spellCastInterrupted", unitID, "ALERT")
+end
+
+-- Detect spell channels
+function Artemis:UNIT_SPELLCAST_CHANNEL_START(...)
+ local _, unitID, spell, rank, lineID, spellID = ...
+ if not (unitID == "player") and not (unitID == "target") then
+ return
+ end
+ channeling[unitID] = true
+
+ local name, _, _, _, startTime, endTime, _, notInterruptible = UnitChannelInfo(unitID)
+ local table = {uid = unitID, n = name, sid = spellID, s = startTime, e = endTime, ni = notInterruptible}
+
+ Artemis:Transmit("spellChannel", table, "ALERT")
+end
+
+function Artemis:UNIT_SPELLCAST_CHANNEL_UPDATE (...)
+ local _, unitID, spell, rank, lineID, spellID = ...
+ if not (unitID == "player") and not (unitID == "target") then
+ return
+ end
+ local name, _, _, _, startTime, endTime, _, notInterruptible = UnitChannelInfo(unitID)
+ local table = {uid = unitID, n = name, sid = spellID, s = startTime, e = endTime, ni = notInterruptible}
+
+ Artemis:Transmit("spellChannel", table, "ALERT")
+end
+
+-- Detect cancellation of channels
+function Artemis:UNIT_SPELLCAST_CHANNEL_STOP (...)
+ local source, unitID, _, _, lineID = ...
+ if not (unitID == "player") and not (unitID == "target") then
+ return
+ end
+
+ channeling[unitID] = false
+
+ Artemis:Transmit("spellChannelInterrupted", unitID, "ALERT")
+end
+
+function Artemis:ZONE_CHANGED_NEW_AREA (...)
+ local pvpType, isSubZonePVP, factionName = GetZonePVPInfo()
+
+ Artemis:Transmit("zone", {z = GetRealZoneText(), s = GetSubZoneText(), t = pvpType, p = isSubZonePVP, f = factionName})
+end
+function Artemis:ZONE_CHANGED (...)
+ local pvpType, isSubZonePVP, factionName = GetZonePVPInfo()
+
+ Artemis:Transmit("zone", {z = GetRealZoneText(), s = GetSubZoneText(), t = pvpType, p = isSubZonePVP, f = factionName})
+end
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceAddon-3.0/AceAddon-3.0.lua b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceAddon-3.0/AceAddon-3.0.lua
new file mode 100644
index 000000000..a7f7279cc
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceAddon-3.0/AceAddon-3.0.lua
@@ -0,0 +1,674 @@
+--- **AceAddon-3.0** provides a template for creating addon objects.
+-- It'll provide you with a set of callback functions that allow you to simplify the loading
+-- process of your addon.\\
+-- Callbacks provided are:\\
+-- * **OnInitialize**, which is called directly after the addon is fully loaded.
+-- * **OnEnable** which gets called during the PLAYER_LOGIN event, when most of the data provided by the game is already present.
+-- * **OnDisable**, which is only called when your addon is manually being disabled.
+-- @usage
+-- -- A small (but complete) addon, that doesn't do anything,
+-- -- but shows usage of the callbacks.
+-- local MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon")
+--
+-- function MyAddon:OnInitialize()
+-- -- do init tasks here, like loading the Saved Variables,
+-- -- or setting up slash commands.
+-- end
+--
+-- function MyAddon:OnEnable()
+-- -- Do more initialization here, that really enables the use of your addon.
+-- -- Register Events, Hook functions, Create Frames, Get information from
+-- -- the game that wasn't available in OnInitialize
+-- end
+--
+-- function MyAddon:OnDisable()
+-- -- Unhook, Unregister Events, Hide frames that you created.
+-- -- You would probably only use an OnDisable if you want to
+-- -- build a "standby" mode, or be able to toggle modules on/off.
+-- end
+-- @class file
+-- @name AceAddon-3.0.lua
+-- @release $Id: AceAddon-3.0.lua 1084 2013-04-27 20:14:11Z nevcairiel $
+
+local MAJOR, MINOR = "AceAddon-3.0", 12
+local AceAddon, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not AceAddon then return end -- No Upgrade needed.
+
+AceAddon.frame = AceAddon.frame or CreateFrame("Frame", "AceAddon30Frame") -- Our very own frame
+AceAddon.addons = AceAddon.addons or {} -- addons in general
+AceAddon.statuses = AceAddon.statuses or {} -- statuses of addon.
+AceAddon.initializequeue = AceAddon.initializequeue or {} -- addons that are new and not initialized
+AceAddon.enablequeue = AceAddon.enablequeue or {} -- addons that are initialized and waiting to be enabled
+AceAddon.embeds = AceAddon.embeds or setmetatable({}, {__index = function(tbl, key) tbl[key] = {} return tbl[key] end }) -- contains a list of libraries embedded in an addon
+
+-- Lua APIs
+local tinsert, tconcat, tremove = table.insert, table.concat, table.remove
+local fmt, tostring = string.format, tostring
+local select, pairs, next, type, unpack = select, pairs, next, type, unpack
+local loadstring, assert, error = loadstring, assert, error
+local setmetatable, getmetatable, rawset, rawget = setmetatable, getmetatable, rawset, rawget
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: LibStub, IsLoggedIn, geterrorhandler
+
+--[[
+ xpcall safecall implementation
+]]
+local xpcall = xpcall
+
+local function errorhandler(err)
+ return geterrorhandler()(err)
+end
+
+local function CreateDispatcher(argCount)
+ local code = [[
+ local xpcall, eh = ...
+ local method, ARGS
+ local function call() return method(ARGS) end
+
+ local function dispatch(func, ...)
+ method = func
+ if not method then return end
+ ARGS = ...
+ return xpcall(call, eh)
+ end
+
+ return dispatch
+ ]]
+
+ local ARGS = {}
+ for i = 1, argCount do ARGS[i] = "arg"..i end
+ code = code:gsub("ARGS", tconcat(ARGS, ", "))
+ return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler)
+end
+
+local Dispatchers = setmetatable({}, {__index=function(self, argCount)
+ local dispatcher = CreateDispatcher(argCount)
+ rawset(self, argCount, dispatcher)
+ return dispatcher
+end})
+Dispatchers[0] = function(func)
+ return xpcall(func, errorhandler)
+end
+
+local function safecall(func, ...)
+ -- we check to see if the func is passed is actually a function here and don't error when it isn't
+ -- this safecall is used for optional functions like OnInitialize OnEnable etc. When they are not
+ -- present execution should continue without hinderance
+ if type(func) == "function" then
+ return Dispatchers[select('#', ...)](func, ...)
+ end
+end
+
+-- local functions that will be implemented further down
+local Enable, Disable, EnableModule, DisableModule, Embed, NewModule, GetModule, GetName, SetDefaultModuleState, SetDefaultModuleLibraries, SetEnabledState, SetDefaultModulePrototype
+
+-- used in the addon metatable
+local function addontostring( self ) return self.name end
+
+-- Check if the addon is queued for initialization
+local function queuedForInitialization(addon)
+ for i = 1, #AceAddon.initializequeue do
+ if AceAddon.initializequeue[i] == addon then
+ return true
+ end
+ end
+ return false
+end
+
+--- Create a new AceAddon-3.0 addon.
+-- Any libraries you specified will be embeded, and the addon will be scheduled for
+-- its OnInitialize and OnEnable callbacks.
+-- The final addon object, with all libraries embeded, will be returned.
+-- @paramsig [object ,]name[, lib, ...]
+-- @param object Table to use as a base for the addon (optional)
+-- @param name Name of the addon object to create
+-- @param lib List of libraries to embed into the addon
+-- @usage
+-- -- Create a simple addon object
+-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon", "AceEvent-3.0")
+--
+-- -- Create a Addon object based on the table of a frame
+-- local MyFrame = CreateFrame("Frame")
+-- MyAddon = LibStub("AceAddon-3.0"):NewAddon(MyFrame, "MyAddon", "AceEvent-3.0")
+function AceAddon:NewAddon(objectorname, ...)
+ local object,name
+ local i=1
+ if type(objectorname)=="table" then
+ object=objectorname
+ name=...
+ i=2
+ else
+ name=objectorname
+ end
+ if type(name)~="string" then
+ error(("Usage: NewAddon([object,] name, [lib, lib, lib, ...]): 'name' - string expected got '%s'."):format(type(name)), 2)
+ end
+ if self.addons[name] then
+ error(("Usage: NewAddon([object,] name, [lib, lib, lib, ...]): 'name' - Addon '%s' already exists."):format(name), 2)
+ end
+
+ object = object or {}
+ object.name = name
+
+ local addonmeta = {}
+ local oldmeta = getmetatable(object)
+ if oldmeta then
+ for k, v in pairs(oldmeta) do addonmeta[k] = v end
+ end
+ addonmeta.__tostring = addontostring
+
+ setmetatable( object, addonmeta )
+ self.addons[name] = object
+ object.modules = {}
+ object.orderedModules = {}
+ object.defaultModuleLibraries = {}
+ Embed( object ) -- embed NewModule, GetModule methods
+ self:EmbedLibraries(object, select(i,...))
+
+ -- add to queue of addons to be initialized upon ADDON_LOADED
+ tinsert(self.initializequeue, object)
+ return object
+end
+
+
+--- Get the addon object by its name from the internal AceAddon registry.
+-- Throws an error if the addon object cannot be found (except if silent is set).
+-- @param name unique name of the addon object
+-- @param silent if true, the addon is optional, silently return nil if its not found
+-- @usage
+-- -- Get the Addon
+-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
+function AceAddon:GetAddon(name, silent)
+ if not silent and not self.addons[name] then
+ error(("Usage: GetAddon(name): 'name' - Cannot find an AceAddon '%s'."):format(tostring(name)), 2)
+ end
+ return self.addons[name]
+end
+
+-- - Embed a list of libraries into the specified addon.
+-- This function will try to embed all of the listed libraries into the addon
+-- and error if a single one fails.
+--
+-- **Note:** This function is for internal use by :NewAddon/:NewModule
+-- @paramsig addon, [lib, ...]
+-- @param addon addon object to embed the libs in
+-- @param lib List of libraries to embed into the addon
+function AceAddon:EmbedLibraries(addon, ...)
+ for i=1,select("#", ... ) do
+ local libname = select(i, ...)
+ self:EmbedLibrary(addon, libname, false, 4)
+ end
+end
+
+-- - Embed a library into the addon object.
+-- This function will check if the specified library is registered with LibStub
+-- and if it has a :Embed function to call. It'll error if any of those conditions
+-- fails.
+--
+-- **Note:** This function is for internal use by :EmbedLibraries
+-- @paramsig addon, libname[, silent[, offset]]
+-- @param addon addon object to embed the library in
+-- @param libname name of the library to embed
+-- @param silent marks an embed to fail silently if the library doesn't exist (optional)
+-- @param offset will push the error messages back to said offset, defaults to 2 (optional)
+function AceAddon:EmbedLibrary(addon, libname, silent, offset)
+ local lib = LibStub:GetLibrary(libname, true)
+ if not lib and not silent then
+ error(("Usage: EmbedLibrary(addon, libname, silent, offset): 'libname' - Cannot find a library instance of %q."):format(tostring(libname)), offset or 2)
+ elseif lib and type(lib.Embed) == "function" then
+ lib:Embed(addon)
+ tinsert(self.embeds[addon], libname)
+ return true
+ elseif lib then
+ error(("Usage: EmbedLibrary(addon, libname, silent, offset): 'libname' - Library '%s' is not Embed capable"):format(libname), offset or 2)
+ end
+end
+
+--- Return the specified module from an addon object.
+-- Throws an error if the addon object cannot be found (except if silent is set)
+-- @name //addon//:GetModule
+-- @paramsig name[, silent]
+-- @param name unique name of the module
+-- @param silent if true, the module is optional, silently return nil if its not found (optional)
+-- @usage
+-- -- Get the Addon
+-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
+-- -- Get the Module
+-- MyModule = MyAddon:GetModule("MyModule")
+function GetModule(self, name, silent)
+ if not self.modules[name] and not silent then
+ error(("Usage: GetModule(name, silent): 'name' - Cannot find module '%s'."):format(tostring(name)), 2)
+ end
+ return self.modules[name]
+end
+
+local function IsModuleTrue(self) return true end
+
+--- Create a new module for the addon.
+-- The new module can have its own embeded libraries and/or use a module prototype to be mixed into the module.\\
+-- A module has the same functionality as a real addon, it can have modules of its own, and has the same API as
+-- an addon object.
+-- @name //addon//:NewModule
+-- @paramsig name[, prototype|lib[, lib, ...]]
+-- @param name unique name of the module
+-- @param prototype object to derive this module from, methods and values from this table will be mixed into the module (optional)
+-- @param lib List of libraries to embed into the addon
+-- @usage
+-- -- Create a module with some embeded libraries
+-- MyModule = MyAddon:NewModule("MyModule", "AceEvent-3.0", "AceHook-3.0")
+--
+-- -- Create a module with a prototype
+-- local prototype = { OnEnable = function(self) print("OnEnable called!") end }
+-- MyModule = MyAddon:NewModule("MyModule", prototype, "AceEvent-3.0", "AceHook-3.0")
+function NewModule(self, name, prototype, ...)
+ if type(name) ~= "string" then error(("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'name' - string expected got '%s'."):format(type(name)), 2) end
+ if type(prototype) ~= "string" and type(prototype) ~= "table" and type(prototype) ~= "nil" then error(("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'prototype' - table (prototype), string (lib) or nil expected got '%s'."):format(type(prototype)), 2) end
+
+ if self.modules[name] then error(("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'name' - Module '%s' already exists."):format(name), 2) end
+
+ -- modules are basically addons. We treat them as such. They will be added to the initializequeue properly as well.
+ -- NewModule can only be called after the parent addon is present thus the modules will be initialized after their parent is.
+ local module = AceAddon:NewAddon(fmt("%s_%s", self.name or tostring(self), name))
+
+ module.IsModule = IsModuleTrue
+ module:SetEnabledState(self.defaultModuleState)
+ module.moduleName = name
+
+ if type(prototype) == "string" then
+ AceAddon:EmbedLibraries(module, prototype, ...)
+ else
+ AceAddon:EmbedLibraries(module, ...)
+ end
+ AceAddon:EmbedLibraries(module, unpack(self.defaultModuleLibraries))
+
+ if not prototype or type(prototype) == "string" then
+ prototype = self.defaultModulePrototype or nil
+ end
+
+ if type(prototype) == "table" then
+ local mt = getmetatable(module)
+ mt.__index = prototype
+ setmetatable(module, mt) -- More of a Base class type feel.
+ end
+
+ safecall(self.OnModuleCreated, self, module) -- Was in Ace2 and I think it could be a cool thing to have handy.
+ self.modules[name] = module
+ tinsert(self.orderedModules, module)
+
+ return module
+end
+
+--- Returns the real name of the addon or module, without any prefix.
+-- @name //addon//:GetName
+-- @paramsig
+-- @usage
+-- print(MyAddon:GetName())
+-- -- prints "MyAddon"
+function GetName(self)
+ return self.moduleName or self.name
+end
+
+--- Enables the Addon, if possible, return true or false depending on success.
+-- This internally calls AceAddon:EnableAddon(), thus dispatching a OnEnable callback
+-- and enabling all modules of the addon (unless explicitly disabled).\\
+-- :Enable() also sets the internal `enableState` variable to true
+-- @name //addon//:Enable
+-- @paramsig
+-- @usage
+-- -- Enable MyModule
+-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
+-- MyModule = MyAddon:GetModule("MyModule")
+-- MyModule:Enable()
+function Enable(self)
+ self:SetEnabledState(true)
+
+ -- nevcairiel 2013-04-27: don't enable an addon/module if its queued for init still
+ -- it'll be enabled after the init process
+ if not queuedForInitialization(self) then
+ return AceAddon:EnableAddon(self)
+ end
+end
+
+--- Disables the Addon, if possible, return true or false depending on success.
+-- This internally calls AceAddon:DisableAddon(), thus dispatching a OnDisable callback
+-- and disabling all modules of the addon.\\
+-- :Disable() also sets the internal `enableState` variable to false
+-- @name //addon//:Disable
+-- @paramsig
+-- @usage
+-- -- Disable MyAddon
+-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
+-- MyAddon:Disable()
+function Disable(self)
+ self:SetEnabledState(false)
+ return AceAddon:DisableAddon(self)
+end
+
+--- Enables the Module, if possible, return true or false depending on success.
+-- Short-hand function that retrieves the module via `:GetModule` and calls `:Enable` on the module object.
+-- @name //addon//:EnableModule
+-- @paramsig name
+-- @usage
+-- -- Enable MyModule using :GetModule
+-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
+-- MyModule = MyAddon:GetModule("MyModule")
+-- MyModule:Enable()
+--
+-- -- Enable MyModule using the short-hand
+-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
+-- MyAddon:EnableModule("MyModule")
+function EnableModule(self, name)
+ local module = self:GetModule( name )
+ return module:Enable()
+end
+
+--- Disables the Module, if possible, return true or false depending on success.
+-- Short-hand function that retrieves the module via `:GetModule` and calls `:Disable` on the module object.
+-- @name //addon//:DisableModule
+-- @paramsig name
+-- @usage
+-- -- Disable MyModule using :GetModule
+-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
+-- MyModule = MyAddon:GetModule("MyModule")
+-- MyModule:Disable()
+--
+-- -- Disable MyModule using the short-hand
+-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
+-- MyAddon:DisableModule("MyModule")
+function DisableModule(self, name)
+ local module = self:GetModule( name )
+ return module:Disable()
+end
+
+--- Set the default libraries to be mixed into all modules created by this object.
+-- Note that you can only change the default module libraries before any module is created.
+-- @name //addon//:SetDefaultModuleLibraries
+-- @paramsig lib[, lib, ...]
+-- @param lib List of libraries to embed into the addon
+-- @usage
+-- -- Create the addon object
+-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon")
+-- -- Configure default libraries for modules (all modules need AceEvent-3.0)
+-- MyAddon:SetDefaultModuleLibraries("AceEvent-3.0")
+-- -- Create a module
+-- MyModule = MyAddon:NewModule("MyModule")
+function SetDefaultModuleLibraries(self, ...)
+ if next(self.modules) then
+ error("Usage: SetDefaultModuleLibraries(...): cannot change the module defaults after a module has been registered.", 2)
+ end
+ self.defaultModuleLibraries = {...}
+end
+
+--- Set the default state in which new modules are being created.
+-- Note that you can only change the default state before any module is created.
+-- @name //addon//:SetDefaultModuleState
+-- @paramsig state
+-- @param state Default state for new modules, true for enabled, false for disabled
+-- @usage
+-- -- Create the addon object
+-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon")
+-- -- Set the default state to "disabled"
+-- MyAddon:SetDefaultModuleState(false)
+-- -- Create a module and explicilty enable it
+-- MyModule = MyAddon:NewModule("MyModule")
+-- MyModule:Enable()
+function SetDefaultModuleState(self, state)
+ if next(self.modules) then
+ error("Usage: SetDefaultModuleState(state): cannot change the module defaults after a module has been registered.", 2)
+ end
+ self.defaultModuleState = state
+end
+
+--- Set the default prototype to use for new modules on creation.
+-- Note that you can only change the default prototype before any module is created.
+-- @name //addon//:SetDefaultModulePrototype
+-- @paramsig prototype
+-- @param prototype Default prototype for the new modules (table)
+-- @usage
+-- -- Define a prototype
+-- local prototype = { OnEnable = function(self) print("OnEnable called!") end }
+-- -- Set the default prototype
+-- MyAddon:SetDefaultModulePrototype(prototype)
+-- -- Create a module and explicitly Enable it
+-- MyModule = MyAddon:NewModule("MyModule")
+-- MyModule:Enable()
+-- -- should print "OnEnable called!" now
+-- @see NewModule
+function SetDefaultModulePrototype(self, prototype)
+ if next(self.modules) then
+ error("Usage: SetDefaultModulePrototype(prototype): cannot change the module defaults after a module has been registered.", 2)
+ end
+ if type(prototype) ~= "table" then
+ error(("Usage: SetDefaultModulePrototype(prototype): 'prototype' - table expected got '%s'."):format(type(prototype)), 2)
+ end
+ self.defaultModulePrototype = prototype
+end
+
+--- Set the state of an addon or module
+-- This should only be called before any enabling actually happend, e.g. in/before OnInitialize.
+-- @name //addon//:SetEnabledState
+-- @paramsig state
+-- @param state the state of an addon or module (enabled=true, disabled=false)
+function SetEnabledState(self, state)
+ self.enabledState = state
+end
+
+
+--- Return an iterator of all modules associated to the addon.
+-- @name //addon//:IterateModules
+-- @paramsig
+-- @usage
+-- -- Enable all modules
+-- for name, module in MyAddon:IterateModules() do
+-- module:Enable()
+-- end
+local function IterateModules(self) return pairs(self.modules) end
+
+-- Returns an iterator of all embeds in the addon
+-- @name //addon//:IterateEmbeds
+-- @paramsig
+local function IterateEmbeds(self) return pairs(AceAddon.embeds[self]) end
+
+--- Query the enabledState of an addon.
+-- @name //addon//:IsEnabled
+-- @paramsig
+-- @usage
+-- if MyAddon:IsEnabled() then
+-- MyAddon:Disable()
+-- end
+local function IsEnabled(self) return self.enabledState end
+local mixins = {
+ NewModule = NewModule,
+ GetModule = GetModule,
+ Enable = Enable,
+ Disable = Disable,
+ EnableModule = EnableModule,
+ DisableModule = DisableModule,
+ IsEnabled = IsEnabled,
+ SetDefaultModuleLibraries = SetDefaultModuleLibraries,
+ SetDefaultModuleState = SetDefaultModuleState,
+ SetDefaultModulePrototype = SetDefaultModulePrototype,
+ SetEnabledState = SetEnabledState,
+ IterateModules = IterateModules,
+ IterateEmbeds = IterateEmbeds,
+ GetName = GetName,
+}
+local function IsModule(self) return false end
+local pmixins = {
+ defaultModuleState = true,
+ enabledState = true,
+ IsModule = IsModule,
+}
+-- Embed( target )
+-- target (object) - target object to embed aceaddon in
+--
+-- this is a local function specifically since it's meant to be only called internally
+function Embed(target, skipPMixins)
+ for k, v in pairs(mixins) do
+ target[k] = v
+ end
+ if not skipPMixins then
+ for k, v in pairs(pmixins) do
+ target[k] = target[k] or v
+ end
+ end
+end
+
+
+-- - Initialize the addon after creation.
+-- This function is only used internally during the ADDON_LOADED event
+-- It will call the **OnInitialize** function on the addon object (if present),
+-- and the **OnEmbedInitialize** function on all embeded libraries.
+--
+-- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing.
+-- @param addon addon object to intialize
+function AceAddon:InitializeAddon(addon)
+ safecall(addon.OnInitialize, addon)
+
+ local embeds = self.embeds[addon]
+ for i = 1, #embeds do
+ local lib = LibStub:GetLibrary(embeds[i], true)
+ if lib then safecall(lib.OnEmbedInitialize, lib, addon) end
+ end
+
+ -- we don't call InitializeAddon on modules specifically, this is handled
+ -- from the event handler and only done _once_
+end
+
+-- - Enable the addon after creation.
+-- Note: This function is only used internally during the PLAYER_LOGIN event, or during ADDON_LOADED,
+-- if IsLoggedIn() already returns true at that point, e.g. for LoD Addons.
+-- It will call the **OnEnable** function on the addon object (if present),
+-- and the **OnEmbedEnable** function on all embeded libraries.\\
+-- This function does not toggle the enable state of the addon itself, and will return early if the addon is disabled.
+--
+-- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing.
+-- Use :Enable on the addon itself instead.
+-- @param addon addon object to enable
+function AceAddon:EnableAddon(addon)
+ if type(addon) == "string" then addon = AceAddon:GetAddon(addon) end
+ if self.statuses[addon.name] or not addon.enabledState then return false end
+
+ -- set the statuses first, before calling the OnEnable. this allows for Disabling of the addon in OnEnable.
+ self.statuses[addon.name] = true
+
+ safecall(addon.OnEnable, addon)
+
+ -- make sure we're still enabled before continueing
+ if self.statuses[addon.name] then
+ local embeds = self.embeds[addon]
+ for i = 1, #embeds do
+ local lib = LibStub:GetLibrary(embeds[i], true)
+ if lib then safecall(lib.OnEmbedEnable, lib, addon) end
+ end
+
+ -- enable possible modules.
+ local modules = addon.orderedModules
+ for i = 1, #modules do
+ self:EnableAddon(modules[i])
+ end
+ end
+ return self.statuses[addon.name] -- return true if we're disabled
+end
+
+-- - Disable the addon
+-- Note: This function is only used internally.
+-- It will call the **OnDisable** function on the addon object (if present),
+-- and the **OnEmbedDisable** function on all embeded libraries.\\
+-- This function does not toggle the enable state of the addon itself, and will return early if the addon is still enabled.
+--
+-- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing.
+-- Use :Disable on the addon itself instead.
+-- @param addon addon object to enable
+function AceAddon:DisableAddon(addon)
+ if type(addon) == "string" then addon = AceAddon:GetAddon(addon) end
+ if not self.statuses[addon.name] then return false end
+
+ -- set statuses first before calling OnDisable, this allows for aborting the disable in OnDisable.
+ self.statuses[addon.name] = false
+
+ safecall( addon.OnDisable, addon )
+
+ -- make sure we're still disabling...
+ if not self.statuses[addon.name] then
+ local embeds = self.embeds[addon]
+ for i = 1, #embeds do
+ local lib = LibStub:GetLibrary(embeds[i], true)
+ if lib then safecall(lib.OnEmbedDisable, lib, addon) end
+ end
+ -- disable possible modules.
+ local modules = addon.orderedModules
+ for i = 1, #modules do
+ self:DisableAddon(modules[i])
+ end
+ end
+
+ return not self.statuses[addon.name] -- return true if we're disabled
+end
+
+--- Get an iterator over all registered addons.
+-- @usage
+-- -- Print a list of all installed AceAddon's
+-- for name, addon in AceAddon:IterateAddons() do
+-- print("Addon: " .. name)
+-- end
+function AceAddon:IterateAddons() return pairs(self.addons) end
+
+--- Get an iterator over the internal status registry.
+-- @usage
+-- -- Print a list of all enabled addons
+-- for name, status in AceAddon:IterateAddonStatus() do
+-- if status then
+-- print("EnabledAddon: " .. name)
+-- end
+-- end
+function AceAddon:IterateAddonStatus() return pairs(self.statuses) end
+
+-- Following Iterators are deprecated, and their addon specific versions should be used
+-- e.g. addon:IterateEmbeds() instead of :IterateEmbedsOnAddon(addon)
+function AceAddon:IterateEmbedsOnAddon(addon) return pairs(self.embeds[addon]) end
+function AceAddon:IterateModulesOfAddon(addon) return pairs(addon.modules) end
+
+-- Event Handling
+local function onEvent(this, event, arg1)
+ -- 2011-08-17 nevcairiel - ignore the load event of Blizzard_DebugTools, so a potential startup error isn't swallowed up
+ if (event == "ADDON_LOADED" and arg1 ~= "Blizzard_DebugTools") or event == "PLAYER_LOGIN" then
+ -- if a addon loads another addon, recursion could happen here, so we need to validate the table on every iteration
+ while(#AceAddon.initializequeue > 0) do
+ local addon = tremove(AceAddon.initializequeue, 1)
+ -- this might be an issue with recursion - TODO: validate
+ if event == "ADDON_LOADED" then addon.baseName = arg1 end
+ AceAddon:InitializeAddon(addon)
+ tinsert(AceAddon.enablequeue, addon)
+ end
+
+ if IsLoggedIn() then
+ while(#AceAddon.enablequeue > 0) do
+ local addon = tremove(AceAddon.enablequeue, 1)
+ AceAddon:EnableAddon(addon)
+ end
+ end
+ end
+end
+
+AceAddon.frame:RegisterEvent("ADDON_LOADED")
+AceAddon.frame:RegisterEvent("PLAYER_LOGIN")
+AceAddon.frame:SetScript("OnEvent", onEvent)
+
+-- upgrade embeded
+for name, addon in pairs(AceAddon.addons) do
+ Embed(addon, true)
+end
+
+-- 2010-10-27 nevcairiel - add new "orderedModules" table
+if oldminor and oldminor < 10 then
+ for name, addon in pairs(AceAddon.addons) do
+ addon.orderedModules = {}
+ for module_name, module in pairs(addon.modules) do
+ tinsert(addon.orderedModules, module)
+ end
+ end
+end
diff --git a/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceAddon-3.0/AceAddon-3.0.xml b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceAddon-3.0/AceAddon-3.0.xml
new file mode 100644
index 000000000..e24640c36
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceAddon-3.0/AceAddon-3.0.xml
@@ -0,0 +1,4 @@
+
+
+
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceComm-3.0/AceComm-3.0.lua b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceComm-3.0/AceComm-3.0.lua
new file mode 100644
index 000000000..5815530cc
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceComm-3.0/AceComm-3.0.lua
@@ -0,0 +1,301 @@
+--- **AceComm-3.0** allows you to send messages of unlimited length over the addon comm channels.
+-- It'll automatically split the messages into multiple parts and rebuild them on the receiving end.\\
+-- **ChatThrottleLib** is of course being used to avoid being disconnected by the server.
+--
+-- **AceComm-3.0** can be embeded into your addon, either explicitly by calling AceComm:Embed(MyAddon) or by
+-- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
+-- and can be accessed directly, without having to explicitly call AceComm itself.\\
+-- It is recommended to embed AceComm, otherwise you'll have to specify a custom `self` on all calls you
+-- make into AceComm.
+-- @class file
+-- @name AceComm-3.0
+-- @release $Id: AceComm-3.0.lua 1161 2017-08-12 14:30:16Z funkydude $
+
+--[[ AceComm-3.0
+
+TODO: Time out old data rotting around from dead senders? Not a HUGE deal since the number of possible sender names is somewhat limited.
+
+]]
+
+local CallbackHandler = LibStub("CallbackHandler-1.0")
+local CTL = assert(ChatThrottleLib, "AceComm-3.0 requires ChatThrottleLib")
+
+local MAJOR, MINOR = "AceComm-3.0", 10
+local AceComm,oldminor = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not AceComm then return end
+
+-- Lua APIs
+local type, next, pairs, tostring = type, next, pairs, tostring
+local strsub, strfind = string.sub, string.find
+local match = string.match
+local tinsert, tconcat = table.insert, table.concat
+local error, assert = error, assert
+
+-- WoW APIs
+local Ambiguate = Ambiguate
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: LibStub, DEFAULT_CHAT_FRAME, geterrorhandler, RegisterAddonMessagePrefix
+
+AceComm.embeds = AceComm.embeds or {}
+
+-- for my sanity and yours, let's give the message type bytes some names
+local MSG_MULTI_FIRST = "\001"
+local MSG_MULTI_NEXT = "\002"
+local MSG_MULTI_LAST = "\003"
+local MSG_ESCAPE = "\004"
+
+-- remove old structures (pre WoW 4.0)
+AceComm.multipart_origprefixes = nil
+AceComm.multipart_reassemblers = nil
+
+-- the multipart message spool: indexed by a combination of sender+distribution+
+AceComm.multipart_spool = AceComm.multipart_spool or {}
+
+--- Register for Addon Traffic on a specified prefix
+-- @param prefix A printable character (\032-\255) classification of the message (typically AddonName or AddonNameEvent), max 16 characters
+-- @param method Callback to call on message reception: Function reference, or method name (string) to call on self. Defaults to "OnCommReceived"
+function AceComm:RegisterComm(prefix, method)
+ if method == nil then
+ method = "OnCommReceived"
+ end
+
+ if #prefix > 16 then -- TODO: 15?
+ error("AceComm:RegisterComm(prefix,method): prefix length is limited to 16 characters")
+ end
+ RegisterAddonMessagePrefix(prefix)
+
+ return AceComm._RegisterComm(self, prefix, method) -- created by CallbackHandler
+end
+
+local warnedPrefix=false
+
+--- Send a message over the Addon Channel
+-- @param prefix A printable character (\032-\255) classification of the message (typically AddonName or AddonNameEvent)
+-- @param text Data to send, nils (\000) not allowed. Any length.
+-- @param distribution Addon channel, e.g. "RAID", "GUILD", etc; see SendAddonMessage API
+-- @param target Destination for some distributions; see SendAddonMessage API
+-- @param prio OPTIONAL: ChatThrottleLib priority, "BULK", "NORMAL" or "ALERT". Defaults to "NORMAL".
+-- @param callbackFn OPTIONAL: callback function to be called as each chunk is sent. receives 3 args: the user supplied arg (see next), the number of bytes sent so far, and the number of bytes total to send.
+-- @param callbackArg: OPTIONAL: first arg to the callback function. nil will be passed if not specified.
+function AceComm:SendCommMessage(prefix, text, distribution, target, prio, callbackFn, callbackArg)
+ prio = prio or "NORMAL" -- pasta's reference implementation had different prio for singlepart and multipart, but that's a very bad idea since that can easily lead to out-of-sequence delivery!
+ if not( type(prefix)=="string" and
+ type(text)=="string" and
+ type(distribution)=="string" and
+ (target==nil or type(target)=="string") and
+ (prio=="BULK" or prio=="NORMAL" or prio=="ALERT")
+ ) then
+ error('Usage: SendCommMessage(addon, "prefix", "text", "distribution"[, "target"[, "prio"[, callbackFn, callbackarg]]])', 2)
+ end
+
+ local textlen = #text
+ local maxtextlen = 255 -- Yes, the max is 255 even if the dev post said 256. I tested. Char 256+ get silently truncated. /Mikk, 20110327
+ local queueName = prefix..distribution..(target or "")
+
+ local ctlCallback = nil
+ if callbackFn then
+ ctlCallback = function(sent)
+ return callbackFn(callbackArg, sent, textlen)
+ end
+ end
+
+ local forceMultipart
+ if match(text, "^[\001-\009]") then -- 4.1+: see if the first character is a control character
+ -- we need to escape the first character with a \004
+ if textlen+1 > maxtextlen then -- would we go over the size limit?
+ forceMultipart = true -- just make it multipart, no escape problems then
+ else
+ text = "\004" .. text
+ end
+ end
+
+ if not forceMultipart and textlen <= maxtextlen then
+ -- fits all in one message
+ CTL:SendAddonMessage(prio, prefix, text, distribution, target, queueName, ctlCallback, textlen)
+ else
+ maxtextlen = maxtextlen - 1 -- 1 extra byte for part indicator in prefix(4.0)/start of message(4.1)
+
+ -- first part
+ local chunk = strsub(text, 1, maxtextlen)
+ CTL:SendAddonMessage(prio, prefix, MSG_MULTI_FIRST..chunk, distribution, target, queueName, ctlCallback, maxtextlen)
+
+ -- continuation
+ local pos = 1+maxtextlen
+
+ while pos+maxtextlen <= textlen do
+ chunk = strsub(text, pos, pos+maxtextlen-1)
+ CTL:SendAddonMessage(prio, prefix, MSG_MULTI_NEXT..chunk, distribution, target, queueName, ctlCallback, pos+maxtextlen-1)
+ pos = pos + maxtextlen
+ end
+
+ -- final part
+ chunk = strsub(text, pos)
+ CTL:SendAddonMessage(prio, prefix, MSG_MULTI_LAST..chunk, distribution, target, queueName, ctlCallback, textlen)
+ end
+end
+
+
+----------------------------------------
+-- Message receiving
+----------------------------------------
+
+do
+ local compost = setmetatable({}, {__mode = "k"})
+ local function new()
+ local t = next(compost)
+ if t then
+ compost[t]=nil
+ for i=#t,3,-1 do -- faster than pairs loop. don't even nil out 1/2 since they'll be overwritten
+ t[i]=nil
+ end
+ return t
+ end
+
+ return {}
+ end
+
+ local function lostdatawarning(prefix,sender,where)
+ DEFAULT_CHAT_FRAME:AddMessage(MAJOR..": Warning: lost network data regarding '"..tostring(prefix).."' from '"..tostring(sender).."' (in "..where..")")
+ end
+
+ function AceComm:OnReceiveMultipartFirst(prefix, message, distribution, sender)
+ local key = prefix.."\t"..distribution.."\t"..sender -- a unique stream is defined by the prefix + distribution + sender
+ local spool = AceComm.multipart_spool
+
+ --[[
+ if spool[key] then
+ lostdatawarning(prefix,sender,"First")
+ -- continue and overwrite
+ end
+ --]]
+
+ spool[key] = message -- plain string for now
+ end
+
+ function AceComm:OnReceiveMultipartNext(prefix, message, distribution, sender)
+ local key = prefix.."\t"..distribution.."\t"..sender -- a unique stream is defined by the prefix + distribution + sender
+ local spool = AceComm.multipart_spool
+ local olddata = spool[key]
+
+ if not olddata then
+ --lostdatawarning(prefix,sender,"Next")
+ return
+ end
+
+ if type(olddata)~="table" then
+ -- ... but what we have is not a table. So make it one. (Pull a composted one if available)
+ local t = new()
+ t[1] = olddata -- add old data as first string
+ t[2] = message -- and new message as second string
+ spool[key] = t -- and put the table in the spool instead of the old string
+ else
+ tinsert(olddata, message)
+ end
+ end
+
+ function AceComm:OnReceiveMultipartLast(prefix, message, distribution, sender)
+ local key = prefix.."\t"..distribution.."\t"..sender -- a unique stream is defined by the prefix + distribution + sender
+ local spool = AceComm.multipart_spool
+ local olddata = spool[key]
+
+ if not olddata then
+ --lostdatawarning(prefix,sender,"End")
+ return
+ end
+
+ spool[key] = nil
+
+ if type(olddata) == "table" then
+ -- if we've received a "next", the spooled data will be a table for rapid & garbage-free tconcat
+ tinsert(olddata, message)
+ AceComm.callbacks:Fire(prefix, tconcat(olddata, ""), distribution, sender)
+ compost[olddata] = true
+ else
+ -- if we've only received a "first", the spooled data will still only be a string
+ AceComm.callbacks:Fire(prefix, olddata..message, distribution, sender)
+ end
+ end
+end
+
+
+
+
+
+
+----------------------------------------
+-- Embed CallbackHandler
+----------------------------------------
+
+if not AceComm.callbacks then
+ AceComm.callbacks = CallbackHandler:New(AceComm,
+ "_RegisterComm",
+ "UnregisterComm",
+ "UnregisterAllComm")
+end
+
+AceComm.callbacks.OnUsed = nil
+AceComm.callbacks.OnUnused = nil
+
+local function OnEvent(self, event, prefix, message, distribution, sender)
+ if event == "CHAT_MSG_ADDON" then
+ sender = Ambiguate(sender, "none")
+ local control, rest = match(message, "^([\001-\009])(.*)")
+ if control then
+ if control==MSG_MULTI_FIRST then
+ AceComm:OnReceiveMultipartFirst(prefix, rest, distribution, sender)
+ elseif control==MSG_MULTI_NEXT then
+ AceComm:OnReceiveMultipartNext(prefix, rest, distribution, sender)
+ elseif control==MSG_MULTI_LAST then
+ AceComm:OnReceiveMultipartLast(prefix, rest, distribution, sender)
+ elseif control==MSG_ESCAPE then
+ AceComm.callbacks:Fire(prefix, rest, distribution, sender)
+ else
+ -- unknown control character, ignore SILENTLY (dont warn unnecessarily about future extensions!)
+ end
+ else
+ -- single part: fire it off immediately and let CallbackHandler decide if it's registered or not
+ AceComm.callbacks:Fire(prefix, message, distribution, sender)
+ end
+ else
+ assert(false, "Received "..tostring(event).." event?!")
+ end
+end
+
+AceComm.frame = AceComm.frame or CreateFrame("Frame", "AceComm30Frame")
+AceComm.frame:SetScript("OnEvent", OnEvent)
+AceComm.frame:UnregisterAllEvents()
+AceComm.frame:RegisterEvent("CHAT_MSG_ADDON")
+
+
+----------------------------------------
+-- Base library stuff
+----------------------------------------
+
+local mixins = {
+ "RegisterComm",
+ "UnregisterComm",
+ "UnregisterAllComm",
+ "SendCommMessage",
+}
+
+-- Embeds AceComm-3.0 into the target object making the functions from the mixins list available on target:..
+-- @param target target object to embed AceComm-3.0 in
+function AceComm:Embed(target)
+ for k, v in pairs(mixins) do
+ target[v] = self[v]
+ end
+ self.embeds[target] = true
+ return target
+end
+
+function AceComm:OnEmbedDisable(target)
+ target:UnregisterAllComm()
+end
+
+-- Update embeds
+for target, v in pairs(AceComm.embeds) do
+ AceComm:Embed(target)
+end
diff --git a/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceComm-3.0/AceComm-3.0.xml b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceComm-3.0/AceComm-3.0.xml
new file mode 100644
index 000000000..2829688e0
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceComm-3.0/AceComm-3.0.xml
@@ -0,0 +1,5 @@
+
+
+
+
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceComm-3.0/ChatThrottleLib.lua b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceComm-3.0/ChatThrottleLib.lua
new file mode 100644
index 000000000..05a0363d9
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceComm-3.0/ChatThrottleLib.lua
@@ -0,0 +1,524 @@
+--
+-- ChatThrottleLib by Mikk
+--
+-- Manages AddOn chat output to keep player from getting kicked off.
+--
+-- ChatThrottleLib:SendChatMessage/:SendAddonMessage functions that accept
+-- a Priority ("BULK", "NORMAL", "ALERT") as well as prefix for SendChatMessage.
+--
+-- Priorities get an equal share of available bandwidth when fully loaded.
+-- Communication channels are separated on extension+chattype+destination and
+-- get round-robinned. (Destination only matters for whispers and channels,
+-- obviously)
+--
+-- Will install hooks for SendChatMessage and SendAddonMessage to measure
+-- bandwidth bypassing the library and use less bandwidth itself.
+--
+--
+-- Fully embeddable library. Just copy this file into your addon directory,
+-- add it to the .toc, and it's done.
+--
+-- Can run as a standalone addon also, but, really, just embed it! :-)
+--
+-- LICENSE: ChatThrottleLib is released into the Public Domain
+--
+
+local CTL_VERSION = 23
+
+local _G = _G
+
+if _G.ChatThrottleLib then
+ if _G.ChatThrottleLib.version >= CTL_VERSION then
+ -- There's already a newer (or same) version loaded. Buh-bye.
+ return
+ elseif not _G.ChatThrottleLib.securelyHooked then
+ print("ChatThrottleLib: Warning: There's an ANCIENT ChatThrottleLib.lua (pre-wow 2.0, =v16) in it!")
+ -- ATTEMPT to unhook; this'll behave badly if someone else has hooked...
+ -- ... and if someone has securehooked, they can kiss that goodbye too... >.<
+ _G.SendChatMessage = _G.ChatThrottleLib.ORIG_SendChatMessage
+ if _G.ChatThrottleLib.ORIG_SendAddonMessage then
+ _G.SendAddonMessage = _G.ChatThrottleLib.ORIG_SendAddonMessage
+ end
+ end
+ _G.ChatThrottleLib.ORIG_SendChatMessage = nil
+ _G.ChatThrottleLib.ORIG_SendAddonMessage = nil
+end
+
+if not _G.ChatThrottleLib then
+ _G.ChatThrottleLib = {}
+end
+
+ChatThrottleLib = _G.ChatThrottleLib -- in case some addon does "local ChatThrottleLib" above us and we're copypasted (AceComm-2, sigh)
+local ChatThrottleLib = _G.ChatThrottleLib
+
+ChatThrottleLib.version = CTL_VERSION
+
+
+
+------------------ TWEAKABLES -----------------
+
+ChatThrottleLib.MAX_CPS = 800 -- 2000 seems to be safe if NOTHING ELSE is happening. let's call it 800.
+ChatThrottleLib.MSG_OVERHEAD = 40 -- Guesstimate overhead for sending a message; source+dest+chattype+protocolstuff
+
+ChatThrottleLib.BURST = 4000 -- WoW's server buffer seems to be about 32KB. 8KB should be safe, but seen disconnects on _some_ servers. Using 4KB now.
+
+ChatThrottleLib.MIN_FPS = 20 -- Reduce output CPS to half (and don't burst) if FPS drops below this value
+
+
+local setmetatable = setmetatable
+local table_remove = table.remove
+local tostring = tostring
+local GetTime = GetTime
+local math_min = math.min
+local math_max = math.max
+local next = next
+local strlen = string.len
+local GetFramerate = GetFramerate
+local strlower = string.lower
+local unpack,type,pairs,wipe = unpack,type,pairs,wipe
+local UnitInRaid,UnitInParty = UnitInRaid,UnitInParty
+
+
+-----------------------------------------------------------------------
+-- Double-linked ring implementation
+
+local Ring = {}
+local RingMeta = { __index = Ring }
+
+function Ring:New()
+ local ret = {}
+ setmetatable(ret, RingMeta)
+ return ret
+end
+
+function Ring:Add(obj) -- Append at the "far end" of the ring (aka just before the current position)
+ if self.pos then
+ obj.prev = self.pos.prev
+ obj.prev.next = obj
+ obj.next = self.pos
+ obj.next.prev = obj
+ else
+ obj.next = obj
+ obj.prev = obj
+ self.pos = obj
+ end
+end
+
+function Ring:Remove(obj)
+ obj.next.prev = obj.prev
+ obj.prev.next = obj.next
+ if self.pos == obj then
+ self.pos = obj.next
+ if self.pos == obj then
+ self.pos = nil
+ end
+ end
+end
+
+
+
+-----------------------------------------------------------------------
+-- Recycling bin for pipes
+-- A pipe is a plain integer-indexed queue of messages
+-- Pipes normally live in Rings of pipes (3 rings total, one per priority)
+
+ChatThrottleLib.PipeBin = nil -- pre-v19, drastically different
+local PipeBin = setmetatable({}, {__mode="k"})
+
+local function DelPipe(pipe)
+ PipeBin[pipe] = true
+end
+
+local function NewPipe()
+ local pipe = next(PipeBin)
+ if pipe then
+ wipe(pipe)
+ PipeBin[pipe] = nil
+ return pipe
+ end
+ return {}
+end
+
+
+
+
+-----------------------------------------------------------------------
+-- Recycling bin for messages
+
+ChatThrottleLib.MsgBin = nil -- pre-v19, drastically different
+local MsgBin = setmetatable({}, {__mode="k"})
+
+local function DelMsg(msg)
+ msg[1] = nil
+ -- there's more parameters, but they're very repetetive so the string pool doesn't suffer really, and it's faster to just not delete them.
+ MsgBin[msg] = true
+end
+
+local function NewMsg()
+ local msg = next(MsgBin)
+ if msg then
+ MsgBin[msg] = nil
+ return msg
+ end
+ return {}
+end
+
+
+-----------------------------------------------------------------------
+-- ChatThrottleLib:Init
+-- Initialize queues, set up frame for OnUpdate, etc
+
+
+function ChatThrottleLib:Init()
+
+ -- Set up queues
+ if not self.Prio then
+ self.Prio = {}
+ self.Prio["ALERT"] = { ByName = {}, Ring = Ring:New(), avail = 0 }
+ self.Prio["NORMAL"] = { ByName = {}, Ring = Ring:New(), avail = 0 }
+ self.Prio["BULK"] = { ByName = {}, Ring = Ring:New(), avail = 0 }
+ end
+
+ -- v4: total send counters per priority
+ for _, Prio in pairs(self.Prio) do
+ Prio.nTotalSent = Prio.nTotalSent or 0
+ end
+
+ if not self.avail then
+ self.avail = 0 -- v5
+ end
+ if not self.nTotalSent then
+ self.nTotalSent = 0 -- v5
+ end
+
+
+ -- Set up a frame to get OnUpdate events
+ if not self.Frame then
+ self.Frame = CreateFrame("Frame")
+ self.Frame:Hide()
+ end
+ self.Frame:SetScript("OnUpdate", self.OnUpdate)
+ self.Frame:SetScript("OnEvent", self.OnEvent) -- v11: Monitor P_E_W so we can throttle hard for a few seconds
+ self.Frame:RegisterEvent("PLAYER_ENTERING_WORLD")
+ self.OnUpdateDelay = 0
+ self.LastAvailUpdate = GetTime()
+ self.HardThrottlingBeginTime = GetTime() -- v11: Throttle hard for a few seconds after startup
+
+ -- Hook SendChatMessage and SendAddonMessage so we can measure unpiped traffic and avoid overloads (v7)
+ if not self.securelyHooked then
+ -- Use secure hooks as of v16. Old regular hook support yanked out in v21.
+ self.securelyHooked = true
+ --SendChatMessage
+ hooksecurefunc("SendChatMessage", function(...)
+ return ChatThrottleLib.Hook_SendChatMessage(...)
+ end)
+ --SendAddonMessage
+ hooksecurefunc("SendAddonMessage", function(...)
+ return ChatThrottleLib.Hook_SendAddonMessage(...)
+ end)
+ end
+ self.nBypass = 0
+end
+
+
+-----------------------------------------------------------------------
+-- ChatThrottleLib.Hook_SendChatMessage / .Hook_SendAddonMessage
+
+local bMyTraffic = false
+
+function ChatThrottleLib.Hook_SendChatMessage(text, chattype, language, destination, ...)
+ if bMyTraffic then
+ return
+ end
+ local self = ChatThrottleLib
+ local size = strlen(tostring(text or "")) + strlen(tostring(destination or "")) + self.MSG_OVERHEAD
+ self.avail = self.avail - size
+ self.nBypass = self.nBypass + size -- just a statistic
+end
+function ChatThrottleLib.Hook_SendAddonMessage(prefix, text, chattype, destination, ...)
+ if bMyTraffic then
+ return
+ end
+ local self = ChatThrottleLib
+ local size = tostring(text or ""):len() + tostring(prefix or ""):len();
+ size = size + tostring(destination or ""):len() + self.MSG_OVERHEAD
+ self.avail = self.avail - size
+ self.nBypass = self.nBypass + size -- just a statistic
+end
+
+
+
+-----------------------------------------------------------------------
+-- ChatThrottleLib:UpdateAvail
+-- Update self.avail with how much bandwidth is currently available
+
+function ChatThrottleLib:UpdateAvail()
+ local now = GetTime()
+ local MAX_CPS = self.MAX_CPS;
+ local newavail = MAX_CPS * (now - self.LastAvailUpdate)
+ local avail = self.avail
+
+ if now - self.HardThrottlingBeginTime < 5 then
+ -- First 5 seconds after startup/zoning: VERY hard clamping to avoid irritating the server rate limiter, it seems very cranky then
+ avail = math_min(avail + (newavail*0.1), MAX_CPS*0.5)
+ self.bChoking = true
+ elseif GetFramerate() < self.MIN_FPS then -- GetFrameRate call takes ~0.002 secs
+ avail = math_min(MAX_CPS, avail + newavail*0.5)
+ self.bChoking = true -- just a statistic
+ else
+ avail = math_min(self.BURST, avail + newavail)
+ self.bChoking = false
+ end
+
+ avail = math_max(avail, 0-(MAX_CPS*2)) -- Can go negative when someone is eating bandwidth past the lib. but we refuse to stay silent for more than 2 seconds; if they can do it, we can.
+
+ self.avail = avail
+ self.LastAvailUpdate = now
+
+ return avail
+end
+
+
+-----------------------------------------------------------------------
+-- Despooling logic
+-- Reminder:
+-- - We have 3 Priorities, each containing a "Ring" construct ...
+-- - ... made up of N "Pipe"s (1 for each destination/pipename)
+-- - and each pipe contains messages
+
+function ChatThrottleLib:Despool(Prio)
+ local ring = Prio.Ring
+ while ring.pos and Prio.avail > ring.pos[1].nSize do
+ local msg = table_remove(ring.pos, 1)
+ if not ring.pos[1] then -- did we remove last msg in this pipe?
+ local pipe = Prio.Ring.pos
+ Prio.Ring:Remove(pipe)
+ Prio.ByName[pipe.name] = nil
+ DelPipe(pipe)
+ else
+ Prio.Ring.pos = Prio.Ring.pos.next
+ end
+ local didSend=false
+ local lowerDest = strlower(msg[3] or "")
+ if lowerDest == "raid" and not UnitInRaid("player") then
+ -- do nothing
+ elseif lowerDest == "party" and not UnitInParty("player") then
+ -- do nothing
+ else
+ Prio.avail = Prio.avail - msg.nSize
+ bMyTraffic = true
+ msg.f(unpack(msg, 1, msg.n))
+ bMyTraffic = false
+ Prio.nTotalSent = Prio.nTotalSent + msg.nSize
+ DelMsg(msg)
+ didSend = true
+ end
+ -- notify caller of delivery (even if we didn't send it)
+ if msg.callbackFn then
+ msg.callbackFn (msg.callbackArg, didSend)
+ end
+ -- USER CALLBACK MAY ERROR
+ end
+end
+
+
+function ChatThrottleLib.OnEvent(this,event)
+ -- v11: We know that the rate limiter is touchy after login. Assume that it's touchy after zoning, too.
+ local self = ChatThrottleLib
+ if event == "PLAYER_ENTERING_WORLD" then
+ self.HardThrottlingBeginTime = GetTime() -- Throttle hard for a few seconds after zoning
+ self.avail = 0
+ end
+end
+
+
+function ChatThrottleLib.OnUpdate(this,delay)
+ local self = ChatThrottleLib
+
+ self.OnUpdateDelay = self.OnUpdateDelay + delay
+ if self.OnUpdateDelay < 0.08 then
+ return
+ end
+ self.OnUpdateDelay = 0
+
+ self:UpdateAvail()
+
+ if self.avail < 0 then
+ return -- argh. some bastard is spewing stuff past the lib. just bail early to save cpu.
+ end
+
+ -- See how many of our priorities have queued messages (we only have 3, don't worry about the loop)
+ local n = 0
+ for prioname,Prio in pairs(self.Prio) do
+ if Prio.Ring.pos or Prio.avail < 0 then
+ n = n + 1
+ end
+ end
+
+ -- Anything queued still?
+ if n<1 then
+ -- Nope. Move spillover bandwidth to global availability gauge and clear self.bQueueing
+ for prioname, Prio in pairs(self.Prio) do
+ self.avail = self.avail + Prio.avail
+ Prio.avail = 0
+ end
+ self.bQueueing = false
+ self.Frame:Hide()
+ return
+ end
+
+ -- There's stuff queued. Hand out available bandwidth to priorities as needed and despool their queues
+ local avail = self.avail/n
+ self.avail = 0
+
+ for prioname, Prio in pairs(self.Prio) do
+ if Prio.Ring.pos or Prio.avail < 0 then
+ Prio.avail = Prio.avail + avail
+ if Prio.Ring.pos and Prio.avail > Prio.Ring.pos[1].nSize then
+ self:Despool(Prio)
+ -- Note: We might not get here if the user-supplied callback function errors out! Take care!
+ end
+ end
+ end
+
+end
+
+
+
+
+-----------------------------------------------------------------------
+-- Spooling logic
+
+function ChatThrottleLib:Enqueue(prioname, pipename, msg)
+ local Prio = self.Prio[prioname]
+ local pipe = Prio.ByName[pipename]
+ if not pipe then
+ self.Frame:Show()
+ pipe = NewPipe()
+ pipe.name = pipename
+ Prio.ByName[pipename] = pipe
+ Prio.Ring:Add(pipe)
+ end
+
+ pipe[#pipe + 1] = msg
+
+ self.bQueueing = true
+end
+
+function ChatThrottleLib:SendChatMessage(prio, prefix, text, chattype, language, destination, queueName, callbackFn, callbackArg)
+ if not self or not prio or not prefix or not text or not self.Prio[prio] then
+ error('Usage: ChatThrottleLib:SendChatMessage("{BULK||NORMAL||ALERT}", "prefix", "text"[, "chattype"[, "language"[, "destination"]]]', 2)
+ end
+ if callbackFn and type(callbackFn)~="function" then
+ error('ChatThrottleLib:ChatMessage(): callbackFn: expected function, got '..type(callbackFn), 2)
+ end
+
+ local nSize = text:len()
+
+ if nSize>255 then
+ error("ChatThrottleLib:SendChatMessage(): message length cannot exceed 255 bytes", 2)
+ end
+
+ nSize = nSize + self.MSG_OVERHEAD
+
+ -- Check if there's room in the global available bandwidth gauge to send directly
+ if not self.bQueueing and nSize < self:UpdateAvail() then
+ self.avail = self.avail - nSize
+ bMyTraffic = true
+ _G.SendChatMessage(text, chattype, language, destination)
+ bMyTraffic = false
+ self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize
+ if callbackFn then
+ callbackFn (callbackArg, true)
+ end
+ -- USER CALLBACK MAY ERROR
+ return
+ end
+
+ -- Message needs to be queued
+ local msg = NewMsg()
+ msg.f = _G.SendChatMessage
+ msg[1] = text
+ msg[2] = chattype or "SAY"
+ msg[3] = language
+ msg[4] = destination
+ msg.n = 4
+ msg.nSize = nSize
+ msg.callbackFn = callbackFn
+ msg.callbackArg = callbackArg
+
+ self:Enqueue(prio, queueName or (prefix..(chattype or "SAY")..(destination or "")), msg)
+end
+
+
+function ChatThrottleLib:SendAddonMessage(prio, prefix, text, chattype, target, queueName, callbackFn, callbackArg)
+ if not self or not prio or not prefix or not text or not chattype or not self.Prio[prio] then
+ error('Usage: ChatThrottleLib:SendAddonMessage("{BULK||NORMAL||ALERT}", "prefix", "text", "chattype"[, "target"])', 2)
+ end
+ if callbackFn and type(callbackFn)~="function" then
+ error('ChatThrottleLib:SendAddonMessage(): callbackFn: expected function, got '..type(callbackFn), 2)
+ end
+
+ local nSize = text:len();
+
+ if RegisterAddonMessagePrefix then
+ if nSize>255 then
+ error("ChatThrottleLib:SendAddonMessage(): message length cannot exceed 255 bytes", 2)
+ end
+ else
+ nSize = nSize + prefix:len() + 1
+ if nSize>255 then
+ error("ChatThrottleLib:SendAddonMessage(): prefix + message length cannot exceed 254 bytes", 2)
+ end
+ end
+
+ nSize = nSize + self.MSG_OVERHEAD;
+
+ -- Check if there's room in the global available bandwidth gauge to send directly
+ if not self.bQueueing and nSize < self:UpdateAvail() then
+ self.avail = self.avail - nSize
+ bMyTraffic = true
+ _G.SendAddonMessage(prefix, text, chattype, target)
+ bMyTraffic = false
+ self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize
+ if callbackFn then
+ callbackFn (callbackArg, true)
+ end
+ -- USER CALLBACK MAY ERROR
+ return
+ end
+
+ -- Message needs to be queued
+ local msg = NewMsg()
+ msg.f = _G.SendAddonMessage
+ msg[1] = prefix
+ msg[2] = text
+ msg[3] = chattype
+ msg[4] = target
+ msg.n = (target~=nil) and 4 or 3;
+ msg.nSize = nSize
+ msg.callbackFn = callbackFn
+ msg.callbackArg = callbackArg
+
+ self:Enqueue(prio, queueName or (prefix..chattype..(target or "")), msg)
+end
+
+
+
+
+-----------------------------------------------------------------------
+-- Get the ball rolling!
+
+ChatThrottleLib:Init()
+
+--[[ WoWBench debugging snippet
+if(WOWB_VER) then
+ local function SayTimer()
+ print("SAY: "..GetTime().." "..arg1)
+ end
+ ChatThrottleLib.Frame:SetScript("OnEvent", SayTimer)
+ ChatThrottleLib.Frame:RegisterEvent("CHAT_MSG_SAY")
+end
+]]
+
+
diff --git a/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceConsole-3.0/AceConsole-3.0.lua b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceConsole-3.0/AceConsole-3.0.lua
new file mode 100644
index 000000000..0567a6563
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceConsole-3.0/AceConsole-3.0.lua
@@ -0,0 +1,250 @@
+--- **AceConsole-3.0** provides registration facilities for slash commands.
+-- You can register slash commands to your custom functions and use the `GetArgs` function to parse them
+-- to your addons individual needs.
+--
+-- **AceConsole-3.0** can be embeded into your addon, either explicitly by calling AceConsole:Embed(MyAddon) or by
+-- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
+-- and can be accessed directly, without having to explicitly call AceConsole itself.\\
+-- It is recommended to embed AceConsole, otherwise you'll have to specify a custom `self` on all calls you
+-- make into AceConsole.
+-- @class file
+-- @name AceConsole-3.0
+-- @release $Id: AceConsole-3.0.lua 1143 2016-07-11 08:52:03Z nevcairiel $
+local MAJOR,MINOR = "AceConsole-3.0", 7
+
+local AceConsole, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not AceConsole then return end -- No upgrade needed
+
+AceConsole.embeds = AceConsole.embeds or {} -- table containing objects AceConsole is embedded in.
+AceConsole.commands = AceConsole.commands or {} -- table containing commands registered
+AceConsole.weakcommands = AceConsole.weakcommands or {} -- table containing self, command => func references for weak commands that don't persist through enable/disable
+
+-- Lua APIs
+local tconcat, tostring, select = table.concat, tostring, select
+local type, pairs, error = type, pairs, error
+local format, strfind, strsub = string.format, string.find, string.sub
+local max = math.max
+
+-- WoW APIs
+local _G = _G
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: DEFAULT_CHAT_FRAME, SlashCmdList, hash_SlashCmdList
+
+local tmp={}
+local function Print(self,frame,...)
+ local n=0
+ if self ~= AceConsole then
+ n=n+1
+ tmp[n] = "|cff33ff99"..tostring( self ).."|r:"
+ end
+ for i=1, select("#", ...) do
+ n=n+1
+ tmp[n] = tostring(select(i, ...))
+ end
+ frame:AddMessage( tconcat(tmp," ",1,n) )
+end
+
+--- Print to DEFAULT_CHAT_FRAME or given ChatFrame (anything with an .AddMessage function)
+-- @paramsig [chatframe ,] ...
+-- @param chatframe Custom ChatFrame to print to (or any frame with an .AddMessage function)
+-- @param ... List of any values to be printed
+function AceConsole:Print(...)
+ local frame = ...
+ if type(frame) == "table" and frame.AddMessage then -- Is first argument something with an .AddMessage member?
+ return Print(self, frame, select(2,...))
+ else
+ return Print(self, DEFAULT_CHAT_FRAME, ...)
+ end
+end
+
+
+--- Formatted (using format()) print to DEFAULT_CHAT_FRAME or given ChatFrame (anything with an .AddMessage function)
+-- @paramsig [chatframe ,] "format"[, ...]
+-- @param chatframe Custom ChatFrame to print to (or any frame with an .AddMessage function)
+-- @param format Format string - same syntax as standard Lua format()
+-- @param ... Arguments to the format string
+function AceConsole:Printf(...)
+ local frame = ...
+ if type(frame) == "table" and frame.AddMessage then -- Is first argument something with an .AddMessage member?
+ return Print(self, frame, format(select(2,...)))
+ else
+ return Print(self, DEFAULT_CHAT_FRAME, format(...))
+ end
+end
+
+
+
+
+--- Register a simple chat command
+-- @param command Chat command to be registered WITHOUT leading "/"
+-- @param func Function to call when the slash command is being used (funcref or methodname)
+-- @param persist if false, the command will be soft disabled/enabled when aceconsole is used as a mixin (default: true)
+function AceConsole:RegisterChatCommand( command, func, persist )
+ if type(command)~="string" then error([[Usage: AceConsole:RegisterChatCommand( "command", func[, persist ]): 'command' - expected a string]], 2) end
+
+ if persist==nil then persist=true end -- I'd rather have my addon's "/addon enable" around if the author screws up. Having some extra slash regged when it shouldnt be isn't as destructive. True is a better default. /Mikk
+
+ local name = "ACECONSOLE_"..command:upper()
+
+ if type( func ) == "string" then
+ SlashCmdList[name] = function(input, editBox)
+ self[func](self, input, editBox)
+ end
+ else
+ SlashCmdList[name] = func
+ end
+ _G["SLASH_"..name.."1"] = "/"..command:lower()
+ AceConsole.commands[command] = name
+ -- non-persisting commands are registered for enabling disabling
+ if not persist then
+ if not AceConsole.weakcommands[self] then AceConsole.weakcommands[self] = {} end
+ AceConsole.weakcommands[self][command] = func
+ end
+ return true
+end
+
+--- Unregister a chatcommand
+-- @param command Chat command to be unregistered WITHOUT leading "/"
+function AceConsole:UnregisterChatCommand( command )
+ local name = AceConsole.commands[command]
+ if name then
+ SlashCmdList[name] = nil
+ _G["SLASH_" .. name .. "1"] = nil
+ hash_SlashCmdList["/" .. command:upper()] = nil
+ AceConsole.commands[command] = nil
+ end
+end
+
+--- Get an iterator over all Chat Commands registered with AceConsole
+-- @return Iterator (pairs) over all commands
+function AceConsole:IterateChatCommands() return pairs(AceConsole.commands) end
+
+
+local function nils(n, ...)
+ if n>1 then
+ return nil, nils(n-1, ...)
+ elseif n==1 then
+ return nil, ...
+ else
+ return ...
+ end
+end
+
+
+--- Retreive one or more space-separated arguments from a string.
+-- Treats quoted strings and itemlinks as non-spaced.
+-- @param str The raw argument string
+-- @param numargs How many arguments to get (default 1)
+-- @param startpos Where in the string to start scanning (default 1)
+-- @return Returns arg1, arg2, ..., nextposition\\
+-- Missing arguments will be returned as nils. 'nextposition' is returned as 1e9 at the end of the string.
+function AceConsole:GetArgs(str, numargs, startpos)
+ numargs = numargs or 1
+ startpos = max(startpos or 1, 1)
+
+ local pos=startpos
+
+ -- find start of new arg
+ pos = strfind(str, "[^ ]", pos)
+ if not pos then -- whoops, end of string
+ return nils(numargs, 1e9)
+ end
+
+ if numargs<1 then
+ return pos
+ end
+
+ -- quoted or space separated? find out which pattern to use
+ local delim_or_pipe
+ local ch = strsub(str, pos, pos)
+ if ch=='"' then
+ pos = pos + 1
+ delim_or_pipe='([|"])'
+ elseif ch=="'" then
+ pos = pos + 1
+ delim_or_pipe="([|'])"
+ else
+ delim_or_pipe="([| ])"
+ end
+
+ startpos = pos
+
+ while true do
+ -- find delimiter or hyperlink
+ local ch,_
+ pos,_,ch = strfind(str, delim_or_pipe, pos)
+
+ if not pos then break end
+
+ if ch=="|" then
+ -- some kind of escape
+
+ if strsub(str,pos,pos+1)=="|H" then
+ -- It's a |H....|hhyper link!|h
+ pos=strfind(str, "|h", pos+2) -- first |h
+ if not pos then break end
+
+ pos=strfind(str, "|h", pos+2) -- second |h
+ if not pos then break end
+ elseif strsub(str,pos, pos+1) == "|T" then
+ -- It's a |T....|t texture
+ pos=strfind(str, "|t", pos+2)
+ if not pos then break end
+ end
+
+ pos=pos+2 -- skip past this escape (last |h if it was a hyperlink)
+
+ else
+ -- found delimiter, done with this arg
+ return strsub(str, startpos, pos-1), AceConsole:GetArgs(str, numargs-1, pos+1)
+ end
+
+ end
+
+ -- search aborted, we hit end of string. return it all as one argument. (yes, even if it's an unterminated quote or hyperlink)
+ return strsub(str, startpos), nils(numargs-1, 1e9)
+end
+
+
+--- embedding and embed handling
+
+local mixins = {
+ "Print",
+ "Printf",
+ "RegisterChatCommand",
+ "UnregisterChatCommand",
+ "GetArgs",
+}
+
+-- Embeds AceConsole into the target object making the functions from the mixins list available on target:..
+-- @param target target object to embed AceBucket in
+function AceConsole:Embed( target )
+ for k, v in pairs( mixins ) do
+ target[v] = self[v]
+ end
+ self.embeds[target] = true
+ return target
+end
+
+function AceConsole:OnEmbedEnable( target )
+ if AceConsole.weakcommands[target] then
+ for command, func in pairs( AceConsole.weakcommands[target] ) do
+ target:RegisterChatCommand( command, func, false, true ) -- nonpersisting and silent registry
+ end
+ end
+end
+
+function AceConsole:OnEmbedDisable( target )
+ if AceConsole.weakcommands[target] then
+ for command, func in pairs( AceConsole.weakcommands[target] ) do
+ target:UnregisterChatCommand( command ) -- TODO: this could potentially unregister a command from another application in case of command conflicts. Do we care?
+ end
+ end
+end
+
+for addon in pairs(AceConsole.embeds) do
+ AceConsole:Embed(addon)
+end
diff --git a/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceConsole-3.0/AceConsole-3.0.xml b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceConsole-3.0/AceConsole-3.0.xml
new file mode 100644
index 000000000..371278a62
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceConsole-3.0/AceConsole-3.0.xml
@@ -0,0 +1,4 @@
+
+
+
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceEvent-3.0/AceEvent-3.0.lua b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceEvent-3.0/AceEvent-3.0.lua
new file mode 100644
index 000000000..bbf55c299
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceEvent-3.0/AceEvent-3.0.lua
@@ -0,0 +1,126 @@
+--- AceEvent-3.0 provides event registration and secure dispatching.
+-- All dispatching is done using **CallbackHandler-1.0**. AceEvent is a simple wrapper around
+-- CallbackHandler, and dispatches all game events or addon message to the registrees.
+--
+-- **AceEvent-3.0** can be embeded into your addon, either explicitly by calling AceEvent:Embed(MyAddon) or by
+-- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
+-- and can be accessed directly, without having to explicitly call AceEvent itself.\\
+-- It is recommended to embed AceEvent, otherwise you'll have to specify a custom `self` on all calls you
+-- make into AceEvent.
+-- @class file
+-- @name AceEvent-3.0
+-- @release $Id: AceEvent-3.0.lua 1161 2017-08-12 14:30:16Z funkydude $
+local CallbackHandler = LibStub("CallbackHandler-1.0")
+
+local MAJOR, MINOR = "AceEvent-3.0", 4
+local AceEvent = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not AceEvent then return end
+
+-- Lua APIs
+local pairs = pairs
+
+AceEvent.frame = AceEvent.frame or CreateFrame("Frame", "AceEvent30Frame") -- our event frame
+AceEvent.embeds = AceEvent.embeds or {} -- what objects embed this lib
+
+-- APIs and registry for blizzard events, using CallbackHandler lib
+if not AceEvent.events then
+ AceEvent.events = CallbackHandler:New(AceEvent,
+ "RegisterEvent", "UnregisterEvent", "UnregisterAllEvents")
+end
+
+function AceEvent.events:OnUsed(target, eventname)
+ AceEvent.frame:RegisterEvent(eventname)
+end
+
+function AceEvent.events:OnUnused(target, eventname)
+ AceEvent.frame:UnregisterEvent(eventname)
+end
+
+
+-- APIs and registry for IPC messages, using CallbackHandler lib
+if not AceEvent.messages then
+ AceEvent.messages = CallbackHandler:New(AceEvent,
+ "RegisterMessage", "UnregisterMessage", "UnregisterAllMessages"
+ )
+ AceEvent.SendMessage = AceEvent.messages.Fire
+end
+
+--- embedding and embed handling
+local mixins = {
+ "RegisterEvent", "UnregisterEvent",
+ "RegisterMessage", "UnregisterMessage",
+ "SendMessage",
+ "UnregisterAllEvents", "UnregisterAllMessages",
+}
+
+--- Register for a Blizzard Event.
+-- The callback will be called with the optional `arg` as the first argument (if supplied), and the event name as the second (or first, if no arg was supplied)
+-- Any arguments to the event will be passed on after that.
+-- @name AceEvent:RegisterEvent
+-- @class function
+-- @paramsig event[, callback [, arg]]
+-- @param event The event to register for
+-- @param callback The callback function to call when the event is triggered (funcref or method, defaults to a method with the event name)
+-- @param arg An optional argument to pass to the callback function
+
+--- Unregister an event.
+-- @name AceEvent:UnregisterEvent
+-- @class function
+-- @paramsig event
+-- @param event The event to unregister
+
+--- Register for a custom AceEvent-internal message.
+-- The callback will be called with the optional `arg` as the first argument (if supplied), and the event name as the second (or first, if no arg was supplied)
+-- Any arguments to the event will be passed on after that.
+-- @name AceEvent:RegisterMessage
+-- @class function
+-- @paramsig message[, callback [, arg]]
+-- @param message The message to register for
+-- @param callback The callback function to call when the message is triggered (funcref or method, defaults to a method with the event name)
+-- @param arg An optional argument to pass to the callback function
+
+--- Unregister a message
+-- @name AceEvent:UnregisterMessage
+-- @class function
+-- @paramsig message
+-- @param message The message to unregister
+
+--- Send a message over the AceEvent-3.0 internal message system to other addons registered for this message.
+-- @name AceEvent:SendMessage
+-- @class function
+-- @paramsig message, ...
+-- @param message The message to send
+-- @param ... Any arguments to the message
+
+
+-- Embeds AceEvent into the target object making the functions from the mixins list available on target:..
+-- @param target target object to embed AceEvent in
+function AceEvent:Embed(target)
+ for k, v in pairs(mixins) do
+ target[v] = self[v]
+ end
+ self.embeds[target] = true
+ return target
+end
+
+-- AceEvent:OnEmbedDisable( target )
+-- target (object) - target object that is being disabled
+--
+-- Unregister all events messages etc when the target disables.
+-- this method should be called by the target manually or by an addon framework
+function AceEvent:OnEmbedDisable(target)
+ target:UnregisterAllEvents()
+ target:UnregisterAllMessages()
+end
+
+-- Script to fire blizzard events into the event listeners
+local events = AceEvent.events
+AceEvent.frame:SetScript("OnEvent", function(this, event, ...)
+ events:Fire(event, ...)
+end)
+
+--- Finally: upgrade our old embeds
+for target, v in pairs(AceEvent.embeds) do
+ AceEvent:Embed(target)
+end
diff --git a/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceEvent-3.0/AceEvent-3.0.xml b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceEvent-3.0/AceEvent-3.0.xml
new file mode 100644
index 000000000..dbe7d9933
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceEvent-3.0/AceEvent-3.0.xml
@@ -0,0 +1,4 @@
+
+
+
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceTimer-3.0/AceTimer-3.0.lua b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceTimer-3.0/AceTimer-3.0.lua
new file mode 100644
index 000000000..8ba6b3c9d
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceTimer-3.0/AceTimer-3.0.lua
@@ -0,0 +1,276 @@
+--- **AceTimer-3.0** provides a central facility for registering timers.
+-- AceTimer supports one-shot timers and repeating timers. All timers are stored in an efficient
+-- data structure that allows easy dispatching and fast rescheduling. Timers can be registered
+-- or canceled at any time, even from within a running timer, without conflict or large overhead.\\
+-- AceTimer is currently limited to firing timers at a frequency of 0.01s as this is what the WoW timer API
+-- restricts us to.
+--
+-- All `:Schedule` functions will return a handle to the current timer, which you will need to store if you
+-- need to cancel the timer you just registered.
+--
+-- **AceTimer-3.0** can be embeded into your addon, either explicitly by calling AceTimer:Embed(MyAddon) or by
+-- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
+-- and can be accessed directly, without having to explicitly call AceTimer itself.\\
+-- It is recommended to embed AceTimer, otherwise you'll have to specify a custom `self` on all calls you
+-- make into AceTimer.
+-- @class file
+-- @name AceTimer-3.0
+-- @release $Id: AceTimer-3.0.lua 1119 2014-10-14 17:23:29Z nevcairiel $
+
+local MAJOR, MINOR = "AceTimer-3.0", 17 -- Bump minor on changes
+local AceTimer, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not AceTimer then return end -- No upgrade needed
+AceTimer.activeTimers = AceTimer.activeTimers or {} -- Active timer list
+local activeTimers = AceTimer.activeTimers -- Upvalue our private data
+
+-- Lua APIs
+local type, unpack, next, error, select = type, unpack, next, error, select
+-- WoW APIs
+local GetTime, C_TimerAfter = GetTime, C_Timer.After
+
+local function new(self, loop, func, delay, ...)
+ if delay < 0.01 then
+ delay = 0.01 -- Restrict to the lowest time that the C_Timer API allows us
+ end
+
+ local timer = {...}
+ timer.object = self
+ timer.func = func
+ timer.looping = loop
+ timer.argsCount = select("#", ...)
+ timer.delay = delay
+ timer.ends = GetTime() + delay
+
+ activeTimers[timer] = timer
+
+ -- Create new timer closure to wrap the "timer" object
+ timer.callback = function()
+ if not timer.cancelled then
+ if type(timer.func) == "string" then
+ -- We manually set the unpack count to prevent issues with an arg set that contains nil and ends with nil
+ -- e.g. local t = {1, 2, nil, 3, nil} print(#t) will result in 2, instead of 5. This fixes said issue.
+ timer.object[timer.func](timer.object, unpack(timer, 1, timer.argsCount))
+ else
+ timer.func(unpack(timer, 1, timer.argsCount))
+ end
+
+ if timer.looping and not timer.cancelled then
+ -- Compensate delay to get a perfect average delay, even if individual times don't match up perfectly
+ -- due to fps differences
+ local time = GetTime()
+ local delay = timer.delay - (time - timer.ends)
+ -- Ensure the delay doesn't go below the threshold
+ if delay < 0.01 then delay = 0.01 end
+ C_TimerAfter(delay, timer.callback)
+ timer.ends = time + delay
+ else
+ activeTimers[timer.handle or timer] = nil
+ end
+ end
+ end
+
+ C_TimerAfter(delay, timer.callback)
+ return timer
+end
+
+--- Schedule a new one-shot timer.
+-- The timer will fire once in `delay` seconds, unless canceled before.
+-- @param callback Callback function for the timer pulse (funcref or method name).
+-- @param delay Delay for the timer, in seconds.
+-- @param ... An optional, unlimited amount of arguments to pass to the callback function.
+-- @usage
+-- MyAddOn = LibStub("AceAddon-3.0"):NewAddon("MyAddOn", "AceTimer-3.0")
+--
+-- function MyAddOn:OnEnable()
+-- self:ScheduleTimer("TimerFeedback", 5)
+-- end
+--
+-- function MyAddOn:TimerFeedback()
+-- print("5 seconds passed")
+-- end
+function AceTimer:ScheduleTimer(func, delay, ...)
+ if not func or not delay then
+ error(MAJOR..": ScheduleTimer(callback, delay, args...): 'callback' and 'delay' must have set values.", 2)
+ end
+ if type(func) == "string" then
+ if type(self) ~= "table" then
+ error(MAJOR..": ScheduleTimer(callback, delay, args...): 'self' - must be a table.", 2)
+ elseif not self[func] then
+ error(MAJOR..": ScheduleTimer(callback, delay, args...): Tried to register '"..func.."' as the callback, but it doesn't exist in the module.", 2)
+ end
+ end
+ return new(self, nil, func, delay, ...)
+end
+
+--- Schedule a repeating timer.
+-- The timer will fire every `delay` seconds, until canceled.
+-- @param callback Callback function for the timer pulse (funcref or method name).
+-- @param delay Delay for the timer, in seconds.
+-- @param ... An optional, unlimited amount of arguments to pass to the callback function.
+-- @usage
+-- MyAddOn = LibStub("AceAddon-3.0"):NewAddon("MyAddOn", "AceTimer-3.0")
+--
+-- function MyAddOn:OnEnable()
+-- self.timerCount = 0
+-- self.testTimer = self:ScheduleRepeatingTimer("TimerFeedback", 5)
+-- end
+--
+-- function MyAddOn:TimerFeedback()
+-- self.timerCount = self.timerCount + 1
+-- print(("%d seconds passed"):format(5 * self.timerCount))
+-- -- run 30 seconds in total
+-- if self.timerCount == 6 then
+-- self:CancelTimer(self.testTimer)
+-- end
+-- end
+function AceTimer:ScheduleRepeatingTimer(func, delay, ...)
+ if not func or not delay then
+ error(MAJOR..": ScheduleRepeatingTimer(callback, delay, args...): 'callback' and 'delay' must have set values.", 2)
+ end
+ if type(func) == "string" then
+ if type(self) ~= "table" then
+ error(MAJOR..": ScheduleRepeatingTimer(callback, delay, args...): 'self' - must be a table.", 2)
+ elseif not self[func] then
+ error(MAJOR..": ScheduleRepeatingTimer(callback, delay, args...): Tried to register '"..func.."' as the callback, but it doesn't exist in the module.", 2)
+ end
+ end
+ return new(self, true, func, delay, ...)
+end
+
+--- Cancels a timer with the given id, registered by the same addon object as used for `:ScheduleTimer`
+-- Both one-shot and repeating timers can be canceled with this function, as long as the `id` is valid
+-- and the timer has not fired yet or was canceled before.
+-- @param id The id of the timer, as returned by `:ScheduleTimer` or `:ScheduleRepeatingTimer`
+function AceTimer:CancelTimer(id)
+ local timer = activeTimers[id]
+
+ if not timer then
+ return false
+ else
+ timer.cancelled = true
+ activeTimers[id] = nil
+ return true
+ end
+end
+
+--- Cancels all timers registered to the current addon object ('self')
+function AceTimer:CancelAllTimers()
+ for k,v in pairs(activeTimers) do
+ if v.object == self then
+ AceTimer.CancelTimer(self, k)
+ end
+ end
+end
+
+--- Returns the time left for a timer with the given id, registered by the current addon object ('self').
+-- This function will return 0 when the id is invalid.
+-- @param id The id of the timer, as returned by `:ScheduleTimer` or `:ScheduleRepeatingTimer`
+-- @return The time left on the timer.
+function AceTimer:TimeLeft(id)
+ local timer = activeTimers[id]
+ if not timer then
+ return 0
+ else
+ return timer.ends - GetTime()
+ end
+end
+
+
+-- ---------------------------------------------------------------------
+-- Upgrading
+
+-- Upgrade from old hash-bucket based timers to C_Timer.After timers.
+if oldminor and oldminor < 10 then
+ -- disable old timer logic
+ AceTimer.frame:SetScript("OnUpdate", nil)
+ AceTimer.frame:SetScript("OnEvent", nil)
+ AceTimer.frame:UnregisterAllEvents()
+ -- convert timers
+ for object,timers in pairs(AceTimer.selfs) do
+ for handle,timer in pairs(timers) do
+ if type(timer) == "table" and timer.callback then
+ local newTimer
+ if timer.delay then
+ newTimer = AceTimer.ScheduleRepeatingTimer(timer.object, timer.callback, timer.delay, timer.arg)
+ else
+ newTimer = AceTimer.ScheduleTimer(timer.object, timer.callback, timer.when - GetTime(), timer.arg)
+ end
+ -- Use the old handle for old timers
+ activeTimers[newTimer] = nil
+ activeTimers[handle] = newTimer
+ newTimer.handle = handle
+ end
+ end
+ end
+ AceTimer.selfs = nil
+ AceTimer.hash = nil
+ AceTimer.debug = nil
+elseif oldminor and oldminor < 17 then
+ -- Upgrade from old animation based timers to C_Timer.After timers.
+ AceTimer.inactiveTimers = nil
+ AceTimer.frame = nil
+ local oldTimers = AceTimer.activeTimers
+ -- Clear old timer table and update upvalue
+ AceTimer.activeTimers = {}
+ activeTimers = AceTimer.activeTimers
+ for handle, timer in pairs(oldTimers) do
+ local newTimer
+ -- Stop the old timer animation
+ local duration, elapsed = timer:GetDuration(), timer:GetElapsed()
+ timer:GetParent():Stop()
+ if timer.looping then
+ newTimer = AceTimer.ScheduleRepeatingTimer(timer.object, timer.func, duration, unpack(timer.args, 1, timer.argsCount))
+ else
+ newTimer = AceTimer.ScheduleTimer(timer.object, timer.func, duration - elapsed, unpack(timer.args, 1, timer.argsCount))
+ end
+ -- Use the old handle for old timers
+ activeTimers[newTimer] = nil
+ activeTimers[handle] = newTimer
+ newTimer.handle = handle
+ end
+
+ -- Migrate transitional handles
+ if oldminor < 13 and AceTimer.hashCompatTable then
+ for handle, id in pairs(AceTimer.hashCompatTable) do
+ local t = activeTimers[id]
+ if t then
+ activeTimers[id] = nil
+ activeTimers[handle] = t
+ t.handle = handle
+ end
+ end
+ AceTimer.hashCompatTable = nil
+ end
+end
+
+-- ---------------------------------------------------------------------
+-- Embed handling
+
+AceTimer.embeds = AceTimer.embeds or {}
+
+local mixins = {
+ "ScheduleTimer", "ScheduleRepeatingTimer",
+ "CancelTimer", "CancelAllTimers",
+ "TimeLeft"
+}
+
+function AceTimer:Embed(target)
+ AceTimer.embeds[target] = true
+ for _,v in pairs(mixins) do
+ target[v] = AceTimer[v]
+ end
+ return target
+end
+
+-- AceTimer:OnEmbedDisable(target)
+-- target (object) - target object that AceTimer is embedded in.
+--
+-- cancel all timers registered for the object
+function AceTimer:OnEmbedDisable(target)
+ target:CancelAllTimers()
+end
+
+for addon in pairs(AceTimer.embeds) do
+ AceTimer:Embed(addon)
+end
diff --git a/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceTimer-3.0/AceTimer-3.0.xml b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceTimer-3.0/AceTimer-3.0.xml
new file mode 100644
index 000000000..be43d8ead
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/AceTimer-3.0/AceTimer-3.0.xml
@@ -0,0 +1,4 @@
+
+
+
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/LibStub/LibStub.lua b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/LibStub/LibStub.lua
new file mode 100644
index 000000000..0a41ac04d
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/LibStub/LibStub.lua
@@ -0,0 +1,30 @@
+-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info
+-- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
+local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
+local LibStub = _G[LIBSTUB_MAJOR]
+
+if not LibStub or LibStub.minor < LIBSTUB_MINOR then
+ LibStub = LibStub or {libs = {}, minors = {} }
+ _G[LIBSTUB_MAJOR] = LibStub
+ LibStub.minor = LIBSTUB_MINOR
+
+ function LibStub:NewLibrary(major, minor)
+ assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
+ minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
+
+ local oldminor = self.minors[major]
+ if oldminor and oldminor >= minor then return nil end
+ self.minors[major], self.libs[major] = minor, self.libs[major] or {}
+ return self.libs[major], oldminor
+ end
+
+ function LibStub:GetLibrary(major, silent)
+ if not self.libs[major] and not silent then
+ error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
+ end
+ return self.libs[major], self.minors[major]
+ end
+
+ function LibStub:IterateLibraries() return pairs(self.libs) end
+ setmetatable(LibStub, { __call = LibStub.GetLibrary })
+end
diff --git a/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/json.lua b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/json.lua
new file mode 100644
index 000000000..8bdc71440
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/Libs/json.lua
@@ -0,0 +1,382 @@
+local json = LibStub:NewLibrary("json", 1)
+if not json then return end
+
+--
+-- json.lua
+--
+-- Copyright (c) 2015 rxi
+--
+-- This library is free software; you can redistribute it and/or modify it
+-- under the terms of the MIT license. See LICENSE for details.
+--
+
+
+-------------------------------------------------------------------------------
+-- Encode
+-------------------------------------------------------------------------------
+
+local encode
+
+local escape_char_map = {
+ [ "\\" ] = "\\\\",
+ [ "\"" ] = "\\\"",
+ [ "\b" ] = "\\b",
+ [ "\f" ] = "\\f",
+ [ "\n" ] = "\\n",
+ [ "\r" ] = "\\r",
+ [ "\t" ] = "\\t",
+}
+
+local escape_char_map_inv = { [ "\\/" ] = "/" }
+for k, v in pairs(escape_char_map) do
+ escape_char_map_inv[v] = k
+end
+
+
+local function escape_char(c)
+ return escape_char_map[c] or string.format("\\u%04x", c:byte())
+end
+
+
+local function encode_nil(val)
+ return "null"
+end
+
+
+local function encode_table(val, stack)
+ local res = {}
+ stack = stack or {}
+
+ -- Circular reference?
+ if stack[val] then error("circular reference") end
+
+ stack[val] = true
+
+ if val[1] ~= nil or next(val) == nil then
+ -- Treat as array -- check keys are valid and it is not sparse
+ local n = 0
+ for k in pairs(val) do
+ if type(k) ~= "number" then
+ error("invalid table: mixed or invalid key types")
+ end
+ n = n + 1
+ end
+ if n ~= #val then
+ error("invalid table: sparse array")
+ end
+ -- Encode
+ for i, v in ipairs(val) do
+ table.insert(res, encode(v, stack))
+ end
+ stack[val] = nil
+ return "[" .. table.concat(res, ",") .. "]"
+
+ else
+ -- Treat as an object
+ for k, v in pairs(val) do
+ if type(k) ~= "string" then
+ error("invalid table: mixed or invalid key types")
+ end
+ table.insert(res, encode(k, stack) .. ":" .. encode(v, stack))
+ end
+ stack[val] = nil
+ return "{" .. table.concat(res, ",") .. "}"
+ end
+end
+
+
+local function encode_string(val)
+ return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"'
+end
+
+
+local function encode_number(val)
+ -- Check for NaN, -inf and inf
+ if val ~= val or val <= -math.huge or val >= math.huge then
+ error("unexpected number value '" .. tostring(val) .. "'")
+ end
+ return string.format("%.14g", val)
+end
+
+
+local type_func_map = {
+ [ "nil" ] = encode_nil,
+ [ "table" ] = encode_table,
+ [ "string" ] = encode_string,
+ [ "number" ] = encode_number,
+ [ "boolean" ] = tostring,
+}
+
+
+encode = function(val, stack)
+ local t = type(val)
+ local f = type_func_map[t]
+ if f then
+ return f(val, stack)
+ end
+ error("unexpected type '" .. t .. "'")
+end
+
+
+function json.encode(val)
+ return ( encode(val) )
+end
+
+
+-------------------------------------------------------------------------------
+-- Decode
+-------------------------------------------------------------------------------
+
+local parse
+
+local function create_set(...)
+ local res = {}
+ for i = 1, select("#", ...) do
+ res[ select(i, ...) ] = true
+ end
+ return res
+end
+
+local space_chars = create_set(" ", "\t", "\r", "\n")
+local delim_chars = create_set(" ", "\t", "\r", "\n", "]", "}", ",")
+local escape_chars = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u")
+local literals = create_set("true", "false", "null")
+
+local literal_map = {
+ [ "true" ] = true,
+ [ "false" ] = false,
+ [ "null" ] = nil,
+}
+
+
+local function next_char(str, idx, set, negate)
+ for i = idx, #str do
+ if set[str:sub(i, i)] ~= negate then
+ return i
+ end
+ end
+ return #str + 1
+end
+
+
+local function decode_error(str, idx, msg)
+ local line_count = 1
+ local col_count = 1
+ for i = 1, idx - 1 do
+ col_count = col_count + 1
+ if str:sub(i, i) == "\n" then
+ line_count = line_count + 1
+ col_count = 1
+ end
+ end
+ error( string.format("%s at line %d col %d", msg, line_count, col_count) )
+end
+
+
+local function codepoint_to_utf8(n)
+ -- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=iws-appendixa
+ local f = math.floor
+ if n <= 0x7f then
+ return string.char(n)
+ elseif n <= 0x7ff then
+ return string.char(f(n / 64) + 192, n % 64 + 128)
+ elseif n <= 0xffff then
+ return string.char(f(n / 4096) + 224, f(n % 4096 / 64) + 128, n % 64 + 128)
+ elseif n <= 0x10ffff then
+ return string.char(f(n / 262144) + 240, f(n % 262144 / 4096) + 128,
+ f(n % 4096 / 64) + 128, n % 64 + 128)
+ end
+ error( string.format("invalid unicode codepoint '%x'", n) )
+end
+
+
+local function parse_unicode_escape(s)
+ local n1 = tonumber( s:sub(3, 6), 16 )
+ local n2 = tonumber( s:sub(9, 12), 16 )
+ -- Surrogate pair?
+ if n2 then
+ return codepoint_to_utf8((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000)
+ else
+ return codepoint_to_utf8(n1)
+ end
+end
+
+
+local function parse_string(str, i)
+ local has_unicode_escape = false
+ local has_surrogate_escape = false
+ local has_escape = false
+ local last
+ for j = i + 1, #str do
+ local x = str:byte(j)
+
+ if x < 32 then
+ decode_error(str, j, "control character in string")
+ end
+
+ if last == 92 then -- "\\" (escape char)
+ if x == 117 then -- "u" (unicode escape sequence)
+ local hex = str:sub(j + 1, j + 5)
+ if not hex:find("%x%x%x%x") then
+ decode_error(str, j, "invalid unicode escape in string")
+ end
+ if hex:find("^[dD][89aAbB]") then
+ has_surrogate_escape = true
+ else
+ has_unicode_escape = true
+ end
+ else
+ local c = string.char(x)
+ if not escape_chars[c] then
+ decode_error(str, j, "invalid escape char '" .. c .. "' in string")
+ end
+ has_escape = true
+ end
+ last = nil
+
+ elseif x == 34 then -- '"' (end of string)
+ local s = str:sub(i + 1, j - 1)
+ if has_surrogate_escape then
+ s = s:gsub("\\u[dD][89aAbB]..\\u....", parse_unicode_escape)
+ end
+ if has_unicode_escape then
+ s = s:gsub("\\u....", parse_unicode_escape)
+ end
+ if has_escape then
+ s = s:gsub("\\.", escape_char_map_inv)
+ end
+ return s, j + 1
+
+ else
+ last = x
+ end
+ end
+ decode_error(str, i, "expected closing quote for string")
+end
+
+
+local function parse_number(str, i)
+ local x = next_char(str, i, delim_chars)
+ local s = str:sub(i, x - 1)
+ local n = tonumber(s)
+ if not n then
+ decode_error(str, i, "invalid number '" .. s .. "'")
+ end
+ return n, x
+end
+
+
+local function parse_literal(str, i)
+ local x = next_char(str, i, delim_chars)
+ local word = str:sub(i, x - 1)
+ if not literals[word] then
+ decode_error(str, i, "invalid literal '" .. word .. "'")
+ end
+ return literal_map[word], x
+end
+
+
+local function parse_array(str, i)
+ local res = {}
+ local n = 1
+ i = i + 1
+ while 1 do
+ local x
+ i = next_char(str, i, space_chars, true)
+ -- Empty / end of array?
+ if str:sub(i, i) == "]" then
+ i = i + 1
+ break
+ end
+ -- Read token
+ x, i = parse(str, i)
+ res[n] = x
+ n = n + 1
+ -- Next token
+ i = next_char(str, i, space_chars, true)
+ local chr = str:sub(i, i)
+ i = i + 1
+ if chr == "]" then break end
+ if chr ~= "," then decode_error(str, i, "expected ']' or ','") end
+ end
+ return res, i
+end
+
+
+local function parse_object(str, i)
+ local res = {}
+ i = i + 1
+ while 1 do
+ local key, val
+ i = next_char(str, i, space_chars, true)
+ -- Empty / end of object?
+ if str:sub(i, i) == "}" then
+ i = i + 1
+ break
+ end
+ -- Read key
+ if str:sub(i, i) ~= '"' then
+ decode_error(str, i, "expected string for key")
+ end
+ key, i = parse(str, i)
+ -- Read ':' delimiter
+ i = next_char(str, i, space_chars, true)
+ if str:sub(i, i) ~= ":" then
+ decode_error(str, i, "expected ':' after key")
+ end
+ i = next_char(str, i + 1, space_chars, true)
+ -- Read value
+ val, i = parse(str, i)
+ -- Set
+ res[key] = val
+ -- Next token
+ i = next_char(str, i, space_chars, true)
+ local chr = str:sub(i, i)
+ i = i + 1
+ if chr == "}" then break end
+ if chr ~= "," then decode_error(str, i, "expected '}' or ','") end
+ end
+ return res, i
+end
+
+
+local char_func_map = {
+ [ '"' ] = parse_string,
+ [ "0" ] = parse_number,
+ [ "1" ] = parse_number,
+ [ "2" ] = parse_number,
+ [ "3" ] = parse_number,
+ [ "4" ] = parse_number,
+ [ "5" ] = parse_number,
+ [ "6" ] = parse_number,
+ [ "7" ] = parse_number,
+ [ "8" ] = parse_number,
+ [ "9" ] = parse_number,
+ [ "-" ] = parse_number,
+ [ "t" ] = parse_literal,
+ [ "f" ] = parse_literal,
+ [ "n" ] = parse_literal,
+ [ "[" ] = parse_array,
+ [ "{" ] = parse_object,
+}
+
+
+parse = function(str, idx)
+ local chr = str:sub(idx, idx)
+ local f = char_func_map[chr]
+ if f then
+ return f(str, idx)
+ end
+ decode_error(str, idx, "unexpected character '" .. chr .. "'")
+end
+
+
+function json.decode(str)
+ if type(str) ~= "string" then
+ error("expected argument of type string, got " .. type(str))
+ end
+ return ( parse(str, next_char(str, 1, space_chars, true)) )
+end
+
+
+return json
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/embeds.xml b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/embeds.xml
new file mode 100644
index 000000000..36826abe0
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/WoW/Resources/Addon source/embeds.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/WoW/Resources/wow-addon.zip b/Artemis/Artemis/Modules/Games/WoW/Resources/wow-addon.zip
new file mode 100644
index 000000000..70d820a9a
Binary files /dev/null and b/Artemis/Artemis/Modules/Games/WoW/Resources/wow-addon.zip differ
diff --git a/Artemis/Artemis/Modules/Games/WoW/WoWAddresses.cs b/Artemis/Artemis/Modules/Games/WoW/WoWAddresses.cs
deleted file mode 100644
index 487eeab04..000000000
--- a/Artemis/Artemis/Modules/Games/WoW/WoWAddresses.cs
+++ /dev/null
@@ -1,256 +0,0 @@
-namespace Artemis.Modules.Games.WoW
-{
- public static class WoWAddresses
- {
- public enum ActivateSettings
- {
- Activate_Offset = 0x34,
- AutoDismount_Activate_Pointer = 0xe56850,
- AutoInteract_Activate_Pointer = 0xe56848,
- AutoLoot_Activate_Pointer = 0xe56868,
- AutoSelfCast_Activate_Pointer = 0xe56874
- }
-
- public enum Battleground
- {
- MaxBattlegroundId = 0xec3fdc,
- PvpExitWindow = 0xec4198,
- StatPvp = 0xc3c03c
- }
-
- public enum Chat
- {
- chatBufferPos = 0xeb1bf0,
- chatBufferStart = 0xe58190,
- msgFormatedChat = 0x65,
- NextMessage = 0x17e8
- }
-
- public enum ClickToMove
- {
- CTM = 0xddf8f0,
- CTM_PUSH = 0xddf8ac,
- CTM_X = 0xddf918,
- CTM_Y = 0xddf91c,
- CTM_Z = 0xddf920
- }
-
- public enum CorpsePlayer
- {
- X = 0xe57894,
- Y = 0xe57898,
- Z = 0xe5789c
- }
-
- public enum DBC
- {
- FactionTemplate = 0,
- ItemClass = 0xd173c0,
- ItemSubClass = 0,
- Lock = 0,
- Map = 0xd291a0,
- QuestPOIPoint = 0xd1e950,
- ResearchSite = 0xd1d2d0,
- SpellCategories = 0,
- Unknown = 0xf35428
- }
-
- public enum EventsListener
- {
- BaseEvents = 0xcb2474,
- EventOffsetCount = 0x48,
- EventOffsetName = 0x18,
- EventsCount = 0xcb2470
- }
-
- public enum Fishing
- {
- BobberHasMoved = 0xf8
- }
-
- public enum FunctionWow
- {
- CGUnit_C__InitializeTrackingState = 0x30623b,
- CGUnit_C__Interact = 0x524ff,
- CGWorldFrame__Intersect = 0x5e46ab,
- ClntObjMgrGetActivePlayerObj = 0x816d7,
- FrameScript__GetLocalizedText = 0x300b48,
- FrameScript_ExecuteBuffer = 0xa6772,
- IsOutdoors = 0,
- Spell_C_HandleTerrainClick = 0x2b76ff,
- strlen = 0x74fcb0,
- UnitCanAttack = 0,
- WowClientDB2__GetRowPointer = 0x20c775
- }
-
- public enum GameInfo
- {
- AreaId = 0xc32c2c,
- buildWoWVersionString = 0xd002a8,
- gameState = 0xe56a49,
- GetTime = 0xcb2150,
- isLoading = 0xca59b0,
- LastHardwareAction = 0xd0e090,
- MapTextureId = 0xc3bd28,
- SubAreaId = 0xc32c24,
- subZoneMap = 0xe56a68,
- TextBoxActivated = 0xbbe9ac,
- zoneMap = 0xe56a64
- }
-
- public enum GameObject
- {
- CachedCastBarCaption = 12,
- CachedData0 = 20,
- CachedIconName = 8,
- CachedName = 180,
- CachedQuestItem1 = 0x9c,
- CachedSize = 0x98,
- DBCacheRow = 620,
- GAMEOBJECT_FIELD_X = 0x138,
- GAMEOBJECT_FIELD_Y = 0x13c,
- GAMEOBJECT_FIELD_Z = 320,
- PackedRotationQuaternion = 0x150,
- TransformationMatrice = 0x278
- }
-
- public enum Hooking
- {
- DX_DEVICE = 0xcc523c,
- DX_DEVICE_IDX = 0x2508,
- ENDSCENE_IDX = 0xa8
- }
-
- public enum Login
- {
- realmName = 0xf35e16
- }
-
- public enum MovementFlagsOffsets
- {
- Offset1 = 0x124,
- Offset2 = 0x40
- }
-
- public enum ObjectManager
- {
- continentId = 0x108,
- firstObject = 0xd8,
- localGuid = 0xf8,
- nextObject = 0x44,
- objectGUID = 0x30,
- objectTYPE = 0x10
- }
-
- public enum Party
- {
- NumOfPlayers = 200,
- NumOfPlayersSuBGroup = 0xcc,
- PartyOffset = 0xeb5458,
- PlayerGuid = 0x10
- }
-
- public enum PetBattle
- {
- IsInBattle = 0xba8a10
- }
-
- public enum Player
- {
- LocalPlayerSpellsOnCooldown = 0xd372b8,
- petGUID = 0xec7158,
- playerName = 0xf35e20,
- RetrieveCorpseWindow = 0xe576f4,
- RuneStartCooldown = 0xf18aa8,
- SkillMaxValue = 0x400,
- SkillValue = 0x200
- }
-
- public enum PlayerNameStore
- {
- PlayerNameNextOffset = 20,
- PlayerNameStorePtr = 0xd0b4e0,
- PlayerNameStringOffset = 0x11
- }
-
- public enum PowerIndex
- {
- Multiplicator = 0x10,
- PowerIndexArrays = 0xddf914
- }
-
- public enum Quests
- {
- QuestGiverStatus = 0xf4
- }
-
- public enum SpellBook
- {
- FirstTalentBookPtr = 0xeb52ec,
- KnownAllSpells = 0xeb5130,
- MountBookMountsPtr = 0xeb5194,
- MountBookNumMounts = 0xeb5190,
- NextTalentBookPtr = 0xeb52e4,
- SpellBookNumSpells = 0xeb5134,
- SpellBookSpellsPtr = 0xeb5138,
- SpellDBCMaxIndex = 0x30d40,
- TalentBookOverrideSpellId = 0x1c,
- TalentBookSpellId = 20
- }
-
- public enum UnitBaseGetUnitAura
- {
- AuraSize = 0x58,
- AuraStructCasterLevel = 0x3a,
- AuraStructCount = 0x39,
- AuraStructCreatorGuid = 0x20,
- AuraStructDuration = 60,
- AuraStructFlag = 0x34,
- AuraStructMask = 0x35,
- AuraStructSpellEndTime = 0x40,
- AuraStructSpellId = 0x30,
- AuraStructUnk1 = 0x3b,
- AuraStructUnk2 = 0x44,
- AuraTable1 = 0x1150,
- AuraTable2 = 0x580
- }
-
- public enum UnitField
- {
- CachedIsBoss = 0x60,
- CachedModelId1 = 0x6c,
- CachedName = 0x80,
- CachedQuestItem1 = 60,
- CachedSubName = 0,
- CachedTypeFlag = 0x24,
- CachedUnitClassification = 0x2c,
- CanInterrupt = 0xfc4,
- CanInterruptOffset = 0xe02ea0,
- CanInterruptOffset2 = 0xe02ea4,
- CanInterruptOffset3 = 0xe02ea8,
- CastingSpellEndTime = 0x108c,
- CastingSpellID = 0x1064,
- CastingSpellStartTime = 0x1088,
- ChannelSpellEndTime = 0x1098,
- ChannelSpellID = 0x1090,
- ChannelSpellStartTime = 0x1094,
- DBCacheRow = 0xc80,
- TransportGUID = 0xae8,
- UNIT_FIELD_R = 0xb08,
- UNIT_FIELD_X = 0xaf8,
- UNIT_FIELD_Y = 0xafc,
- UNIT_FIELD_Z = 0xb00
- }
-
- public enum VMT
- {
- CGUnit_C__GetFacing = 0x35
- }
-
- public class ObjectManagerClass
- {
- public static uint clientConnection;
- public static uint sCurMgr;
- }
- }
-}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/WoW/WoWDataModel.cs b/Artemis/Artemis/Modules/Games/WoW/WoWDataModel.cs
index 3edf73ecc..c82ae1885 100644
--- a/Artemis/Artemis/Modules/Games/WoW/WoWDataModel.cs
+++ b/Artemis/Artemis/Modules/Games/WoW/WoWDataModel.cs
@@ -1,11 +1,33 @@
using Artemis.Modules.Abstract;
-using Artemis.Modules.Games.WoW.Data;
+using Artemis.Modules.Games.WoW.Models;
+using MoonSharp.Interpreter;
namespace Artemis.Modules.Games.WoW
{
+ [MoonSharpUserData]
public class WoWDataModel : ModuleDataModel
{
+ public WoWDataModel()
+ {
+ Player = new WoWUnit();
+ Target = new WoWUnit();
+ }
+
public WoWUnit Player { get; set; }
public WoWUnit Target { get; set; }
+
+ public string Realm { get; set; }
+ public string Zone { get; set; }
+ public string SubZone { get; set; }
+
+ public WoWState State { get; set; }
}
-}
\ No newline at end of file
+
+ public enum WoWState
+ {
+ LoggedOut,
+ Ingame,
+ Afk,
+ Dnd
+ }
+}
diff --git a/Artemis/Artemis/Modules/Games/WoW/WoWModel.cs b/Artemis/Artemis/Modules/Games/WoW/WoWModel.cs
index c50926dfa..f3a53d9d9 100644
--- a/Artemis/Artemis/Modules/Games/WoW/WoWModel.cs
+++ b/Artemis/Artemis/Modules/Games/WoW/WoWModel.cs
@@ -1,116 +1,261 @@
-using System;
-using System.Linq;
-using Artemis.DAL;
-using Artemis.Managers;
-using Artemis.Modules.Abstract;
-using Artemis.Modules.Games.WoW.Data;
-using Artemis.Settings;
-using Artemis.Utilities.Memory;
-using Process.NET;
-using Process.NET.Memory;
-
-namespace Artemis.Modules.Games.WoW
-{
- public class WoWModel : ModuleModel
- {
- private readonly GamePointersCollection _pointer;
- private ProcessSharp _process;
-
-
- public WoWModel(DeviceManager deviceManager, LuaManager luaManager) : base(deviceManager, luaManager)
- {
- Settings = SettingsProvider.Load();
- DataModel = new WoWDataModel();
- ProcessNames.Add("Wow-64");
-
- // Currently WoW is locked behind a hidden trigger (obviously not that hidden since you're reading this)
- // It is using memory reading and lets first try to contact Blizzard
- var settings = SettingsProvider.Load();
- Settings.IsEnabled = settings.GamestatePort == 62575 && Settings.IsEnabled;
-
- _pointer = SettingsProvider.Load().WorldOfWarcraft;
- //_pointer = new GamePointersCollection
- //{
- // Game = "WorldOfWarcraft",
- // GameVersion = "7.0.3.22810",
- // GameAddresses = new List
- // {
- // new GamePointer
- // {
- // Description = "ObjectManager",
- // BasePointer = new IntPtr(0x1578070)
- // },
- // new GamePointer
- // {
- // Description = "LocalPlayer",
- // BasePointer = new IntPtr(0x169DF10)
- // },
- // new GamePointer
- // {
- // Description = "NameCache",
- // BasePointer = new IntPtr(0x151DCE8)
- // },
- // new GamePointer
- // {
- // Description = "TargetGuid",
- // BasePointer = new IntPtr(0x179C940)
- // }
- // }
- //};
- //var res = JsonConvert.SerializeObject(_pointer, Formatting.Indented);
- }
-
- public override string Name => "WoW";
- public override bool IsOverlay => false;
- public override bool IsBoundToProcess => true;
-
- public override void Dispose()
- {
- base.Dispose();
-
- _process?.Dispose();
- _process = null;
- }
-
- public override void Update()
- {
- if (_process == null)
- {
- var tempProcess = MemoryHelpers.GetProcessIfRunning(ProcessNames[0]);
- if (tempProcess == null)
- return;
-
- _process = new ProcessSharp(tempProcess, MemoryType.Remote);
- }
-
- if (ProfileModel == null || DataModel == null || _process == null)
- return;
-
- var dataModel = (WoWDataModel) DataModel;
-
- var objectManager = new WoWObjectManager(_process,
- _pointer.GameAddresses.First(a => a.Description == "ObjectManager").BasePointer);
- var nameCache = new WoWNameCache(_process,
- _pointer.GameAddresses.First(a => a.Description == "NameCache").BasePointer);
- var player = new WoWPlayer(_process,
- _pointer.GameAddresses.First(a => a.Description == "LocalPlayer").BasePointer,
- _pointer.GameAddresses.First(a => a.Description == "TargetGuid").BasePointer, true);
-
- dataModel.Player = player;
- if (dataModel.Player != null && dataModel.Player.Guid != Guid.Empty)
- {
- dataModel.Player.UpdateDetails(nameCache);
- var target = player.GetTarget(objectManager);
- if (target == null)
- return;
-
- dataModel.Target = new WoWUnit(target.Process, target.BaseAddress);
- dataModel.Target.UpdateDetails(nameCache);
- }
- else
- {
- dataModel.Target = null;
- }
- }
- }
+using Artemis.DAL;
+using Artemis.Managers;
+using Artemis.Modules.Abstract;
+using Artemis.Modules.Games.WoW.Models;
+using Artemis.Properties;
+using Artemis.Services;
+using Artemis.Utilities;
+using Microsoft.Win32;
+using Newtonsoft.Json.Linq;
+using System.IO;
+using System.IO.Compression;
+
+namespace Artemis.Modules.Games.WoW
+{
+ public class WoWModel : ModuleModel
+ {
+ private readonly MetroDialogService _dialogService;
+ private readonly WowPacketScanner _packetScanner;
+
+ public WoWModel(DeviceManager deviceManager, LuaManager luaManager, WowPacketScanner packetScanner, MetroDialogService dialogService) : base(deviceManager, luaManager)
+ {
+ Settings = SettingsProvider.Load();
+ DataModel = new WoWDataModel();
+ ProcessNames.Add("Wow-64");
+
+ _packetScanner = packetScanner;
+ _dialogService = dialogService;
+ _packetScanner.RaiseDataReceived += (sender, args) => HandleGameData(args.Command, args.Data);
+
+ FindWoW();
+
+ // I simply cannot be sure wether this addon will bring people's accounts in trouble so
+ // lets remove it whenever Artemis isn't running the WoW module.
+ // (This also means the addon isnt left behind should the user uninstall Artemis.)
+ RemoveAddon();
+ }
+
+ public override string Name => "WoW";
+ public override bool IsOverlay => false;
+ public override bool IsBoundToProcess => true;
+
+ public override void Enable()
+ {
+ PlaceAddon();
+ _packetScanner.Start();
+ base.Enable();
+ }
+
+ public override void Dispose()
+ {
+ RemoveAddon();
+ _packetScanner.Stop();
+ base.Dispose();
+ }
+
+ public override void Update()
+ {
+ var dataModel = (WoWDataModel) DataModel;
+
+ dataModel.Player.Update();
+ dataModel.Target.Update();
+ }
+
+ public void FindWoW()
+ {
+ var gameSettings = Settings as WoWSettings;
+ if (gameSettings == null)
+ return;
+
+ // If already propertly set up, don't do anything
+ if (gameSettings.GameDirectory != null && File.Exists(gameSettings.GameDirectory + @"\Wow.exe"))
+ return;
+
+ var key = Registry.LocalMachine.OpenSubKey(
+ @"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\World of Warcraft");
+ var path = key?.GetValue("DisplayIcon")?.ToString();
+ if (string.IsNullOrEmpty(path) || !File.Exists(path))
+ return;
+
+ gameSettings.GameDirectory = path.Substring(0, path.Length - 8);
+ gameSettings.Save();
+ }
+
+ public void ChangeDirectory(string directory, bool checkExe)
+ {
+ var settings = (WoWSettings) Settings;
+ if (checkExe && !File.Exists(directory + @"\Wow.exe"))
+ {
+ _dialogService.ShowErrorMessageBox("Please select a valid WoW directory\n\n" +
+ @"By default WoW is in C:\Program Files (x86)\World of Warcraft");
+
+ settings.GameDirectory = string.Empty;
+ settings.Save();
+ return;
+ }
+ settings.GameDirectory = directory;
+ settings.Save();
+ }
+
+ public void PlaceAddon()
+ {
+ var settings = (WoWSettings) Settings;
+ var path = settings.GameDirectory;
+
+ if (!File.Exists(path + @"\Wow.exe"))
+ return;
+
+ // Load the ZIP from resources
+ using (var stream = new MemoryStream(Resources.wow_addon))
+ {
+ using (var archive = new ZipArchive(stream))
+ {
+ archive.ExtractToDirectory(settings.GameDirectory + @"\Interface\Addons\Artemis", true);
+ }
+ }
+ }
+
+ public void RemoveAddon()
+ {
+ var settings = (WoWSettings) Settings;
+ if (Directory.Exists(settings.GameDirectory + @"\Interface\Addons\Artemis"))
+ Directory.Delete(settings.GameDirectory + @"\Interface\Addons\Artemis", true);
+ }
+
+ private void HandleGameData(string command, string data)
+ {
+ JToken json = null;
+ if (!data.StartsWith("\"") && !data.EndsWith("\""))
+ json = JToken.Parse(data);
+
+ lock (DataModel)
+ {
+ var dataModel = (WoWDataModel) DataModel;
+ switch (command)
+ {
+ case "gameState":
+ ParseGameState(data, dataModel);
+ break;
+ case "player":
+ ParsePlayer(json, dataModel);
+ break;
+ case "target":
+ ParseTarget(json, dataModel);
+ break;
+ case "playerState":
+ ParsePlayerState(json, dataModel);
+ break;
+ case "targetState":
+ ParseTargetState(json, dataModel);
+ break;
+ case "buffs":
+ ParseAuras(json, dataModel, true);
+ break;
+ case "debuffs":
+ ParseAuras(json, dataModel, false);
+ break;
+ case "spellCast":
+ ParseSpellCast(json, dataModel, false);
+ break;
+ case "instantSpellCast":
+ ParseInstantSpellCast(json, dataModel);
+ break;
+ case "spellCastFailed":
+ ParseSpellCastFailed(data, dataModel);
+ break;
+ case "spellCastInterrupted":
+ ParseSpellCastInterrupted(data, dataModel);
+ break;
+ case "spellChannel":
+ ParseSpellCast(json, dataModel, true);
+ break;
+ case "spellChannelInterrupted":
+ ParseSpellCastInterrupted(data, dataModel);
+ break;
+ default:
+ Logger.Warn("The WoW addon sent an unknown command: {0}", command);
+ break;
+ }
+ }
+ }
+
+ private void ParseGameState(string data, WoWDataModel dataModel)
+ {
+ if (data == "\"ingame\"")
+ dataModel.State = WoWState.Ingame;
+ else if (data == "\"afk\"")
+ dataModel.State = WoWState.Afk;
+ else if (data == "\"dnd\"")
+ dataModel.State = WoWState.Dnd;
+ else if (data == "\"loggedOut\"")
+ dataModel.State = WoWState.LoggedOut;
+ }
+
+ private void ParsePlayer(JToken json, WoWDataModel dataModel)
+ {
+ dataModel.Player.ApplyJson(json);
+
+ // At this point class/race data is available so no point pretending to be logged out
+ if (dataModel.State == WoWState.LoggedOut)
+ dataModel.State = WoWState.Ingame;
+ }
+
+ private void ParseTarget(JToken json, WoWDataModel dataModel)
+ {
+ dataModel.Target.ApplyJson(json);
+ }
+
+ private void ParsePlayerState(JToken json, WoWDataModel dataModel)
+ {
+ dataModel.Player.ApplyStateJson(json);
+ }
+
+ private void ParseTargetState(JToken json, WoWDataModel dataModel)
+ {
+ dataModel.Target.ApplyStateJson(json);
+ }
+
+ private void ParseAuras(JToken json, WoWDataModel dataModel, bool buffs)
+ {
+ dataModel.Player.ApplyAuraJson(json, buffs);
+ }
+
+ private void ParseSpellCast(JToken json, WoWDataModel dataModel, bool isChannel)
+ {
+ if (json["uid"].Value() == "player")
+ dataModel.Player.CastBar.ApplyJson(json, isChannel);
+ else if (json["uid"].Value() == "target")
+ dataModel.Target.CastBar.ApplyJson(json, isChannel);
+ }
+
+ private void ParseInstantSpellCast(JToken json, WoWDataModel dataModel)
+ {
+ var spell = new WoWSpell
+ {
+ Name = json["n"].Value(),
+ Id = json["sid"].Value()
+ };
+
+ if (json["uid"].Value() == "player")
+ dataModel.Player.AddInstantCast(spell);
+ else if (json["uid"].Value() == "target")
+ dataModel.Target.AddInstantCast(spell);
+ }
+
+ private void ParseSpellCastFailed(string data, WoWDataModel dataModel)
+ {
+ if (data == "\"player\"")
+ dataModel.Player.CastBar.Clear();
+ else if (data == "\"target\"")
+ dataModel.Target.CastBar.Clear();
+ }
+
+ private void ParseSpellCastInterrupted(string data, WoWDataModel dataModel)
+ {
+ if (data == "\"player\"")
+ dataModel.Player.CastBar.Clear();
+ else if (data == "\"target\"")
+ dataModel.Target.CastBar.Clear();
+ }
+ }
}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/WoW/WoWPacketScanner.cs b/Artemis/Artemis/Modules/Games/WoW/WoWPacketScanner.cs
new file mode 100644
index 000000000..df4b85e3b
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/WoW/WoWPacketScanner.cs
@@ -0,0 +1,127 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Ninject.Extensions.Logging;
+using PcapDotNet.Core;
+using PcapDotNet.Packets;
+
+namespace Artemis.Modules.Games.WoW
+{
+ public class WowPacketScanner
+ {
+ private const string MsgStart = "\u0001";
+ private const string MsgNext = "\u0002";
+ private const string MsgLast = "\u0003";
+ private PacketCommunicator _communicator;
+ private string _dataParts;
+
+ public WowPacketScanner(ILogger logger)
+ {
+ Logger = logger;
+ }
+
+ public ILogger Logger { get; }
+
+ public event EventHandler RaiseDataReceived;
+
+ public void Start()
+ {
+ // Start scanning WoW packets
+ // Retrieve the device list from the local machine
+ IList allDevices = LivePacketDevice.AllLocalMachine;
+
+ if (allDevices.Count == 0)
+ {
+ Logger.Warn("No interfaces found! Can't scan WoW packets.");
+ return;
+ }
+
+ // Take the selected adapter
+ PacketDevice selectedDevice = allDevices.First();
+
+ // Open the device
+ _communicator = selectedDevice.Open(65536, PacketDeviceOpenAttributes.Promiscuous, 40);
+ Logger.Debug("Listening on " + selectedDevice.Description + " for WoW packets");
+
+ // Compile the filter
+ using (var filter = _communicator.CreateFilter("tcp"))
+ {
+ // Set the filter
+ _communicator.SetFilter(filter);
+ }
+
+ Task.Run(() => ReceivePackets());
+ }
+
+ public void Stop()
+ {
+ _communicator?.Break();
+ _communicator?.Dispose();
+ _communicator = null;
+ }
+
+ private void ReceivePackets()
+ {
+ // start the capture
+ try
+ {
+ _communicator.ReceivePackets(0, PacketHandler);
+ }
+ catch (InvalidOperationException)
+ {
+ // ignored, happens on shutdown
+ }
+ }
+
+ // Callback function invoked by Pcap.Net for every incoming packet
+ private void PacketHandler(Packet packet)
+ {
+ var str = Encoding.Default.GetString(packet.Buffer);
+ if (!str.ToLower().Contains("artemis"))
+ return;
+
+ // Split the string at the prefix
+ var parts = str.Split(new[] {"(artemis)"}, StringSplitOptions.None);
+ if (parts.Length < 2)
+ return;
+ var msg = parts[1];
+ // Start escape char
+ if (msg.StartsWith(MsgStart))
+ _dataParts = msg.Substring(1);
+ else if (msg.StartsWith(MsgNext))
+ _dataParts = _dataParts + msg.Substring(1);
+ else if (msg.StartsWith(MsgLast))
+ {
+ _dataParts = _dataParts + msg.Substring(1);
+ var dataParts = _dataParts.Split('|');
+ // Data is wrapped in artemis(), take this off
+ OnRaiseDataReceived(dataParts[0].Substring(8), dataParts[1].Substring(0, dataParts[1].Length - 1));
+ }
+ else
+ {
+ var dataParts = msg.Split('|');
+ // Data is wrapped in artemis(), take this off
+ OnRaiseDataReceived(dataParts[0].Substring(8), dataParts[1].Substring(0, dataParts[1].Length - 1));
+ }
+ }
+
+ private void OnRaiseDataReceived(string command, string data)
+ {
+ RaiseDataReceived?.Invoke(this, new WowDataReceivedEventArgs(command, data));
+ }
+
+ public class WowDataReceivedEventArgs : EventArgs
+ {
+ public WowDataReceivedEventArgs(string command, string data)
+ {
+ Command = command;
+ Data = data;
+ }
+
+ public string Command { get; }
+ public string Data { get; set; }
+ }
+ }
+}
diff --git a/Artemis/Artemis/Modules/Games/WoW/WoWSettings.cs b/Artemis/Artemis/Modules/Games/WoW/WoWSettings.cs
index 2b2797c93..524fdac66 100644
--- a/Artemis/Artemis/Modules/Games/WoW/WoWSettings.cs
+++ b/Artemis/Artemis/Modules/Games/WoW/WoWSettings.cs
@@ -4,5 +4,6 @@ namespace Artemis.Modules.Games.WoW
{
public class WoWSettings : ModuleSettings
{
+ public string GameDirectory { get; set; }
}
-}
\ No newline at end of file
+}
diff --git a/Artemis/Artemis/Modules/Games/WoW/WoWView.xaml b/Artemis/Artemis/Modules/Games/WoW/WoWView.xaml
index 9537d78fd..13569a79e 100644
--- a/Artemis/Artemis/Modules/Games/WoW/WoWView.xaml
+++ b/Artemis/Artemis/Modules/Games/WoW/WoWView.xaml
@@ -1,19 +1,13 @@
-
+
+
@@ -23,7 +17,7 @@
@@ -39,11 +33,20 @@
Style="{StaticResource MahApps.Metro.Styles.ToggleSwitchButton.Win10}" ToolTip="Note: You can't enable an module when Artemis is disabled" />
+
+
+
+
+
+
+
+
+
-
+
-
+
diff --git a/Artemis/Artemis/Modules/Games/WoW/WoWView.xaml.cs b/Artemis/Artemis/Modules/Games/WoW/WoWView.xaml.cs
index 2e0bac541..33c9f8eb0 100644
--- a/Artemis/Artemis/Modules/Games/WoW/WoWView.xaml.cs
+++ b/Artemis/Artemis/Modules/Games/WoW/WoWView.xaml.cs
@@ -12,4 +12,4 @@ namespace Artemis.Modules.Games.WoW
InitializeComponent();
}
}
-}
\ No newline at end of file
+}
diff --git a/Artemis/Artemis/Modules/Games/WoW/WoWViewModel.cs b/Artemis/Artemis/Modules/Games/WoW/WoWViewModel.cs
index eed8a1228..1aca250f2 100644
--- a/Artemis/Artemis/Modules/Games/WoW/WoWViewModel.cs
+++ b/Artemis/Artemis/Modules/Games/WoW/WoWViewModel.cs
@@ -1,4 +1,5 @@
-using Artemis.Managers;
+using System.Windows.Forms;
+using Artemis.Managers;
using Artemis.Modules.Abstract;
using Ninject;
@@ -13,5 +14,23 @@ namespace Artemis.Modules.Games.WoW
}
public override bool UsesProfileEditor => true;
+
+ public void PlaceAddon()
+ {
+ ((WoWModel) ModuleModel).PlaceAddon();
+ }
+
+ public void BrowseDirectory()
+ {
+ var dialog = new FolderBrowserDialog {SelectedPath = ((WoWSettings) Settings).GameDirectory};
+ var result = dialog.ShowDialog();
+ if (result != DialogResult.OK)
+ return;
+
+ ((WoWSettings) Settings).GameDirectory = dialog.SelectedPath;
+ ((WoWModel) ModuleModel).PlaceAddon();
+ Settings.Save();
+ NotifyOfPropertyChange(() => Settings);
+ }
}
}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/General/GeneralProfile/GeneralProfileModel.cs b/Artemis/Artemis/Modules/General/GeneralProfile/GeneralProfileModel.cs
index dbe22a298..c3250e246 100644
--- a/Artemis/Artemis/Modules/General/GeneralProfile/GeneralProfileModel.cs
+++ b/Artemis/Artemis/Modules/General/GeneralProfile/GeneralProfileModel.cs
@@ -12,6 +12,7 @@ using Artemis.Managers;
using Artemis.Modules.Abstract;
using Artemis.Utilities;
using Artemis.Utilities.ActiveWindowDetection;
+using Betwixt;
using CSCore.CoreAudioAPI;
using Newtonsoft.Json;
using SpotifyAPI.Local;
@@ -28,7 +29,7 @@ namespace Artemis.Modules.General.GeneralProfile
AudioCaptureManager audioCaptureManager) : base(deviceManager, luaManager)
{
_lastMusicUpdate = DateTime.Now;
-
+
Settings = SettingsProvider.Load();
DataModel = new GeneralProfileDataModel();
diff --git a/Artemis/Artemis/NLog.xsd b/Artemis/Artemis/NLog.xsd
index 78043e413..8397127c4 100644
--- a/Artemis/Artemis/NLog.xsd
+++ b/Artemis/Artemis/NLog.xsd
@@ -164,6 +164,7 @@
+
@@ -326,6 +327,7 @@
+
@@ -334,6 +336,11 @@
Name of the target.
+
+
+ Delay the flush until the LogEvent has been confirmed as written
+
+
Condition expression. Log events who meet this condition will cause a flush on the wrapped target.
@@ -403,13 +410,14 @@
-
+
-
+
+
@@ -477,9 +485,9 @@
Maximum queue size.
-
+
- Indicates whether to include dictionary contents.
+ Indicates whether to include stack contents.
@@ -492,9 +500,9 @@
Indicates whether to include NLog-specific extensions to log4j schema.
-
+
- Indicates whether to include stack contents.
+ Indicates whether to include dictionary contents.
@@ -512,6 +520,11 @@
NDC item separator.
+
+
+ Indicates whether to include dictionary contents.
+
+
Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit
@@ -1001,6 +1014,7 @@
+
@@ -1049,6 +1063,11 @@
Optional entrytype. When not set, or when not convertable to then determined by
+
+
+ Maximum Event log size in kilobytes. If null, the value won't be set. Default is 512 Kilobytes as specified by Eventlog API
+
+
Message length limit to write to the Event Log.
@@ -1117,18 +1136,19 @@
+
-
+
+
-
@@ -1136,7 +1156,6 @@
-
@@ -1228,6 +1247,11 @@
Value indicationg whether file creation calls should be synchronized by a system global mutex.
+
+
+ Maximum number of log filenames that should be stored as existing.
+
+
Indicates whether the footer should be written only when the file is archived.
@@ -1253,11 +1277,6 @@
Indicates whether to create directories if they do not exist.
-
-
- Indicates whether to enable log file(s) to be deleted.
-
-
File attributes (Windows only).
@@ -1273,6 +1292,16 @@
Indicates whether to replace file contents on each write instead of appending log message at the end.
+
+
+ Indicates whether to enable log file(s) to be deleted.
+
+
+
+
+ Number of times the write is appended on the file before NLog discards the log message.
+
+
Indicates whether concurrent writes to the log file by multiple processes on the same host.
@@ -1283,11 +1312,6 @@
Indicates whether to keep log file open instead of opening and closing it on each logging event.
-
-
- Maximum number of log filenames that should be stored as existing.
-
-
Indicates whether concurrent writes to the log file by multiple processes on different network hosts.
@@ -1323,11 +1347,6 @@
Delay in milliseconds to wait before attempting to write to the file again.
-
-
- Number of times the write is appended on the file before NLog discards the log message.
-
-
@@ -1587,6 +1606,7 @@
+
@@ -1599,11 +1619,16 @@
Name of the parameter.
-
+
Type of the parameter.
+
+
+ Type of the parameter. Obsolete alias for
+
+
@@ -2020,13 +2045,14 @@
-
+
-
+
+
@@ -2094,9 +2120,9 @@
Maximum queue size.
-
+
- Indicates whether to include dictionary contents.
+ Indicates whether to include stack contents.
@@ -2109,9 +2135,9 @@
Indicates whether to include NLog-specific extensions to log4j schema.
-
+
- Indicates whether to include stack contents.
+ Indicates whether to include dictionary contents.
@@ -2129,6 +2155,11 @@
NDC item separator.
+
+
+ Indicates whether to include dictionary contents.
+
+
Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit
@@ -2487,8 +2518,10 @@
+
+
@@ -2534,6 +2567,11 @@
Web service namespace. Only used with Soap.
+
+
+ Indicates whether to pre-authenticate the HttpWebRequest (Requires 'Authorization' in parameters)
+
+
Protocol to be used when calling web service.
@@ -2677,8 +2715,10 @@
+
+
@@ -2690,6 +2730,11 @@
Option to include all properties from the log events
+
+
+ Indicates whether to include contents of the dictionary.
+
+
Option to render the empty object value {}
@@ -2700,12 +2745,18 @@
Option to suppress the extra spaces in the output json
+
+
+ Indicates whether to include contents of the dictionary.
+
+
+
@@ -2714,6 +2765,11 @@
Determines wether or not this attribute will be Json encoded.
+
+
+ Indicates whether to escape non-ascii characters
+
+
Layout that will be rendered as the attribute's value.
@@ -2754,7 +2810,26 @@
-
+
+
+
+
+
+
+
+ Option to include all properties from the log events
+
+
+
+
+ Indicates whether to include contents of the dictionary.
+
+
+
+
+ Indicates whether to include contents of the dictionary.
+
+
@@ -2929,6 +3004,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Action to be taken when filter matches.
+
+
+
+
+ Layout to be used to filter log messages.
+
+
+
+
+ Default number of unique filter values to expect, will automatically increase if needed
+
+
+
+
+ Append FilterCount to the when an event is no longer filtered
+
+
+
+
+ Insert FilterCount value into when an event is no longer filtered
+
+
+
+
+ Max number of unique filter values to expect simultaneously
+
+
+
+
+ Max length of filter values, will truncate if above limit
+
+
+
+
+ Default buffer size for the internal buffers
+
+
+
+
+ Reuse internal buffers, and doesn't have to constantly allocate new buffers
+
+
+
+
+ How long before a filter expires, and logging is accepted again
+
+
+
+
+
diff --git a/Artemis/Artemis/Profiles/Layers/Conditions/DataModelCondition.cs b/Artemis/Artemis/Profiles/Layers/Conditions/DataModelCondition.cs
index 31aafa17d..265eb7ef3 100644
--- a/Artemis/Artemis/Profiles/Layers/Conditions/DataModelCondition.cs
+++ b/Artemis/Artemis/Profiles/Layers/Conditions/DataModelCondition.cs
@@ -12,6 +12,8 @@ namespace Artemis.Profiles.Layers.Conditions
lock (layerModel.Properties.Conditions)
{
var checkConditions = layerModel.Properties.Conditions.Where(c => c.Field != null).ToList();
+ if (!checkConditions.Any())
+ return true;
switch (layerModel.Properties.ConditionType)
{
case ConditionType.AnyMet:
diff --git a/Artemis/Artemis/Profiles/Layers/Models/LayerConditionModel.cs b/Artemis/Artemis/Profiles/Layers/Models/LayerConditionModel.cs
index 560d74408..9b54a81ab 100644
--- a/Artemis/Artemis/Profiles/Layers/Models/LayerConditionModel.cs
+++ b/Artemis/Artemis/Profiles/Layers/Models/LayerConditionModel.cs
@@ -1,118 +1,174 @@
-using System;
-using System.Globalization;
-using Artemis.Modules.Abstract;
-using Artemis.Utilities;
-using DynamicExpresso;
-using MahApps.Metro.Controls;
-
-namespace Artemis.Profiles.Layers.Models
-{
- public class LayerConditionModel
- {
- private readonly Interpreter _interpreter;
- private object _lastValue;
-
- public LayerConditionModel()
- {
- _interpreter = new Interpreter();
- }
-
- public string Field { get; set; }
- public string Value { get; set; }
- public string Operator { get; set; }
- public string Type { get; set; }
- public HotKey HotKey { get; set; }
-
- public bool ConditionMet(ModuleDataModel subject)
- {
- lock (subject)
- {
- if (string.IsNullOrEmpty(Field) || string.IsNullOrEmpty(Type))
- return false;
-
- var inspect = GeneralHelpers.GetPropertyValue(subject, Field);
- if (inspect == null)
- {
- _lastValue = null;
- return false;
- }
-
- bool returnValue;
- if (Operator == "changed" || Operator == "decreased" || Operator == "increased")
- returnValue = EvaluateEventOperator(subject, inspect);
- else
- returnValue = EvaluateOperator(subject);
-
- _lastValue = inspect;
- return returnValue;
- }
- }
-
- private bool EvaluateEventOperator(ModuleDataModel subject, object inspect)
- {
- // DynamicExpresso doesn't want a null so when it was previously null (should only happen first iteration)
- // return false since that would be the only possible outcome
- if (_lastValue == null)
- return false;
-
- // Assign the right parameter
- var rightParam = new Parameter("value", _lastValue);
-
- // Come up with the proper operator
- var changeOperator = "";
- if (Operator == "changed")
- changeOperator = "!=";
- else if (Operator == "decreased")
- changeOperator = "<";
- else if (Operator == "increased")
- changeOperator = ">";
-
- // Evaluate the result and store it
- var returnValue = _interpreter.Eval($"subject.{Field} {changeOperator} value",
- new Parameter("subject", subject.GetType(), subject), rightParam);
-
- // Set the last value to the new value
- _lastValue = inspect;
- // Return the evaluated result
- return returnValue;
- }
-
- private bool EvaluateOperator(ModuleDataModel subject)
- {
- // Since _lastValue won't be used, rely on Value to not be null
- if (string.IsNullOrEmpty(Value))
- return false;
-
- // Put the subject in a list, allowing Dynamic Linq to be used.
- if (Type == "String")
- {
- return _interpreter.Eval($"subject.{Field}.ToLower(){Operator}(value)",
- new Parameter("subject", subject.GetType(), subject),
- new Parameter("value", Value.ToLower()));
- }
-
- Parameter rightParam = null;
- switch (Type)
- {
- case "Enum":
- var enumType = GeneralHelpers.GetPropertyValue(subject, Field).GetType();
- rightParam = new Parameter("value", Enum.Parse(enumType, Value));
- break;
- case "Boolean":
- rightParam = new Parameter("value", bool.Parse(Value));
- break;
- case "Int32":
- rightParam = new Parameter("value", int.Parse(Value));
- break;
- case "Single":
- // Parse commas as decimals
- rightParam = new Parameter("value", float.Parse(Value.Replace(",", "."),
- CultureInfo.InvariantCulture));
- break;
- }
-
- return _interpreter.Eval($"subject.{Field} {Operator} value",
- new Parameter("subject", subject.GetType(), subject), rightParam);
- }
- }
-}
\ No newline at end of file
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Windows.Documents;
+using Artemis.Modules.Abstract;
+using Artemis.Utilities;
+using DynamicExpresso;
+using MahApps.Metro.Controls;
+
+namespace Artemis.Profiles.Layers.Models
+{
+ public class LayerConditionModel
+ {
+ private readonly Interpreter _interpreter;
+ private object _lastValue;
+ private Regex _rgx;
+
+ public LayerConditionModel()
+ {
+ _interpreter = new Interpreter();
+ _rgx = new Regex("\\((.*?)\\)");
+ }
+
+ public string Field { get; set; }
+ public string Value { get; set; }
+ public string Operator { get; set; }
+ public string Type { get; set; }
+ public HotKey HotKey { get; set; }
+
+ public bool ConditionMet(ModuleDataModel subject)
+ {
+ lock (subject)
+ {
+ if (string.IsNullOrEmpty(Field) || string.IsNullOrEmpty(Type))
+ return false;
+
+ // If the path points to a collection, look inside this collection
+ if (Field.Contains("("))
+ {
+ // Find the collection in the field path
+ var collectionField = _rgx.Match(Field).Groups[1].Value;
+ var collectionInspect = (IEnumerable) GeneralHelpers.GetPropertyValue(subject, collectionField);
+ var operatorParts = Operator.Split('|');
+ var field = Field.Split(')').Last().Substring(1);
+
+ _lastValue = collectionInspect;
+
+ if (operatorParts[0] == "any")
+ {
+ var anyMatch = false;
+ foreach (var collectionValue in collectionInspect)
+ {
+ anyMatch = EvaluateOperator(collectionValue, field, operatorParts[1]);
+ if (anyMatch)
+ break;
+ }
+ return anyMatch;
+ }
+ if (operatorParts[0] == "all")
+ {
+ var allMatch = true;
+ foreach (var collectionValue in collectionInspect)
+ {
+ allMatch = EvaluateOperator(collectionValue, field, operatorParts[1]);
+ if (!allMatch)
+ break;
+ }
+ return allMatch;
+ }
+ if (operatorParts[0] == "none")
+ {
+ var noneMatch = true;
+ foreach (var collectionValue in collectionInspect)
+ {
+ noneMatch = !EvaluateOperator(collectionValue, field, operatorParts[1]);
+ if (!noneMatch)
+ break;
+ }
+ return noneMatch;
+ }
+ }
+
+ var inspect = GeneralHelpers.GetPropertyValue(subject, Field);
+ if (inspect == null)
+ {
+ _lastValue = null;
+ return false;
+ }
+
+ bool returnValue;
+ if (Operator == "changed" || Operator == "decreased" || Operator == "increased")
+ returnValue = EvaluateEventOperator(subject, inspect);
+ else
+ returnValue = EvaluateOperator(subject, Field);
+
+ _lastValue = inspect;
+ return returnValue;
+ }
+ }
+
+ private bool EvaluateEventOperator(ModuleDataModel subject, object inspect)
+ {
+ // DynamicExpresso doesn't want a null so when it was previously null (should only happen first iteration)
+ // return false since that would be the only possible outcome
+ if (_lastValue == null)
+ return false;
+
+ // Assign the right parameter
+ var rightParam = new Parameter("value", _lastValue);
+
+ // Come up with the proper operator
+ var changeOperator = "";
+ if (Operator == "changed")
+ changeOperator = "!=";
+ else if (Operator == "decreased")
+ changeOperator = "<";
+ else if (Operator == "increased")
+ changeOperator = ">";
+
+ // Evaluate the result and store it
+ var returnValue = _interpreter.Eval($"subject.{Field} {changeOperator} value", new Parameter("subject", subject.GetType(), subject), rightParam);
+
+ // Set the last value to the new value
+ _lastValue = inspect;
+ // Return the evaluated result
+ return returnValue;
+ }
+
+ private bool EvaluateOperator(object subject, string field, string operatorOverwrite = null)
+ {
+ // Since _lastValue won't be used, rely on Value to not be null
+ if (string.IsNullOrEmpty(Value))
+ return false;
+
+ if (Type == "String")
+ {
+ var stringExpressionText = operatorOverwrite == null
+ ? $"subject.{field}.ToLower(){Operator}(value)"
+ : $"subject.{field}.ToLower(){operatorOverwrite}(value)";
+
+ return _interpreter.Eval(stringExpressionText, new Parameter("subject", subject.GetType(), subject), new Parameter("value", Value.ToLower()));
+ }
+
+ Parameter rightParam = null;
+ switch (Type)
+ {
+ case "Enum":
+ var enumType = GeneralHelpers.GetPropertyValue(subject, field).GetType();
+ rightParam = new Parameter("value", Enum.Parse(enumType, Value));
+ break;
+ case "Boolean":
+ rightParam = new Parameter("value", bool.Parse(Value));
+ break;
+ case "Int32":
+ rightParam = new Parameter("value", int.Parse(Value));
+ break;
+ case "Single":
+ // Parse commas as decimals
+ rightParam = new Parameter("value", float.Parse(Value.Replace(",", "."),
+ CultureInfo.InvariantCulture));
+ break;
+ }
+
+ var expressionText = operatorOverwrite == null
+ ? $"subject.{field} {Operator} value"
+ : $"subject.{field} {operatorOverwrite} value";
+
+ return _interpreter.Eval(expressionText, new Parameter("subject", subject.GetType(), subject), rightParam);
+ }
+ }
+}
diff --git a/Artemis/Artemis/Profiles/Layers/Models/LayerModel.cs b/Artemis/Artemis/Profiles/Layers/Models/LayerModel.cs
index 25f27bf48..709c86a73 100644
--- a/Artemis/Artemis/Profiles/Layers/Models/LayerModel.cs
+++ b/Artemis/Artemis/Profiles/Layers/Models/LayerModel.cs
@@ -11,6 +11,7 @@ using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Types.Keyboard;
using Artemis.Utilities;
using Artemis.Utilities.ParentChild;
+using Betwixt;
using Newtonsoft.Json;
namespace Artemis.Profiles.Layers.Models
@@ -26,8 +27,14 @@ namespace Artemis.Profiles.Layers.Models
var model = Properties as KeyboardPropertiesModel;
if (model != null)
GifImage = new GifImage(model.GifFile, Properties.AnimationSpeed);
+
+ LayerConditionsMet += OnLayerConditionsMet;
+ LayerConditionsUnmet += OnLayerConditionsUnmet;
}
+ public event EventHandler LayerConditionsMet;
+ public event EventHandler LayerConditionsUnmet;
+
[JsonIgnore]
public ImageSource LayerImage => LayerType.DrawThumbnail(this);
@@ -43,7 +50,18 @@ namespace Artemis.Profiles.Layers.Models
public bool AreConditionsMet(ModuleDataModel dataModel)
{
// Conditions are not even checked if the layer isn't enabled
- return Enabled && LayerCondition.ConditionsMet(this, dataModel);
+ if (!Enabled)
+ return false;
+
+ FadeTweener?.Update(40);
+ var conditionsMet = LayerCondition.ConditionsMet(this, dataModel);
+ if (conditionsMet && !_conditionsMetLastFrame)
+ OnLayerConditionsMet();
+ if (!conditionsMet && _conditionsMetLastFrame)
+ OnLayerConditionsUnmet();
+
+ _conditionsMetLastFrame = conditionsMet;
+ return FadeTweener != null && FadeTweener.Running || conditionsMet;
}
///
@@ -96,7 +114,37 @@ namespace Artemis.Profiles.Layers.Models
if (Brush == null || !preview && !RenderAllowed)
return;
+ ApplyHierarchyOpacity(c);
LayerType.Draw(this, c);
+ PopHierarchyOpacity(c);
+ }
+
+ private void ApplyHierarchyOpacity(DrawingContext c)
+ {
+ if (FadeTweener != null && FadeTweener.Running)
+ c.PushOpacity(FadeTweener.Value);
+
+ var current = this;
+ while (current.Parent != null)
+ {
+ current = current.Parent;
+ if (current.FadeTweener != null && current.FadeTweener.Running)
+ c.PushOpacity(current.FadeTweener.Value);
+ }
+ }
+
+ private void PopHierarchyOpacity(DrawingContext c)
+ {
+ if (FadeTweener != null && FadeTweener.Running)
+ c.Pop();
+
+ var current = this;
+ while (current.Parent != null)
+ {
+ current = current.Parent;
+ if (current.FadeTweener != null && current.FadeTweener.Running)
+ c.Pop();
+ }
}
///
@@ -303,6 +351,29 @@ namespace Artemis.Profiles.Layers.Models
keybindModel.Unregister();
}
+ private void OnLayerConditionsMet(object sender, EventArgs eventArgs)
+ {
+ if (FadeInTime <= 0)
+ return;
+ if (FadeTweener != null && FadeTweener.Running)
+ FadeTweener = new Tweener(FadeTweener.Value, 1, FadeInTime, Ease.Quint.Out, TweenModel.LerpFuncFloat);
+ else
+ FadeTweener = new Tweener(0, 1, FadeInTime, Ease.Quint.Out, TweenModel.LerpFuncFloat);
+ FadeTweener.Start();
+ }
+
+ private void OnLayerConditionsUnmet(object sender, EventArgs eventArgs)
+ {
+ if (FadeOutTime <= 0)
+ return;
+
+ if (FadeTweener != null && FadeTweener.Running)
+ FadeTweener = new Tweener(FadeTweener.Value, 0, FadeOutTime, Ease.Quint.In, TweenModel.LerpFuncFloat);
+ else
+ FadeTweener = new Tweener(1, 0, FadeOutTime, Ease.Quint.In, TweenModel.LerpFuncFloat);
+ FadeTweener.Start();
+ }
+
#region Properties
#region Layer type properties
@@ -321,6 +392,8 @@ namespace Artemis.Profiles.Layers.Models
public bool RenderAllowed { get; set; }
public bool Expanded { get; set; }
public bool IsEvent { get; set; }
+ public double FadeInTime { get; set; }
+ public double FadeOutTime { get; set; }
public LayerPropertiesModel Properties { get; set; }
public EventPropertiesModel EventProperties { get; set; }
@@ -341,6 +414,10 @@ namespace Artemis.Profiles.Layers.Models
#region Render properties
[JsonIgnore] private Brush _brush;
+ [JsonIgnore] private bool _conditionsMetLastFrame;
+
+ [JsonIgnore]
+ public Tweener FadeTweener { get; set; }
[JsonIgnore]
public double X { get; set; }
@@ -416,5 +493,15 @@ namespace Artemis.Profiles.Layers.Models
{
return $"{nameof(Name)}: {Name}, {nameof(Order)}: {Order}, {nameof(X)}: {X}, {nameof(Y)}: {Y}, {nameof(Width)}: {Width}, {nameof(Height)}: {Height}";
}
+
+ protected virtual void OnLayerConditionsMet()
+ {
+ LayerConditionsMet?.Invoke(this, EventArgs.Empty);
+ }
+
+ protected virtual void OnLayerConditionsUnmet()
+ {
+ LayerConditionsUnmet?.Invoke(this, EventArgs.Empty);
+ }
}
}
diff --git a/Artemis/Artemis/Profiles/Layers/Models/LayerPropertiesModel.cs b/Artemis/Artemis/Profiles/Layers/Models/LayerPropertiesModel.cs
index 3fcd8df46..482782a29 100644
--- a/Artemis/Artemis/Profiles/Layers/Models/LayerPropertiesModel.cs
+++ b/Artemis/Artemis/Profiles/Layers/Models/LayerPropertiesModel.cs
@@ -42,7 +42,6 @@ namespace Artemis.Profiles.Layers.Models
public double Width { get; set; }
public double Height { get; set; }
public bool Contain { get; set; }
- public double Opacity { get; set; }
public double AnimationSpeed { get; set; }
public double OpacityEaseTime { get; set; }
public double HeightEaseTime { get; set; }
@@ -55,6 +54,10 @@ namespace Artemis.Profiles.Layers.Models
public List LayerKeybindModels { get; set; } = new List();
public List DynamicProperties { get; set; } = new List();
+ // Opacity isn't saved since it's only accesable by LUA
+ [JsonIgnore]
+ public double Opacity { get; set; } = 1;
+
[JsonConverter(typeof(BrushJsonConverter))]
public Brush Brush
{
diff --git a/Artemis/Artemis/Profiles/Layers/Models/TweenModel.cs b/Artemis/Artemis/Profiles/Layers/Models/TweenModel.cs
index cc997b510..c2a4af6e5 100644
--- a/Artemis/Artemis/Profiles/Layers/Models/TweenModel.cs
+++ b/Artemis/Artemis/Profiles/Layers/Models/TweenModel.cs
@@ -136,7 +136,7 @@ namespace Artemis.Profiles.Layers.Models
}
}
- private static float LerpFuncFloat(float start, float end, float percent)
+ public static float LerpFuncFloat(float start, float end, float percent)
{
return start + (end - start) * percent;
}
diff --git a/Artemis/Artemis/Profiles/Lua/Modules/Gui/LuaSlider.cs b/Artemis/Artemis/Profiles/Lua/Modules/Gui/LuaSlider.cs
new file mode 100644
index 000000000..0a14af4f8
--- /dev/null
+++ b/Artemis/Artemis/Profiles/Lua/Modules/Gui/LuaSlider.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+using Artemis.Managers;
+using MoonSharp.Interpreter;
+using MoonSharp.Interpreter.Interop;
+
+namespace Artemis.Profiles.Lua.Modules.Gui
+{
+ [MoonSharpUserData]
+ public class LuaSlider
+ {
+ private readonly LuaManager _luaManager;
+
+ public LuaSlider(LuaManager luaManager, int interval, double intialValue, double minimum, double maximum, double x, double y, double? width, double? height)
+ {
+ _luaManager = luaManager;
+
+ Slider = new Slider { Value = intialValue, TickFrequency = interval, Minimum = minimum, Maximum = maximum, TickPlacement = TickPlacement.BottomRight, IsSnapToTickEnabled = true};
+
+ if (width != null)
+ Slider.Width = width.Value;
+ if (height != null)
+ Slider.Height = height.Value;
+
+ Slider.ValueChanged += SliderOnValueChanged;
+ }
+
+ [MoonSharpVisible(false)]
+ public Slider Slider { get; }
+
+ public double Value
+ {
+ get => Slider.Dispatcher.Invoke(() => (double) Slider.Value);
+ set => Slider.Dispatcher.Invoke(() => Slider.Value = value);
+ }
+
+ public int Interval
+ {
+ get => Slider.Dispatcher.Invoke(() => (int) Slider.Interval);
+ set => Slider.Dispatcher.Invoke(() => Slider.Interval = value);
+ }
+
+ private void SliderOnValueChanged(object sender, RoutedPropertyChangedEventArgs routedPropertyChangedEventArgs)
+ {
+ _luaManager.EventsModule.LuaInvoke(_luaManager.ProfileModel, () => OnValueChanged(this));
+ }
+
+ public event EventHandler ValueChanged;
+
+ protected virtual void OnValueChanged(LuaSlider slider)
+ {
+ ValueChanged?.Invoke(slider, null);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Profiles/Lua/Modules/Gui/LuaWindowViewModel.cs b/Artemis/Artemis/Profiles/Lua/Modules/Gui/LuaWindowViewModel.cs
index 5c927cdb1..f7201069e 100644
--- a/Artemis/Artemis/Profiles/Lua/Modules/Gui/LuaWindowViewModel.cs
+++ b/Artemis/Artemis/Profiles/Lua/Modules/Gui/LuaWindowViewModel.cs
@@ -83,6 +83,18 @@ namespace Artemis.Profiles.Lua.Modules.Gui
return element;
}
+ public LuaSlider CreateSlider(int interval, double initialValue, double minimum, double maximum, double x, double y, double? width = 200.0, double? height = 20.0)
+ {
+ LuaSlider element = null;
+ Execute.OnUIThread(() =>
+ {
+ element = new LuaSlider(_luaManager, interval, initialValue, minimum, maximum, x, y, width, height);
+ AddControl(element.Slider, x, y);
+ });
+
+ return element;
+ }
+
private void AddControl(UIElement uiElement, double x, double y)
{
Canvas.Children.Add(uiElement);
diff --git a/Artemis/Artemis/Properties/AssemblyInfo.cs b/Artemis/Artemis/Properties/AssemblyInfo.cs
index 1019f22b2..f51f5f42f 100644
--- a/Artemis/Artemis/Properties/AssemblyInfo.cs
+++ b/Artemis/Artemis/Properties/AssemblyInfo.cs
@@ -53,7 +53,7 @@ using System.Windows;
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.10.0.0")]
-[assembly: AssemblyFileVersion("1.10.0.0")]
+[assembly: AssemblyVersion("1.11.0.0")]
+[assembly: AssemblyFileVersion("1.11.0.0")]
+[assembly: AssemblyMetadata("SquirrelAwareVersion", "1")]
[assembly: InternalsVisibleTo("Artemis.Explorables")]
-
diff --git a/Artemis/Artemis/Properties/Resources.Designer.cs b/Artemis/Artemis/Properties/Resources.Designer.cs
index 2ae2a31ad..998a7d83b 100644
--- a/Artemis/Artemis/Properties/Resources.Designer.cs
+++ b/Artemis/Artemis/Properties/Resources.Designer.cs
@@ -19,7 +19,7 @@ namespace Artemis.Properties {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
@@ -70,6 +70,29 @@ namespace Artemis.Properties {
}
}
+ ///
+ /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-16"?>
+ ///<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
+ /// <RegistrationInfo>
+ /// <Date>2017-11-12T17:45:45.4993602</Date>
+ /// <Author>SpoinkyNL</Author>
+ /// <Description>Task to run Artemis on PC startup without showing a UAC dialog</Description>
+ /// <URI>\Artemis autorun</URI>
+ /// </RegistrationInfo>
+ /// <Triggers>
+ /// <LogonTrigger>
+ /// <Enabled>true</Enabled>
+ /// <Delay>PT30S</Delay>
+ /// </LogonTrigger>
+ /// </Triggers>
+ /// <Set [rest of string was truncated]";.
+ ///
+ internal static string Artemis_autorun {
+ get {
+ return ResourceManager.GetString("Artemis_autorun", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized resource of type System.Drawing.Bitmap.
///
@@ -105,6 +128,7 @@ namespace Artemis.Properties {
///{
/// "uri" "http://localhost:{{port}}/csgo_game_event"
/// "timeout" "0.1"
+ /// "heartbeat" "0.1"
/// "data"
/// {
/// "provider" "1"
@@ -437,5 +461,15 @@ namespace Artemis.Properties {
return ((byte[])(obj));
}
}
+
+ ///
+ /// Looks up a localized resource of type System.Byte[].
+ ///
+ internal static byte[] wow_addon {
+ get {
+ object obj = ResourceManager.GetObject("wow_addon", resourceCulture);
+ return ((byte[])(obj));
+ }
+ }
}
}
diff --git a/Artemis/Artemis/Properties/Resources.resx b/Artemis/Artemis/Properties/Resources.resx
index fa4d5de48..8518cab2e 100644
--- a/Artemis/Artemis/Properties/Resources.resx
+++ b/Artemis/Artemis/Properties/Resources.resx
@@ -223,4 +223,10 @@
..\Resources\Keyboards\k95-platinum.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+ ..\Modules\Games\WoW\Resources\wow-addon.zip;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ ..\Resources\Artemis autorun.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16
+
\ No newline at end of file
diff --git a/Artemis/Artemis/Resources/Artemis autorun.xml b/Artemis/Artemis/Resources/Artemis autorun.xml
new file mode 100644
index 000000000..cd46cbf98
Binary files /dev/null and b/Artemis/Artemis/Resources/Artemis autorun.xml differ
diff --git a/Artemis/Artemis/Resources/lua-placeholder.lua b/Artemis/Artemis/Resources/lua-placeholder.lua
index ab5b2d17d..3dfdc4244 100644
--- a/Artemis/Artemis/Resources/lua-placeholder.lua
+++ b/Artemis/Artemis/Resources/lua-placeholder.lua
@@ -15,39 +15,39 @@
-- This event is raised after every profile update, before drawing.
function updateHandler(profile, eventArgs)
- -- Don't do anything when previewing (this means the editor is open)
- if eventArgs.Preview then
- return
- end
+ -- Don't do anything when previewing (this means the editor is open)
+ if eventArgs.Preview then
+ return
+ end
- -- In this example we only want to update once per frame when the keyboard is
- -- updated. If you don't do this the updateHandler will trigger on every
- -- device's update.
- if eventArgs.DeviceType != "keyboard" then
+ -- In this example we only want to update once per frame when the keyboard is
+ -- updated. If you don't do this the updateHandler will trigger on every
+ -- device's update.
+ if not (eventArgs.DeviceType == "keyboard") then
return
end
-
- -- Custom update code here
+
+ -- Custom update code here
end
-- This event is raised after every profile draw, after updating.
function drawHandler(profile, eventArgs)
- -- Don't do anything when previewing (this means the editor is open)
- if eventArgs.Preview then
- return
- end
+ -- Don't do anything when previewing (this means the editor is open)
+ if eventArgs.Preview then
+ return
+ end
- -- In this example we only want to draw to the keyboard. Each device has it's
- -- own drawing event
- if eventArgs.DeviceType != "keyboard" then
+ -- In this example we only want to draw to the keyboard. Each device has it's
+ -- own drawing event
+ if not (eventArgs.DeviceType == "keyboard") then
return
end
-
- -- Custom draw code here
+
+ -- Custom draw code here
end
-- Register the default events, you can rename/remove these if you so desire.
-- These events are raised every 40 ms (25 times a second).
-Events.DeviceUpdating.add(updateHandler);
-Events.DeviceDrawing.add(drawHandler);
\ No newline at end of file
+Events.DeviceUpdating.add(updateHandler)
+Events.DeviceDrawing.add(drawHandler)
\ No newline at end of file
diff --git a/Artemis/Artemis/Settings/GeneralSettings.cs b/Artemis/Artemis/Settings/GeneralSettings.cs
index 13240abee..e4883c874 100644
--- a/Artemis/Artemis/Settings/GeneralSettings.cs
+++ b/Artemis/Artemis/Settings/GeneralSettings.cs
@@ -4,10 +4,12 @@ using System.IO;
using System.Windows;
using Artemis.DAL;
using Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing;
+using Artemis.Properties;
using Artemis.Utilities;
using Artemis.Utilities.ActiveWindowDetection;
using Caliburn.Micro;
using MahApps.Metro;
+using Microsoft.Win32.TaskScheduler;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Squirrel;
@@ -111,10 +113,8 @@ namespace Artemis.Settings
{
try
{
- if (Autorun)
- mgr.CreateShortcutsForExecutable("Artemis.exe", ShortcutLocation.Startup, false, "--autorun");
- else
- mgr.RemoveShortcutsForExecutable("Artemis.exe", ShortcutLocation.Startup);
+ // Clean up the shortcut used by the old method
+ mgr.RemoveShortcutsForExecutable("Artemis.exe", ShortcutLocation.Startup);
}
catch (FileNotFoundException)
{
@@ -125,6 +125,25 @@ namespace Artemis.Settings
// Ignored, only happens when running from VS
}
+ using (var ts = new TaskService())
+ {
+ var existing = ts.FindTask("Artemis autorun");
+ if (Autorun)
+ {
+ // Overwrite any existing tasks in case the installation folder changed
+ var path = Path.GetTempFileName();
+ var xml = Resources.Artemis_autorun.Replace("{{executablePath}}", mgr.RootAppDirectory + "\\Update.exe");
+
+ File.WriteAllText(path, xml);
+ ts.RootFolder.ImportTask(null, path);
+ File.Delete(path);
+ }
+ else if (existing != null)
+ {
+ // Remove the task if it is present
+ ts.RootFolder.DeleteTask("Artemis autorun");
+ }
+ }
}
}
@@ -159,4 +178,4 @@ namespace Artemis.Settings
ScreenCaptureManager.UpdateRate = 1.0 / ScreenCaptureFPS;
}
}
-}
\ No newline at end of file
+}
diff --git a/Artemis/Artemis/Utilities/GeneralHelpers.cs b/Artemis/Artemis/Utilities/GeneralHelpers.cs
index afc5be9d5..526ed7a65 100644
--- a/Artemis/Artemis/Utilities/GeneralHelpers.cs
+++ b/Artemis/Artemis/Utilities/GeneralHelpers.cs
@@ -5,7 +5,6 @@ using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Threading;
-using System.Windows;
using Microsoft.Win32;
using Newtonsoft.Json;
using static System.String;
@@ -42,10 +41,12 @@ namespace Artemis.Utilities
return GetPropertyValue(value, path.Replace(propertyNames[0] + ".", ""));
}
- public static List GenerateTypeMap(object o) => GenerateTypeMap(o.GetType().GetProperties());
+ public static List GenerateTypeMap(object o)
+ {
+ return GenerateTypeMap(o.GetType().GetProperties());
+ }
- private static List GenerateTypeMap(IEnumerable getProperties,
- string path = "")
+ private static List GenerateTypeMap(IEnumerable getProperties, string path = "", bool inList = false)
{
var list = new List();
foreach (var propInfo in getProperties)
@@ -62,13 +63,28 @@ namespace Artemis.Utilities
if (propInfo.PropertyType.BaseType?.Name == "Enum")
friendlyName = "(Choice)";
- var parent = new PropertyCollection
+ // At this point the loop is in the item type contained in the list
+ PropertyCollection parent;
+ if (path.Contains("Item") && inList)
{
- Type = propInfo.PropertyType.Name,
- DisplayType = friendlyName,
- Display = $"{path.Replace(".", " → ")}{propInfo.Name}",
- Path = $"{path}{propInfo.Name}"
- };
+ parent = new PropertyCollection
+ {
+ Type = propInfo.PropertyType.Name,
+ DisplayType = friendlyName,
+ Display = $"{path.Replace("Item.", "").Replace(".", " → ")}{propInfo.Name}",
+ Path = $"{path.Replace("Item.", "")}{propInfo.Name}"
+ };
+ }
+ else
+ {
+ parent = new PropertyCollection
+ {
+ Type = propInfo.PropertyType.Name,
+ DisplayType = friendlyName,
+ Display = $"{path.Replace(".", " → ")}{propInfo.Name}",
+ Path = $"{path}{propInfo.Name}"
+ };
+ }
if (propInfo.PropertyType.BaseType?.Name == "Enum")
{
@@ -80,10 +96,19 @@ namespace Artemis.Utilities
list.Add(parent);
// Don't go into Strings, DateTimes or anything with JsonIgnore on it
- if (propInfo.PropertyType.Name != "String" &&
+ if (propInfo.PropertyType.Name != "String" &&
propInfo.PropertyType.Name != "DateTime" &&
propInfo.CustomAttributes.All(a => a.AttributeType != typeof(JsonIgnoreAttribute)))
- list.AddRange(GenerateTypeMap(propInfo.PropertyType.GetProperties(), path + $"{propInfo.Name}."));
+ {
+ var newPath = $"{path}{propInfo.Name}.";
+ var toInList = propInfo.PropertyType.Name == "List`1";
+ if (toInList)
+ {
+ inList = true;
+ newPath = $"({path}{propInfo.Name}).";
+ }
+ list.AddRange(GenerateTypeMap(propInfo.PropertyType.GetProperties(), newPath, inList));
+ }
}
return list;
}
@@ -114,6 +139,21 @@ namespace Artemis.Utilities
return null;
}
+ public static void ExecuteSta(Action action)
+ {
+ var thread = new Thread(action.Invoke);
+ thread.SetApartmentState(ApartmentState.STA); //Set the thread to STA
+ thread.Start();
+ thread.Join();
+ }
+
+ public static T ParseEnum(string value, bool ignoreCase = true, bool stripWhitespaces = true)
+ {
+ if (stripWhitespaces)
+ value = value.Replace(" ", "");
+ return (T) Enum.Parse(typeof(T), value, true);
+ }
+
public struct PropertyCollection
{
public string Display { get; set; }
@@ -128,13 +168,5 @@ namespace Artemis.Utilities
public List Children { get; set; }
public string DisplayType { get; set; }
}
-
- public static void ExecuteSta(Action action)
- {
- var thread = new Thread(action.Invoke);
- thread.SetApartmentState(ApartmentState.STA); //Set the thread to STA
- thread.Start();
- thread.Join();
- }
}
-}
\ No newline at end of file
+}
diff --git a/Artemis/Artemis/ViewModels/GamesViewModel.cs b/Artemis/Artemis/ViewModels/GamesViewModel.cs
index 68a5d6041..21914d534 100644
--- a/Artemis/Artemis/ViewModels/GamesViewModel.cs
+++ b/Artemis/Artemis/ViewModels/GamesViewModel.cs
@@ -1,9 +1,6 @@
using System.Collections.Generic;
using System.Linq;
-using Artemis.DAL;
-using Artemis.Managers;
using Artemis.Modules.Abstract;
-using Artemis.Settings;
using Artemis.ViewModels.Abstract;
namespace Artemis.ViewModels
@@ -16,18 +13,7 @@ namespace Artemis.ViewModels
{
DisplayName = "Games";
- // Currently WoW is locked behind a hidden trigger (obviously not that hidden since you're reading this)
- // It is using memory reading and lets first try to contact Blizzard
- if (SettingsProvider.Load().GamestatePort == 62575)
- {
- _vms = moduleViewModels.Where(m => m.ModuleModel.IsBoundToProcess)
- .OrderBy(g => g.DisplayName).ToList();
- }
- else
- {
- _vms = moduleViewModels.Where(m => m.ModuleModel.IsBoundToProcess && m.DisplayName != "WoW")
- .OrderBy(g => g.DisplayName).ToList();
- }
+ _vms = moduleViewModels.Where(m => m.ModuleModel.IsBoundToProcess).OrderBy(g => g.DisplayName).ToList();
}
protected override void OnActivate()
@@ -37,4 +23,4 @@ namespace Artemis.ViewModels
Items.AddRange(_vms);
}
}
-}
\ No newline at end of file
+}
diff --git a/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs b/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs
index b0d3b1daf..6068aec2b 100644
--- a/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs
+++ b/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs
@@ -26,7 +26,6 @@ using Artemis.Styles.DropTargetAdorners;
using Artemis.Utilities;
using Artemis.Utilities.ActiveWindowDetection;
using Caliburn.Micro;
-using Castle.Components.DictionaryAdapter;
using GongSolutions.Wpf.DragDrop;
using MahApps.Metro;
using MahApps.Metro.Controls;
@@ -406,8 +405,6 @@ namespace Artemis.ViewModels
ProfileNames.Clear();
if (_moduleModel != null && _deviceManager.ActiveKeyboard != null)
ProfileNames.AddRange(ProfileProvider.GetProfileNames(_deviceManager.ActiveKeyboard, _moduleModel));
-
- NotifyOfPropertyChange(() => SelectedProfile);
});
}
@@ -444,7 +441,7 @@ namespace Artemis.ViewModels
return;
LoadProfiles();
- _moduleModel.ChangeProfile(profile);
+ SelectedProfileName = profile.Name;
}
public async void RenameProfile()
@@ -456,7 +453,8 @@ namespace Artemis.ViewModels
await ProfileEditorModel.RenameProfile(SelectedProfile);
LoadProfiles();
- _moduleModel.ChangeProfile(renameProfile);
+ SelectedProfileName = "Default";
+ SelectedProfileName = renameProfile.Name;
}
public async void DuplicateProfile()
@@ -469,7 +467,7 @@ namespace Artemis.ViewModels
return;
LoadProfiles();
- _moduleModel.ChangeProfile(newProfle);
+ SelectedProfileName = newProfle.Name;
}
public async void DeleteProfile()
@@ -477,12 +475,17 @@ namespace Artemis.ViewModels
if (SelectedProfile == null)
return;
- var confirmed = await ProfileEditorModel.DeleteProfile(SelectedProfile, _moduleModel);
+ var confirmed = await ProfileEditorModel.ConfirmDeleteProfile(SelectedProfile, _moduleModel);
if (!confirmed)
return;
+ var deleteProfile = SelectedProfile;
+
+ _moduleModel.ChangeProfile(null);
+ ProfileProvider.DeleteProfile(deleteProfile);
+
LoadProfiles();
- ProfileEditorModel.ChangeProfileByName(_moduleModel, null);
+ SelectedProfileName = "Default";
}
public async void ImportProfile()
@@ -499,7 +502,7 @@ namespace Artemis.ViewModels
return;
LoadProfiles();
- _moduleModel.ChangeProfile(importProfile);
+ SelectedProfileName = importProfile.Name;
}
public void ExportProfile()
@@ -633,7 +636,7 @@ namespace Artemis.ViewModels
return SelectedProfile.GetRenderLayers(null, false, true);
if (SelectedLayer == null || !SelectedLayer.Enabled)
- return new EditableList();
+ return new List();
if (SelectedLayer.LayerType is FolderType)
drawLayers = SelectedLayer.GetRenderLayers(null, false, true);
diff --git a/Artemis/Artemis/ViewModels/Profiles/LayerConditionViewModel.cs b/Artemis/Artemis/ViewModels/Profiles/LayerConditionViewModel.cs
index 596b6b1ea..ef71e7ed3 100644
--- a/Artemis/Artemis/ViewModels/Profiles/LayerConditionViewModel.cs
+++ b/Artemis/Artemis/ViewModels/Profiles/LayerConditionViewModel.cs
@@ -1,4 +1,5 @@
-using System.ComponentModel;
+using System.Collections.Generic;
+using System.ComponentModel;
using System.Linq;
using Artemis.Profiles.Layers.Models;
using Artemis.Utilities;
@@ -41,6 +42,13 @@ namespace Artemis.ViewModels.Profiles
new NamedOperator("Ends with", ".EndsWith")
};
+ private readonly NamedOperator[] _listOperatorsPrefixes =
+ {
+ new NamedOperator("Any", "any"),
+ new NamedOperator("All", "all"),
+ new NamedOperator("None", "none")
+ };
+
private HotKey _hotKey;
private bool _keybindIsVisible;
private GeneralHelpers.PropertyCollection _selectedDataModelProp;
@@ -205,7 +213,6 @@ namespace Artemis.ViewModels.Profiles
{
Operators.Clear();
DropdownValues.Clear();
-
switch (SelectedDataModelProp.Type)
{
case "Int32":
@@ -228,7 +235,16 @@ namespace Artemis.ViewModels.Profiles
UserValueIsVisible = true;
break;
}
-
+ // If the selected value is in a list, prefix all choices with list choices
+ if (SelectedDataModelProp.Path != null && SelectedDataModelProp.Path.Contains("("))
+ {
+ var listOperators = new List();
+ foreach (var o in Operators)
+ listOperators.AddRange(_listOperatorsPrefixes.Select(p => new NamedOperator(p.Display + " " + o.Display.ToLower(), p.Value + "|" + o.Value)));
+
+ Operators.Clear();
+ Operators.AddRange(listOperators);
+ }
// Add Changed operator is the type is event
if (_editorViewModel.ProposedLayer.IsEvent)
{
diff --git a/Artemis/Artemis/ViewModels/Profiles/LayerDynamicPropertiesViewModel.cs b/Artemis/Artemis/ViewModels/Profiles/LayerDynamicPropertiesViewModel.cs
index 54e056009..46d527905 100644
--- a/Artemis/Artemis/ViewModels/Profiles/LayerDynamicPropertiesViewModel.cs
+++ b/Artemis/Artemis/ViewModels/Profiles/LayerDynamicPropertiesViewModel.cs
@@ -3,7 +3,6 @@ using System.Linq;
using Artemis.Profiles.Layers.Models;
using Artemis.Utilities;
using Caliburn.Micro;
-using Castle.Core.Internal;
namespace Artemis.ViewModels.Profiles
{
@@ -219,7 +218,7 @@ namespace Artemis.ViewModels.Profiles
.DynamicProperties
.Where(p => p.LayerProperty != _property).ToList();
- if (!Proposed.GameProperty.IsNullOrEmpty())
+ if (!string.IsNullOrEmpty(Proposed.GameProperty))
proposedProperties.DynamicProperties.Add(Proposed);
}
}
diff --git a/Artemis/Artemis/Views/LayerEditorView.xaml b/Artemis/Artemis/Views/LayerEditorView.xaml
index 4895a6fa6..5521cdd6a 100644
--- a/Artemis/Artemis/Views/LayerEditorView.xaml
+++ b/Artemis/Artemis/Views/LayerEditorView.xaml
@@ -46,6 +46,7 @@
+
@@ -66,6 +67,14 @@
+
+
+
+
+
+
+
+
diff --git a/Artemis/Artemis/lib/SDKDLL.dll b/Artemis/Artemis/lib/SDKDLL.dll
index a71619198..057316385 100644
Binary files a/Artemis/Artemis/lib/SDKDLL.dll and b/Artemis/Artemis/lib/SDKDLL.dll differ
diff --git a/Artemis/Artemis/packages.config b/Artemis/Artemis/packages.config
index d4e1ed0f9..992429d67 100644
--- a/Artemis/Artemis/packages.config
+++ b/Artemis/Artemis/packages.config
@@ -1,14 +1,13 @@
-
-
-
+
+
-
-
+
+
-
+
@@ -17,18 +16,20 @@
-
+
-
-
+
+
+
-
-
+
+
-
+
+
\ No newline at end of file
diff --git a/Artemis/Artemis86Wrapper/Artemis86Wrapper.csproj b/Artemis/Artemis86Wrapper/Artemis86Wrapper.csproj
index e8bfd36d6..5f24107b8 100644
--- a/Artemis/Artemis86Wrapper/Artemis86Wrapper.csproj
+++ b/Artemis/Artemis86Wrapper/Artemis86Wrapper.csproj
@@ -49,9 +49,8 @@
4
-
- ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll
- True
+
+ ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll
diff --git a/Artemis/Artemis86Wrapper/packages.config b/Artemis/Artemis86Wrapper/packages.config
index 92824ba6e..e4ac9c6d7 100644
--- a/Artemis/Artemis86Wrapper/packages.config
+++ b/Artemis/Artemis86Wrapper/packages.config
@@ -1,5 +1,4 @@
-
-
+
\ No newline at end of file