-
Posts
288 -
Joined
-
Last visited
Content Type
Forums
Articles
Bug Tracker
Downloads
Store
Everything posted by reapler
-
Hello, you've searched in the wrong class. It's in wManager.Wow.Helpers.Bag.GetContainerNumFreeSlots.
-
Possible to change process name of attached WoW process?
reapler replied to Brian's topic in Developers assistance
So, i wrote a method which works (at least for me): [DllImport("user32.dll")] static extern bool SetWindowText(IntPtr hWnd, string text); public void SetText(string processname, string text) { IntPtr mainWindowHandle = IntPtr.Zero; foreach (var obj in System.Diagnostics.Process.GetProcesses()) { //or you can search for other parameter / characteristics which wow contains but searching for processname is normaly enough if (obj.ProcessName == processname)// => in my case the executable in my wow folder is Wow.exe { Logging.Write("Process found: " + obj.ProcessName + "[" + obj.Id + "]."); mainWindowHandle = obj.MainWindowHandle; break; } } if (mainWindowHandle != IntPtr.Zero) { SetWindowText(mainWindowHandle, text); } else { Logging.Write("No process with the name '" +processname+"' was found.\nPlease check your executable's name."); } } usage: SetText("Wow","Hello World!"); but remember: processname != windowtext => the field "ProcessName" is read only so it can't be changed on running processes. If you really want to change the process' name, you can only influence it on startup or by creating a new process. Edit: this one gets the right one, if several processes exist: [DllImport("user32.dll")] static extern bool SetWindowText(IntPtr hWnd, string text); public void SetText(string processname, string text) { IntPtr mainWindowHandle = IntPtr.Zero; foreach (var obj in System.Diagnostics.Process.GetProcesses()) { if (obj.ProcessName == processname)// => in my case the executable in my wow folder is Wow.exe { if (wManager.Wow.Memory.PlayerName(obj.Id) == wManager.Wow.ObjectManager.ObjectManager.Me.Name) { Logging.Write("Process found: " + obj.ProcessName + "[" + obj.Id + "][" + wManager.Wow.ObjectManager.ObjectManager.Me.Name+ "]"); mainWindowHandle = obj.MainWindowHandle; break; } } } if (mainWindowHandle != IntPtr.Zero) { SetWindowText(mainWindowHandle, text); } else { Logging.Write("No process with the name '" +processname+"' was found.\nPlease check your executable's name."); } } -
Possible to change process name of attached WoW process?
reapler replied to Brian's topic in Developers assistance
Hello, it's not possible to change the process name(on runtime => you can retaliate at msdn documentation) and you must specify which IntPtr do you mean: There are several IntPtr which you can get from the process but i belive you want the mainwindowhandle? or you can explain for what the IntPtr is needed. Edit: forgot to write that you can change the process name by simply rename wow.exe but it will doesn't affect the process name while it's running: Logging.Write(wManager.Wow.Memory.WowMemory.Memory.GetProcess().ProcessName); -
ah ok i see, thanks anyway
-
That fits perfect, tank you
-
Hello, i would like to ask if someone knows an event which fires on generate path requests and also return the start & end position for the requested path. The current event which i'm using is "MovementEvents.OnMovementPulse" but it has already generated the path to the destination. The reason is why i need that is i want to diminish the effort for my plugin because i don't need the generated path and it's pointless if it takes a few seconds to generate while i only need the start & destination position in the end.
-
Hello, i would like to suggest to add a option for wrobot, that saves the window position of wrobot for the used character. It would be more comfortable in my eyes if the user don't need to move the window at every start. Best regards
-
(BUG) NPC Database
reapler replied to Arcangelo's topic in WRobot for Wow Vanilla - Help and support
hm i think the database is working as intend maybe it's just the product itself with a missing condition. For a workaround you could register the movement events and replace the current moveto/onmovement with your desired npc but it's abit too much work. I think you can also resolve the problem with a plugin which lookup the npc database & temporary blacklist the npc by its faction on Initialize(): foreach (var obj in NpcDB.ListNpc) { if ((int) obj.Faction != ObjectManager.Me.Faction && obj.Faction != Npc.FactionType.Neutral) { wManagerSetting.AddBlackListNpcEntry(obj.Entry, true); } } -
Ok @Drumstix66. I've found the problems. 1. It doesn't started the procedure because your next npc also evaded so it counted to 2000+. 2. grinder product / internal behavior itself has a bug which is try to regen even while the player was attacked by the blacklisted npc (i belive event-based regen which doesn't check the incombat condition) 3. it can happen that the behavior that i've written will be ignored by a customclass(but most of the time people play with Fightclasses anyway so i'll take a look into it later) I'll implement a better system to support multiple evaded npc & lock regen behavior.
-
@Drumstix66 Thank you for your feedback. I will rewrite it asap according to your information. And if possible i need maybe the previous log due the spam-log(just pm me :) )
-
Hello, i made a method in my custom grinder that looks like this: public void DoNotDisturb(bool s) { log("DoNotDisturb: "+s); wManagerSetting.CurrentSetting.LootMobs = !s; Conditions.ForceIgnoreIsAttacked = s; wManagerSetting.CurrentSetting.DontStartFighting = s; if (s) { Fight.StopFight(); Interact.InteractGameObject(ObjectManager.Me.GetBaseAddress); Blacklist.AllHostileNpc(30, 10000); } //if on the way to vendor stop regen /*if (s && wManagerSetting.CurrentSetting.FoodPercent != 1) { //log("Save percent setting: " + wManagerSetting.CurrentSetting.FoodPercent); FoodPercent = wManagerSetting.CurrentSetting.FoodPercent; DrinkPercent = wManagerSetting.CurrentSetting.DrinkPercent; wManagerSetting.CurrentSetting.FoodPercent = 1; wManagerSetting.CurrentSetting.DrinkPercent = 1; } else if (!s) { //log("restore percent setting" + FoodPercent); wManagerSetting.CurrentSetting.FoodPercent = FoodPercent; wManagerSetting.CurrentSetting.DrinkPercent = DrinkPercent; }*/ } You can uncomment the consumable stuff if you want to use it. if you wanna check the position of your destination of your path (good to use in a movement event) then this would help you: if (MovementManager.CurrentPath.LastOrDefault().DistanceTo(YOURPOSITION) < 5) { DoNotDisturb(true); } else { DoNotDisturb(false); } otherwise this would fit better: if (ObjectManager.Me.Position.DistanceTo(YOURPOSITION) > 5) { DoNotDisturb(true); } else { DoNotDisturb(false); } Edit: I remember that you need the food percent block because the bot will try to regen in combat
-
Hello you can use this code in quest order editor at runcode: ItemsManager.UseItem("Hearthstone"); var t = System.Threading.Tasks.Task.Run(async delegate { await System.Threading.Tasks.Task.Delay(10000); //execute this block after 10000ms even after dispose robotManager.Helpful.Logging.Write("execution2"); }); //this will be executed immediately robotManager.Helpful.Logging.Write("execution1"); but i guess you just need a simple sleep so it would be: ItemsManager.UseItem("Hearthstone"); System.Threading.Thread.Sleep(10000); robotManager.Helpful.Logging.Write("execution1");
-
Hello again, i made a workaround for that if someone is interested(a bit ugly): public void Initialize() { EventsLuaWithArgs.OnEventsLuaWithArgs += Events; Lua.LuaDoString ( "wframe = CreateFrame('Frame') " + "local Frame = true " + "arg = {'1', '2', '3', '4','5', '6', '7', '8', '9', '10', '11', '12','13', '14'} " + "wframe:RegisterEvent('COMBAT_LOG_EVENT_UNFILTERED') " + "wframe:SetScript('OnEvent', function(self, event, ...) " + "for i=1, 14 " + "do " + "if select(i, ...) == nil or select(i, ...) == '' then " + "arg[i] = '' " + "else " + "arg[i] = select(i, ...) " + "end " + "end " + "RunMacroText('/click '..arg[1]..'§'..arg[2]..'§'..arg[3]..'§'..arg[4]..'§'..arg[5]..'§'..arg[6]..'§'..arg[7]..'§'..arg[8]..'§'..arg[9]..'§'..arg[10]..'§'..arg[11]..'§'..arg[12]..'§'..arg[13]..'§'..arg[14]..'') " + "end) " ); //... } public void Events(LuaEventsId id, List<string> args) { //Combatlog if (id == LuaEventsId.EXECUTE_CHAT_LINE) { string[] arg = args[0].Replace("/click", "").Split('§'); Logging.Write(arg[3]); Logging.Write(arg[9]); } }
-
Hello, i have answered a similar question here:
-
Hello, you can decompile wrobot's library to get the api documentation(MemoryRobot-, robotManager- & wManager in Wrobot\Bin) common decompiler are Jetbrains dotPeek, ILSpy, redgate's .net reflector & Justcompile. I also recommend to add it to reference and good extensions for VS make your life easier: ReSharper or Coderush are good extensions. And for testing things i'll prefer to link the build to Wrobots plugins folder so you can just compile and run directly with Wrobot & output the log with "robotManager.Helpful.Logging.Write("text");".
-
Hello, what you are looking for is a descriptor field. I researched a bit in my decompiler and have found in HB your "WowGameObject.State". It has "return (WoWGameObjectState) this.Bytes1[0];" in Wrobot it's "WoWGameObject.GOType" with "return (WoWGameObjectType) (Memory.WowMemory.Memory.ReadInt32(this.GetDescriptorAddress(Descriptors.GameObjectFields.Bytes1)) >> 8 & (int) byte.MaxValue);" but if you looking at the enum of "WoWGameObjectState"(HB) / "WoWGameObjectType(Wrobot)" you'll notice it's different. I guess you need to read with wrobot additional offset to get your information i think it can be: .Data0, .Data1 or .Data8 from WoWGameObject. So if you looking where it gets used you'll find WoWGameObject.LockEntry which looks very promising: ... switch (this.GOType) { case WoWGameObjectType.Door: case WoWGameObjectType.Button: return this.Data1; ... But i'm not sure(couldn't test it now) so you can try to compare some values with the door while open/closed. If it's still returning the not desired value you can try to return the other data what i mentioned above. I hope that helps a bit. Good Luck
-
I can also confirm this bug but it's not the only one reason that trigger it for e.g. hearthstone:
-
previous profile code/threads/events subscribers
reapler replied to camelot10's topic in Developers assistance
Hello, if you start a thread it will persist till you abort it. That means if you load a profile with a starting thread you need to save it somewhere to abort it later (it's more easily if it's on the same instance). For this purpose you can use a thread manager like this: public class ThreadManager { public int TableId = 1; Dictionary<string, Thread> _threads = new Dictionary<string, Thread>(); public void Start(Action method, string threadName) { if (!_threads.ContainsKey(threadName)) { Thread Thread = new Thread(() => method()); Thread.Name = Convert.ToString(TableId); Thread.Start(); _threads.Add(threadName, Thread); log("Start Thread " + method.Method.Name + "."); } else { log("Thread " + method.Method.Name + " already executed."); } } public void Start(Action method) { if (!_threads.ContainsKey(method.Method.Name)) { Thread Thread = new Thread(() => method()); Thread.Name = Convert.ToString(TableId); Thread.Start(); _threads.Add(method.Method.Name, Thread); log("Start Thread " + method.Method.Name + "."); } else { log("Thread " + method.Method.Name + " already executed."); } } public void Abort(string threadName) { if (_threads.ContainsKey(threadName)) { _threads[threadName].Abort(); _threads.Remove(threadName); log("Abort Thread " + threadName + "."); } } public void Abort(Action method) { if (_threads.ContainsKey(method.Method.Name)) { _threads[method.Method.Name].Abort(); _threads.Remove(method.Method.Name); log("Abort Thread " + method.Method.Name + "."); } } } but this one can only handle methods with return type void (if you want more you need func<>) that would perfectly fit if a event exist. But the question is what if not? How do you abort it, if you have started the new profile/thread while "Dictionary<string, Thread> _threads = new Dictionary<string, Thread>();" is new initialized? For this purpose you could use System.Runtime.Caching.MemoryCache to save your thread on memory to access it later & abort it like this: public class CacheManager { public void SaveTocache(string cacheKey, object savedItem, DateTime absoluteExpiration) { if (!IsIncache(cacheKey)) { MemoryCache.Default.Add(cacheKey, savedItem, absoluteExpiration); } else { MemoryCache.Default.Set(cacheKey, savedItem, absoluteExpiration); } } public T GetFromCache<T>(string cacheKey) where T : class { return MemoryCache.Default[cacheKey] as T; } public void RemoveFromCache(string cacheKey) { MemoryCache.Default.Remove(cacheKey); } public bool IsIncache(string cacheKey) { return MemoryCache.Default[cacheKey] != null; } } public class ThreadManager { public int TableId = 1; public CacheManager CacheManager_ = new CacheManager(); Dictionary<string, Thread> _threads = new Dictionary<string, Thread>(); public void Start(Action method, string threadName, bool cache = false, DateTime cacheExpiration = default(DateTime)) { if (!cache) { if (!_threads.ContainsKey(threadName)) { Thread Thread = new Thread(() => method()); Thread.Name = Convert.ToString(TableId); Thread.Start(); _threads.Add(threadName, Thread); Logging.Write("Start Thread " + threadName + "."); } else { Logging.Write("Thread " + threadName + " already executed."); } } else { if (!CacheManager_.IsIncache(threadName)) { Thread Thread = new Thread(() => method()); Thread.Name = Convert.ToString(TableId); Thread.Start(); if (cacheExpiration == default(DateTime)) { CacheManager_.SaveTocache(threadName, Thread, DateTime.Now.AddMinutes(30)); Logging.Write("Start Thread " + threadName + ".\nExpires at " + DateTime.Now.AddMinutes(30)); } else { CacheManager_.SaveTocache(threadName, Thread, cacheExpiration); Logging.Write("Start Thread " + threadName + ".\nExpires at " + cacheExpiration); } } else { Logging.Write("Thread " + threadName + " already executed."); } } } public void Start(Action method, bool cache = false, DateTime cacheExpiration = default(DateTime)) { if (!cache) { if (!_threads.ContainsKey(method.Method.Name)) { Thread Thread = new Thread(() => method()); Thread.Name = Convert.ToString(TableId); Thread.Start(); _threads.Add(method.Method.Name, Thread); Logging.Write("Start Thread " + method.Method.Name + "."); } else { Logging.Write("Thread " + method.Method.Name + " already executed."); } } else { if (!CacheManager_.IsIncache(method.Method.Name)) { Thread Thread = new Thread(() => method()); Thread.Name = Convert.ToString(TableId); Thread.Start(); if (cacheExpiration == default(DateTime)) { CacheManager_.SaveTocache(method.Method.Name, Thread, DateTime.Now.AddMinutes(30)); Logging.Write("Start Thread " + method.Method.Name + ".\nExpires at " + DateTime.Now.AddMinutes(30)); } else { CacheManager_.SaveTocache(method.Method.Name, Thread, cacheExpiration); Logging.Write("Start Thread " + method.Method.Name + ".\nExpires at " + cacheExpiration); } } else { Logging.Write("Thread " + method.Method.Name + " already executed."); } } } public void Abort(string threadName, bool cache = false) { if (!cache) { if (_threads.ContainsKey(threadName)) { _threads[threadName].Abort(); _threads.Remove(threadName); Logging.Write("Abort Thread " + threadName + "."); } } else { if (CacheManager_.IsIncache(threadName)) { CacheManager_.GetFromCache<Thread>(threadName).Abort(); CacheManager_.RemoveFromCache(threadName); Logging.Write("Abort Thread " + threadName + "."); } else { Logging.Write("Thread " + threadName + "could not be found in cache."); } } } public void Abort(Action method, bool cache = false) { if (!cache) { if (_threads.ContainsKey(method.Method.Name)) { _threads[method.Method.Name].Abort(); _threads.Remove(method.Method.Name); Logging.Write("Abort Thread " + method.Method.Name + "."); } } else { if (CacheManager_.IsIncache(method.Method.Name)) { CacheManager_.GetFromCache<Thread>(method.Method.Name).Abort(); CacheManager_.RemoveFromCache(method.Method.Name); Logging.Write("Abort Thread " + method.Method.Name + "."); } else { Logging.Write("Thread " + method.Method.Name + "could not be found in cache."); } } } } But keep in mind that the thread is still executed even if it expires in the cache. In the end you can access the thread to abort it even from your new thread now. And yes it would be easier if an event exist to manage your current profile/thread but i haven't found the correct one :) but i had these snippets already on my disk. I hope that it can help you. -
big noob needs help (teleport = false) if using hearthstone
reapler replied to dafuqlol's topic in Developers assistance
Hello, that what you have described is a minor bug that shouldn't occur while the player is using a portal or hearthstone( maybe it needs to get reported ;) ). Here's a workaround for the heartstone that should work: wManager.Wow.Helpers.EventsLuaWithArgs.OnEventsLuaWithArgs += (id, args) => { if (id == wManager.Wow.Enums.LuaEventsId.UNIT_SPELLCAST_SUCCEEDED && args[0] == "player" && args[1] == "Hearthstone") { robotManager.Helpful.Logging.Write("Player casted hearthstone\n=>Set CloseIfPlayerTeleported to false"); wManager.wManagerSetting.CurrentSetting.CloseIfPlayerTeleported = false; var t = System.Threading.Tasks.Task.Run(async delegate { await System.Threading.Tasks.Task.Delay(6000); robotManager.Helpful.Logging.Write("Player changed different zone\n=>Set CloseIfPlayerTeleported to true"); wManager.wManagerSetting.CurrentSetting.CloseIfPlayerTeleported = true; }); } }; and if the first message coming too late just replace UNIT_SPELLCAST_SUCCEEDED Delay(6000) with UNIT_SPELLCAST_START Delay(13000) -
Hello, so far i know you have two options to achieve your goal: 1. write a plugin to use the nearest portal(if your character is standing right there => method: wManager.Wow.Helpers.InteractGameObject) 2. rewrite the grinder profile to a quest profile in order to use c# snippets(that result in more capabilities but also requires a bit work) feel free to ask if you need something else
-
This should work in a pulse method: WoWLocalPlayer me = ObjectManager.Me; WoWUnit LootableUnit = ObjectManager.GetObjectWoWUnit() .Where(i => i.IsLootable) .OrderBy(i => i.Position.DistanceTo(ObjectManager.Me.Position)) .FirstOrDefault(); if (LootableUnit != null && MovementManager.CurrentPath.LastOrDefault() != LootableUnit.Position && LootableUnit.Position.DistanceTo(me.Position) > 5) { MovementManager.Go(PathFinder.FindPath(LootableUnit.Position)); } else if (LootableUnit.Position.DistanceTo(me.Position) < 5 && !me.IsLooting()) { Interact.InteractGameObject(LootableUnit.GetBaseAddress, true); }
-
Hello, i looked abit in CE and got a few offsets for 3.3.5a which works on right & left click: public static Vector3 GetCursorPosition() { try { int address = Memory.WowMemory.Memory.ReadInt32((uint)Memory.WowMemory.Memory.ReadInt32((uint)GetWoWBase() + 0x007743A0) + 0x2B0); float _X = Memory.WowMemory.Memory.ReadFloat((uint)address + 0x3C); float _Y = Memory.WowMemory.Memory.ReadFloat((uint)address + 0x40); float _Z = Memory.WowMemory.Memory.ReadFloat((uint)address + 0x44); return new Vector3(_X, _Y, _Z); } catch (Exception ex) { Logging.WriteError("Error: " + ex, true); return new Vector3(0.0f, 0.0f, 0.0f); } } I hope it can take off abit work. Best regards
-
I guess that's a brilliant solution to overwrite guid for this purpose :) but it needs the mouseoverguid instead of mouseover for 3.3.5: public void CastSpell(string spellName, WoWUnit unit) { uint MouseOverGUID = 0x00BD07A0; wManager.Wow.Memory.WowMemory.Memory.WriteUInt64(MouseOverGUID, unit.Guid); SpellManager.CastSpellByNameOn(spellName, "mouseover"); } and @forerun i belive you need to search it couldn't find the offset myself currently :/
-
@Pelle now i could test it more, that should work: public List<WoWGameObject> WoWGameObjects(string name) { return ObjectManager.GetObjectWoWGameObject().Where(i => i != null && i.Name == name //&& i.GetDistance <= RealmHopSettings.CurrentSetting.DistanceBeforeHopping ).OrderBy(i => ObjectManager.Me.Position.DistanceTo(i.Position)).ToList(); } public List<WoWUnit> GetNearestUnits(string name) { return ObjectManager.GetObjectWoWUnit().Where(i => i != null && !i.IsDead && i.Name == name && i.GetDistance <= RealmHopSettings.CurrentSetting.DistanceBeforeHopping ).OrderBy(i => ObjectManager.Me.Position.DistanceTo(i.Position)).ToList(); }