[C#] Getting GCD or SpellCooldown menu

User Tag List

Results 1 to 11 of 11
  1. #1
    Empted's Avatar Contributor
    Reputation
    83
    Join Date
    Aug 2011
    Posts
    117
    Thanks G/R
    0/5
    Trade Feedback
    2 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    [C#] Getting GCD or SpellCooldown

    Credits go to Nesox for GCD snippet, just updated the function to the current patch and declared all needed. GetSpellCD made in the same way here.
    PHP Code:
            public enum eSpellHistory uint
            
    {
                
    SpellHistory=0xBD0B68,
                
    FirstRec=0x8,
                
    NextRec 0x4,
                
    StartTime=0x10,
                
    GlobalCooldown 0x30,
                
    SpellID=0x8,
                
    SpellCoolDown=0x20
            
    }
            [
    DllImport("kernel32.dll"SetLastError true)]
            static 
    extern uint QueryPerformanceCounter(out long lpPerformanceCount);
            [
    DllImport("kernel32.dll"SetLastError true)]
            static 
    extern uint QueryPerformanceFrequency(out long lpFrequency);
            public 
    int GetSpellCooldown(int spellID)
            {

                
    long frequency;
                
    long perfCount;
                
    QueryPerformanceFrequency(out frequency);
                
    QueryPerformanceCounter(out perfCount);

                
    //Current time in ms
                
    long currentTime = (perfCount 1000) / frequency;

                
    //Get first list object
                
    var currentListObject wow.ReadUInt((uint)Offsets.eSpellHistory.SpellHistory dwCodeLoc + (uint)Offsets.eSpellHistory.FirstRec);
                
                
    int cooldown 0;
                
    uint startTime 0;//get record with latest starttime
                
    while ((currentListObject != 0) && ((currentListObject 1) == 0))
                {

                    if (
    wow.ReadInt(currentListObject + (uint)Offsets.eSpellHistory.SpellID) == spellID)//filter by ID here
                    
    {
                        var 
    currentStartTime wow.ReadUInt(currentListObject + (uint)Offsets.eSpellHistory.StartTime);
                        if (
    currentStartTime startTime//get CD for the latest start time record
                        
    {
                            
    startTime currentStartTime;
                            var 
    spellCD=wow.ReadInt(currentListObject + (uint)Offsets.eSpellHistory.SpellCoolDown);
                            
    cooldown = (int)(startTime spellCD currentTime);
                        }
                    }
                    
    //Get next list object
                    
    currentListObject wow.ReadUInt(currentListObject + (uint)Offsets.eSpellHistory.NextRec);
                }
                return (
    cooldown<0) ? cooldown/1000;
            }
            public 
    bool GlobalCooldown
            
    {
                
    get
                
    {
                    
    long frequency;
                    
    long perfCount;
                    
    QueryPerformanceFrequency(out frequency);
                    
    QueryPerformanceCounter(out perfCount);

                    
    //Current time in ms
                    
    long currentTime = (perfCount 1000) / frequency;

                    
    //Get first list object
                    
    var currentListObject wow.ReadUInt((uint)Offsets.eSpellHistory.SpellHistory dwCodeLoc + (uint)Offsets.eSpellHistory.FirstRec);

                    while ((
    currentListObject != 0) && ((currentListObject 1) == 0))
                    {
                        var 
    bytes wow.ReadBytes(currentListObject0x100);
                        
    //Start time of the spell cooldown in ms
                        
    var startTime wow.ReadUInt(currentListObject + (uint)Offsets.eSpellHistory.StartTime);

                        
    //Absolute gcd of the spell in ms
                        
    var globalCooldown wow.ReadUInt(currentListObject + (uint)Offsets.eSpellHistory.GlobalCooldown);

                        
    //Spell on gcd?
                        
    if ((startTime globalCooldown) > currentTime)
                            return 
    true;


                        
    //Get next list object
                        
    currentListObject wow.ReadUInt(currentListObject + (uint)Offsets.eSpellHistory.NextRec);
                    }
                    return 
    false;
                }
            } 
    Last edited by Empted; 10-26-2012 at 09:28 AM. Reason: update spellhistory enum

    [C#] Getting GCD or SpellCooldown
  2. #2
    iceblockman's Avatar Member
    Reputation
    2
    Join Date
    Jun 2012
    Posts
    36
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    nice that's what i am currently looking for.
    Additional info I figured out
    1. dwCodeLoc = wowbase
    2. there are 0 to 3 records for the same spell id
    3. the spellcooldown field for spell not cause gcd is always 0

    //edit
    3. the spellcooldown field for spell not cause/trigger gcd is not always 0 , also is not always the spell cd duration
    Last edited by iceblockman; 10-27-2012 at 01:36 AM.

  3. #3
    Empted's Avatar Contributor
    Reputation
    83
    Join Date
    Aug 2011
    Posts
    117
    Thanks G/R
    0/5
    Trade Feedback
    2 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    1 Yes, true
    2 Actually, don't know much about SpellHistory structure, still there is function named SpellHistory::GarbageCollect, so I suppose that yes, there can be not a single record for one spell ID (that's why I pick the latest start time record to get cooldown).
    3 It's not really so. Some of no-gcd spells may have no cooldown, check for interrupt casts (mage counterspell), I guess there will be.
    Last edited by Empted; 10-26-2012 at 01:59 PM.

  4. #4
    iceblockman's Avatar Member
    Reputation
    2
    Join Date
    Jun 2012
    Posts
    36
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    yeah my third points is not correct. I checked a few more no gcd spell, the spellcooldown field some show 0 some is correct duration.

    how you guys find the offset ? may i request a few more offsets like deathnight rune cd offset ?

  5. #5
    Empted's Avatar Contributor
    Reputation
    83
    Join Date
    Aug 2011
    Posts
    117
    Thanks G/R
    0/5
    Trade Feedback
    2 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by iceblockman View Post
    yeah my third points is not correct. I checked a few more no gcd spell, the spellcooldown field some show 0 some is correct duration.

    how you guys find the offset ? may i request a few more offsets like deathnight rune cd offset ?
    You are welcome: http://www.ownedcore.com/forums/worl...ple-stuff.html ([Guide] Finding not so simple stuff.)

  6. #6
    -Ryuk-'s Avatar Elite User CoreCoins Purchaser Authenticator enabled
    Reputation
    529
    Join Date
    Nov 2009
    Posts
    1,028
    Thanks G/R
    38/51
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If you are injected you can do this by calling Spell_C_GetSpellCooldown (WoW 5.0.5.16135 = 0x3E60E0(rebased))

    The code is as follows:

    Code:
                int start = 0;
                int duration = 0;
                bool isReady = false;
                int unk0 = 0;
    
    
                _getSpellCooldown(spellid, false, ref duration, ref start, ref isReady, ref unk0);
    
    
                int result = start + duration - (int) GeneralHelper.PerformanceCount;
    To get the time in seconds do:

    Code:
    result/1000f
    |Leacher:11/2009|Donor:02/2010|Established Member:09/2010|Contributor:09/2010|Elite:08/2013|

  7. #7
    Empted's Avatar Contributor
    Reputation
    83
    Join Date
    Aug 2011
    Posts
    117
    Thanks G/R
    0/5
    Trade Feedback
    2 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by -Ryuk- View Post
    If you are injected you can do this by calling Spell_C_GetSpellCooldown (WoW 5.0.5.16135 = 0x3E60E0(rebased))
    Thank you, It seems to be more reliable . Though I avoid calling functions because of having multiple threads (need for sync then, which slows down the whole process).
    Last edited by Empted; 11-01-2012 at 05:27 PM.

  8. #8
    reliasn's Avatar Legendary Authenticator enabled
    Reputation
    774
    Join Date
    Jan 2009
    Posts
    136
    Thanks G/R
    24/215
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Updated offsets for 7.0.3.22345 (Windows 32-bit). And a working C++ sample:

    Code:
    long getCurrentTime(){
        LARGE_INTEGER frequency, counter;
        QueryPerformanceFrequency(&frequency);
        QueryPerformanceCounter(&counter);
        long currentTime = (counter.QuadPart * 1000) / frequency.QuadPart;
        return currentTime;
    }
    
    int getSpellCooldown(int id){
        long currentTime = getCurrentTime();
    
        DWORD spellObj = read<DWORD>(wowBase + s_spellHistory + 8), startTime = 0;   // s_spellHistory = 0xD37308
        int cooldown = 0;
        while(spellObj && ((spellObj & 1) == 0)){
            DWORD spellId = read<DWORD>(spellObj + 0x8);
            if(spellId == id){
                DWORD sTime = read<DWORD>(spellObj + 0x10);
                if(sTime > startTime){
                    startTime = sTime;
                    DWORD spellCd = read<DWORD>(spellObj + 0x14);
                    cooldown = startTime + spellCd - currentTime;
                }
            }
            spellObj = read<DWORD>(spellObj + 4);
        }
        
        return cooldown < 0 ? 0 : cooldown;
    }
    
    int getGlobalCooldown(){
        long currentTime = getCurrentTime();
    
        DWORD spellObj = read<DWORD>(wowBase + s_spellHistory + 8);   // s_spellHistory = 0xD37308
        int cooldown = 0;
        while(spellObj && ((spellObj & 1) == 0)){
            DWORD sTime = read<DWORD>(spellObj + 0x10);
            int globalCd = read<DWORD>(spellObj + 0x30);
            cooldown = sTime + globalCd - currentTime;
            if(cooldown > 0){
                return cooldown;
            }
            spellObj = read<DWORD>(spellObj + 4);
        }
        
        return 0;
    }
    I implemented a loop to log the Global Cooldown and casted 2s Frostbolts on a dummy and got curious about something:
    1 - When casting the first spell, the global cooldown starts at 1500 and ends at 0, as expected.
    2 - While spamming the spell, there would be times the global cooldown would start on some value higher than 1500.
    Code:
    First Number = Frostbolt Cooldown, Third = Global Cooldown
    // First cast starts
    CD: 0 0 1495
    CD: 0 0 1479
    CD: 0 0 1464
    CD: 0 0 1449
    CD: 0 0 1433
    CD: 0 0 1413
    CD: 0 0 1402
    CD: 0 0 1382
    CD: 0 0 1369
    ...
    // First cast ends
    CD: 0 0 265
    CD: 0 0 249
    CD: 0 0 234
    CD: 0 0 182
    CD: 0 0 170
    CD: 0 0 121
    CD: 0 0 108
    CD: 0 0 88
    CD: 0 0 73
    CD: 0 0 31
    CD: 0 0 15
    CD: 0 0 0
    CD: 0 0 0
    CD: 0 0 0
    // New cast begins
    CD: 380 0 1880
    CD: 360 0 1860
    CD: 344 0 1844
    Is this because WoW queued a new spell and the new global cooldown is 1500 + remaining cast on the current spell?

  9. #9
    Zazazu's Avatar Contributor
    Reputation
    191
    Join Date
    Jun 2016
    Posts
    390
    Thanks G/R
    5/143
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    PHP Code:
    DWORD sTime read<DWORD>(spellObj 0x10);
    int globalCd read<DWORD>(spellObj 0x30);
    cooldown sTime globalCd currentTime;
    if(
    cooldown 0){
                return 
    cooldown;

    DWORD sTime = read<DWORD>(spellObj + 0x28); // 0x28 StartGCD

    Start cast spell != start GCD

  10. #10
    reliasn's Avatar Legendary Authenticator enabled
    Reputation
    774
    Join Date
    Jan 2009
    Posts
    136
    Thanks G/R
    24/215
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Zazazu View Post
    DWORD sTime = read<DWORD>(spellObj + 0x2; // 0x28 StartGCD

    Start cast spell != start GCD
    They are very, very close to each other. I was logging the difference between 0x10 and 0x28 and they are most of the times equal. Only when spamming that I would get about 4-30ms difference.

    Regarding the GCD > 1500, is it correct what I said? Although I read the correct value from 0x28, I still get GCD > 1500.

    Edit: It's definitely adding the remaining cast to my final GCD. Started casting Hearthstone, spammed some spell and the remaining Hearthstone cast is being added to the GCD.
    Last edited by reliasn; 08-08-2016 at 02:14 PM.

  11. #11
    Zazazu's Avatar Contributor
    Reputation
    191
    Join Date
    Jun 2016
    Posts
    390
    Thanks G/R
    5/143
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by reliasn View Post
    Although I read the correct value from 0x28, I still get GCD > 1500.
    I think y get time wrong spell
    Like this (Last GCD: wow+s_spellHistory+8):
    Code:
    #1 GCD SpellID: 19750 [False] 43223399 + 1500 - 43230441 = -5542 [0]
    #2 GCD SpellID: 19750 [True] 43229039 + 1500 - 43230441 = 98 [92] [0]
    Actual GCD #1, y code get time from #2, but spell #2 casting and not actual firing GCD. Actual GCD still from spell #1.

    For spam spell (SpellCooldowns: wow+s_spellHistory+4):
    Code:
    #1	GCD SpellID: 19750 [False] 43568437 + 1500 - 43571494 = -1557 [0]
    #2	GCD SpellID: 19750 [False] 43566632 + 1500 - 43571494 = -3362 [0]
    #3	GCD SpellID: 19750 [True] 43570357 + 1500 - 43571494 = 363 [358]
    #4	GCD SpellID: 19750 [False] 43564835 + 1500 - 43571494 = -5159 [0]
    #5	GCD SpellID: 19750 [False] 43562965 + 1500 - 43571494 = -7029 [0]
    Spell #3 -- spell is casting
    Spell #1 -- last casting spell, and last spell triggered GCD
    Last edited by Zazazu; 08-08-2016 at 04:23 PM.

Similar Threads

  1. Get your first mount in WoW easily
    By Matt in forum World of Warcraft Guides
    Replies: 3
    Last Post: 11-03-2006, 09:46 PM
  2. How to get to the outlands on a live blizzard server
    By Matt in forum World of Warcraft Exploits
    Replies: 4
    Last Post: 06-16-2006, 05:27 PM
  3. You can still get to the airport :)
    By janzi9 in forum World of Warcraft Exploits
    Replies: 2
    Last Post: 03-27-2006, 01:25 PM
  4. Get on to where the Auction house people are!
    By janzi9 in forum World of Warcraft Exploits
    Replies: 0
    Last Post: 03-06-2006, 11:44 PM
  5. Getting into BG with that pesky deserters buff!
    By janzi9 in forum World of Warcraft Exploits
    Replies: 0
    Last Post: 03-06-2006, 11:35 PM
All times are GMT -5. The time now is 02:25 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