Do the spells you're testing with only have a global cooldown?
Do the spells you're testing with only have a global cooldown?
This appears to be the new address for this function and the offsets in the first post seem to still be the same as well. However, I still keep getting 0 for all my spells' cooldowns with 0x14. I must be doing something wrong.Code:uint currentListObject = Memory.ReadUInt(0x13256C8 + 0x8);
For spells without gcd the cooldown length is at listObject + 0x20.
Quick and dirty solution:
Code:public bool IsSpellReady(String sSpellName) { long frequency; long perfCount; Kernel32.QueryPerformanceFrequency(out frequency); Kernel32.QueryPerformanceCounter(out perfCount); //Current time in ms long currentTime = (perfCount * 1000) / frequency; //Get first list object uint currentListObject = Memory.Read<uint>(0x013256C8 + 0x8); while ((currentListObject != 0) && ((currentListObject & 1) == 0)) { uint spellId = Memory.Read<uint>(currentListObject + 0x8); if (GetSpellName(spellId) == sSpellName) { //Start time of the spell cooldown in ms uint startTime = Memory.Read<uint>(currentListObject + 0x10); //Cooldown of spells with gcd int cooldown1 = Memory.Read<int>(currentListObject + 0x14); //Cooldown of spells without gcd int cooldown2 = Memory.Read<int>(currentListObject + 0x20); int cooldownLength = Math.Max(cooldown1, cooldown2); if ((startTime + cooldownLength) > currentTime) { return false; } } currentListObject = Memory.Read<uint>(currentListObject + 4); } return true; }
Thanks a bunch Gorzul. That was exactly what I was looking for. I knew the 0x20 was in there for some reason I just never tested it lol.
Hi I was wondering if this method got obsolete since
uint cd = Memory.ReadUInt(currentListObject + 0x2C);
always returns 0.
Im trying to make a method that would return true if the spell is currently in cooldown.
here is what im trying:
The problem of using time is that im not sure if the start time stored in the list would match the start time that you get by usingCode:public Boolean IsSpellReady(uint spellid) { //Get first list object uint currentListObject = Memory.ReadUInt(hProcess, (spellsOnCooldown + 0x8)); while ((currentListObject != 0) && ((currentListObject & 1) == 0)) { uint currentSpellId = Memory.ReadUInt(hProcess, currentListObject + 8); if (currentSpellId == spellid) { uint cd = Memory.ReadUInt(hProcess, (currentListObject + 0x2C)); if (cd!=0) { return false; } else { return true; } } //Get next list object currentListObject = Memory.ReadUInt(hProcess, currentListObject + 4); } return true; }
And if they do match what if the cooldown increases by an external factor eg. u get silenced or if using a Death knight you use both of u runes(that increases the cd of all spells in the same talent tree).Code:long frequency; long perfCount; Kernel32.QueryPerformanceFrequency(out frequency); Kernel32.QueryPerformanceCounter(out perfCount); //Current time in ms long currentTime = (perfCount * 1000) / frequency;
I searched a lot to try to find more nfo about spell cooldowns or action bar cooldows but I didnt had any luck.
I really prefere not to use time counters nor inyection (not that im scared about it :P its just that my reading class does only reading no inyection at all)
any ideas?
Last edited by mordok; 10-25-2009 at 12:27 AM.
"I'm not going to expose my methods for time bending, as i don't want to do get nerfed!"-Kynox
Some of the offsets changed afaik just use Spell_C__GetCooldown![]()
List starts at 0x0133B7C0
First item [list + 0x8]
Next item [item + 0x4]
Code:spellId = process.Read<int>( address.Offset( 0x8 ) ); start = process.Read<int>( address.Offset( 0x10 ) ); length = process.Read<int>( address.Offset( 0x14 ) ) + process.Read<int>( address.Offset( 0x20 ) ); isEnabled = process.Read<byte>( address.Offset( 0x24 ) ) == 1; globalLength = process.Read<int>( address.Offset( 0x2c ) );
And for calculation of remaining time (in seconds):
Note that length needs 2 values. Sometimes there is negative value at 0x14 (for example Penance with glyph and talent) and you need to add value at 0x20. However if the cooldown on spell is negated completely by talents (for example Power Word: Shield) you will still get negative value even after adding value at 0x20.Code:Math.Max( Math.Max( length, globalLength ) - ( Environment.TickCount - start ), 0 ) / 1000f;
"Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live." - Martin Golding
"I cried a little earlier when I had to poop" - Sku
This always returns 0 : (
Code:Math.Max( Math.Max( length, globalLength ) - ( Environment.TickCount - start ), 0 ) / 1000f;
Last edited by mordok; 10-25-2009 at 10:13 AM.
"I'm not going to expose my methods for time bending, as i don't want to do get nerfed!"-Kynox
It's working fine for me http://dl.getdropbox.com/u/1799304/cooldowns.png
Check your offsets and values you are getting from item + 0x14 and item + 0x20. I think I've read somewhere they can be different depending on CVars, but I'm not sure.
Well I did further testing for a Death Knight and realized the following:
uint spellsOnCooldown = 0x0133B7C0;
//Death Knight
public static uint Icy_Touch_3 = 49903;
public static uint Rune_Tap = 48982;
When I test Icy_Touch_3 ill get the correct cooldown time but just the first time I throw the spell, once I throw it once no matter what it always return 0. (until wow decides its time to remove it from the list ^^)
Then I tested Rune_Tap, and no matter what I do it always return 0.
here is the method im using to test it, -1 represents not in list.
My guess is im messing somthing with spellIDs maby they change if spells ready and theres all ready one spell of the kind in the current list. (that would explain Gurzul usedCode:public float IsSpellReady2(uint spellid) { //Get first list object uint currentListObject = Memory.ReadUInt(hProcess, (spellsOnCooldown + 0x8)); while ((currentListObject != 0) && ((currentListObject & 1) == 0)) { uint currentSpellId = Memory.ReadUInt(hProcess, currentListObject + 8); if (currentSpellId == spellid) { int start = Memory.ReadInt(hProcess, (currentListObject + 0x10)); int cd1 = Memory.ReadInt(hProcess, (currentListObject + 0x14)); int cd2 = Memory.ReadInt(hProcess, (currentListObject + 0x20)); int length = cd1 + cd2; int globalLength = Memory.ReadInt(hProcess, (currentListObject + 0x2C)); float cdleft = Math.Max(Math.Max(length, globalLength) - (Environment.TickCount - start), 0); return cdleft; } //Get next list object currentListObject = Memory.ReadUInt(hProcess, currentListObject + 4); } return -1; }
GetSpellName(spellId) to find it but wouldnt explain why rune tap alawys return 0)
Last edited by mordok; 10-25-2009 at 12:01 PM.
"I'm not going to expose my methods for time bending, as i don't want to do get nerfed!"-Kynox
You must read the whole list. There are duplicates in the list.
1) there can be 2 items for each spell - one for normal cooldown, one for global cooldown
2) when the cooldown is over, wow doesn't remove it from the list immediately and IIRC it will always add new item, so for example you can have for one spell 2 entries for normal cooldown - one expired, one active
Ill try that now, many thanks kryso you did take a lot of time to help ^^ (+rep).
--------------------------------------------------------------------------------------------
Allright so now I can see Ice Touch works all the time, but if I spend 2 frost runes the cd increases and thats ignored by the calculations. I guess I could check rune cds in some sort of way and add that to the method logic but thats a pitty coz it would make the method death knights only.
Also no matter what Rune_Tap still remain always 0.
Here is the method maby other classes can use it.
Does anyone now what game client versions this offsets where, so I can find them in 3.2.2 binary.???Code:public float IsSpellReady2(uint spellid) { //Get first list object uint currentListObject = Memory.ReadUInt(hProcess, (spellsOnCooldown + 0x8)); while ((currentListObject != 0) && ((currentListObject & 1) == 0)) { uint currentSpellId = Memory.ReadUInt(hProcess, currentListObject + 8); if (currentSpellId == spellid) { int start = Memory.ReadInt(hProcess, (currentListObject + 0x10)); int cd1 = Memory.ReadInt(hProcess, (currentListObject + 0x14)); int cd2 = Memory.ReadInt(hProcess, (currentListObject + 0x20)); int length = cd1 + cd2; int globalLength = Memory.ReadInt(hProcess, (currentListObject + 0x2C)); float cdleft = Math.Max(Math.Max(length, globalLength) - (Environment.TickCount - start), 0); if (cdleft != 0) { return cdleft; } } //Get next list object currentListObject = Memory.ReadUInt(hProcess, currentListObject + 4); } return -1; }
Anyway I wish there was a way to read cd directly from action bars coz this method is usless for death knights. If there was a way of reading action bars cd I could ignore rune calculations, and therefore make a game class independent cooldown method(no inyectional :P).
Last edited by mordok; 10-25-2009 at 01:45 PM.
"I'm not going to expose my methods for time bending, as i don't want to do get nerfed!"-Kynox
Also worth noting that if you do:
[initialOffset+0x4] you will get a pointer to the LAST object in the list, good for making sure you're actually at the end