mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Lots of WoW stuff
Added icons to audio and keypress layers Added text explaining audio and keypress layers
This commit is contained in:
parent
62ef77662e
commit
4b994ee061
@ -152,8 +152,8 @@
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="CUE.NET, Version=1.0.3.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\CUE.NET.1.0.3\lib\net45\CUE.NET.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\CUE.NET\bin\CUE.NET.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="DeltaCompressionDotNet, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1d14d6e5194e7f4a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\DeltaCompressionDotNet.1.0.0\lib\net45\DeltaCompressionDotNet.dll</HintPath>
|
||||
@ -246,6 +246,10 @@
|
||||
<HintPath>..\packages\squirrel.windows.1.4.4\lib\Net45\NuGet.Squirrel.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Process.NET, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Process.NET.1.0.1\lib\Process.NET.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Splat, Version=1.6.2.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Splat.1.6.2\lib\Net45\Splat.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
@ -331,6 +335,7 @@
|
||||
<Compile Include="DAL\SettingsProvider.cs" />
|
||||
<Compile Include="DeviceProviders\Corsair\CorsairMice.cs" />
|
||||
<Compile Include="DeviceProviders\Corsair\CorsairHeadsets.cs" />
|
||||
<Compile Include="DeviceProviders\Corsair\CorsairMousemats.cs" />
|
||||
<Compile Include="DeviceProviders\Corsair\Utilities\KeyMap.cs" />
|
||||
<Compile Include="DeviceProviders\DeviceProvider.cs" />
|
||||
<Compile Include="DeviceProviders\Logitech\G810.cs" />
|
||||
@ -363,7 +368,6 @@
|
||||
<Compile Include="Managers\ProfileManager.cs" />
|
||||
<Compile Include="Models\EffectModel.cs" />
|
||||
<Compile Include="Models\Interfaces\IDataModel.cs" />
|
||||
<Compile Include="Modules\Effects\AudioVisualizer\AudioVisualization.cs" />
|
||||
<Compile Include="Modules\Effects\Bubbles\Bubbles.cs" />
|
||||
<Compile Include="Modules\Effects\WindowsProfile\PerformanceInfo.cs" />
|
||||
<Compile Include="Modules\Games\EurotruckSimulator2\Data\Ets2TelemetryData.cs" />
|
||||
@ -385,11 +389,23 @@
|
||||
<DependentUpon>UnrealTournamentView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Modules\Games\UnrealTournament\UnrealTournamentViewModel.cs" />
|
||||
<Compile Include="Modules\Games\WorldofWarcraft\WoWDataModel.cs" />
|
||||
<Compile Include="Modules\Games\WorldofWarcraft\WoWModel.cs" />
|
||||
<Compile Include="Modules\Games\WorldofWarcraft\WoWSettings.cs" />
|
||||
<Compile Include="Modules\Games\WorldofWarcraft\WoWViewModel.cs" />
|
||||
<Compile Include="Modules\Games\WorldofWarcraft\WoWAddresses.cs" />
|
||||
<Compile Include="Modules\Games\WoW\Data\Int128.cs" />
|
||||
<Compile Include="Modules\Games\WoW\Data\WoWEnums.cs" />
|
||||
<Compile Include="Modules\Games\WoW\Data\WoWOffsets.cs" />
|
||||
<Compile Include="Modules\Games\WoW\Data\WoWStructs.cs" />
|
||||
<Compile Include="Modules\Games\WoW\Data\WoWNameCache.cs" />
|
||||
<Compile Include="Modules\Games\WoW\Data\WoWObjectManager.cs" />
|
||||
<Compile Include="Modules\Games\WoW\Data\WoWObject.cs" />
|
||||
<Compile Include="Modules\Games\WoW\Data\WoWPlayer.cs" />
|
||||
<Compile Include="Modules\Games\WoW\Data\WoWUnit.cs" />
|
||||
<Compile Include="Modules\Games\WoW\WoWView.xaml.cs">
|
||||
<DependentUpon>WoWView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Modules\Games\WoW\WoWDataModel.cs" />
|
||||
<Compile Include="Modules\Games\WoW\WoWModel.cs" />
|
||||
<Compile Include="Modules\Games\WoW\WoWSettings.cs" />
|
||||
<Compile Include="Modules\Games\WoW\WoWViewModel.cs" />
|
||||
<Compile Include="Modules\Games\WoW\WoWAddresses.cs" />
|
||||
<Compile Include="Profiles\Layers\Animations\NoneAnimation.cs" />
|
||||
<Compile Include="Profiles\Layers\Models\EventPropertiesModel.cs" />
|
||||
<Compile Include="Profiles\Layers\Models\KeyboardEventPropertiesModel.cs" />
|
||||
@ -410,10 +426,14 @@
|
||||
</Compile>
|
||||
<Compile Include="Profiles\Layers\Types\KeyPress\KeyPressPropertiesViewModel.cs" />
|
||||
<Compile Include="Profiles\Layers\Types\KeyPress\KeyPressType.cs" />
|
||||
<Compile Include="Profiles\Layers\Types\Mousemat\MousematPropertiesView.xaml.cs">
|
||||
<DependentUpon>MousematPropertiesView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Profiles\Layers\Types\Mousemat\MousematPropertiesViewModel.cs" />
|
||||
<Compile Include="Profiles\Layers\Types\Mousemat\MousematType.cs" />
|
||||
<Compile Include="Profiles\ProfileModel.cs" />
|
||||
<Compile Include="Profiles\Layers\Models\SimplePropertiesModel.cs" />
|
||||
<Compile Include="Profiles\Layers\Types\Keyboard\KeyboardPropertiesModel.cs" />
|
||||
<Compile Include="Modules\Effects\AudioVisualizer\AudioVisualizerModel.cs" />
|
||||
<Compile Include="Modules\Effects\AudioVisualizer\Utilities\FftEventArgs.cs" />
|
||||
<Compile Include="Modules\Effects\AudioVisualizer\Utilities\SampleAggregator.cs" />
|
||||
<Compile Include="Modules\Effects\Bubbles\Bubble.cs" />
|
||||
@ -632,6 +652,8 @@
|
||||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<None Include="Resources\keypress.png" />
|
||||
<None Include="Resources\mousemat.png" />
|
||||
<EmbeddedResource Include="Modules\Games\UnrealTournament\Resources\ut-plugin.zip" />
|
||||
<EmbeddedResource Include="Modules\Games\Witcher3\Resources\witcher3-mod.zip" />
|
||||
<None Include="app.manifest">
|
||||
@ -713,6 +735,10 @@
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Modules\Games\WoW\WoWView.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Profiles\Layers\Types\Audio\AudioPropertiesView.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
@ -725,6 +751,10 @@
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Profiles\Layers\Types\Mousemat\MousematPropertiesView.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Resources\Icons.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
@ -841,6 +871,7 @@
|
||||
<None Include="Modules\Games\UnrealTournament\Resources\redeemer.gif" />
|
||||
<None Include="Modules\Games\EurotruckSimulator2\Resources\Win32\ets2-telemetry-server.dll" />
|
||||
<None Include="Modules\Games\EurotruckSimulator2\Resources\Win64\ets2-telemetry-server.dll" />
|
||||
<None Include="Resources\audio.png" />
|
||||
<Content Include="Resources\CounterStrike\csgoGamestateConfiguration.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
104
Artemis/Artemis/DeviceProviders/Corsair/CorsairMousemats.cs
Normal file
104
Artemis/Artemis/DeviceProviders/Corsair/CorsairMousemats.cs
Normal file
@ -0,0 +1,104 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using CUE.NET;
|
||||
using CUE.NET.Devices.Generic.Enums;
|
||||
using CUE.NET.Devices.Mousemat.Enums;
|
||||
using Ninject.Extensions.Logging;
|
||||
|
||||
namespace Artemis.DeviceProviders.Corsair
|
||||
{
|
||||
internal class CorsairMousemats : DeviceProvider
|
||||
{
|
||||
public CorsairMousemats(ILogger logger)
|
||||
{
|
||||
Logger = logger;
|
||||
Type = DeviceType.Mousemat;
|
||||
}
|
||||
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
public override bool TryEnable()
|
||||
{
|
||||
CanUse = CanInitializeSdk();
|
||||
if (CanUse && !CueSDK.IsInitialized)
|
||||
CueSDK.Initialize();
|
||||
|
||||
Logger.Debug("Attempted to enable Corsair mousemat. CanUse: {0}", CanUse);
|
||||
|
||||
if (CanUse)
|
||||
CueSDK.MousematSDK.UpdateMode = UpdateMode.Manual;
|
||||
|
||||
return CanUse;
|
||||
}
|
||||
|
||||
public override void Disable()
|
||||
{
|
||||
throw new NotImplementedException("Can only disable a keyboard");
|
||||
}
|
||||
|
||||
public override void UpdateDevice(Bitmap bitmap)
|
||||
{
|
||||
if (!CanUse || bitmap == null)
|
||||
return;
|
||||
if (bitmap.Width != bitmap.Height)
|
||||
throw new ArgumentException("Bitmap must be a perfect square");
|
||||
|
||||
var yStep = (double) bitmap.Width/5;
|
||||
var xStep = (double) bitmap.Width/7;
|
||||
|
||||
// This approach will break if any mousemats with different LED amounts are released, for now it will do.
|
||||
using (bitmap)
|
||||
{
|
||||
var ledIndex = 1;
|
||||
// Color each LED according to one of the pixels
|
||||
foreach (var corsairLed in CueSDK.MousematSDK.Leds.OrderBy(l => l.ToString()))
|
||||
{
|
||||
Color col;
|
||||
// Left side
|
||||
if (ledIndex < 6)
|
||||
{
|
||||
col = ledIndex != 5
|
||||
? bitmap.GetPixel(0, (int) (ledIndex*yStep + yStep/2))
|
||||
: bitmap.GetPixel(0, (int) (ledIndex*yStep) - 1);
|
||||
}
|
||||
// Bottom
|
||||
else if (ledIndex < 11)
|
||||
{
|
||||
// Start at index 2 because the corner belongs to the left side
|
||||
var zoneIndex = ledIndex - 4;
|
||||
col = bitmap.GetPixel((int) (zoneIndex*xStep + xStep/2), 0);
|
||||
}
|
||||
// Right side
|
||||
else
|
||||
{
|
||||
var zoneIndex = ledIndex - 10;
|
||||
col = zoneIndex != 5
|
||||
? bitmap.GetPixel(0, bitmap.Height - ((int) (zoneIndex*yStep + yStep/2)))
|
||||
: bitmap.GetPixel(0, bitmap.Height - ((int) (zoneIndex*yStep) - 1));
|
||||
}
|
||||
|
||||
corsairLed.Color = col;
|
||||
ledIndex++;
|
||||
}
|
||||
}
|
||||
CueSDK.MousematSDK.Update();
|
||||
}
|
||||
|
||||
private static bool CanInitializeSdk()
|
||||
{
|
||||
// This will skip the check-loop if the SDK is initialized
|
||||
if (CueSDK.IsInitialized)
|
||||
return CueSDK.IsSDKAvailable(CorsairDeviceType.Mousemat);
|
||||
|
||||
for (var tries = 0; tries < 9; tries++)
|
||||
{
|
||||
if (CueSDK.IsSDKAvailable(CorsairDeviceType.Mousemat))
|
||||
return true;
|
||||
Thread.Sleep(2000);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -46,6 +46,7 @@ namespace Artemis.DeviceProviders
|
||||
Keyboard,
|
||||
Mouse,
|
||||
Headset,
|
||||
Generic
|
||||
Generic,
|
||||
Mousemat
|
||||
}
|
||||
}
|
||||
@ -22,6 +22,9 @@ namespace Artemis.InjectionModules
|
||||
// Headsets
|
||||
Bind<DeviceProvider>().To<CorsairHeadsets>().InSingletonScope();
|
||||
|
||||
// Mousemats
|
||||
Bind<DeviceProvider>().To<CorsairMousemats>().InSingletonScope();
|
||||
|
||||
// Other
|
||||
Bind<DeviceProvider>().To<LogitechGeneric>().InSingletonScope();
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ using Artemis.Profiles.Layers.Types.Keyboard;
|
||||
using Artemis.Profiles.Layers.Types.KeyboardGif;
|
||||
using Artemis.Profiles.Layers.Types.KeyPress;
|
||||
using Artemis.Profiles.Layers.Types.Mouse;
|
||||
using Artemis.Profiles.Layers.Types.Mousemat;
|
||||
using Ninject.Modules;
|
||||
|
||||
namespace Artemis.InjectionModules
|
||||
@ -36,6 +37,7 @@ namespace Artemis.InjectionModules
|
||||
Bind<ILayerType>().To<KeyboardType>();
|
||||
Bind<ILayerType>().To<KeyboardGifType>();
|
||||
Bind<ILayerType>().To<MouseType>();
|
||||
Bind<ILayerType>().To<MousematType>();
|
||||
Bind<ILayerType>().To<GenericType>();
|
||||
Bind<ILayerType>().To<KeyPressType>();
|
||||
Bind<ILayerType>().To<AudioType>();
|
||||
|
||||
@ -31,6 +31,7 @@ namespace Artemis.Managers
|
||||
MiceProviders = deviceProviders.Where(d => d.Type == DeviceType.Mouse).ToList();
|
||||
HeadsetProviders = deviceProviders.Where(d => d.Type == DeviceType.Headset).ToList();
|
||||
GenericProviders = deviceProviders.Where(d => d.Type == DeviceType.Generic).ToList();
|
||||
MousematProviders = deviceProviders.Where(d => d.Type == DeviceType.Mousemat).ToList();
|
||||
|
||||
_logger.Info("Intialized DeviceManager with {0} device providers", deviceProviders.Count);
|
||||
}
|
||||
@ -38,6 +39,7 @@ namespace Artemis.Managers
|
||||
public List<DeviceProvider> MiceProviders { get; set; }
|
||||
public List<DeviceProvider> HeadsetProviders { get; set; }
|
||||
public List<DeviceProvider> GenericProviders { get; set; }
|
||||
public List<DeviceProvider> MousematProviders { get; set; }
|
||||
|
||||
[Inject]
|
||||
public MetroDialogService DialogService { get; set; }
|
||||
@ -47,6 +49,8 @@ namespace Artemis.Managers
|
||||
public KeyboardProvider ActiveKeyboard { get; set; }
|
||||
|
||||
public bool ChangingKeyboard { get; private set; }
|
||||
|
||||
|
||||
public event EventHandler<KeyboardChangedEventArgs> OnKeyboardChangedEvent;
|
||||
|
||||
/// <summary>
|
||||
@ -137,6 +141,8 @@ namespace Artemis.Managers
|
||||
headsetProvider.TryEnableAsync();
|
||||
foreach (var genericProvider in GenericProviders)
|
||||
genericProvider.TryEnableAsync();
|
||||
foreach (var mousematProviders in MousematProviders)
|
||||
mousematProviders.TryEnableAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -132,18 +132,20 @@ namespace Artemis.Managers
|
||||
var mice = _deviceManager.MiceProviders.Where(m => m.CanUse).ToList();
|
||||
var headsets = _deviceManager.HeadsetProviders.Where(m => m.CanUse).ToList();
|
||||
var generics = _deviceManager.GenericProviders.Where(m => m.CanUse).ToList();
|
||||
var mousemats = _deviceManager.MousematProviders.Where(m => m.CanUse).ToList();
|
||||
var keyboardOnly = !mice.Any() && !headsets.Any() && !generics.Any() && !mousemats.Any();
|
||||
|
||||
// Setup the frame for this tick
|
||||
using (var frame = new RenderFrame(_deviceManager.ActiveKeyboard))
|
||||
{
|
||||
if (renderEffect.Initialized)
|
||||
renderEffect.Render(frame, !mice.Any() && !headsets.Any() && !generics.Any());
|
||||
renderEffect.Render(frame, keyboardOnly);
|
||||
|
||||
// Draw enabled overlays on top of the renderEffect
|
||||
foreach (var overlayModel in _effectManager.EnabledOverlays)
|
||||
{
|
||||
overlayModel.Update();
|
||||
overlayModel.RenderOverlay(frame, !mice.Any() && !headsets.Any() && !generics.Any());
|
||||
overlayModel.RenderOverlay(frame, keyboardOnly);
|
||||
}
|
||||
|
||||
// Update the keyboard
|
||||
@ -156,6 +158,8 @@ namespace Artemis.Managers
|
||||
headset.UpdateDevice(frame.HeadsetBitmap);
|
||||
foreach (var generic in generics)
|
||||
generic.UpdateDevice(frame.GenericBitmap);
|
||||
foreach (var mousemat in mousemats)
|
||||
mousemat.UpdateDevice(frame.MousematBitmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -177,6 +181,9 @@ namespace Artemis.Managers
|
||||
GenericBitmap = new Bitmap(40, 40);
|
||||
GenericBitmap.SetResolution(96, 96);
|
||||
|
||||
MousematBitmap = new Bitmap(40, 40);
|
||||
MousematBitmap.SetResolution(96, 96);
|
||||
|
||||
using (var g = Graphics.FromImage(KeyboardBitmap))
|
||||
g.Clear(Color.Black);
|
||||
using (var g = Graphics.FromImage(MouseBitmap))
|
||||
@ -185,12 +192,15 @@ namespace Artemis.Managers
|
||||
g.Clear(Color.Black);
|
||||
using (var g = Graphics.FromImage(GenericBitmap))
|
||||
g.Clear(Color.Black);
|
||||
using (var g = Graphics.FromImage(MousematBitmap))
|
||||
g.Clear(Color.Black);
|
||||
}
|
||||
|
||||
public Bitmap KeyboardBitmap { get; set; }
|
||||
public Bitmap MouseBitmap { get; set; }
|
||||
public Bitmap HeadsetBitmap { get; set; }
|
||||
public Bitmap GenericBitmap { get; set; }
|
||||
public Bitmap MousematBitmap { get; set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
@ -114,7 +114,7 @@ namespace Artemis.Managers
|
||||
if (!ProgramEnabled)
|
||||
return;
|
||||
|
||||
var runningProcesses = Process.GetProcesses();
|
||||
var runningProcesses = System.Diagnostics.Process.GetProcesses();
|
||||
|
||||
// If the currently active effect is a disabled game, get rid of it.
|
||||
if (EffectManager.ActiveEffect != null)
|
||||
|
||||
@ -88,6 +88,12 @@ namespace Artemis.Models
|
||||
Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Generic),
|
||||
DataModel, devRec, false, true);
|
||||
}
|
||||
// Render mousemats layer-by-layer
|
||||
using (var g = Graphics.FromImage(frame.MousematBitmap))
|
||||
{
|
||||
Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Mousemat),
|
||||
DataModel, devRec, false, true);
|
||||
}
|
||||
|
||||
// Trace debugging
|
||||
if (DateTime.Now.AddSeconds(-2) <= LastTrace)
|
||||
|
||||
@ -1,23 +0,0 @@
|
||||
using System.ComponentModel;
|
||||
using System.Configuration;
|
||||
|
||||
namespace Artemis.Modules.Effects.AudioVisualizer
|
||||
{
|
||||
// This class allows you to handle specific events on the settings class:
|
||||
// The SettingChanging event is raised before a setting's value is changed.
|
||||
// The PropertyChanged event is raised after a setting's value is changed.
|
||||
// The SettingsLoaded event is raised after the setting values are loaded.
|
||||
// The SettingsSaving event is raised before the setting values are saved.
|
||||
internal sealed partial class AudioVisualization
|
||||
{
|
||||
private void SettingChangingEventHandler(object sender, SettingChangingEventArgs e)
|
||||
{
|
||||
// Add code to handle the SettingChangingEvent event here.
|
||||
}
|
||||
|
||||
private void SettingsSavingEventHandler(object sender, CancelEventArgs e)
|
||||
{
|
||||
// Add code to handle the SettingsSaving event here.
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,206 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Linq;
|
||||
using Artemis.Managers;
|
||||
using Artemis.Models;
|
||||
using Artemis.Modules.Effects.AudioVisualizer.Utilities;
|
||||
using Artemis.Profiles.Layers.Models;
|
||||
using Artemis.Utilities;
|
||||
using Artemis.Utilities.Keyboard;
|
||||
using NAudio.CoreAudioApi;
|
||||
using NAudio.Wave;
|
||||
|
||||
namespace Artemis.Modules.Effects.AudioVisualizer
|
||||
{
|
||||
public class AudioVisualizerModel : EffectModel
|
||||
{
|
||||
private const int FftLength = 2048;
|
||||
private readonly SampleAggregator _sampleAggregator = new SampleAggregator(FftLength);
|
||||
private bool _fromBottom;
|
||||
private bool _generating;
|
||||
private int _sensitivity;
|
||||
private IWaveIn _waveIn;
|
||||
|
||||
public AudioVisualizerModel(MainManager mainManager) : base(mainManager, null, null)
|
||||
{
|
||||
Name = "Audiovisualizer";
|
||||
DeviceIds = new List<string>();
|
||||
SpectrumData = new List<byte>();
|
||||
Initialized = false;
|
||||
}
|
||||
|
||||
public int Lines { get; set; }
|
||||
|
||||
public List<byte> SpectrumData { get; set; }
|
||||
public List<KeyboardRectangle> SoundRectangles { get; set; }
|
||||
|
||||
public List<string> DeviceIds { get; set; }
|
||||
public string SelectedDeviceId { get; set; }
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
Initialized = false;
|
||||
_sampleAggregator.PerformFFT = false;
|
||||
_sampleAggregator.FftCalculated -= FftCalculated;
|
||||
|
||||
if (_waveIn == null)
|
||||
return;
|
||||
_waveIn.StopRecording();
|
||||
_waveIn.DataAvailable -= OnDataAvailable;
|
||||
_waveIn = null;
|
||||
}
|
||||
|
||||
public override void Enable()
|
||||
{
|
||||
Initialized = false;
|
||||
Lines = MainManager.DeviceManager.ActiveKeyboard.Width;
|
||||
|
||||
// TODO: Device selection
|
||||
SelectedDeviceId = new MMDeviceEnumerator()
|
||||
.EnumerateAudioEndPoints(DataFlow.All, DeviceState.Active)
|
||||
.FirstOrDefault()?.ID;
|
||||
|
||||
// Apply settings
|
||||
SoundRectangles = new List<KeyboardRectangle>();
|
||||
for (var i = 0; i < Lines; i++)
|
||||
{
|
||||
SoundRectangles.Add(new KeyboardRectangle(
|
||||
MainManager.DeviceManager.ActiveKeyboard,
|
||||
0, 0, new List<Color>
|
||||
{
|
||||
Color.Red,
|
||||
Color.Yellow,
|
||||
Color.Lime
|
||||
},
|
||||
LinearGradientMode.Vertical)
|
||||
{ContainedBrush = false, Height = 0});
|
||||
}
|
||||
_sensitivity = 2;
|
||||
_fromBottom = true;
|
||||
_sampleAggregator.FftCalculated += FftCalculated;
|
||||
_sampleAggregator.PerformFFT = true;
|
||||
|
||||
// Start listening for sound data
|
||||
_waveIn = new WasapiLoopbackCapture();
|
||||
_waveIn.DataAvailable += OnDataAvailable;
|
||||
_waveIn.StartRecording();
|
||||
|
||||
Initialized = true;
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
// TODO: Use lock instead of a bool
|
||||
// Start filling the model
|
||||
_generating = true;
|
||||
|
||||
if (SelectedDeviceId == null)
|
||||
return;
|
||||
|
||||
var device = new MMDeviceEnumerator()
|
||||
.EnumerateAudioEndPoints(DataFlow.All, DeviceState.Active)
|
||||
.FirstOrDefault(d => d.ID == SelectedDeviceId);
|
||||
|
||||
if (device == null || SpectrumData == null)
|
||||
return;
|
||||
if (!SpectrumData.Any())
|
||||
return;
|
||||
|
||||
// Parse spectrum data
|
||||
for (var i = 0; i < Lines; i++)
|
||||
{
|
||||
int height;
|
||||
if (SpectrumData.Count - 1 < i || SpectrumData[i] == 0)
|
||||
height = 0;
|
||||
else
|
||||
height = (int) Math.Round(SpectrumData[i]/2.55);
|
||||
|
||||
// Apply Sensitivity setting
|
||||
height = height*_sensitivity;
|
||||
var keyboardHeight =
|
||||
(int) Math.Round(MainManager.DeviceManager.ActiveKeyboard.Height/100.00*height*KeyboardScale);
|
||||
if (keyboardHeight > SoundRectangles[i].Height)
|
||||
SoundRectangles[i].Height = keyboardHeight;
|
||||
else
|
||||
SoundRectangles[i].Height = SoundRectangles[i].Height -
|
||||
5; // was FadeSpeed setting
|
||||
// Apply Bars setting
|
||||
SoundRectangles[i].X = i*KeyboardScale;
|
||||
SoundRectangles[i].Width = KeyboardScale;
|
||||
|
||||
if (_fromBottom)
|
||||
SoundRectangles[i].Y = MainManager.DeviceManager.ActiveKeyboard.Height*KeyboardScale -
|
||||
SoundRectangles[i].Height;
|
||||
}
|
||||
_generating = false;
|
||||
}
|
||||
|
||||
private void OnDataAvailable(object sender, WaveInEventArgs e)
|
||||
{
|
||||
var buffer = e.Buffer;
|
||||
var bytesRecorded = e.BytesRecorded;
|
||||
var bufferIncrement = _waveIn.WaveFormat.BlockAlign;
|
||||
|
||||
for (var index = 0; index < bytesRecorded; index += bufferIncrement)
|
||||
{
|
||||
var sample32 = BitConverter.ToSingle(buffer, index);
|
||||
_sampleAggregator.Add(sample32);
|
||||
}
|
||||
}
|
||||
|
||||
private void FftCalculated(object sender, FftEventArgs e)
|
||||
{
|
||||
if (_generating)
|
||||
return;
|
||||
|
||||
int x;
|
||||
var b0 = 0;
|
||||
|
||||
SpectrumData.Clear();
|
||||
for (x = 0; x < Lines; x++)
|
||||
{
|
||||
float peak = 0;
|
||||
var b1 = (int) Math.Pow(2, x*10.0/(Lines - 1));
|
||||
if (b1 > 2047)
|
||||
b1 = 2047;
|
||||
if (b1 <= b0)
|
||||
b1 = b0 + 1;
|
||||
for (; b0 < b1; b0++)
|
||||
{
|
||||
if (peak < e.Result[1 + b0].X)
|
||||
peak = e.Result[1 + b0].X;
|
||||
}
|
||||
var y = (int) (Math.Sqrt(peak)*3*255 - 4);
|
||||
if (y > 255)
|
||||
y = 255;
|
||||
if (y < 0)
|
||||
y = 0;
|
||||
SpectrumData.Add((byte) y);
|
||||
}
|
||||
}
|
||||
|
||||
public override List<LayerModel> GetRenderLayers(bool keyboardOnly)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override void Render(RenderFrame frame, bool keyboardOnly)
|
||||
{
|
||||
if (SpectrumData == null || SoundRectangles == null)
|
||||
return;
|
||||
|
||||
// Lock the _spectrumData array while busy with it
|
||||
_generating = true;
|
||||
|
||||
using (var g = Graphics.FromImage(frame.KeyboardBitmap))
|
||||
{
|
||||
foreach (var soundRectangle in SoundRectangles)
|
||||
soundRectangle.Draw(g);
|
||||
}
|
||||
|
||||
_generating = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3,110 +3,31 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
|
||||
xmlns:cal="http://www.caliburnproject.org"
|
||||
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="476.986" d:DesignWidth="538.772">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
|
||||
<Grid Margin="15, 5, 15, 5">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
|
||||
</Grid.RowDefinitions>
|
||||
<StackPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Margin="0,0,1,0">
|
||||
<Label FontSize="20" HorizontalAlignment="Left">
|
||||
<Label.Content>
|
||||
<AccessText TextWrapping="Wrap"
|
||||
Text="Visualizes the default audio device on the keyboard." />
|
||||
</Label.Content>
|
||||
</Label>
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<Label Content="Enable effect" Margin="0 3 0 0" HorizontalAlignment="Right" />
|
||||
<ToggleButton x:Name="EffectEnabled" Margin="0 3 0 0" Width="25" Height="25"
|
||||
Style="{DynamicResource MetroCircleToggleButtonStyle}"
|
||||
cal:Message.Attach="[Event Click] = [Action ToggleEffect]"
|
||||
ToolTip="Note: You can't enable an effect when Artemis is disabled" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
<!-- Top color -->
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center"
|
||||
Height="16" Margin="0,8">
|
||||
Color used on top
|
||||
</TextBlock>
|
||||
<xctk:ColorPicker x:Name="TopColor"
|
||||
SelectedColor="{Binding Path=EffectSettings.TopColor, Mode=TwoWay}"
|
||||
Grid.Row="1" Grid.Column="1" Width="110" HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center" Margin="0,5,-1,5" Height="22" />
|
||||
<Label Grid.Row="0" FontSize="20" MaxWidth="500" HorizontalAlignment="Left">
|
||||
<Label.Content>
|
||||
<AccessText TextWrapping="Wrap" Text="Gone!" />
|
||||
</Label.Content>
|
||||
</Label>
|
||||
|
||||
<!-- Middle color -->
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center"
|
||||
Height="16" Margin="0,8">
|
||||
Color used in the middle
|
||||
<TextBlock Grid.Row="1" VerticalAlignment="Center" Margin="0,8" TextWrapping="Wrap"
|
||||
HorizontalAlignment="Left" TextAlignment="Justify">
|
||||
<Run Text="In case you're wondering where these effects went, they are now part of the layer system." />
|
||||
<LineBreak />
|
||||
<Run Text="To use them, navigate to the Windows Profile effect and select one of these profiles:" />
|
||||
<LineBreak /><Run Text="• Default - Key waves" /><LineBreak />
|
||||
<Run Text="• Default - Audio visualization" /><LineBreak /><Run /><LineBreak />
|
||||
<Run Text="You can also add these effects to your own profile, even in games! " /><LineBreak />
|
||||
<Run
|
||||
Text="To do so, create a new layer, open up its property window and change the type according to what you want it to be, 'key press' or 'audio visualization'." />
|
||||
</TextBlock>
|
||||
<xctk:ColorPicker x:Name="MiddleColor"
|
||||
SelectedColor="{Binding Path=EffectSettings.MiddleColor, Mode=TwoWay}"
|
||||
Grid.Row="2" Grid.Column="1" Width="110" HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center" Margin="0,5,-1,5" Height="22" />
|
||||
|
||||
<!-- Bottom color -->
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center"
|
||||
Height="16" Margin="0,8">
|
||||
Color used on the bottom
|
||||
</TextBlock>
|
||||
<xctk:ColorPicker x:Name="Bottom"
|
||||
SelectedColor="{Binding Path=EffectSettings.BottomColor, Mode=TwoWay}"
|
||||
Grid.Row="3" Grid.Column="1" Width="110" HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center" Margin="0,5,-1,5" Height="22" />
|
||||
|
||||
<!-- Bar direction -->
|
||||
<TextBlock Grid.Row="4" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center"
|
||||
Height="16" Margin="0,9,0,10">
|
||||
Grow bars bottom
|
||||
</TextBlock>
|
||||
<controls:ToggleSwitch IsChecked="{Binding Path=EffectSettings.FromBottom, Mode=TwoWay}"
|
||||
Grid.Row="4" Grid.Column="1" HorizontalAlignment="Right" OnLabel="Yes"
|
||||
OffLabel="No" Margin="0,0,-5,0" Width="114" />
|
||||
|
||||
<!-- Sensitivity -->
|
||||
<TextBlock Grid.Row="5" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center"
|
||||
Height="16" Margin="0,8">
|
||||
Volume sensitivity multiplier
|
||||
</TextBlock>
|
||||
<Slider x:Name="Sensitivity" Grid.Row="5" Grid.Column="1" VerticalAlignment="Center"
|
||||
HorizontalAlignment="Right" Width="110" TickPlacement="BottomRight" TickFrequency="1"
|
||||
Value="{Binding Path=EffectSettings.Sensitivity, Mode=TwoWay}" Minimum="1" Maximum="10"
|
||||
SmallChange="1" IsSnapToTickEnabled="True" />
|
||||
|
||||
<!-- Fade speed -->
|
||||
<TextBlock Grid.Row="6" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center"
|
||||
Height="16" Margin="0,8">
|
||||
Bar fade-out speed
|
||||
</TextBlock>
|
||||
<Slider x:Name="FadeSpeed" Grid.Row="6" Grid.Column="1" VerticalAlignment="Center"
|
||||
HorizontalAlignment="Right" Width="110" TickPlacement="BottomRight" TickFrequency="1"
|
||||
Value="{Binding Path=EffectSettings.FadeSpeed, Mode=TwoWay}" Minimum="1" Maximum="3"
|
||||
SmallChange="1" IsSnapToTickEnabled="True" />
|
||||
|
||||
<!-- Buttons -->
|
||||
<StackPanel Grid.Column="0" Grid.Row="7" Orientation="Horizontal" VerticalAlignment="Bottom">
|
||||
<Button x:Name="ResetSettings" Content="Reset effect" VerticalAlignment="Top" Width="100"
|
||||
Style="{DynamicResource SquareButtonStyle}" />
|
||||
<Button x:Name="SaveSettings" Content="Save changes" VerticalAlignment="Top" Width="100"
|
||||
Margin="10,0,0,0"
|
||||
Style="{DynamicResource SquareButtonStyle}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
@ -1,13 +1,14 @@
|
||||
using Artemis.Managers;
|
||||
using Artemis.Modules.Effects.ProfilePreview;
|
||||
using Artemis.ViewModels.Abstract;
|
||||
|
||||
namespace Artemis.Modules.Effects.AudioVisualizer
|
||||
{
|
||||
public sealed class AudioVisualizerViewModel : EffectViewModel
|
||||
{
|
||||
public AudioVisualizerViewModel(MainManager main, AudioVisualizerModel model) : base(main, model)
|
||||
public AudioVisualizerViewModel(MainManager main, ProfilePreviewModel model) : base(main, model)
|
||||
{
|
||||
DisplayName = "Audio Visualization";
|
||||
DisplayName = "Audio Visualization / Key waves";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -79,6 +79,13 @@ namespace Artemis.Modules.Effects.ProfilePreview
|
||||
DataModel,
|
||||
devRec, true, true);
|
||||
}
|
||||
// Render mousemats layer-by-layer
|
||||
using (var g = Graphics.FromImage(frame.MousematBitmap))
|
||||
{
|
||||
Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Mousemat),
|
||||
DataModel,
|
||||
devRec, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,8 +74,7 @@ namespace Artemis.Modules.Games.Witcher3
|
||||
|
||||
archive.ExtractToDirectory(folder + @"witcher3-mod", true);
|
||||
|
||||
Process.Start(
|
||||
new ProcessStartInfo("https://github.com/SpoinkyNL/Artemis/wiki/The-Witcher-3"));
|
||||
System.Diagnostics.Process.Start(new ProcessStartInfo("https://github.com/SpoinkyNL/Artemis/wiki/The-Witcher-3"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
2256
Artemis/Artemis/Modules/Games/WoW/Data/Int128.cs
Normal file
2256
Artemis/Artemis/Modules/Games/WoW/Data/Int128.cs
Normal file
File diff suppressed because it is too large
Load Diff
157
Artemis/Artemis/Modules/Games/WoW/Data/WoWEnums.cs
Normal file
157
Artemis/Artemis/Modules/Games/WoW/Data/WoWEnums.cs
Normal file
@ -0,0 +1,157 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
63
Artemis/Artemis/Modules/Games/WoW/Data/WoWNameCache.cs
Normal file
63
Artemis/Artemis/Modules/Games/WoW/Data/WoWNameCache.cs
Normal file
@ -0,0 +1,63 @@
|
||||
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<IntPtr>(CurrentCacheAddress);
|
||||
var index = 0;
|
||||
while (current != IntPtr.Zero)
|
||||
{
|
||||
var guid = Process.Memory.Read<Guid>(current + 0x20);
|
||||
if (guid.Equals(searchGuid))
|
||||
{
|
||||
var pRace = Process.Memory.Read<int>(current + 0x88);
|
||||
var pClass = Process.Memory.Read<int>(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<IntPtr>(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; }
|
||||
}
|
||||
}
|
||||
73
Artemis/Artemis/Modules/Games/WoW/Data/WoWObject.cs
Normal file
73
Artemis/Artemis/Modules/Games/WoW/Data/WoWObject.cs
Normal file
@ -0,0 +1,73 @@
|
||||
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<Guid>(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<T>(int offset)
|
||||
{
|
||||
var address = GetAddress();
|
||||
if (address == IntPtr.Zero)
|
||||
return default(T);
|
||||
|
||||
var ptr = Process.Memory.Read<IntPtr>(address + 0x10);
|
||||
return Process.Memory.Read<T>(ptr + offset);
|
||||
}
|
||||
|
||||
public T ReadField<T>(Enum offset)
|
||||
{
|
||||
var address = GetAddress();
|
||||
if (address == IntPtr.Zero)
|
||||
return default(T);
|
||||
|
||||
var ptr = Process.Memory.Read<IntPtr>(address + 0x10);
|
||||
return Process.Memory.Read<T>(ptr + Convert.ToInt32(offset));
|
||||
}
|
||||
|
||||
private IntPtr GetAddress()
|
||||
{
|
||||
return _readPointer
|
||||
? Process.Memory.Read<IntPtr>(Process.Native.MainModule.BaseAddress + BaseAddress.ToInt32())
|
||||
: BaseAddress;
|
||||
}
|
||||
|
||||
public WoWDetails GetNpcDetails()
|
||||
{
|
||||
var address = GetAddress();
|
||||
if (address == IntPtr.Zero)
|
||||
return null;
|
||||
|
||||
var npcCachePtr = Process.Memory.Read<IntPtr>(address + 0x1760);
|
||||
if (npcCachePtr == IntPtr.Zero)
|
||||
return null;
|
||||
|
||||
var npcName = Process.Memory.Read(Process.Memory.Read<IntPtr>(npcCachePtr + 0x00A0), Encoding.ASCII, 48);
|
||||
return new WoWDetails(Guid, 0, 0, WoWEnums.WoWType.Npc, npcName);
|
||||
}
|
||||
}
|
||||
}
|
||||
92
Artemis/Artemis/Modules/Games/WoW/Data/WoWObjectManager.cs
Normal file
92
Artemis/Artemis/Modules/Games/WoW/Data/WoWObjectManager.cs
Normal file
@ -0,0 +1,92 @@
|
||||
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<WoWStructs.Guid, WoWObject> 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<WoWStructs.CurrentManager>(Process.Memory.Read<IntPtr>(CurrentManagerAddress));
|
||||
}
|
||||
|
||||
public IntPtr GetNextObjectFromCurrent(IntPtr current)
|
||||
{
|
||||
var mgr = GetCurrentManager();
|
||||
|
||||
return Process.Memory.Read<IntPtr>(
|
||||
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<Dictionary<WoWStructs.Guid, WoWObject>> ObjectsUpdated;
|
||||
|
||||
// Loop through the games object list.
|
||||
public IEnumerable<WoWObject> 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<int>(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<WoWStructs.Guid, WoWObject> e)
|
||||
{
|
||||
ObjectsUpdated?.Invoke(this, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
368
Artemis/Artemis/Modules/Games/WoW/Data/WoWOffsets.cs
Normal file
368
Artemis/Artemis/Modules/Games/WoW/Data/WoWOffsets.cs
Normal file
@ -0,0 +1,368 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
23
Artemis/Artemis/Modules/Games/WoW/Data/WoWPlayer.cs
Normal file
23
Artemis/Artemis/Modules/Games/WoW/Data/WoWPlayer.cs
Normal file
@ -0,0 +1,23 @@
|
||||
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<Guid>(Process.Native.MainModule.BaseAddress + _targetIntPtr.ToInt32());
|
||||
return manager.EnumVisibleObjects().FirstOrDefault(o => o.Guid == targetGuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
181
Artemis/Artemis/Modules/Games/WoW/Data/WoWStructs.cs
Normal file
181
Artemis/Artemis/Modules/Games/WoW/Data/WoWStructs.cs
Normal file
@ -0,0 +1,181 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
31
Artemis/Artemis/Modules/Games/WoW/Data/WoWUnit.cs
Normal file
31
Artemis/Artemis/Modules/Games/WoW/Data/WoWUnit.cs
Normal file
@ -0,0 +1,31 @@
|
||||
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<int>(UnitData.Health);
|
||||
public int MaxHealth => ReadField<int>(UnitData.MaxHealth);
|
||||
public int Power => ReadField<int>(UnitData.Power);
|
||||
public int SecondaryPower => ReadField<int>(UnitData.SecondaryPower);
|
||||
public int TertiaryPower => ReadField<int>(UnitData.TertiaryPower);
|
||||
public int MaxPower => ReadField<int>(UnitData.MaxPower);
|
||||
public PowerType PowerType => (PowerType) ReadField<int>(UnitData.DisplayPower);
|
||||
public int Level => ReadField<int>(UnitData.Level);
|
||||
|
||||
public WoWDetails Details { get; set; }
|
||||
|
||||
public void UpdateDetails(WoWNameCache nameCache)
|
||||
{
|
||||
Details = GetNpcDetails() ?? nameCache.GetNameByGuid(Guid);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
namespace Artemis.Modules.Games.WorldofWarcraft
|
||||
namespace Artemis.Modules.Games.WoW
|
||||
{
|
||||
public static class WoWAddresses
|
||||
{
|
||||
11
Artemis/Artemis/Modules/Games/WoW/WoWDataModel.cs
Normal file
11
Artemis/Artemis/Modules/Games/WoW/WoWDataModel.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using Artemis.Models.Interfaces;
|
||||
using Artemis.Modules.Games.WoW.Data;
|
||||
|
||||
namespace Artemis.Modules.Games.WoW
|
||||
{
|
||||
public class WoWDataModel : IDataModel
|
||||
{
|
||||
public WoWUnit Player { get; set; }
|
||||
public WoWUnit Target { get; set; }
|
||||
}
|
||||
}
|
||||
107
Artemis/Artemis/Modules/Games/WoW/WoWModel.cs
Normal file
107
Artemis/Artemis/Modules/Games/WoW/WoWModel.cs
Normal file
@ -0,0 +1,107 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Artemis.DAL;
|
||||
using Artemis.Managers;
|
||||
using Artemis.Models;
|
||||
using Artemis.Modules.Games.WoW.Data;
|
||||
using Artemis.Profiles.Layers.Models;
|
||||
using Artemis.Utilities.Memory;
|
||||
using Process.NET;
|
||||
|
||||
namespace Artemis.Modules.Games.WoW
|
||||
{
|
||||
public class WoWModel : GameModel
|
||||
{
|
||||
private readonly GamePointersCollection _pointer;
|
||||
private ProcessSharp _process;
|
||||
|
||||
public WoWModel(MainManager mainManager)
|
||||
: base(mainManager, SettingsProvider.Load<WoWSettings>(), new WoWDataModel())
|
||||
{
|
||||
Name = "WoW";
|
||||
ProcessName = "Wow-64";
|
||||
Scale = 4;
|
||||
Enabled = Settings.Enabled;
|
||||
Initialized = false;
|
||||
|
||||
// TODO: Retrieve from GitHub
|
||||
_pointer = new GamePointersCollection
|
||||
{
|
||||
Game = "WorldOfWarcraft",
|
||||
GameVersion = "7.0.3.22522",
|
||||
GameAddresses = new List<GamePointer>
|
||||
{
|
||||
new GamePointer
|
||||
{
|
||||
Description = "ObjectManager",
|
||||
BasePointer = new IntPtr(0x1575E10)
|
||||
},
|
||||
new GamePointer
|
||||
{
|
||||
Description = "LocalPlayer",
|
||||
BasePointer = new IntPtr(0x169BCB0)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public int Scale { get; set; }
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
Initialized = false;
|
||||
|
||||
_process.Dispose();
|
||||
_process = null;
|
||||
}
|
||||
|
||||
public override void Enable()
|
||||
{
|
||||
var tempProcess = MemoryHelpers.GetProcessIfRunning(ProcessName);
|
||||
if (tempProcess == null)
|
||||
return;
|
||||
|
||||
_process = new ProcessSharp(tempProcess);
|
||||
_process.Memory = new ExternalProcessMemory(_process.Handle);
|
||||
|
||||
Initialized = true;
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
if ((Profile == 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, new IntPtr(0x151BA88));
|
||||
var player = new WoWPlayer(_process,
|
||||
_pointer.GameAddresses.First(a => a.Description == "LocalPlayer").BasePointer, new IntPtr(0x179A6E0),
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
public override List<LayerModel> GetRenderLayers(bool keyboardOnly)
|
||||
{
|
||||
return Profile.GetRenderLayers(DataModel, keyboardOnly);
|
||||
}
|
||||
}
|
||||
}
|
||||
8
Artemis/Artemis/Modules/Games/WoW/WoWSettings.cs
Normal file
8
Artemis/Artemis/Modules/Games/WoW/WoWSettings.cs
Normal file
@ -0,0 +1,8 @@
|
||||
using Artemis.Settings;
|
||||
|
||||
namespace Artemis.Modules.Games.WoW
|
||||
{
|
||||
public class WoWSettings : GameSettings
|
||||
{
|
||||
}
|
||||
}
|
||||
56
Artemis/Artemis/Modules/Games/WoW/WoWView.xaml
Normal file
56
Artemis/Artemis/Modules/Games/WoW/WoWView.xaml
Normal file
@ -0,0 +1,56 @@
|
||||
<UserControl x:Class="Artemis.Modules.Games.WoW.WoWView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
|
||||
xmlns:cal="http://www.caliburnproject.org"
|
||||
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="476.986" d:DesignWidth="538.772">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
|
||||
<Grid Margin="15, 5, 15, 5">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
|
||||
</Grid.RowDefinitions>
|
||||
<StackPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Margin="0,0,1,0">
|
||||
<Label FontSize="20" HorizontalAlignment="Left">
|
||||
<Label.Content>
|
||||
<AccessText TextWrapping="Wrap"
|
||||
Text="For Azeroth" />
|
||||
</Label.Content>
|
||||
</Label>
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<Label Content="Enable effect" Margin="0 3 0 0" HorizontalAlignment="Right" />
|
||||
<ToggleButton x:Name="EffectEnabled" Margin="0 3 0 0" Width="25" Height="25"
|
||||
IsChecked="{Binding Path=GameSettings.Enabled, Mode=TwoWay}"
|
||||
Style="{DynamicResource MetroCircleToggleButtonStyle}"
|
||||
cal:Message.Attach="[Event Click] = [Action ToggleEffect]" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Profile editor -->
|
||||
<ContentControl Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" x:Name="ProfileEditor" Margin="0,0,-30,0" />
|
||||
|
||||
<!-- Buttons -->
|
||||
<StackPanel Grid.Column="0" Grid.Row="9" Orientation="Horizontal" VerticalAlignment="Bottom">
|
||||
<Button x:Name="ResetSettings" Content="Reset effect" VerticalAlignment="Top" Width="100"
|
||||
Style="{DynamicResource SquareButtonStyle}" />
|
||||
<Button x:Name="SaveSettings" Content="Save changes" VerticalAlignment="Top" Width="100"
|
||||
Margin="10,0,0,0"
|
||||
Style="{DynamicResource SquareButtonStyle}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
15
Artemis/Artemis/Modules/Games/WoW/WoWView.xaml.cs
Normal file
15
Artemis/Artemis/Modules/Games/WoW/WoWView.xaml.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Artemis.Modules.Games.WoW
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for WoWView.xaml
|
||||
/// </summary>
|
||||
public partial class WoWView : UserControl
|
||||
{
|
||||
public WoWView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
15
Artemis/Artemis/Modules/Games/WoW/WoWViewModel.cs
Normal file
15
Artemis/Artemis/Modules/Games/WoW/WoWViewModel.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using Artemis.InjectionFactories;
|
||||
using Artemis.Managers;
|
||||
using Artemis.ViewModels.Abstract;
|
||||
|
||||
namespace Artemis.Modules.Games.WoW
|
||||
{
|
||||
public sealed class WoWViewModel : GameViewModel
|
||||
{
|
||||
public WoWViewModel(MainManager main, IProfileEditorVmFactory pFactory, WoWModel model)
|
||||
: base(main, model, pFactory)
|
||||
{
|
||||
DisplayName = "WoW";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
using Artemis.Models.Interfaces;
|
||||
|
||||
namespace Artemis.Modules.Games.WorldofWarcraft
|
||||
{
|
||||
public class WoWDataModel : IDataModel
|
||||
{
|
||||
public Player Player { get; set; } = new Player();
|
||||
}
|
||||
|
||||
|
||||
public class Player
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public int Health { get; set; }
|
||||
public int MaxHealth { get; set; }
|
||||
}
|
||||
}
|
||||
@ -1,54 +0,0 @@
|
||||
//using System.Collections.Generic;
|
||||
//using Artemis.Managers;
|
||||
//using Artemis.Models;
|
||||
//using Artemis.Profiles.Layers.Models;
|
||||
//using Artemis.Utilities.Memory;
|
||||
//
|
||||
//namespace Artemis.Modules.Games.WorldofWarcraft
|
||||
//{
|
||||
// public class WoWModel : GameModel
|
||||
// {
|
||||
// private Memory _memory;
|
||||
//
|
||||
// public WoWModel(MainManager mainManager): base(mainManager, SettingsProvider.Load<WoWSettings>(), new WoWDataModel())
|
||||
// {
|
||||
// Name = "WoW";
|
||||
// ProcessName = "Wow-64";
|
||||
// Scale = 4;
|
||||
// Enabled = Settings.Enabled;
|
||||
// Initialized = false;
|
||||
// }
|
||||
//
|
||||
// public int Scale { get; set; }
|
||||
//
|
||||
// public override void Dispose()
|
||||
// {
|
||||
// Initialized = false;
|
||||
// }
|
||||
//
|
||||
// public override void Enable()
|
||||
// {
|
||||
// var tempProcess = MemoryHelpers.GetProcessIfRunning(ProcessName);
|
||||
// if (tempProcess == null)
|
||||
// return;
|
||||
//
|
||||
// _memory = new Memory(tempProcess);
|
||||
//
|
||||
// Initialized = true;
|
||||
// }
|
||||
//
|
||||
// public override void Update()
|
||||
// {
|
||||
// if (Profile == null || DataModel == null || _memory == null)
|
||||
// return;
|
||||
//
|
||||
//// _memory.ReadMemory();
|
||||
// }
|
||||
//
|
||||
// public override List<LayerModel> GetRenderLayers(bool keyboardOnly)
|
||||
// {
|
||||
// return Profile.GetRenderLayers(DataModel, keyboardOnly);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
using Artemis.Settings;
|
||||
|
||||
namespace Artemis.Modules.Games.WorldofWarcraft
|
||||
{
|
||||
public class WoWSettings : GameSettings
|
||||
{
|
||||
private WoWSettings()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
//using Artemis.InjectionFactories;
|
||||
//using Artemis.Managers;
|
||||
//using Artemis.ViewModels.Abstract;
|
||||
//
|
||||
//namespace Artemis.Modules.Games.WorldofWarcraft
|
||||
//{
|
||||
// public sealed class WoWViewModel : GameViewModel
|
||||
// {
|
||||
// public WoWViewModel(MainManager main, IProfileEditorVmFactory pFactory, WoWModel model): base(main, model, pFactory)
|
||||
// {
|
||||
// DisplayName = "WoW";
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
@ -70,6 +70,7 @@ namespace Artemis.Profiles.Layers.Interfaces
|
||||
Keyboard,
|
||||
Mouse,
|
||||
Headset,
|
||||
Generic
|
||||
Generic,
|
||||
Mousemat
|
||||
}
|
||||
}
|
||||
@ -3,7 +3,6 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using Artemis.Managers;
|
||||
using Artemis.Models.Interfaces;
|
||||
using Artemis.Modules.Effects.AudioVisualizer.Utilities;
|
||||
using Artemis.Profiles.Layers.Abstract;
|
||||
@ -28,10 +27,10 @@ namespace Artemis.Profiles.Layers.Types.Audio
|
||||
private int _lines;
|
||||
private AudioPropertiesModel _previousSettings;
|
||||
|
||||
public AudioType(MainManager mainManager)
|
||||
public AudioType()
|
||||
{
|
||||
_device =
|
||||
new MMDeviceEnumerator().EnumerateAudioEndPoints(DataFlow.All, DeviceState.Active).FirstOrDefault();
|
||||
_device = new MMDeviceEnumerator()
|
||||
.EnumerateAudioEndPoints(DataFlow.All, DeviceState.Active).FirstOrDefault();
|
||||
|
||||
_sampleAggregator.FftCalculated += FftCalculated;
|
||||
_sampleAggregator.PerformFFT = true;
|
||||
@ -55,7 +54,7 @@ namespace Artemis.Profiles.Layers.Types.Audio
|
||||
var visual = new DrawingVisual();
|
||||
using (var c = visual.RenderOpen())
|
||||
{
|
||||
c.DrawImage(ImageUtilities.BitmapToBitmapImage(Resources.gif), thumbnailRect);
|
||||
c.DrawImage(ImageUtilities.BitmapToBitmapImage(Resources.audio), thumbnailRect);
|
||||
}
|
||||
|
||||
var image = new DrawingImage(visual.Drawing);
|
||||
|
||||
@ -33,7 +33,7 @@
|
||||
<!-- Animation Speed -->
|
||||
<TextBlock Grid.Row="0" Grid.Column="2" Margin="10,13,10,10" FontSize="13.333" Text="Animation speed:"
|
||||
VerticalAlignment="Top" Height="18" />
|
||||
<Slider x:Name="RotationSpeed" Grid.Row="0" Grid.Column="3" VerticalAlignment="Top"
|
||||
<Slider x:Name="AnimationSpeed" Grid.Row="0" Grid.Column="3" VerticalAlignment="Top"
|
||||
TickPlacement="None" TickFrequency="0.05"
|
||||
Value="{Binding Path=LayerModel.Properties.AnimationSpeed, Mode=TwoWay}" Minimum="0.5" Maximum="5"
|
||||
SmallChange="0" IsSnapToTickEnabled="True" Margin="10,12,10,2" Height="24" />
|
||||
|
||||
@ -42,7 +42,7 @@ namespace Artemis.Profiles.Layers.Types.KeyPress
|
||||
var visual = new DrawingVisual();
|
||||
using (var c = visual.RenderOpen())
|
||||
{
|
||||
c.DrawImage(ImageUtilities.BitmapToBitmapImage(Resources.gif), thumbnailRect);
|
||||
c.DrawImage(ImageUtilities.BitmapToBitmapImage(Resources.keypress), thumbnailRect);
|
||||
}
|
||||
|
||||
var image = new DrawingImage(visual.Drawing);
|
||||
@ -87,7 +87,20 @@ namespace Artemis.Profiles.Layers.Types.KeyPress
|
||||
if (layerModel.Properties is KeyPressPropertiesModel)
|
||||
return;
|
||||
|
||||
layerModel.Properties = new KeyPressPropertiesModel(layerModel.Properties);
|
||||
// Setup brush as a radial
|
||||
layerModel.Properties = new KeyPressPropertiesModel(layerModel.Properties)
|
||||
{
|
||||
Brush = new RadialGradientBrush(new GradientStopCollection
|
||||
{
|
||||
new GradientStop(Colors.Red, 0.85),
|
||||
new GradientStop(Color.FromArgb(0, 255, 0, 0), 0.95),
|
||||
new GradientStop(Colors.Red, 0.55),
|
||||
new GradientStop(Color.FromArgb(0, 255, 0, 0), 0.45)
|
||||
})
|
||||
};
|
||||
// Setup defaults
|
||||
((KeyPressPropertiesModel) layerModel.Properties).AnimationSpeed = 2.5;
|
||||
((KeyPressPropertiesModel) layerModel.Properties).Scale = 8;
|
||||
}
|
||||
|
||||
public LayerPropertiesViewModel SetupViewModel(LayerEditorViewModel layerEditorViewModel,
|
||||
|
||||
@ -0,0 +1,68 @@
|
||||
<UserControl x:Class="Artemis.Profiles.Layers.Types.Mousemat.MousematPropertiesView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:ncore="http://schemas.ncore.com/wpf/xaml/colorbox"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="300" d:DesignWidth="300">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<!-- Animation -->
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Margin="10" FontSize="13.333" Text="Animation:"
|
||||
VerticalAlignment="Center"
|
||||
Height="18" />
|
||||
<ComboBox Grid.Row="0" Grid.Column="1" Margin="10,10,10,0" x:Name="LayerAnimations" VerticalAlignment="Top"
|
||||
Height="22">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Path=Name, Mode=OneWay}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<!-- Animation Speed -->
|
||||
<TextBlock Grid.Row="0" Grid.Column="2" Margin="10" FontSize="13.333" Text="Animation speed:"
|
||||
VerticalAlignment="Center" Height="18" />
|
||||
<Slider x:Name="RotationSpeed" Grid.Row="0" Grid.Column="3" VerticalAlignment="Center"
|
||||
TickPlacement="None" TickFrequency="0.05"
|
||||
Value="{Binding Path=LayerModel.Properties.AnimationSpeed, Mode=TwoWay}" Minimum="0.05" Maximum="3"
|
||||
SmallChange="0" IsSnapToTickEnabled="True" Margin="10,12,10,2" Height="24" />
|
||||
|
||||
<!-- Colors -->
|
||||
<StackPanel Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Orientation="Horizontal" x:Name="ShowBrush">
|
||||
<TextBlock Margin="10,13,10,0" FontSize="13.333" Text="Color(s):"
|
||||
VerticalAlignment="Top" Height="18" Width="130" />
|
||||
<Border Margin="10" BorderBrush="{StaticResource ControlBorderBrush}"
|
||||
BorderThickness="1" SnapsToDevicePixels="True" ToolTip="Click to edit">
|
||||
<ncore:ColorBox Brush="{Binding Path=Brush, Mode=TwoWay}" Height="24" Width="134" />
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Dynamic -->
|
||||
<Label Grid.Row="3" Grid.Column="0" FontSize="20" HorizontalAlignment="Left"
|
||||
Content="Dynamic" Width="97" VerticalAlignment="Bottom" />
|
||||
|
||||
<!-- Dynamic property views -->
|
||||
<ContentControl Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="4" x:Name="OpacityProperties" />
|
||||
|
||||
<!-- Note -->
|
||||
<TextBlock Grid.Row="5" Grid.Column="0" Grid.ColumnSpan="4" Margin="10,2,10,10" FontSize="13.333"
|
||||
Foreground="{DynamicResource HighlightBrush}"
|
||||
Text="Note: If your mousemat has multiple controllable LEDs you can create a gradient. Artemis will take the colors in the gradient and assign them to the LEDs"
|
||||
VerticalAlignment="Top" Height="Auto" TextWrapping="Wrap" />
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@ -0,0 +1,15 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Artemis.Profiles.Layers.Types.Mousemat
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for MousematPropertiesView.xaml
|
||||
/// </summary>
|
||||
public partial class MousematPropertiesView : UserControl
|
||||
{
|
||||
public MousematPropertiesView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
using System.Linq;
|
||||
using Artemis.Profiles.Layers.Abstract;
|
||||
using Artemis.Profiles.Layers.Interfaces;
|
||||
using Artemis.ViewModels.Profiles;
|
||||
using Caliburn.Micro;
|
||||
|
||||
namespace Artemis.Profiles.Layers.Types.Mousemat
|
||||
{
|
||||
public class MousematPropertiesViewModel : LayerPropertiesViewModel
|
||||
{
|
||||
private ILayerAnimation _selectedLayerAnimation;
|
||||
|
||||
public MousematPropertiesViewModel(LayerEditorViewModel editorVm) : base(editorVm)
|
||||
{
|
||||
LayerAnimations = new BindableCollection<ILayerAnimation>(editorVm.LayerAnimations);
|
||||
OpacityProperties = new LayerDynamicPropertiesViewModel("Opacity", editorVm);
|
||||
|
||||
SelectedLayerAnimation =
|
||||
LayerAnimations.FirstOrDefault(l => l.Name == editorVm.ProposedLayer.LayerAnimation?.Name) ??
|
||||
LayerAnimations.First(l => l.Name == "None");
|
||||
}
|
||||
|
||||
public BindableCollection<ILayerAnimation> LayerAnimations { get; set; }
|
||||
public LayerDynamicPropertiesViewModel OpacityProperties { get; set; }
|
||||
|
||||
public ILayerAnimation SelectedLayerAnimation
|
||||
{
|
||||
get { return _selectedLayerAnimation; }
|
||||
set
|
||||
{
|
||||
if (Equals(value, _selectedLayerAnimation)) return;
|
||||
_selectedLayerAnimation = value;
|
||||
NotifyOfPropertyChange(() => SelectedLayerAnimation);
|
||||
}
|
||||
}
|
||||
|
||||
public override void ApplyProperties()
|
||||
{
|
||||
OpacityProperties.Apply(LayerModel);
|
||||
LayerModel.Properties.Brush = Brush;
|
||||
LayerModel.LayerAnimation = SelectedLayerAnimation;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,95 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using Artemis.Models.Interfaces;
|
||||
using Artemis.Profiles.Layers.Abstract;
|
||||
using Artemis.Profiles.Layers.Animations;
|
||||
using Artemis.Profiles.Layers.Interfaces;
|
||||
using Artemis.Profiles.Layers.Models;
|
||||
using Artemis.Properties;
|
||||
using Artemis.Utilities;
|
||||
using Artemis.ViewModels.Profiles;
|
||||
|
||||
namespace Artemis.Profiles.Layers.Types.Mousemat
|
||||
{
|
||||
public class MousematType : ILayerType
|
||||
{
|
||||
public string Name { get; } = "Mousemat";
|
||||
public bool ShowInEdtor { get; } = false;
|
||||
public DrawType DrawType { get; } = DrawType.Mousemat;
|
||||
|
||||
public ImageSource DrawThumbnail(LayerModel layer)
|
||||
{
|
||||
var thumbnailRect = new Rect(0, 0, 18, 18);
|
||||
var visual = new DrawingVisual();
|
||||
using (var c = visual.RenderOpen())
|
||||
c.DrawImage(ImageUtilities.BitmapToBitmapImage(Resources.mousemat), thumbnailRect);
|
||||
|
||||
var image = new DrawingImage(visual.Drawing);
|
||||
return image;
|
||||
}
|
||||
|
||||
public void Draw(LayerModel layer, DrawingContext c)
|
||||
{
|
||||
// If an animation is present, let it handle the drawing
|
||||
if (layer.LayerAnimation != null && !(layer.LayerAnimation is NoneAnimation))
|
||||
{
|
||||
layer.LayerAnimation.Draw(layer.Properties, layer.AppliedProperties, c);
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise draw the rectangle with its applied dimensions and brush
|
||||
var rect = new Rect(layer.AppliedProperties.X*4,
|
||||
layer.AppliedProperties.Y*4,
|
||||
layer.AppliedProperties.Width*4,
|
||||
layer.AppliedProperties.Height*4);
|
||||
|
||||
c.PushClip(new RectangleGeometry(rect));
|
||||
c.DrawRectangle(layer.AppliedProperties.Brush, null, rect);
|
||||
c.Pop();
|
||||
}
|
||||
|
||||
public void Update(LayerModel layerModel, IDataModel dataModel, bool isPreview = false)
|
||||
{
|
||||
// Mousemat layers are always drawn 10*10 (which is 40*40 when scaled up)
|
||||
layerModel.Properties.Width = 10;
|
||||
layerModel.Properties.Height = 10;
|
||||
layerModel.Properties.X = 0;
|
||||
layerModel.Properties.Y = 0;
|
||||
layerModel.Properties.Contain = true;
|
||||
|
||||
layerModel.AppliedProperties = new SimplePropertiesModel(layerModel.Properties);
|
||||
|
||||
if (isPreview || dataModel == null)
|
||||
return;
|
||||
|
||||
// If not previewing, apply dynamic properties according to datamodel
|
||||
var props = (SimplePropertiesModel) layerModel.AppliedProperties;
|
||||
foreach (var dynamicProperty in props.DynamicProperties)
|
||||
dynamicProperty.ApplyProperty(dataModel, layerModel.AppliedProperties);
|
||||
}
|
||||
|
||||
public void SetupProperties(LayerModel layerModel)
|
||||
{
|
||||
if (layerModel.Properties is SimplePropertiesModel)
|
||||
return;
|
||||
|
||||
layerModel.Properties = new SimplePropertiesModel(layerModel.Properties);
|
||||
|
||||
// Remove height and width dynamic properties since they are not applicable
|
||||
layerModel.Properties.DynamicProperties.Remove(
|
||||
layerModel.Properties.DynamicProperties.FirstOrDefault(d => d.LayerProperty == "Height"));
|
||||
layerModel.Properties.DynamicProperties.Remove(
|
||||
layerModel.Properties.DynamicProperties.FirstOrDefault(d => d.LayerProperty == "Width"));
|
||||
}
|
||||
|
||||
public LayerPropertiesViewModel SetupViewModel(LayerEditorViewModel layerEditorViewModel,
|
||||
LayerPropertiesViewModel layerPropertiesViewModel)
|
||||
{
|
||||
if (layerPropertiesViewModel is MousematPropertiesViewModel)
|
||||
return layerPropertiesViewModel;
|
||||
return new MousematPropertiesViewModel(layerEditorViewModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -52,5 +52,5 @@ using System.Windows;
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
[assembly: AssemblyVersion("1.3.2.0")]
|
||||
[assembly: AssemblyFileVersion("1.3.2.0")]
|
||||
[assembly: AssemblyVersion("1.3.3.0")]
|
||||
[assembly: AssemblyFileVersion("1.3.3.0")]
|
||||
30
Artemis/Artemis/Properties/Resources.Designer.cs
generated
30
Artemis/Artemis/Properties/Resources.Designer.cs
generated
@ -60,6 +60,16 @@ namespace Artemis.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap audio {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("audio", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
@ -258,6 +268,16 @@ namespace Artemis.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap keypress {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("keypress", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
@ -298,6 +318,16 @@ namespace Artemis.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap mousemat {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("mousemat", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
|
||||
@ -199,4 +199,13 @@
|
||||
<data name="ets2_telemetry_server_x86" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Modules\Games\EurotruckSimulator2\Resources\Win32\ets2-telemetry-server.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="mousemat" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\mousemat.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="keypress" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\keypress.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="audio" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\audio.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
</root>
|
||||
BIN
Artemis/Artemis/Resources/audio.png
Normal file
BIN
Artemis/Artemis/Resources/audio.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
BIN
Artemis/Artemis/Resources/keypress.png
Normal file
BIN
Artemis/Artemis/Resources/keypress.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
BIN
Artemis/Artemis/Resources/mousemat.png
Normal file
BIN
Artemis/Artemis/Resources/mousemat.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.Win32;
|
||||
@ -76,9 +77,14 @@ namespace Artemis.Utilities
|
||||
if (friendlyName != Empty)
|
||||
list.Add(parent);
|
||||
|
||||
if (propertyInfo.PropertyType.Name != "String" && propertyInfo.PropertyType.Name != "DateTime")
|
||||
// Don't go into Strings, DateTimes or anything with JsonIgnore on it
|
||||
if (propertyInfo.PropertyType.Name != "String" &&
|
||||
propertyInfo.PropertyType.Name != "DateTime" &&
|
||||
propertyInfo.CustomAttributes.All(a => a.AttributeType != typeof(JsonIgnoreAttribute)))
|
||||
{
|
||||
list.AddRange(GenerateTypeMap(propertyInfo.PropertyType.GetProperties(),
|
||||
path + $"{propertyInfo.Name}."));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@ -212,7 +212,7 @@ namespace Artemis.ViewModels.Flyouts
|
||||
|
||||
public void NavigateTo(string url)
|
||||
{
|
||||
Process.Start(new ProcessStartInfo(url));
|
||||
System.Diagnostics.Process.Start(new ProcessStartInfo(url));
|
||||
}
|
||||
|
||||
protected override void HandleOpen()
|
||||
|
||||
@ -31,6 +31,7 @@ namespace Artemis.ViewModels.Profiles
|
||||
{
|
||||
Layer = layer;
|
||||
ProposedLayer = Clone(layer);
|
||||
ProposedLayer.Children.Clear();
|
||||
DataModel = DataModel;
|
||||
LayerTypes = new BindableCollection<ILayerType>(types);
|
||||
LayerAnimations = layerAnimations;
|
||||
@ -201,7 +202,7 @@ namespace Artemis.ViewModels.Profiles
|
||||
ProposedLayer.Properties.Conditions.Add(conditionViewModel.LayerConditionModel);
|
||||
|
||||
// If not a keyboard, ignore size and position
|
||||
if (ProposedLayer.LayerType.DrawType != DrawType.Keyboard)
|
||||
if (ProposedLayer.LayerType.DrawType != DrawType.Keyboard || !ProposedLayer.LayerType.ShowInEdtor)
|
||||
{
|
||||
ProposedLayer.Properties.Width = Layer.Properties.Width;
|
||||
ProposedLayer.Properties.Height = Layer.Properties.Height;
|
||||
@ -209,9 +210,9 @@ namespace Artemis.ViewModels.Profiles
|
||||
ProposedLayer.Properties.Y = Layer.Properties.Y;
|
||||
ProposedLayer.Properties.Contain = Layer.Properties.Contain;
|
||||
}
|
||||
|
||||
|
||||
// Ignore the children, can't just temporarily add them to the proposed layer because
|
||||
// that would upset the child layers' relations (sounds like an episode of Dr. Phil amirite?)
|
||||
// that would upset the child layers' relations (sounds like Dr. Phil amirite?)
|
||||
var currentObj = Clone(Layer);
|
||||
currentObj.Children.Clear();
|
||||
var current = JsonConvert.SerializeObject(currentObj, Formatting.Indented);
|
||||
|
||||
@ -7,29 +7,18 @@
|
||||
d:DesignHeight="476.986" d:DesignWidth="538.772">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
|
||||
<Grid Margin="15, 5, 15, 5">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
|
||||
</Grid.RowDefinitions>
|
||||
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" FontSize="20" MaxWidth="500"
|
||||
HorizontalAlignment="Left">
|
||||
<Label Grid.Row="0" FontSize="20" MaxWidth="500" HorizontalAlignment="Left">
|
||||
<Label.Content>
|
||||
<AccessText TextWrapping="Wrap" Text="Welcome to Artemis" />
|
||||
</Label.Content>
|
||||
</Label>
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" VerticalAlignment="Center" Margin="0,8"
|
||||
TextWrapping="Wrap" HorizontalAlignment="Left"
|
||||
MaxWidth="520" TextAlignment="Justify">
|
||||
<TextBlock Grid.Row="1" VerticalAlignment="Center" Margin="0,8" TextWrapping="Wrap"
|
||||
HorizontalAlignment="Left" MaxWidth="520" TextAlignment="Justify">
|
||||
Hello, <LineBreak /><LineBreak />
|
||||
Thanks a bunch for downloading this application. You're going to enjoy this! :)<LineBreak />
|
||||
<LineBreak />
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
<package id="Ninject.Extensions.Logging.nlog4" version="3.2.3.0" targetFramework="net452" />
|
||||
<package id="NLog" version="4.3.7" targetFramework="net461" />
|
||||
<package id="NLog.Schema" version="4.3.7" targetFramework="net461" />
|
||||
<package id="Process.NET" version="1.0.1" targetFramework="net461" />
|
||||
<package id="Splat" version="1.6.2" targetFramework="net461" />
|
||||
<package id="SpotifyAPI-NET" version="2.11.0" targetFramework="net461" />
|
||||
<package id="squirrel.windows" version="1.4.4" targetFramework="net461" />
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user