Jump to content

reapler

Elite user
  • Posts

    288
  • Joined

  • Last visited

Everything posted by reapler

  1. Hello, you need to access the objectmanager to get your desired object: WoWItem item = ObjectManager.GetObjectWoWItem().FirstOrDefault(i => i.Entry == 1205);//Melon Juice Logging.Write(item?.Name ?? "Item not found");
  2. Not fully tested, but this should work: /// <summary> /// Used to get the item quantity by name. /// </summary> /// <param name="itemName">The item name.</param> /// <remarks>Replacement for GetItemCount in vanilla.</remarks> /// <returns></returns> public static int GetItemQuantity(string itemName) { var execute = "local itemCount = 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, \"" + itemName + "\") then " + "itemCount = itemCount + stackCount; " + "end " + "end " + "end " + "end " + "end; " + "return itemCount; "; return Lua.LuaDoString<int>(execute); } /// <summary> /// Used to delete all items by name. /// </summary> /// <param name="itemName">The item to delete.</param> /// <param name="leaveAmount">The amount of items which remain in the bag.</param> /// <remarks>Bug at links with "-"</remarks> public static void DeleteItems(string itemName, int leaveAmount) { var itemQuantity = GetItemQuantity(itemName) - leaveAmount; if (string.IsNullOrWhiteSpace(itemName) || itemQuantity <= 0) return; var execute = "local itemCount = "+itemQuantity+"; " + "local deleted = 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 " + "local leftItems = itemCount - deleted; " + "if string.find(itemLink, \""+ itemName + "\") and leftItems > 0 then " + "if stackCount <= 1 then " + "PickupContainerItem(b, s); " + "DeleteCursorItem(); " + "deleted = deleted + 1; " + "else " + "if (leftItems > stackCount) then " + "SplitContainerItem(b, s, stackCount); " + "DeleteCursorItem(); " + "deleted = deleted + stackCount; " + "else " + "SplitContainerItem(b, s, leftItems); " + "DeleteCursorItem(); " + "deleted = deleted + leftItems; " + "end " + "end " + "end " + "end " + "end " + "end " + "end; "; Lua.LuaDoString(execute); } Usage: DeleteItems("Soul Shard", 20);
  3. @Marsbar Hello, i've written a method for this: 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; } } /// <summary> /// Used to get a list of locations of the item as bag and slot position. /// </summary> /// <param name="itemName">The item name to search.</param> /// <returns></returns> public static List<BagInfo> GetItemLocations(string itemName) { var execute = "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 itemName == '"+itemName+"' "; execute += "then " + "table.insert(bs, b); " + "table.insert(bs, s); " + "\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; } Usage: GetItemLocations("Mutton Chop").ForEach(i => Logging.Write(i.ToString())); Here are also other similar methods to interact with items:
  4. Hello, this is a limitation from the server itself, other servers could also have a dynamic object scope(performance reasons).
  5. 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.
  6. I initially implemented it, because sometimes i had a bug from WRobot's keyboard class which didn't hooked my keys, dunno if it's fully working now.
  7. 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 ;)
  8. 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); }
  9. I forgot to illustrate the other method more detailed. You can actually write your radians to rotation property at the player class (like you did), but after the write it is needed to update the rotation via a nudge: ObjectManager.Me.Rotation = 1.1f; //or use robotmanager's keyboard class Lua.LuaDoString("TurnLeftStart();"); Lua.LuaDoString("TurnLeftStop();");
  10. I assume you are using the "Rotation" property from your playerclass to change the rotation, but this should be only used to get rotation values. This behavior occures because you are only changing your client-side rotation but not your actual rotation on the server. It can be fixed either using the mentioned "Face();" method in my previous posts (dunno if it works on vanilla) or by a nudge turn via keypress / lua (http://wowwiki.wikia.com/wiki/API_TurnLeftStart & http://wowwiki.wikia.com/wiki/API_TurnLeftStop)
  11. 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);
  12. 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
  13. 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));
  14. 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
  15. 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.
  16. 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", });
  17. 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.
  18. Hello, what's your primary goal? Do you want to send items by item name / id? Will the code be used in a plugin or quester profile?
  19. 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.
  20. 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 ;)
  21. 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
  22. Looks great. You can also port it to product and add WRobot bot states or your custom states, since for this sort of plugin it would fit well i think. But it requires a bit work ;)
  23. Thank you for your suggestion, i'll consider to add it, if i'm working on it again.
  24. Hello @hanyuhyhy, as i stated the database or used lua is for 3.3.5a. Everything under or above this version doesn't working correctly or working partially(coordinates are translated differently on some maps). But thank you anyways to tried it on legion.
×
×
  • Create New...