Jump to content

Recommended Posts

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")

 

Link to comment
Share on other sites

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 :(

Link to comment
Share on other sites

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
Link to comment
Share on other sites

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
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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);
    }

 

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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
        );
    }

 

Link to comment
Share on other sites

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
Link to comment
Share on other sites

  • 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

Link to comment
Share on other sites

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);
    }

 

Link to comment
Share on other sites

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.
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...