[Example] Check if spell is available with memory reading menu

User Tag List

Results 1 to 2 of 2
  1. #1
    orby_tale's Avatar Member
    Reputation
    5
    Join Date
    Jul 2009
    Posts
    11
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    [Example] Check if spell is available with memory reading

    Described method will help you to filter out spells which can’t be used due to the lack of mana (or holy power), wrong distance to target or other reasons. This will help to implement good combat rotations for your bot.

    The main trick is in getting information from this function API IsUsableAction - WoWWiki - Your guide to the World of Warcraft
    It seems that all prerequisites are calculated somewhere else and this function just checks two flags stored in memory. So we can easily do the same in our application.

    This piece of code will show the example usage:

    Code:
    of_enabled_action_btns = $9EDC58;
    of_no_mana_for_action_btns = $9EDA18;
    
    
    //i - number of Action button.
    is_available = mr.readUInt( mem_baseaddr + of_enabled_action_btns + i*4);
    not_enough_mana = mr.readUInt( mem_baseaddr + of_no_mana_for_action_btns + i*4);
    So here is the brief example code for building combat loop. First of all we need to prepare our action bar – rearrange spells in priority order. The spell with highest priority goes first. Here is example for retribution paladin:




    Now the example code in Delphi (ya, really which will give you the idea of how to put it all together.

    Credits for cooldown tracking goes to someone from mmowned.
    //4.0.1
    Code:
      SKILLS_BAR_FROM = 60;
      SKILLS_BAR_TO = 72;
    of_action_toolbar_start = $9EE0D4;
    of_spell_cooldowns = $980968;
    of_enabled_action_btns = $9EDC58;
    of_no_mana_for_action_btns = $9EDA18;
    
    
    
    {*******************************************}
    {**** SKILLS *******************************}
    procedure s_Combat.use_spell();
    var
      i : word;
      is_available, not_enough_mana : dword;
      x : byte;
      spid : dword;
      s : AnsiString;
    begin
    
      update_cooldowns();
      if (on_gcd) then begin
        if (gcd_left > 200) then sleep( gcd_left - 200 );
        exit;
      end;
      x := 0;
    
      for i := SKILLS_BAR_FROM to SKILLS_BAR_TO do begin
        inc(x);
        is_available := mr.readUInt( mem_baseaddr + of_enabled_action_btns + i*4);
        not_enough_mana := mr.readUInt( mem_baseaddr + of_no_mana_for_action_btns + i*4);
    
        if (is_available = 1) and ( not_enough_mana <> 1 )    then begin
          //get spell ID from btn
          spid := mr.readUInt(mem_baseaddr + of_action_toolbar_start + (i+1)*4);
    
          if not( on_cooldown(spid) ) then begin
            log(' btn '+inttostr(x)+' available ('+inttostr(spid)+')');
            s := inttostr(x);
            SendKey( wow_hwnd, s[1] );
            break;
          end;
        end;
      end;
      
    end;
    
    
    procedure s_Combat.update_cooldowns();
    var
      perfCount, frequency, currentTime: Int64;
      startTime, cooldown1, cooldown2, cooldownLength, globalLength, left: integer;
      curItem,spellId : dword;
    begin
      n_cooldowns := 0;
      on_gcd := false;
    
      QueryPerformanceFrequency(frequency);
      QueryPerformanceCounter(perfCount);
      currentTime := round( (perfCount * 1000) / frequency );
    
      curItem := mr.readUInt(mem_baseaddr + of_spell_cooldowns + $8);
      while ((curItem <> 0) and ((curItem and 1) = 0)) do begin
        spellId := mr.readUInt(curItem + $8);
        startTime := mr.readInt(curItem + $10);
        cooldown1 := mr.readInt(curItem + $14);
        cooldown2 := mr.readInt(curItem + $20);
        globalLength  := mr.readInt( curItem + $2C );
    
        if ( (startTime + globalLength) > currentTime) then begin
          on_gcd := true;
          gcd_left :=  (startTime + globalLength) - currentTime;
          exit;
        end;
    
    
        cooldownLength := max(cooldown1, cooldown2);
        left := (startTime + cooldownLength) - currentTime ;
        if left > 0 then begin
          //log( Format(' +sp CD: %x %d', [spellId, left]) );
          inc(n_cooldowns);
          spells_on_cooldown[ n_cooldowns ] := spellId;
        end;
        curItem := mr.readUInt(curItem + 4);
      end;
    end;
    
    
    function s_Combat.on_cooldown(spid:dword) : boolean;
    var
      i : word;
    begin
      result := false;
      for i := 1 to n_cooldowns do begin
        if spells_on_cooldown[ i ] = spid then begin
          result := true;
          exit;
        end;
      end;
    end;

    [Example] Check if spell is available with memory reading
  2. #2
    miceiken's Avatar Contributor Authenticator enabled
    Reputation
    208
    Join Date
    Dec 2007
    Posts
    401
    Thanks G/R
    7/8
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Very nice, I have been looking for something to check my cooldown out of process.
    I edited it a bit and tried to convert the cooldown part into a simple bool check on given spellid whether it was on cooldown or not, please note that this code is unclean and not tested!

    Code:
            [DllImport("kernel32.dll")]
            static extern bool QueryPerformanceCounter(out long lpPerformanceCounter);
            [DllImport("kernel32.dll")]
            static extern bool QueryPerformanceFrequency(out long lpFrequency);
            public static bool IsOnCooldown(int SpellId)
            {
                //long perfCount;
                long frequency;
                //QueryPerformanceFrequency(out perfCount);
                QueryPerformanceFrequency(out frequency);
                long perfCount = Memory.ReadRelative<long>(0x008A7F54);
    
                long currentTime = (perfCount * 1000) / frequency;
    
                var CurrentObject = Memory.ReadRelative<uint>(0x00980968 + 0x8);
                while ((CurrentObject != 0) && ((CurrentObject & 1) == 0))
                {
                    var spellId = Memory.Read<uint>(CurrentObject + 0x8);
                    if (spellId == SpellId)
                    {
                        var startTime = Memory.Read<uint>(CurrentObject + 0x10);
                        var cooldown1 = Memory.Read<uint>(CurrentObject + 0x14);
                        var cooldown2 = Memory.Read<uint>(CurrentObject + 0x20);
                        var globalCooldown = Memory.Read<uint>(CurrentObject + 0x2C);
    
                        if ((startTime + globalCooldown) > currentTime)
                            return true; // On global cooldown
    
                        var cooldownLength = Math.Max(cooldown1, cooldown2);
                        if ((startTime + cooldownLength) - currentTime > 0)
                            return true; // On regular cooldown
                    }
    
                    CurrentObject = Memory.Read<uint>(CurrentObject + 0x4);
                }
                return false;
            }
    Also note that instead of using QueryPerformanceCounter I read WoW's internal something, as suggested by Jujubosc here: http://www.mmowned.com/forums/world-...ml#post1970560
    The above method is still there, but commented out, so you go ahead and check what works better

Similar Threads

  1. Replies: 6
    Last Post: 09-08-2012, 03:22 AM
  2. need startup help with memory reading (C++, ReadProcessMemory)
    By sixpounder in forum WoW Memory Editing
    Replies: 13
    Last Post: 03-13-2011, 09:43 AM
  3. [C#/CE help] Need help with memory reading
    By dididii in forum Programming
    Replies: 0
    Last Post: 10-07-2010, 12:26 PM
  4. [Question] Select a Target With Memory Reading
    By fukmeimbroken in forum WoW Memory Editing
    Replies: 15
    Last Post: 03-31-2010, 04:56 AM
  5. [Autoit] Problem with Memory reading for looting *resolved*
    By spudstar99 in forum WoW Memory Editing
    Replies: 4
    Last Post: 05-15-2009, 10:26 PM
All times are GMT -5. The time now is 01:59 PM. Powered by vBulletin® Version 4.2.3
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2024 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search