Skip to content
View in the app

A better way to browse. Learn more.

WRobot

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Left click unit

Featured Replies

A SPECIFIC unit? You can take a look at (decompile) how Droidz does it in the "Interact" class in the Helper namespace (lots of memory writing).

If not, use

Lua.LuaDoString(TargetEnemy("name"))

(I think) or

Lua.RunMaroText("/target name")

 

  • Author
Just now, Matenia said:

A SPECIFIC unit? You can take a look at (decompile) how Droidz does it in the "Interact" class in the Helper namespace (lots of memory writing).

If not, use


Lua.LuaDoString(TargetEnemy("name"))

(I think) or


Lua.RunMaroText("/target name")

 

Thank you, but this only lets me target by name and I need to target by guid :(

Then you'll have to decompile Interact.InteractGameObject in the wManager.dll.
Or just use it and instantly trigger /stopattack right after.

If you just want to your spells to target another unit than your current target, there are plenty of threads on how to do this.

Edited by Matenia

1 hour ago, Skygirl779 said:

Thank you, but this only lets me target by name and I need to target by guid :(

This should gonna do its work:

    public void Target(ulong guid)
    {
        wManager.Wow.Helpers.Lua.RunMacroText("/target "+wManager.Wow.ObjectManager.ObjectManager.GetObjectByGuid(guid)?.Name+"");
    }

Edit: i reconsider my answer, this may not be a ideal solution.

 

If you gonna look at the interact function in WRobot, you'll notice it's a direct function call via asm.

So another solution would be to overwrite the guid from the local player's focus and target it via lua:

    public void Target(WoWObject obj)
    {
        var tmp = ObjectManager.Me.FocusGuid;
        ObjectManager.Me.FocusGuid = obj.Guid;
        Lua.RunMacroText("/target focus");
        ObjectManager.Me.FocusGuid = tmp;
    }

    public void Target(ulong guid)
    {
        var tmp = ObjectManager.Me.FocusGuid;
        ObjectManager.Me.FocusGuid = guid;
        Lua.RunMacroText("/target focus");
        ObjectManager.Me.FocusGuid = tmp;
    }

Usage:

        var firstOrDefault = ObjectManager.GetObjectWoWUnit().OrderBy(i => i.GetDistance).FirstOrDefault();
        if (firstOrDefault != null)
            Target(firstOrDefault.Guid);

 

Edited by reapler

43 minutes ago, reapler said:

This should gonna do its work:


    public void Target(ulong guid)
    {
        wManager.Wow.Helpers.Lua.RunMacroText("/target "+wManager.Wow.ObjectManager.ObjectManager.GetObjectByGuid(guid)?.Name+"");
    }

Edit: i reconsider my answer, this may not be a ideal solution.

 

If you gonna look at the interact function in WRobot, you'll notice it's a direct function call via asm.

So another solution would be to overwrite the guid from the local player's focus and target it via lua:


    public void Target(WoWObject obj)
    {
        var tmp = ObjectManager.Me.FocusGuid;
        ObjectManager.Me.FocusGuid = obj.Guid;
        Lua.RunMacroText("/target focus");
        ObjectManager.Me.FocusGuid = tmp;
    }

    public void Target(ulong guid)
    {
        var tmp = ObjectManager.Me.FocusGuid;
        ObjectManager.Me.FocusGuid = guid;
        Lua.RunMacroText("/target focus");
        ObjectManager.Me.FocusGuid = tmp;
    }

Usage:


        var firstOrDefault = ObjectManager.GetObjectWoWUnit().OrderBy(i => i.GetDistance).FirstOrDefault();
        if (firstOrDefault != null)
            Target(firstOrDefault.Guid);

 

For anyone reading this - this will only work in TBC and onwards where "focus" is an existing unit.
The direct ASM function call reapler was talking about *might* be your only solution in Vanilla if you want to achieve exactly this.

1 minute ago, Matenia said:

For anyone reading this - this will only work in TBC and onwards where "focus" is an existing unit.
The direct ASM function call reapler was talking about *might* be your only solution in Vanilla if you want to achieve exactly this.

It's also possible to do this on vanilla, but with mouseover guid:

    public void Target(ulong guid)
    {
        if (guid == 0)
            return;
        ulong tmp = wManager.Wow.Memory.WowMemory.Memory.ReadUInt64(
            (uint) wManager.Wow.Memory.WowMemory.Memory.MainModuleAddress + 0x74E2C8);
        wManager.Wow.Memory.WowMemory.Memory.WriteUInt64(
            (uint) wManager.Wow.Memory.WowMemory.Memory.MainModuleAddress + 0x74E2C8, guid);
        wManager.Wow.Helpers.Lua.LuaDoString("TargetUnit('mouseover');");
        wManager.Wow.Memory.WowMemory.Memory.WriteUInt64(
            (uint) wManager.Wow.Memory.WowMemory.Memory.MainModuleAddress + 0x74E2C8, tmp);
    }

 

23 minutes ago, reapler said:

It's also possible to do this on vanilla, but with mouseover guid:


    public void Target(ulong guid)
    {
        if (guid == 0)
            return;
        ulong tmp = wManager.Wow.Memory.WowMemory.Memory.ReadUInt64(
            (uint) wManager.Wow.Memory.WowMemory.Memory.MainModuleAddress + 0x74E2C8);
        wManager.Wow.Memory.WowMemory.Memory.WriteUInt64(
            (uint) wManager.Wow.Memory.WowMemory.Memory.MainModuleAddress + 0x74E2C8, guid);
        wManager.Wow.Helpers.Lua.LuaDoString("TargetUnit('mouseover');");
        wManager.Wow.Memory.WowMemory.Memory.WriteUInt64(
            (uint) wManager.Wow.Memory.WowMemory.Memory.MainModuleAddress + 0x74E2C8, tmp);
    }

 

This... changes a lot. I had no idea mouseover was a valid unit in Vanilla.
Do you happen to know if SpellManager.CastSpellByNameOn(name, unit) works in Vanilla? OP might not have to use that Lua call, if it is possible to cast a spell directly on a Lua unit.
Either way, as long as you prevent wRobot from changing target while you manually do it (e.g. pause OnFightLoop, temporarily remove Grinder state from the current product, etc), this should work.
That's amazing.

47 minutes ago, Matenia said:

Do you happen to know if SpellManager.CastSpellByNameOn(name, unit) works in Vanilla?

Yes, in vanilla you need to change the target guid, since the api only allows target or local player as argument. It looks like this:

    public void CastSpell(string spellName, WoWObject obj)
    {
        if (!obj.IsValid)
            return;
        ulong tmp = wManager.Wow.Memory.WowMemory.Memory.ReadUInt64(
            (uint) wManager.Wow.Memory.WowMemory.Memory.MainModuleAddress + 0x74E2D8);
        wManager.Wow.Memory.WowMemory.Memory.WriteUInt64(
            (uint) wManager.Wow.Memory.WowMemory.Memory.MainModuleAddress + 0x74E2D8, obj.Guid);
        Lua.LuaDoString("CastSpellByName('"+spellName+"');");
        wManager.Wow.Memory.WowMemory.Memory.WriteUInt64(
            (uint) wManager.Wow.Memory.WowMemory.Memory.MainModuleAddress + 0x74E2D8, tmp);
    }

Someone may think why not using objectmanager's target property from local player, the reason is the setter has some additional code for actually change the target and some other features.

1 hour ago, reapler said:

Yes, in vanilla you need to change the target guid, since the api only allows target or local player as argument. It looks like this:

Someone may think why not using objectmanager's target property from local player, the reason is the setter has some additional code for actually change the target and some other features.

Plus ObjectManager.Target is marked as readonly (or the GUID is iirc - I tried way back).

Edited by Matenia

  • Author
7 hours ago, reapler said:

This should gonna do its work:


    public void Target(ulong guid)
    {
        wManager.Wow.Helpers.Lua.RunMacroText("/target "+wManager.Wow.ObjectManager.ObjectManager.GetObjectByGuid(guid)?.Name+"");
    }

Edit: i reconsider my answer, this may not be a ideal solution.

 

If you gonna look at the interact function in WRobot, you'll notice it's a direct function call via asm.

So another solution would be to overwrite the guid from the local player's focus and target it via lua:


    public void Target(WoWObject obj)
    {
        var tmp = ObjectManager.Me.FocusGuid;
        ObjectManager.Me.FocusGuid = obj.Guid;
        Lua.RunMacroText("/target focus");
        ObjectManager.Me.FocusGuid = tmp;
    }

    public void Target(ulong guid)
    {
        var tmp = ObjectManager.Me.FocusGuid;
        ObjectManager.Me.FocusGuid = guid;
        Lua.RunMacroText("/target focus");
        ObjectManager.Me.FocusGuid = tmp;
    }

Usage:


        var firstOrDefault = ObjectManager.GetObjectWoWUnit().OrderBy(i => i.GetDistance).FirstOrDefault();
        if (firstOrDefault != null)
            Target(firstOrDefault.Guid);

 

Thank you very much! The focus target is a working solution for me.

That said, it's not perfect; is there an API that allows me to safely call WoW functions from wRobot? I have the necessary technical knowledge, I just don't know how to get wRobot to execute asm in WoW's main thread.

8 minutes ago, Skygirl779 said:

That said, it's not perfect; is there an API that allows me to safely call WoW functions from wRobot? I have the necessary technical knowledge, I just don't know how to get wRobot to execute asm in WoW's main thread.

Yes, you can. For example:

    //3.3.5a 12340
    public void MoveForwardStart()
    {
        wManager.Wow.Memory.WowMemory.InjectAndExecute(
            new []
            {
                //more parameters can be appended by the wrapper
                wManager.Wow.Memory.WowMemory.CallWrapperCode(
                    (uint)wManager.Wow.Memory.WowMemory.Memory.MainModuleAddress + 0x1FC200),
                wManager.Wow.Memory.WowMemory.RetnToHookCode,
            }, true
        );
    }

 

Targeting by guid for vanilla (not tested)

        private static readonly object LockTargeting = new object();

        public static void TargetUnit(ulong guid)
        {
            // Allocate memory for the target guid
            uint alloc = Memory.WowMemory.Memory.AllocateMemory(8);

            // Write guid
            Memory.WowMemory.Memory.WriteUInt64(alloc, guid);

            // Create asm
            string[] asm = new string[]
            {
                    $"mov ecx, {alloc}",
                    $"call {0x489A40}",
                    Memory.WowMemory.RetnToHookCode
            };

            lock (LockTargeting)
            {
                // Execute
                Memory.WowMemory.InjectAndExecute(asm);
            }

            // Free memory
            Memory.WowMemory.Memory.FreeMemory(alloc);
        }

 

Edited by iMod

  • 1 year later...
On 11/17/2017 at 4:51 PM, iMod said:

Targeting by guid for vanilla (not tested)


        private static readonly object LockTargeting = new object();

        public static void TargetUnit(ulong guid)
        {
            // Allocate memory for the target guid
            uint alloc = Memory.WowMemory.Memory.AllocateMemory(8);

            // Write guid
            Memory.WowMemory.Memory.WriteUInt64(alloc, guid);

            // Create asm
            string[] asm = new string[]
            {
                    $"mov ecx, {alloc}",
                    $"call {0x489A40}",
                    Memory.WowMemory.RetnToHookCode
            };

            lock (LockTargeting)
            {
                // Execute
                Memory.WowMemory.InjectAndExecute(asm);
            }

            // Free memory
            Memory.WowMemory.Memory.FreeMemory(alloc);
        }

 

Got a working example of this for 3.3.5a?
Changing $"call {0x489A40}" to $"call {0x524BF0}" does not suffice :S

Because target guid is a static offset in WotLK.
 

ObjectManager.Me.Target = unit.Guid;

works, or if you want to set mouseover:

private static void SetMouseoverGuid(ulong guid)
    {
        switch (Usefuls.WowVersion)
        {
            case 5875:
                Memory.WowMemory.Memory.WriteUInt64((uint)Memory.WowMemory.Memory.MainModuleAddress + 0x74E2C8, guid);
                break;
            case 8606:
                Memory.WowMemory.Memory.WriteUInt64((uint)Memory.WowMemory.Memory.MainModuleAddress + 0x86E950, guid);
                break;
            case 12340:
                Memory.WowMemory.Memory.WriteUInt64((uint) 0x00BD07A0, guid);
                break;
            default:
                throw new Exception("Wow version is not supported!");
        }
    }

private static void SetMouseoverUnit(WoWUnit unit)
    {
        SetMouseoverGuid(unit.Guid);
    }

public static void Target(WoWUnit unit)
    {
        ulong guid = unit.Guid;

        if (guid == 0)
        {
            return;
        }
        ulong tmp = Memory.WowMemory.Memory.ReadUInt64((uint)Memory.WowMemory.Memory.MainModuleAddress + 0x74E2C8);
        SetMouseoverUnit(unit);
        Lua.LuaDoString(@"TargetUnit(""mouseover"");");
		//do something here
        SetMouseoverUnit(tmp);
    }

 

23 minutes ago, Matenia said:

Because target guid is a static offset in WotLK.
 


ObjectManager.Me.Target = unit.Guid;

works, or if you want to set mouseover:


private static void SetMouseoverGuid(ulong guid)
    {
        switch (Usefuls.WowVersion)
        {
            case 5875:
                Memory.WowMemory.Memory.WriteUInt64((uint)Memory.WowMemory.Memory.MainModuleAddress + 0x74E2C8, guid);
                break;
            case 8606:
                Memory.WowMemory.Memory.WriteUInt64((uint)Memory.WowMemory.Memory.MainModuleAddress + 0x86E950, guid);
                break;
            case 12340:
                Memory.WowMemory.Memory.WriteUInt64((uint) 0x00BD07A0, guid);
                break;
            default:
                throw new Exception("Wow version is not supported!");
        }
    }

private static void SetMouseoverUnit(WoWUnit unit)
    {
        SetMouseoverGuid(unit.Guid);
    }

public static void Target(WoWUnit unit)
    {
        ulong guid = unit.Guid;

        if (guid == 0)
        {
            return;
        }
        ulong tmp = Memory.WowMemory.Memory.ReadUInt64((uint)Memory.WowMemory.Memory.MainModuleAddress + 0x74E2C8);
        SetMouseoverUnit(unit);
        Lua.LuaDoString(@"TargetUnit(""mouseover"");");
		//do something here
        SetMouseoverUnit(tmp);
    }

 

ObjectManager.Me.Target = unit.Guid;
Triggers interact/autoattack on hostile/neutral unit which is too annoying to live with.
The Mouseover solution is what I'm using right now but I consider that as an workaround.
I want a clean solution, as in Vanilla with the inject code.

Create an account or sign in to comment

Account

Navigation

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.