[Wow][3.2.2] Getting the ammount of threat for a unit menu

Shout-Out

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 15 of 19
  1. #1
    Nesox's Avatar ★ Elder ★
    Reputation
    1280
    Join Date
    Mar 2007
    Posts
    1,238
    Thanks G/R
    0/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    [Wow][3.2.2] Getting the ammount of threat for a unit

    Oh hai!
    ive been trying for a while now to find the correct offset addy or whatnot for the ammount of threat towards unit, ive looked at theese functions;


    lua_UnitThreatSituation - 0x00598950
    http://www.wowwiki.com/API_UnitThreatSituation

    and

    lua_UnitDetailedThreatSituation - 0x00598A30
    http://www.wowwiki.com/API_UnitDetailedThreatSituation

    they both call this function,

    Code:
    push    0
    push    0
    push    0
    lea     eax, [ebp+var_1]
    push    eax
    lea     edx, [ebp+var_10]
    push    edx
    call    sub_6AE120      ; <".\Unit_C.cpp">
    char __thiscall sub_6AE120(void *this, int a2, int a3, int a4, int a5, int a6)

    a6, a5 and a4 get's passed as 0 and i think a3 and a2 is the objects to compare

    Code:
    char __thiscall sub_6AE120(void *this, int a2, int a3, int a4, int a5, int a6)
    {
      int v6; // eax@1
      int v7; // ebx@1
      int v8; // edi@1
      void *v9; // esi@1
      int v11; // eax@8
      int v12; // edi@8
      int v13; // eax@11
      int v14; // edi@11
      char result; // al@17
      int v17; // eax@1
      int v18; // edx@1
      char v19; // zf@8
      int v20; // eax@12
      int v24; // [sp+10h] [bp-8h]@1
      int v25; // [sp+14h] [bp-4h]@1
      char v26; // [sp+Ch] [bp-Ch]@12
    
      v8 = a2; // one of the units?
      v17 = *(_DWORD *)a2; 
      v18 = *(_DWORD *)(a2 + 4);
      v9 = this;
      v24 = *(_DWORD *)a2;
      v25 = v18;
      v6 = sub_6AB420((int)((char *)this + 4072), v17, (int)&v24);
      v7 = v6;
      if ( *((_DWORD *)v9 + 1017) | *((_DWORD *)v9 + 1016) && v6 )
      {
        if ( a3 )
          *(_BYTE *)a3 = *(_BYTE *)(v6 + 40);
        if ( a4 )                                                   // a4 is passed as 0
          *(_BYTE *)a4 = *(_BYTE *)(v6 + 41);
        _ECX = a5;                                                  // And so is a5
        if ( a5 )
        {
          v11 = *(_DWORD *)v8;
          v19 = *(_DWORD *)v8 == *((_DWORD *)v9 + 1016);
          v12 = *(_DWORD *)(v8 + 4);
          if ( v19 && v12 == *((_DWORD *)v9 + 1017) )
          {
            __asm
            {
              fld     ds:flt_9AE124
              fstp    dword ptr [ecx]
            }
          }
          else
          {
            v13 = GetObjectByGuid(v11, v12, 8);
            v14 = v13;
            if ( !v13 )
              goto LABEL_29;
            sub_649920(v13);
            __asm { fstp    [ebp+arg_4] }
            v20 = (*(int (__thiscall **)(int, char *))(*(_DWORD *)v14 + 0x28))(v14, &v26);
            sub_496B80(v20);
            __asm
            {
              fld     [ebp+arg_4]
              fmul    st, st
              fcompp  st(1), st
              fnstsw  ax
            }
            if ( HIBYTE(_AX) & 1 )
            {
    LABEL_29:
              _EAX = a5;
              a3 = *(_BYTE *)(v7 + 0x29);
              __asm
              {
                fild    [ebp+arg_4]
                fmul    ds:flt_9E95A8
                fstp    dword ptr [eax]
              }
            }
            else
            {
              _ECX = a5;
              a3 = *(_BYTE *)(v7 + 41);
              __asm
              {
                fild    [ebp+arg_4]
                fmul    ds:flt_9E95AC
                fstp    dword ptr [ecx]
              }
            }
          }
        }
        if ( a6 )                                                   // a6 is also 0
          *(_DWORD *)a6 = *(_DWORD *)(v7 + 44);
        result = 1;
      }
      else
      {
        if ( a3 )
          *(_BYTE *)a3 = v6 != 0;
        if ( a4 )
          *(_BYTE *)a4 = 0;
        _EAX = a5;
        if ( a5 )
        {
          __asm
          {
            fldz
            fstp    dword ptr [eax]
          }
        }
        if ( a6 )
          *(_DWORD *)a6 = 0;
        result = 0;
      }
      return result;
    }
    Any ideas?

    Last edited by Nesox; 11-16-2009 at 09:33 AM.

    [Wow][3.2.2] Getting the ammount of threat for a unit
  2. #2
    flo8464's Avatar Active Member
    Reputation
    30
    Join Date
    Apr 2009
    Posts
    434
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    this is the object mentioned as "mob".
    The first argument is a pointer to your GUID
    The second argument is a pointer to something, [ebp + something-1] should contain your threat.

    Wouldn't be hard to find out what that function does if you know what objectbase + 0xFE8 is. :/
    Last edited by flo8464; 11-16-2009 at 10:36 AM.
    Hey, it compiles! Ship it!

  3. #3
    Nesox's Avatar ★ Elder ★
    Reputation
    1280
    Join Date
    Mar 2007
    Posts
    1,238
    Thanks G/R
    0/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by flo8464 View Post
    this is the object mentioned as "mob".
    The first argument is a pointer to your GUID
    The second argument is a pointer to something, [ebp + something-1] should contain your threat.

    Wouldn't be hard to find out what that function does if you know what objectbase + 0xFE8 is. :/
    Ok, thanks gonna fool around some moar with it

  4. #4
    Apoc's Avatar Angry Penguin
    Reputation
    1388
    Join Date
    Jan 2008
    Posts
    2,750
    Thanks G/R
    0/13
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Neat.

    FYI; I did some naming and whatnot...

    CGUnit_C__GetThreatInfo(WoWUnit* this, WGUID* unitGuid, PBYTE threatStatus, PBYTE threatPct, PBYTE rawThreatPct, DWORD* threatValue);

    'this' should be a pointer to the unit who you are checking threat against.
    unitGuid should be a pointer to the GUID of the party/raid/etc member who you want to check the threat levels for.
    threatStatus returns nil and 0-3 for the threat value. (See API UnitThreatSituation - WoWWiki - Your guide to the World of Warcraft)

    The rest are detailed here; API UnitDetailedThreatSituation - WoWWiki - Your guide to the World of Warcraft

    The confusing bit here (that actually got me...) is that the object being pushed into ecx isn't actually anybody in your party (or yourself). It's actually the mob you want to check threat on. (Since threat tables are held within each unit, it needs to check via those [assuming they're private threat tables?])

    Thusly:

    CGUnit_C__GetThreatInfo(pRaidBoss, &localGuid, &threatStatus, &threatPct, &rawThreatPct, &threatValue);

    Correct me if I'm wrong (I may be wrong with the 2 percent vals, but why would you bother using that in a bot anyway? )

  5. #5
    Nesox's Avatar ★ Elder ★
    Reputation
    1280
    Join Date
    Mar 2007
    Posts
    1,238
    Thanks G/R
    0/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Apoc View Post
    Neat.

    FYI; I did some naming and whatnot...

    CGUnit_C__GetThreatInfo(WoWUnit* this, WGUID* unitGuid, PBYTE threatStatus, PBYTE threatPct, PBYTE rawThreatPct, DWORD* threatValue);

    'this' should be a pointer to the unit who you are checking threat against.
    unitGuid should be a pointer to the GUID of the party/raid/etc member who you want to check the threat levels for.
    threatStatus returns nil and 0-3 for the threat value. (See API UnitThreatSituation - WoWWiki - Your guide to the World of Warcraft)

    The rest are detailed here; API UnitDetailedThreatSituation - WoWWiki - Your guide to the World of Warcraft

    The confusing bit here (that actually got me...) is that the object being pushed into ecx isn't actually anybody in your party (or yourself). It's actually the mob you want to check threat on. (Since threat tables are held within each unit, it needs to check via those [assuming they're private threat tables?])

    Thusly:

    CGUnit_C__GetThreatInfo(pRaidBoss, &localGuid, &threatStatus, &threatPct, &rawThreatPct, &threatValue);

    Correct me if I'm wrong (I may be wrong with the 2 percent vals, but why would you bother using that in a bot anyway? )

    Awesum, gonna try it in a sec;
    Gonna use it for enumerating target's in combat, right now im just checking if they are targeting me and if they are affected by combat but that feel really ghey
    so i want to check the actual threat level to see if i got any threat towards said unit to check if it's angry with me

  6. #6
    Kryso's Avatar Active Member
    Reputation
    40
    Join Date
    Jul 2009
    Posts
    97
    Thanks G/R
    0/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Allright, this is what I've found. It looks realy weird, but it works for me. The loop itself can be found in function at 0x006AB420 and looks like this:

    int __thiscall GetEntryByGuid(void *this, int loGuid, QWORD *guid)

    I have no idea why it's passing loGuid and then whole guid (maybe.. well probably.. I've reversed it wrong) nor why we need loGuid & magicNumber (which in my case was always equal to 3)

    Also I've noticed that when NPC is fighting to another NPC, you can't see it's threat most of the time, havent tried with players tho.

    Code:
    Console.WriteLine( "player guid: " + WowClient.World.Player.Guid );
    Console.WriteLine( "target guid: " + WowClient.World.Player.Target.Guid );
    
    IntPtr threatTable = Address.Offset( 0xfe8 );
    Console.WriteLine( "table: " + threatTable.ToHexString() );
    
    uint loGuid = ( uint )( ( ulong )WowClient.World.Player.Guid & 0xffffffff );
    uint magicNumber = ( uint )( process.Read<int>( threatTable.Offset( 0x24 ) ) & loGuid );
    
    IntPtr threatTableUnk = process.Read<IntPtr>( threatTable.Offset( 0x1c ) );
    threatTableUnk = threatTableUnk.Offset( magicNumber * 12 );
    
    IntPtr current = process.Read<IntPtr>( threatTableUnk.Offset( 8 ) );
    while ( current != IntPtr.Zero && current.IsEven() ) {
        Console.WriteLine( "ThreatEntry " + current.ToHexString() );
        Console.WriteLine( " >  loGuid: " + process.Read<IntPtr>( current.Offset( 0x8 ) ).ToHexString() );
        Console.WriteLine( " >  guid: 0x" + process.Read<ulong>( current.Offset( 0x20 ) ).ToString( "x16" ) );
        Console.WriteLine( " >  threat value: " + process.Read<int>( current.Offset( 0x2c ) ) );
    
        current = process.Read<IntPtr>( current.Offset( process.Read<int>( threatTableUnk ) + 4 ) );
    }
    And one silly question from me: Apoc, could you explain naming you're using? What does CG and _C__ mean?
    Last edited by Kryso; 11-16-2009 at 08:43 PM. Reason: simplified :p

  7. #7
    flo8464's Avatar Active Member
    Reputation
    30
    Join Date
    Apr 2009
    Posts
    434
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    CGUnit probably means "Class GameUnit".

    @Topic: Oh lol, didn't check the API description and thought API UnitThreatSituation - WoWWiki - Your guide to the World of Warcraft returns the thread ... but its only that state.

    But interesting to know that 0xFE8 points to a threat-table
    Hey, it compiles! Ship it!

  8. #8
    Apoc's Avatar Angry Penguin
    Reputation
    1388
    Join Date
    Jan 2008
    Posts
    2,750
    Thanks G/R
    0/13
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Kryso View Post
    Allright, this is what I've found. It looks realy weird, but it works for me. The loop itself can be found in function at 0x006AB420 and looks like this:

    int __thiscall GetEntryByGuid(void *this, int loGuid, QWORD *guid)

    I have no idea why it's passing loGuid and then whole guid (maybe.. well probably.. I've reversed it wrong) nor why we need loGuid & magicNumber (which in my case was always equal to 3)

    Also I've noticed that when NPC is fighting to another NPC, you can't see it's threat most of the time, havent tried with players tho.

    Code:
    Console.WriteLine( "player guid: " + WowClient.World.Player.Guid );
    Console.WriteLine( "target guid: " + WowClient.World.Player.Target.Guid );
    
    IntPtr threatTable = Address.Offset( 0xfe8 );
    Console.WriteLine( "table: " + threatTable.ToHexString() );
    
    uint loGuid = ( uint )( ( ulong )WowClient.World.Player.Guid & 0xffffffff );
    uint magicNumber = ( uint )( process.Read<int>( threatTable.Offset( 0x24 ) ) & loGuid );
    
    IntPtr threatTableUnk = process.Read<IntPtr>( threatTable.Offset( 0x1c ) );
    threatTableUnk = threatTableUnk.Offset( magicNumber * 12 );
    
    IntPtr current = process.Read<IntPtr>( threatTableUnk.Offset( 8 ) );
    while ( current != IntPtr.Zero && current.IsEven() ) {
        Console.WriteLine( "ThreatEntry " + current.ToHexString() );
        Console.WriteLine( " >  loGuid: " + process.Read<IntPtr>( current.Offset( 0x8 ) ).ToHexString() );
        Console.WriteLine( " >  guid: 0x" + process.Read<ulong>( current.Offset( 0x20 ) ).ToString( "x16" ) );
        Console.WriteLine( " >  threat value: " + process.Read<int>( current.Offset( 0x2c ) ) );
    
        current = process.Read<IntPtr>( current.Offset( process.Read<int>( threatTableUnk ) + 4 ) );
    }
    And one silly question from me: Apoc, could you explain naming you're using? What does CG and _C__ mean?
    The CGUnit_C/CGObject_C/etc are naming conventions Blizzard actually used in WoW. (Apparent from the alpha PDB) I just use them to keep things somewhat sane.

    And yes; flo is right. ClassGameUnit_Class, kinda redundant, but whatever.

    At any rate; the low GUID is the 'actual unique ID' of the object. The high part is just some hashed object info. (Type, etc) Using the low bytes saves some memory; and makes using a hash bucket easier.

  9. #9
    amadmonk's Avatar Active Member
    Reputation
    124
    Join Date
    Apr 2008
    Posts
    772
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Of course, every modern language supports hashing on 64 bit values, so... :P

    (Note, "modern" language -- I intentionally didn't include C++...)

    FWIW, I've got this working on my bot and the method suggested is the best. I originally wanted to get full threat tables, but I don't think these are kept client-side (it would be an interesting experiment to try to use this method to get detailed threat info on a mob towards a person who is not in your party or raid, is not your focus, lasttarget, target, or mouseover; I'm curious if your client even receives this information... my bet is no)
    Don't believe everything you think.

  10. #10
    namreeb's Avatar Legendary

    Reputation
    668
    Join Date
    Sep 2008
    Posts
    1,029
    Thanks G/R
    8/222
    Trade Feedback
    0 (0%)
    Mentioned
    9 Post(s)
    Tagged
    0 Thread(s)
    No? Doesn't the client warn you when you are about to pull agro off a mob that you don't have the tap on?

  11. #11
    Cypher's Avatar Kynox's Sister's Pimp
    Reputation
    1358
    Join Date
    Apr 2006
    Posts
    5,368
    Thanks G/R
    0/6
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by amadmonk View Post
    Of course, every modern language supports hashing on 64 bit values, so... :P

    (Note, "modern" language -- I intentionally didn't include C++...)

    FWIW, I've got this working on my bot and the method suggested is the best. I originally wanted to get full threat tables, but I don't think these are kept client-side (it would be an interesting experiment to try to use this method to get detailed threat info on a mob towards a person who is not in your party or raid, is not your focus, lasttarget, target, or mouseover; I'm curious if your client even receives this information... my bet is no)
    std::size_t Hash = std::hash<T>()(Foo);

    Where T is the type of the object you're hashing, and Foo is the instance of the object.

    Side note: Yes, this uses TR1, but all major compilers/stl-implementations support TR1, and if they don't, Boost has an implementation.

  12. #12
    rootguy's Avatar Member
    Reputation
    3
    Join Date
    Aug 2008
    Posts
    36
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thank you all for this great piece of info!
    After some playing around i came to the following function def:

    unsigned char WOWUnit::GetThreatInfo(u_int64_t* guid, unsigned long* threatStatus, float* threatPct, float* rawThreatPct, unsigned long* threatValue)

    the percentages are both pointers to floats and the function returns an unsigned byte which is the isTanking value described in the UnitDetailedThreatSituation("unit", "mob") info

    I'll put this to great use in my instance healer bots

  13. #13
    amadmonk's Avatar Active Member
    Reputation
    124
    Join Date
    Apr 2008
    Posts
    772
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I was going to put some snide quip about how that wasn't built into the language, it was just a lib. And then I thought about what I was about to say, and ate a donut instead.
    Don't believe everything you think.

  14. #14
    Cypher's Avatar Kynox's Sister's Pimp
    Reputation
    1358
    Join Date
    Apr 2006
    Posts
    5,368
    Thanks G/R
    0/6
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by amadmonk View Post
    I was going to put some snide quip about how that wasn't built into the language, it was just a lib. And then I thought about what I was about to say, and ate a donut instead.
    Hahahaha. Good call.

    The STL is considered "part of the language" as far as C++ is concerned anyway. There are two "parts" of the "language". The "core language" and the "standard libraries". C++ is a libraries language, it has the bare minimums built into the core language, because the idea is that if possible things should be implemented as libraries.

  15. #15
    FenixTX2's Avatar Active Member
    Reputation
    23
    Join Date
    Mar 2009
    Posts
    125
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hello all,
    I'm trying to call the function in question using asm (currently at 0x005dfc70 in 3.3.3).
    I know it must be something trivial that I'm not doing but i've been at it for a while and was hoping to get a little help.

    Trying to send pCurTarget.baseAddress as the first argument and then a location in memory for player.GUID

    This is pretty much the code I have atm:
    Code:
    OM.wow.Asm.AddLine("fs mov eax, [0x2C]");
    OM.wow.Asm.AddLine("mov eax, [eax]");
    OM.wow.Asm.AddLine("add eax, 0x8");
    OM.wow.Asm.AddLine("mov dword [eax], {0}", OM.Cur_ObjMgr);
    
    OM.wow.Asm.AddLine("push 0");
    OM.wow.Asm.AddLine("push 0");
    OM.wow.Asm.AddLine("push 0");
    OM.wow.Asm.AddLine("push 0");
    OM.wow.Asm.AddLine("mov esp, {0}", playerGUIDLocation);
    OM.wow.Asm.AddLine("mov ecx, {0}", pCurTarget.baseAddress);
    OM.wow.Asm.AddLine("push esp");
    OM.wow.Asm.AddLine("push ecx");
    
    OM.wow.Asm.AddLine("call {0}", 0x005dfc70);
    OM.wow.Asm.AddLine("add esp, 0x14");
    OM.wow.Asm.AddLine("retn");
    WoW just craps out each time I try using this.
    Any help would really be appreciated.

    I have tried allocating memory for each of the return values and pushing those locations instead of "push 0" but WoW just crashed out again.

    Thanks


Page 1 of 2 12 LastLast

Similar Threads

  1. [Selling] Triple Threat wow account, buy 2 get the 3rd free *Bonus offer inside*
    By Unscrupulous in forum WoW-EU Account Buy Sell Trade
    Replies: 2
    Last Post: 05-31-2012, 10:34 AM
  2. [Selling] Triple Threat wow account - Buy 2 get the 3rd FREE *Secret Bonus offer Inside*
    By Unscrupulous in forum WoW-US Account Buy Sell Trade
    Replies: 3
    Last Post: 05-28-2012, 09:21 AM
All times are GMT -5. The time now is 08:23 AM. Powered by vBulletin® Version 4.2.3
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Google Authenticator verification provided by Two-Factor Authentication (Free) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search