Jump to content

reapler

Elite user
  • Posts

    288
  • Joined

  • Last visited

Reputation Activity

  1. Like
    reapler got a reaction from anonymous123 in Plugins and Accept User Keyboard Input   
    I've looked into it, you need to run the hook on its own context via "Application.Run();" to get it working:
    using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Threading.Tasks; using System.Windows.Forms; using robotManager.Helpful; using wManager.Plugin; public class Main : IPlugin { public void Initialize() { KeyBoardHook.Initialize(); KeyBoardHook.OnKeyDown += KeyDown; } public void Dispose() { KeyBoardHook.OnKeyDown -= KeyDown; KeyBoardHook.Dispose(); } public void Settings() { } private static void KeyDown(object sender, KeyBoardHook.KeyArgs keyArgs) { Logging.Write(keyArgs.Key.ToString()); } public class KeyBoardHook { private const int WH_KEYBOARD_LL = 13; private const int WM_KEYDOWN = 0x0100; private const int WM_KEYUP = 0x101; private static readonly LowLevelKeyboardProc Proc = HookCallback; private static IntPtr _hookId = IntPtr.Zero; private static Keys _lastKeyDown = Keys.None; public delegate void KeyBoardHookEventHandler(object sender, KeyArgs e); public static event KeyBoardHookEventHandler OnKeyDown = delegate{}; public static event KeyBoardHookEventHandler OnKeyUp = delegate{}; internal static void Initialize() { Task.Factory.StartNew(() =>//avoid thread blocking from Application.Run(); { _hookId = SetHook(Proc); Application.Run(); //important! need to run in its own "context" }); } internal static void Dispose() { UnhookWindowsHookEx(_hookId); Application.Exit(); } private static IntPtr SetHook(LowLevelKeyboardProc proc) { using (var curProcess = Process.GetCurrentProcess()) using (var curModule = curProcess.MainModule) { return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0); } } private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam); private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) { if (nCode < 0) return CallNextHookEx(_hookId, nCode, wParam, lParam); if (wParam == (IntPtr) WM_KEYDOWN) { var vkCode = (Keys) Marshal.ReadInt32(lParam); if (_lastKeyDown == vkCode) return CallNextHookEx(_hookId, nCode, wParam, lParam); OnKeyDown(null, new KeyArgs(vkCode)); _lastKeyDown = vkCode; } else if (wParam == (IntPtr) WM_KEYUP) { var vkCode = (Keys) Marshal.ReadInt32(lParam); OnKeyUp(null, new KeyArgs(vkCode)); if (_lastKeyDown == vkCode) _lastKeyDown = Keys.None; } return CallNextHookEx(_hookId, nCode, wParam, lParam); } [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool UnhookWindowsHookEx(IntPtr hhk); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr GetModuleHandle(string lpModuleName); public class KeyArgs : EventArgs { public Keys Key { get; private set; } public KeyArgs(Keys key) { this.Key = key; } } } } So far it worked well.
  2. Like
    reapler got a reaction from Avvi in Plugins and Accept User Keyboard Input   
    I've looked into it, you need to run the hook on its own context via "Application.Run();" to get it working:
    using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Threading.Tasks; using System.Windows.Forms; using robotManager.Helpful; using wManager.Plugin; public class Main : IPlugin { public void Initialize() { KeyBoardHook.Initialize(); KeyBoardHook.OnKeyDown += KeyDown; } public void Dispose() { KeyBoardHook.OnKeyDown -= KeyDown; KeyBoardHook.Dispose(); } public void Settings() { } private static void KeyDown(object sender, KeyBoardHook.KeyArgs keyArgs) { Logging.Write(keyArgs.Key.ToString()); } public class KeyBoardHook { private const int WH_KEYBOARD_LL = 13; private const int WM_KEYDOWN = 0x0100; private const int WM_KEYUP = 0x101; private static readonly LowLevelKeyboardProc Proc = HookCallback; private static IntPtr _hookId = IntPtr.Zero; private static Keys _lastKeyDown = Keys.None; public delegate void KeyBoardHookEventHandler(object sender, KeyArgs e); public static event KeyBoardHookEventHandler OnKeyDown = delegate{}; public static event KeyBoardHookEventHandler OnKeyUp = delegate{}; internal static void Initialize() { Task.Factory.StartNew(() =>//avoid thread blocking from Application.Run(); { _hookId = SetHook(Proc); Application.Run(); //important! need to run in its own "context" }); } internal static void Dispose() { UnhookWindowsHookEx(_hookId); Application.Exit(); } private static IntPtr SetHook(LowLevelKeyboardProc proc) { using (var curProcess = Process.GetCurrentProcess()) using (var curModule = curProcess.MainModule) { return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0); } } private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam); private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) { if (nCode < 0) return CallNextHookEx(_hookId, nCode, wParam, lParam); if (wParam == (IntPtr) WM_KEYDOWN) { var vkCode = (Keys) Marshal.ReadInt32(lParam); if (_lastKeyDown == vkCode) return CallNextHookEx(_hookId, nCode, wParam, lParam); OnKeyDown(null, new KeyArgs(vkCode)); _lastKeyDown = vkCode; } else if (wParam == (IntPtr) WM_KEYUP) { var vkCode = (Keys) Marshal.ReadInt32(lParam); OnKeyUp(null, new KeyArgs(vkCode)); if (_lastKeyDown == vkCode) _lastKeyDown = Keys.None; } return CallNextHookEx(_hookId, nCode, wParam, lParam); } [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool UnhookWindowsHookEx(IntPtr hhk); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr GetModuleHandle(string lpModuleName); public class KeyArgs : EventArgs { public Keys Key { get; private set; } public KeyArgs(Keys key) { this.Key = key; } } } } So far it worked well.
  3. Like
    reapler reacted to Avvi in Avvi's C# Tips & Tricks with Helpful Code Snippets   
    Hi all,
    I figured I'd post some things that I have learned during my time of developing in C#. Perhaps some of this is obvious for some of the more experienced WRobot C# writers, but for me, I had to do a lot of forum searching and experimenting to make progress on any of my work. 
     
    How do I get started?
    Please see this post by @Droidz
     
     
    How can I see what Functions are available to me in the WRobot API?
    I recommend using some sort of decompiler in order to see what functions are available in the WRobot API. That is, use something such as dotPeek from jetbrains. See this URL: https://www.jetbrains.com/decompiler/ . Once you have this downloaded, open  the WRobot Binaries located in the (C:\WRobot\Bin) folder in dotPeek. I cannot even begin to explain how many times the recompiled helped me find useful things I could re-use. As a quick tip, I would suggest taking a look at the wManager.wManager.Wow.Helpers functions that are available. Anything listed as public static <variable type>  will be available to use from a Plugin/Profile/Fightclass etc.
     
    What if WRobot doesn't have an available function that I will need?
    WRobot doesn't have everything instantly available, so you may need to resort to using some Lua Functions to get information back from the WoW Client. An example of this that I ran into at some point was getting the number of Character Macros someone has.. Of course this is very specific, but please bear with me for the sake of this example :).
    WoW Lua Reference:  http://wowprogramming.com/docs/api_categories
    Using Lua in C#:
    This snippet will return a List of integers and set the C# variable numberOfMacros  equal to the returned list of the DoString function. To be more specific, it will provide a list of the number of Global account Macros , and the number of Personal Character Macros.
    var numberOfMacros = Lua.LuaDoString<List<int>>("return numCharacterMacros");  
    The below will return just the number Character Macros someone has.  If you need a specific variable from a Lua Function, then do the following: 
    var numPersonalMacros = Lua.LuaDoString<int>("local numAccountMacros, numCharacterMacros = GetNumMacros(); return numCharacterMacros"); The above snippet will set the C# variable numPersonalMacros equal to numCharacterMacros from the lua return value.
    Using a Variable in the Lua.LuaDoString.  The below will return the text body of the macro that has the id of 121.
    var _macroID = 121 string macroBody = Lua.LuaDoString<string>("return GetMacroBody(" + _macroID + ")");  
     
    Executing Lua Code in C#
    This  will leave the party (if the player is in one).
    wManager.Wow.Helpers.Lua.RunMacroText("/run LeaveParty()");  
    What is the difference between Lua.LuaDoString() and RunMacroText()? 
    The difference is in can be understand in how you think about them. Lua.LuaDoString should be seen as a way to retrieve information.. More specifically, the Lua.LuaDoString's purpose is to have a value returned to it, so that you can assign it to a C# Variable. RunMacroText can be used to do something in game. More specifically, RunMacroText should be used when trying to run some sort of in-game script (such as /cast spell).
     
    Plugin Template C#: Plugin-Template.cs
    I have attached a basic plugin template that can be used. In it, I have provided an example of:
    A Basic Implementation of the wManager.Plugin.IPlugin Class (including Settings/Initialize/Dispose) Basic loop that will occur while WRobot is running Settings that can be configured from Plugin Page A Category/Short Description for the Plugin Settings An example of Watching for Game Events. An example of OnRunState / OnAfterRunState for WRobot States Watching For Game Events
    Sometimes you may find that you need to wait for something to occur in game before you can take a specific action. In WoW / WRobot world, these things are called events. Below are two examples of events. The first event will occur when either the Group Loot Settings change, or a Player Enters/Joins the current Party.The second Event will occur when a System Message is received.  I recommend adding this watchForEvents Function in the Initialize function of a plugin, or somewhere where it will only be called once. For an example of this, please see my Plugin Template.
    private void watchForEvents() { EventsLuaWithArgs.OnEventsLuaWithArgs += (LuaEventsId id, List<string> args) => { if (id == wManager.Wow.Enums.LuaEventsId.PARTY_MEMBERS_CHANGED) { Logging.Write("Joined Group or something about the current group was changed."); } if (id == wManager.Wow.Enums.LuaEventsId.CHAT_MSG_SYSTEM) { Logging.Write("We Received a System Message."); } }; }  
    Finding the list of available Game Events:
    Each version of the game is different here, so this is where you will need to be careful. By that I mean, some versions of the game may have an event type, but a different version may not. Blizzard was not always consistent in their name accross different versions of the game, so please be careful to test against multiple versions of the game. 
     Open DotPeek  Search for "LuaEventsID" Double Click LuaEventsId in the Assembly Explorer Window. A window will open displaying a list of Events. What do each of these Events mean?
    WoW Event Reference:  http://wowwiki.wikia.com/wiki/Event_API 
    (Reminder! Some of these may be different in different versions of the game.)
     
    Watching For WRobot State Changes
    In addition to in game events, there are also WRobot 'states'. Similar to Game Events, WRobot states are the particular condition that WRobot is in at a specific time. For example, there is a state called 'MillingState', and another called 'Looting' that come out with WRobot. States are managed by the WRobot FiniteStateMachineEvents Engine. When a State occurs/changes/ends/etc, an event is passed to the FiniteStateMachine (pardon my wording here if this is not 100% correct). There are three main events that we can use to manage our States.
    State Events that occur:
    OnBeforeCheckIfNeedToRunState - This can be used to CANCEL an event if specific conditions are met. OnRunState - This can be used to do something just as the State is being started. OnAfterRunState - This can be used to do something just as the State has completed.  
    Example of OnRunState and OnAfterRunState
    In this example we are watching for when WRobot starts the ToTown State and when it finishes it. We create a boolean that is set to true when the state is started, and then set it to false when the State is completed. I recommend adding the initializeToTownWatcher() function in the Initialize function of a plugin, or somewhere where it will only be called once. For example of this, please see my Plugin Template.
    bool goToTown = false; private void initializeToTownWatcher() { robotManager.Events.FiniteStateMachineEvents.OnRunState += (engine, state, cancelable) => { if (state != null && state.DisplayName == "To Town") { goToTown = true; Logging.Write("Going to Town State has been initiated."); } }; robotManager.Events.FiniteStateMachineEvents.OnAfterRunState += (engine, state) => { if (state != null && state.DisplayName == "To Town") { goToTown = false; Logging.Write("We have completed going To Town State."); } }; } Example of OnBeforeCheckIfNeedToRunState
    In this example, we catch the state with the name of To Town and cancel it by setting the passed in cancelable parameter to true.
    private void cancelToTownState() { robotManager.Events.FiniteStateMachineEvents.OnBeforeCheckIfNeedToRunState += (engine, state, cancelable) => { if (state != null && state.DisplayName == "To Town") { Logging.Write("We have cancelled the To Town State"); cancelable.Cancel = true; } }; } Where can I find other WRobot States?
    Each version of the WRobot is different, so some versions of WRobot may have a state type, but a different version may not. Please be careful to test against multiple versions of the game/WRobot. 
    Open DotPeek Expand wManager Module Expand wManager.Wow.Bot.States namespace.  
     
    MORE TBA....
    The above is my attempt at trying to help newcomers to WRobot at writing their own plugins / fight classes / etc. If there are any questions , suggestions, or even  corrections, please do let me know in the comments and I'll be sure to add/update things as they come up!
     
    Thanks,
    - Avvi 
     
  4. Like
    reapler got a reaction from Avvi in Plugins and Accept User Keyboard Input   
    Hello, you may decompile my plugin which uses keyboardhook & gui: https://wrobot.eu/files/file/1213-aoebutton/
    I hope it's self-explaining, since it's quite old and can't remember anything ;)
     
  5. Like
    reapler got a reaction from sowelu in Radar3D How to use it?   
    Hello, you can subscribe your method to the event on initialize and unsubscribe on dispose:
    public void Initialize() { Radar3D.Pulse(); Radar3D.OnDrawEvent += Radar3DOnDrawEvent; } public void Dispose() { Radar3D.OnDrawEvent -= Radar3DOnDrawEvent; Radar3D.Stop(); } private static void Radar3DOnDrawEvent() { if (ObjectManager.Target.IsValid) Radar3D.DrawLine(ObjectManager.Me.Position, ObjectManager.Target.Position, Color.Chocolate); Radar3D.DrawCircle(ObjectManager.Me.Position, 5, Color.Chocolate); }  
  6. Like
    reapler got a reaction from Matenia in Radar3D How to use it?   
    Hello, you can subscribe your method to the event on initialize and unsubscribe on dispose:
    public void Initialize() { Radar3D.Pulse(); Radar3D.OnDrawEvent += Radar3DOnDrawEvent; } public void Dispose() { Radar3D.OnDrawEvent -= Radar3DOnDrawEvent; Radar3D.Stop(); } private static void Radar3DOnDrawEvent() { if (ObjectManager.Target.IsValid) Radar3D.DrawLine(ObjectManager.Me.Position, ObjectManager.Target.Position, Color.Chocolate); Radar3D.DrawCircle(ObjectManager.Me.Position, 5, Color.Chocolate); }  
  7. Thanks
    reapler got a reaction from sowelu in How to get angle or rotation info?   
    This should finally do the desired work while the other method was just for calculating :)
    /// <summary> /// Used to get the facing from two positions based on the origin rotation. /// </summary> /// <param name="from">The 1. position.</param> /// <param name="to">The 2. position.</param> /// <param name="originRotation">The origin rotation.</param> /// <returns>Negative radian on the right; positive on the left.</returns> public float FacingCenter(Vector3 from, Vector3 to, float originRotation) { var face = NormalizeRadian(Atan2Rotation(from, to) - originRotation); if (face < System.Math.PI) return -face; return NormalizeRadian(originRotation-Atan2Rotation(from, to)); } /// <summary> /// Used to normalize the input radian. /// </summary> /// <param name="radian">The radians to normalize.</param> public float NormalizeRadian(float radian) { if (radian < 0.0) return (float) (-(- radian % (2.0 * System.Math.PI)) + 2.0 * System.Math.PI); return radian % 6.283185f; } /// <summary> /// Used to calculate atan2 of to positions. /// </summary> /// <param name="from">The 1. position.</param> /// <param name="to">The 2. position.</param> /// <param name="addRadian">Radians to add.</param> /// <returns></returns> public float Atan2Rotation(Vector3 from, Vector3 to, float addRadian = 0) { return (float) System.Math.Atan2(to.Y - from.Y, to.X - from.X) + addRadian; }  
    Usage:
    var rot = FacingCenter(ObjectManager.Me.Position, ObjectManager.Target.Position, ObjectManager.Me.Rotation); if (rot < 0) Logging.Write("Facing to right: "+rot); Logging.Write("Facing to left: "+rot);  
  8. Like
    reapler got a reaction from Matenia in How to get angle or rotation info?   
    This should finally do the desired work while the other method was just for calculating :)
    /// <summary> /// Used to get the facing from two positions based on the origin rotation. /// </summary> /// <param name="from">The 1. position.</param> /// <param name="to">The 2. position.</param> /// <param name="originRotation">The origin rotation.</param> /// <returns>Negative radian on the right; positive on the left.</returns> public float FacingCenter(Vector3 from, Vector3 to, float originRotation) { var face = NormalizeRadian(Atan2Rotation(from, to) - originRotation); if (face < System.Math.PI) return -face; return NormalizeRadian(originRotation-Atan2Rotation(from, to)); } /// <summary> /// Used to normalize the input radian. /// </summary> /// <param name="radian">The radians to normalize.</param> public float NormalizeRadian(float radian) { if (radian < 0.0) return (float) (-(- radian % (2.0 * System.Math.PI)) + 2.0 * System.Math.PI); return radian % 6.283185f; } /// <summary> /// Used to calculate atan2 of to positions. /// </summary> /// <param name="from">The 1. position.</param> /// <param name="to">The 2. position.</param> /// <param name="addRadian">Radians to add.</param> /// <returns></returns> public float Atan2Rotation(Vector3 from, Vector3 to, float addRadian = 0) { return (float) System.Math.Atan2(to.Y - from.Y, to.X - from.X) + addRadian; }  
    Usage:
    var rot = FacingCenter(ObjectManager.Me.Position, ObjectManager.Target.Position, ObjectManager.Me.Rotation); if (rot < 0) Logging.Write("Facing to right: "+rot); Logging.Write("Facing to left: "+rot);  
  9. Like
    reapler got a reaction from Matenia in How to get angle or rotation info?   
    Hello, this should work:
    private static double ActualRotation(double value, double min, double max) { if (value < min) return min; return value > max ? max : value; } public static double CalculateFacingCenter(Vector3 source, float playerRotation, Vector3 destination) { Vector3 v2 = destination - source; v2.Z = 0.0f; Vector3 v1 = new Vector3((float) Math.Cos(playerRotation), (float) Math.Sin(playerRotation), 0.0f); return Math.Acos(ActualRotation(Vector3.Dot(ref v1, ref v2) / (v2.Magnitude() * (double) v1.Magnitude()), -1.0, 1.0)); } And additional snippets which could help you:
    /// <summary> /// Used to calculate new position by parameter. /// </summary> /// <param name="from">The position to calculate from.</param> /// <param name="rotation">The rotation of the object in radians.</param> /// <param name="radius">The radius to add.</param> /// <returns></returns> public Vector3 CalculatePosition(Vector3 from, float rotation, float radius) { return new Vector3(System.Math.Sin(rotation) * radius + from.X, System.Math.Cos(rotation) * radius + from.Y, from.Z); } /// <summary> /// Used to calculate atan2 of to positions. /// </summary> /// <param name="from">Position 1.</param> /// <param name="to">Position 2.</param> /// <param name="addRadian">Radians to add.</param> /// <returns></returns> public float Atan2Rotation(Vector3 from, Vector3 to, float addRadian = 0) { return (float) System.Math.Atan2(to.Y - from.Y, to.X - from.X) + addRadian; } /// <summary> /// Used to face to the desired position. /// </summary> /// <param name="to">The position to face.</param> /// <param name="addRadian">Radians to add from the position.</param> public static void Face(Vector3 to, float addRadian = 0) { wManager.Wow.Helpers.ClickToMove.CGPlayer_C__ClickToMove(0, 0, 0, wManager.Wow.ObjectManager.ObjectManager.Me.Guid, 2, (float)System.Math.Atan2(to.Y - wManager.Wow.ObjectManager.ObjectManager.Me.Position.Y, to.X - wManager.Wow.ObjectManager.ObjectManager.Me.Position.X)+addRadian); } Usage for second block(i guess first one should be understandable)
    //turn 180° Face(ObjectManager.Target.Position, (float)System.Math.PI); //turn left Face(ObjectManager.Target.Position, 1.53589f);//88° = 1.53589 rad //turn right Face(ObjectManager.Target.Position, -1.53589f);//88° = 1.53589 rad  
  10. Like
    reapler got a reaction from arkhan in How to get angle or rotation info?   
    Hello, this should work:
    private static double ActualRotation(double value, double min, double max) { if (value < min) return min; return value > max ? max : value; } public static double CalculateFacingCenter(Vector3 source, float playerRotation, Vector3 destination) { Vector3 v2 = destination - source; v2.Z = 0.0f; Vector3 v1 = new Vector3((float) Math.Cos(playerRotation), (float) Math.Sin(playerRotation), 0.0f); return Math.Acos(ActualRotation(Vector3.Dot(ref v1, ref v2) / (v2.Magnitude() * (double) v1.Magnitude()), -1.0, 1.0)); } And additional snippets which could help you:
    /// <summary> /// Used to calculate new position by parameter. /// </summary> /// <param name="from">The position to calculate from.</param> /// <param name="rotation">The rotation of the object in radians.</param> /// <param name="radius">The radius to add.</param> /// <returns></returns> public Vector3 CalculatePosition(Vector3 from, float rotation, float radius) { return new Vector3(System.Math.Sin(rotation) * radius + from.X, System.Math.Cos(rotation) * radius + from.Y, from.Z); } /// <summary> /// Used to calculate atan2 of to positions. /// </summary> /// <param name="from">Position 1.</param> /// <param name="to">Position 2.</param> /// <param name="addRadian">Radians to add.</param> /// <returns></returns> public float Atan2Rotation(Vector3 from, Vector3 to, float addRadian = 0) { return (float) System.Math.Atan2(to.Y - from.Y, to.X - from.X) + addRadian; } /// <summary> /// Used to face to the desired position. /// </summary> /// <param name="to">The position to face.</param> /// <param name="addRadian">Radians to add from the position.</param> public static void Face(Vector3 to, float addRadian = 0) { wManager.Wow.Helpers.ClickToMove.CGPlayer_C__ClickToMove(0, 0, 0, wManager.Wow.ObjectManager.ObjectManager.Me.Guid, 2, (float)System.Math.Atan2(to.Y - wManager.Wow.ObjectManager.ObjectManager.Me.Position.Y, to.X - wManager.Wow.ObjectManager.ObjectManager.Me.Position.X)+addRadian); } Usage for second block(i guess first one should be understandable)
    //turn 180° Face(ObjectManager.Target.Position, (float)System.Math.PI); //turn left Face(ObjectManager.Target.Position, 1.53589f);//88° = 1.53589 rad //turn right Face(ObjectManager.Target.Position, -1.53589f);//88° = 1.53589 rad  
  11. Thanks
    reapler got a reaction from Findeh in Trinket Cooldown Time Left   
    Hello,  this might help you:
    /// <summary> /// Used to get the cooldown of an inventory item. /// </summary> /// <param name="slotId">The slot to get from.</param> /// <returns>The left cooldown of the item.</returns> public int GetInventoryCooldown(WoWInventorySlot slotId) { return Lua.LuaDoString<int>( @" local start, duration, enable = GetInventoryItemCooldown(""player"", "+(int)slotId+@") local coolDown = duration-(GetTime()-start); if (coolDown < 0) then return 0; end return coolDown; "); }  
    Usage:
    Logging.Write("Cooldown of Trinket1: "+GetInventoryCooldown(WoWInventorySlot.Trinket1));  
  12. Thanks
    reapler got a reaction from Findeh in Alot of questions about FightClass and API   
    @Findeh
    private bool CanBleed(WoWUnit unit) { return unit.CreatureTypeTarget != "Elemental" && unit.CreatureTypeTarget != "Mechanical"; } Usage:
    if (CanBleed(ObjectManager.Me.TargetObject)) { new Spell("Rend").Launch(); }  
  13. Thanks
    reapler got a reaction from Findeh in Alot of questions about FightClass and API   
    @apexx Namespace System.Linq is not referenced. So you need to copy this on the top of your code:
    using System.Linq; Both .Where() & .Count() are included in Linq, that's the reason why .Count() couldn't work because it doesn't had an overload available.
    So in the end you can use this:
    if (ObjectManager.GetUnitAttackPlayer().Count(u => u.GetDistance <= 6) > 2) { } Or use other Linq methods.
  14. Thanks
    reapler got a reaction from Findeh in Alot of questions about FightClass and API   
    Yes, that's right but with my snippet you get a string from your spell with lua in this case: "Shadow Word: Pain".
     
    I made a simple method:
    public Spell Spell_(string name) => new Spell(name) { Icon = Lua.LuaDoString<string>( "name, rank, icon, castTime, minRange, maxRange = GetSpellInfo(\"" + name + "\")", "rank") }; This overrides "Icon" to spell's rank. I guess it's not added in vanilla, because it was forgotten as it was backported :)
     
    Usage:
    public void Initialize() { wManager.Wow.Class.Spell eviscerate = Spell_("Eviscerate"); robotManager.Helpful.Logging.Write("Get information of spell: " + eviscerate.Name); robotManager.Helpful.Logging.Write("Spell rank: "+eviscerate.Icon);//now field ".Icon" returns the rank if you use "public Spell Spell_(string name) => new Spell(name)" robotManager.Helpful.Logging.Write("Spell id: "+eviscerate.Id); }  
  15. Thanks
    reapler got a reaction from Findeh in Alot of questions about FightClass and API   
    Welcome @Findeh to WRobot, you can find details & templates about fightclasses here.
    To get a detailed documentation, you can decompile WRobot's libraries here explained.
     
    For this task you could use "wManager.Events.FightEvents.OnFightEnd"
    A plugin already exists here
    "wManager.Wow.ObjectManager.ObjectManager.Me.TargetObject.Health" for futures requests you may search in your decompiler by looking for "health" for example
    Unfortunately no event exists. But you can check it on a loop: "wManager.Wow.Bot.States.ToTown.GoToTownInProgress"
     
  16. Thanks
    reapler got a reaction from Suspect in Difference between RunMacroLua and Ingame Chat?   
    Hello, you can try the following examples to either run a macro or using "Keyboard" class to press a button:
     
    Run wow macro(only work on tbc and above): open worldmap by click.xml
    Press button for 2 seconds: move forward by keyboard button press.xml  Available keys to press: https://msdn.microsoft.com/en-us/library/system.windows.forms.keys(v=vs.71).aspx
     
  17. Like
    reapler got a reaction from sowelu in How to get id or name of item from bagslot   
    Yes, it's also possible. You need to change ""local _, stackCount = GetContainerItemInfo(b, s)\t" +" with GetItemInfo, add your conditions and return a list with a struct of the bag position & its slot.
     
    The struct:
    public struct BagInfo { public int Bag; public int Slot; public BagInfo(int bag, int slot) { Bag = bag; Slot = slot; } public override string ToString() { return "Bag = " + Bag + " ; Slot = " + Slot; } }  
    The disenchant list:
    /// <summary> /// Used to get a list of all disenchantable items as bag and slot position. /// </summary> /// <param name="maxItemLevel">The maximum item level.</param> /// <param name="interactions">The amount of interactions.</param> /// <returns></returns> public static List<BagInfo> DisenchantList(int maxItemLevel = int.MaxValue, int interactions = int.MaxValue)//parameter list can be extended { var execute = "local counter = 0; " + "local leftStacks = 0; " + "local bs = {}" + "for b=0,4 do " + "if GetBagName(b) then " + "for s=1, GetContainerNumSlots(b) do " + "local itemLink = GetContainerItemLink(b, s) " + "if itemLink then " + "local itemName, itemLink, itemRarity, itemLevel, itemMinLevel, itemType, itemSubType, itemStackCount, itemEquipLoc, itemTexture, itemSellPrice = GetItemInfo(itemLink) \t" + "if itemRarity > 1 and itemRarity < 5 " + "and itemLevel <= " + maxItemLevel + " " + "and (itemType == 'Armor' or itemType == 'Weapon') "; execute = execute + "then " + "if (counter < "+interactions+") then " + "table.insert(bs, b); " + "table.insert(bs, s); " + "counter = counter + 1; " + "else " + "leftStacks = leftStacks + 1;" + "end " + "\tend\tend\tend end end return unpack(bs);"; var bs = Lua.LuaDoString<List<int>>(execute); var list = new List<BagInfo>(); for (var i = 0; i < bs.Count; i += 2) { list.Add(new BagInfo(bs[i], bs[i+1])); } return list; }  
    The final method to execute:
    /// <summary> /// Disenchant all items depend on the itemLevel. /// </summary> /// <param name="maxItemLevel">The maximum item level.</param> /// <remarks>AutoLoot must be enabled to work properly.</remarks> public void Disenchant(int maxItemLevel = int.MaxValue) { var disenchant = new Spell("Disenchant"); foreach (var bagInfo in DisenchantList()) { disenchant.Launch(); Thread.Sleep(100); Lua.LuaDoString("UseContainerItem("+bagInfo.Bag+", "+bagInfo.Slot+");"); Thread.Sleep((int)disenchant.CastTime+800); } } Not fully tested, but it should work.
     
    And
    I think you let it compile by WRobot or using a lower framework version, so new additions over the course of the years like this example doesn't support it.
  18. Like
    reapler got a reaction from sowelu in How to get id or name of item from bagslot   
    In my other post, i've written a method to interact with the items: https://wrobot.eu/forums/topic/7064-check-distance/?tab=comments#comment-32142
    You can also use this to right clicking your items to the mail attachment.
    I've rewritten abit, so it returns the left stacks:
    /// <summary> /// Interact with all listed item names. /// </summary> /// <param name="itemNames">The itemNames to interact with.</param> /// <param name="interactions">The amount of interactions.</param> /// <returns>The amount of itemNames / stacks blocked by "interactions".</returns> /// <remarks>Bug at links with "-"</remarks> public static int InteractItems(List<string> itemNames, int interactions = int.MaxValue) { if (!itemNames.Any()) return -1; var execute = "local counter = 0; " + "local leftStacks = 0; " + "for b=0,4 do " + "if GetBagName(b) then " + "for s=1, GetContainerNumSlots(b) do " + "local itemLink = GetContainerItemLink(b, s) " + "if itemLink then " + "local _, stackCount = GetContainerItemInfo(b, s)\t" + "if string.find(itemLink, \""+ itemNames.FirstOrDefault() + "\") "; if (itemNames.Count > 1) { execute = itemNames.Where(obj => itemNames.FirstOrDefault() != obj).Aggregate(execute, (current, obj) => current + "or string.find(itemLink, \"" + obj + "\") "); } execute = execute + "then " + "if (counter < "+interactions+") then " + "UseContainerItem(b, s); " + "counter = counter + 1; " + "else " + "leftStacks = leftStacks + 1;" + "end " + "\tend\tend\tend end end return leftStacks;"; return Lua.LuaDoString<int>(execute); } /// <summary> /// Sends a mail to a recipient. /// </summary> /// <param name="recipient">The recipient.</param> /// <param name="subject">The subject.</param> /// <param name="itemNames">The items to send as names.</param> /// <returns>true if successful ; false if no mailbox available or stacks are left.</returns> public bool SendItems(string recipient, string subject, List<string> itemNames) { var mailBox = ObjectManager.GetObjectWoWGameObject().FirstOrDefault(i => i.IsMailbox && i.GetDistance <= 5); if (mailBox == null || string.IsNullOrWhiteSpace(recipient)) return false; if (subject.Length == 0) subject = "-"; if (mailBox) { const int delayMs = 800; var timeOut = DateTime.Now.AddSeconds(40); Interact.InteractGameObject(mailBox.GetBaseAddress); Thread.Sleep(delayMs); Lua.LuaDoString("RunMacroText('/click MailFrameTab2');"); Thread.Sleep(delayMs); var leftStack = InteractItems(itemNames, 12); Thread.Sleep(delayMs); Lua.LuaDoString($"SendMail(\"{recipient}\",\"{subject}\",\" \");"); Thread.Sleep(delayMs*3); while (leftStack != 0 && DateTime.Now < timeOut) { leftStack = InteractItems(itemNames, 12); Thread.Sleep(delayMs); Lua.LuaDoString($"SendMail(\"{recipient}\",\"{subject}\",\" \");"); Thread.Sleep(delayMs*3); } Lua.LuaDoString("CloseMail();"); if (leftStack != 0) return false; } return true; }  
    Usage:
    SendItems("Reapler", "items for you", new List<string> { "Super Healing Potion", "Heavy Netherweave Bandage", "Super Mana Potion", });  
  19. Thanks
    reapler got a reaction from Suspect in [Plugin] AttachEvent to Lua Event?   
    Hello, for example you can do the following for "COMBAT_LOG_EVENT_UNFILTERED":
    public void Initialize() { wManager.Wow.Helpers.EventsLuaWithArgs.OnEventsLuaWithArgs += delegate(LuaEventsId id, List<string> args) { if (id == LuaEventsId.COMBAT_LOG_EVENT_UNFILTERED) { for (var i = 0; i < args.Count; i++) { robotManager.Helpful.Logging.Write($"args[{i}]: {args[i]}"); } } }; } To get a list of all "LuaEventsId", i recommend to decompile "wManager.dll" in "WRobot\Bin\" and search for the desired value.
  20. Thanks
    reapler got a reaction from Apexx in Is Target Player of Opposite Faction   
    If this happens you should consider to use try and catch to log the error:
    try { // Buff Friendly Targets if (PriestSettings.CurrentSetting.BuffFriendlyTargets) { if (_powerWordFortitude.KnownSpell && _powerWordFortitude.IsSpellUsable && target.Faction == player.Faction && target.IsAlive && target.IsValid && target.GetDistance <= _powerWordFortitude.MaxRange && !TraceLine.TraceLineGo(target.Position) && !target.HaveBuff(_powerWordFortitude.Ids)) { Logging.WriteDebug(target.Name + " is missing Power Word: Fortitude."); _powerWordFortitude.Launch(); Thread.Sleep(SpellManager.GetSpellCooldownTimeLeft(_powerWordFortitude.Id)); } } } catch (Exception e) { Logging.WriteError(e.ToString()); } For example you haven't initialized "PriestSettings.CurrentSetting", so this would result in null and throw an exception.
  21. Like
    reapler got a reaction from sowelu in check distance   
    If you run the instances of WRobot on the same pc, you can checkout my CacheManager here.
    Yes, i recommend to use the "Quester" product and add a quest with "FollowPath" in "Quests Editor" window. It also supports C#.
    I think, you know how to calculate the position, so you could use this:
    //replace "new Vector3()" with your desired position SpellManager.CastSpellByIDAndPosition(1725, new Vector3());  
    To open trade with current target:
    Lua.LuaDoString("RunMacroText('/trade');");  
    Put items to the trade window(another solution, forgot the exact reason why it was in some ways better then the WRobot's method):
    /// <summary> /// Interact with all listed item names. /// </summary> /// <param name="items">Item list</param> /// <remarks>Bug at links with "-"</remarks> public static void InteractItems(List<string> items) { if (!items.Any()) return; var execute = "for b=0,4 do " + "if GetBagName(b) then " + "for s=1, GetContainerNumSlots(b) do " + "local itemLink = GetContainerItemLink(b, s) " + "if itemLink then " + "local _, stackCount = GetContainerItemInfo(b, s)\t" + "if string.find(itemLink, \""+ items.FirstOrDefault() + "\")"; if (items.Count > 1) { execute = items.Where(obj => items.FirstOrDefault() != obj).Aggregate(execute, (current, obj) => current + "or string.find(itemLink, \"" + obj + "\") "); } execute = execute + "then UseContainerItem(b, s)\tend\tend\tend end end"; Lua.LuaDoString(execute); }  
    To press the trade button:
    Lua.LuaDoString("RunMacroText('/click TradeFrameTradeButton');"); Take also a look at https://wrobot.eu/forums/topic/6826-frame-stack-on-wow-tbc-243/ or type "/fstack" in Wow if you have wotlk or above, to get other related frame stuff.
     
    And If you mention a new topic, just open a new thread ;)
     
  22. Thanks
    reapler got a reaction from Apexx in Is Target Player of Opposite Faction   
    Hello, ".PlayerFaction" should do its job:
    if (ObjectManager.Me.PlayerFaction == ((WoWPlayer) ObjectManager.Target).PlayerFaction) { Logging.Write("target same faction"); } if (ObjectManager.Me.PlayerFaction != ((WoWPlayer) ObjectManager.Target).PlayerFaction) { Logging.Write("target hostile faction"); } To check if target is a player:
    ObjectManager.Target.PlayerControlled
  23. Like
    reapler got a reaction from Findeh in Heals Casting Twice With Timer   
    Hello, i've created a small example for this, everything else is explained in the comments:
    using System; using System.Collections.Generic; using System.Threading; using wManager.Plugin; using wManager.Wow.Class; using wManager.Wow.Enums; using wManager.Wow.Helpers; using wManager.Wow.ObjectManager; using static robotManager.Helpful.Logging; public class Main : IPlugin { #region Variables private bool _isLaunched; private int _msDelay = 200; private DateTime _unlockTime = DateTime.Now; private readonly HashSet<string> _noGcdSpells = new HashSet<string> { "Counterspell", //... //http://wowwiki.wikia.com/wiki/Cooldown => Abilities noted for not affecting nor being affected by the global cooldown: }; #endregion #region Properties public bool GcdActive => DateTime.Now < _unlockTime; #endregion #region WRobot Interface public void Initialize() { var pGuid = ToWoWGuid(ObjectManager.Me.Guid); EventsLuaWithArgs.OnEventsLuaWithArgs += delegate(LuaEventsId id, List<string> args) { if ( id == LuaEventsId.COMBAT_LOG_EVENT_UNFILTERED && args[2] == pGuid && !_noGcdSpells.Contains(args[9]) && ( args[1] == "SPELL_CAST_SUCCESS" || args[1] == "SPELL_HEAL" || args[1] == "SPELL_DAMAGE" ) ) { Write("lock"); _unlockTime = DateTime.Now.AddMilliseconds(_msDelay); } }; _isLaunched = true; Write("Loaded"); while (_isLaunched) { try { if (Conditions.ProductIsStartedNotInPause) { Pulse(); } } catch (Exception e) { WriteError(e.ToString()); } Thread.Sleep(30); } } public void Dispose() { _isLaunched = false; } public void Settings() { } #endregion #region Pulse public void Pulse() { var spell = new Spell("Lesser Heal"); if (!GcdActive && spell.IsSpellUsable && !ObjectManager.Me.IsCast && ObjectManager.Me.TargetObject.HealthPercent <= 90 ) { spell.Launch(false, false); //will cast the heal if "_msDelay" was passed } /* if (spell.IsSpellUsable && !ObjectManager.Me.IsCast && ObjectManager.Me.TargetObject.HealthPercent <= 90) { spell.Launch(false, false); //.IsSpellUsable is true after gcd was passed but the heal itself can delay //and cause double heal cast if no additional delay is added like above //so ObjectManager.Me.TargetObject.HealthPercent <= 90 would be true for a short time }*/ } #endregion #region Methods public string ToWoWGuid(ulong guid) { var wowGuid = ObjectManager.Me.Guid.ToString("x").ToUpper(); var c = 16 - wowGuid.Length; for (var i = 0; i < c; i++) { wowGuid = "0" + wowGuid; } return "0x" + wowGuid; } #endregion } if you are going to lower the tickspeed this will rarer happens, but it can still happen. Instant spells aren't included.
  24. Confused
    reapler got a reaction from BetterSister in PathFinder.Pather.FindZ(); on dalaran   
    Yes, the result is good :) I just added my height + 20:

    Thank you.
  25. Thanks
    reapler reacted to Droidz in PathFinder.Pather.FindZ(); on dalaran   
    Hello, you call FindZ() yourself? if yes try to put z position near real z position
×
×
  • Create New...