-
Member
[Help][SL 9.2.7] CGPlayer Auras
Hi, i trying to find all auras, my research of npc:
first table offset 0x6F8, 0xC0 is aura size
Code:
typedef struct {
int AuraId; // + 0
char unknown1[8];
int Duration; // + 12
int EndTime; // + 16
uint64_t CreatorGuid; // + 20
char unknown2[4]; //
int StackCount; // + 28
} AuraRec;
when auras more than 16 we can read low = pm.read_int(start_address+0x6F8-0x
Code:
if low > 0:
high = pm.read_int(start_address+0x6F8-0x4)
shifted_20f = high << 32
result = shifted_20f | low
for offset in range(num_auras): #num_auras random number, didnt found actual
try:
spellid = pm.read_int(result+offset*0xC0+0x98) # 0x98 is spellid offset
so, i can read auras on npc by this method, but i tryed to get auras on players by the same method, and it didnt work
i found 2 tables, with auras list with 0x8 offset and list with 0xC0 offset, but i cant found actual offset from start_address to pointer of that lists
also tryed to decompile UnitAura/UnitBuff/UnitDebuff but its broken
Just a moment... UnitBuff
Just a moment... UnitDebuff
Just a moment... UnitAura
thanks for any information that would help me figure this out
PS i using py.mem to fast debugging before implement it on c++
-
Contributor
Originally Posted by
Trogg
Hi, i trying to find all auras, my research of npc:
first table offset 0x6F8, 0xC0 is aura size
Code:
typedef struct {
int AuraId; // + 0
char unknown1[8];
int Duration; // + 12
int EndTime; // + 16
uint64_t CreatorGuid; // + 20
char unknown2[4]; //
int StackCount; // + 28
} AuraRec;
when auras more than 16 we can read low = pm.read_int(start_address+0x6F8-0x
Code:
if low > 0:
high = pm.read_int(start_address+0x6F8-0x4)
shifted_20f = high << 32
result = shifted_20f | low
for offset in range(num_auras): #num_auras random number, didnt found actual
try:
spellid = pm.read_int(result+offset*0xC0+0x98) # 0x98 is spellid offset
so, i can read auras on npc by this method, but i tryed to get auras on players by the same method, and it didnt work
i found 2 tables, with auras list with 0x8 offset and list with 0xC0 offset, but i cant found actual offset from start_address to pointer of that lists
also tryed to decompile UnitAura/UnitBuff/UnitDebuff but its broken
Just a moment... UnitBuff
Just a moment... UnitDebuff
Just a moment... UnitAura
thanks for any information that would help me figure this out
PS i using py.mem to fast debugging before implement it on c++
I think you have a few values off. I did a quick dump of the binary and looked, this is the part in particular where you'd use it in your stuff:
Code:
v8 = v3 + 0x6E8;
if ( *(_DWORD *)(v3 + 0x12E8) == -1 )
v8 = *(_QWORD *)(v3 + 0x6F0);
v9 = *(_DWORD *)(0xC0i64 * (unsigned int)v6 + v8 + 0x98);
The auras start at 0x6E8, however if 0x12E8 == -1 then you instead start at 0x6F0. The v9 assignment in this example you can see that 0xC0 is in fact the right size of each Aura struct, and 0x98 being the ID (like you mentioned)
It's worth noting that this is still the way things are done in Retail, and have been done for some time. Here's an example structure if you do it in C++:
Code:
// Should be defining base classes, but for this purpose w/e
struct CGUnit_C {
char pad_0000[1768];
union {
struct {
CGAuraStrc Auras[16]; //0x06E8
int32_t AuraCount; //0x12E8
char pad_12EC[4];
};
struct {
int32_t AuraCount2; //0x06E8
char pad_06EC[4];
CGAuraStrc* Auras2; //0x06F0
};
};
CGAuraStrc* GetAuraStrc(uint32_t idx) {
auto count = AuraCount;
if (count == -1) count = AuraCount2;
if (!(idx < count)) return nullptr;
return (AuraCount == -1 ? &Auras2[idx] : &Auras[idx]);
};
};
Last edited by scizzydo; 02-13-2024 at 06:54 PM.
-
Post Thanks / Like - 1 Thanks
Trogg (1 members gave Thanks to scizzydo for this useful post)
-
Member
Thanks, it works, i made a mistake in type (not int, longlong)
There is a way to find flag or what else of chaied group for example in The Council of Blood by Dark Recital - Spell - World of Warcraft ?
dr_chained.png
-
Contributor
Originally Posted by
Trogg
I personally didn't raid during that to give you an answer there, but the link shows it's a debuff. With the method I showed before you iterate all auras, debuff, buff, visible and invisible. There are a lot of auras on units for things that aren't visible. For example, morchie on retail for the fight on Dawn of the infinites, the correct morchie has a different aura. On court of stars, the imposter also does. For event times, like Christmas, the mobs wearing the Christmas hats have auras. Other auras can be like 4pc, etc. not just these auras on yourself, but others.
-
Member
The source of debuff is a player in chained group
Code:
for (const auto& u : playerData.players)
for (const auto& aura : u->auras) {
if (aura->id == 331636 || aura->id == 331637) {
auto caster = aura->CasterGuid();
if (caster==playerData.me->Guid())
//our target
stuff
}
}
-
Member
How to get field 16 (270) from UnitBuff? Cant view from what it come.
Dump: value=UnitBuff("player",1)
[1]="Primordial Arcanic Pulsar",
[2]=135730,
[3]=1,
[5]=0,
[6]=0,
[7]="player",
[8]=false,
[9]=false,
[10]=338825,
[11]=false,
[12]=false,
[13]=true,
[14]=false,
[15]=1,
[16]=270
i can find it by CE, it is double but it is out of range aura table
Last edited by Trogg; 04-05-2024 at 04:49 AM.
-
Contributor
Originally Posted by
Trogg
How to get field 16 (270) from UnitBuff? Cant view from what it come.
Dump: value=UnitBuff("player",1)
[1]="Primordial Arcanic Pulsar",
[2]=135730,
[3]=1,
[5]=0,
[6]=0,
[7]="player",
[8]=false,
[9]=false,
[10]=338825,
[11]=false,
[12]=false,
[13]=true,
[14]=false,
[15]=1,
[16]=270
i can find it by CE, it is double but it is out of range aura table
Those are the attributes. It behaves just like the aura tables, where you read at 0x20 to see if it's -1 (if it is, then the attributes count starts at 0x0), and then there is an array of attributes at either 0x8 or 0x00, depending on that return value.
-
Post Thanks / Like - 1 Thanks
Trogg (1 members gave Thanks to scizzydo for this useful post)
-
Member
pointer to array of attributes must be in start of the aura table pointer or spell?
-
Contributor
Originally Posted by
Trogg
pointer to array of attributes must be in start of the aura table pointer or spell?
They're the first fields in the CGAura struct
This is the count of attributes. a2 in this pseudocode is the CGAuraStrc (in ida an int*, so 0x20 & 0x0 accordingly for count)
Code:
v11 = a2[8];
if ( v11 == -1 )
v11 = *a2;
This is the bottom of the function where it pushes the values to the lua state.
Code:
for ( i = 0i64; (unsigned int)i < v11; i = (unsigned int)(i + 1) )
{
v36 = a2[8];
if ( v36 == -1 )
v37 = *a2;
else
v37 = a2[8];
if ( (unsigned int)i < v37 )
{
if ( v36 == -1 )
v39 = (unsigned int *)*((_QWORD *)a2 + 1);
else
v39 = a2;
v40 = *(float *)&v39[i];
if ( v40 <= 0.0 )
v38 = -(int)(float)-v40;
else
v38 = (int)v40;
}
else
{
v38 = 0;
}
sub_1402C6DE0((__int64)a3, (double)v38);
}
-
Post Thanks / Like - 1 Thanks
Trogg (1 members gave Thanks to scizzydo for this useful post)
-
Member
Ready function:
Code:
void Aura::GetAttrubutes(DWORD_PTR addr)
{
int count = *(int*)(addr + 0x20);
if (count == -1)
count = *(int*)(addr);
int v36 = 0;
int v37 = 0;
int v38 = 0;
uint64_t v39 = 0;
int v40 = 0;
for (int i = 0; i < count; i++)
{
v36 = *(int*)(addr + 0x20);
if (v36 == -1)
v37 = *(int*)(addr);
else
v37 = v36;
if (i < v37)
{
if (v36 == -1) {
v39 = *(uint64_t*)(addr + 8);
v40 = *(float*)(v39 + i * 4);
}
else
v40 = *(float*)(addr + i * 4);
if (v40 <= 0.0)
v38 = -(int)(float)-v40;
else
v38 = (int)v40;
}
else
{
v38 = 0;
}
attributes.push_back(v38);
}
return;
}
-
Contributor
Originally Posted by
Trogg
Ready function:
Code:
void Aura::GetAttrubutes(DWORD_PTR addr)
{
int count = *(int*)(addr + 0x20);
if (count == -1)
count = *(int*)(addr);
int v36 = 0;
int v37 = 0;
int v38 = 0;
uint64_t v39 = 0;
int v40 = 0;
for (int i = 0; i < count; i++)
{
v36 = *(int*)(addr + 0x20);
if (v36 == -1)
v37 = *(int*)(addr);
else
v37 = v36;
if (i < v37)
{
if (v36 == -1) {
v39 = *(uint64_t*)(addr + 8);
v40 = *(float*)(v39 + i * 4);
}
else
v40 = *(float*)(addr + i * 4);
if (v40 <= 0.0)
v38 = -(int)(float)-v40;
else
v38 = (int)v40;
}
else
{
v38 = 0;
}
attributes.push_back(v38);
}
return;
}
Question about your code... are you iterating everything and storing the results in new containers? Do you have a reason? If you go the route of defining structs, and custom iterators, you can avoid new allocations and just use the games data that already exists (much less overhead)
-
Member
This is due to a lack of understanding of how it works. In my head it sounds like this:
do you want to use something? find, save, use, every time searching by reading the aura, if necessary, accessing it several times in my understanding already creates a load, the same with objects, I iterate them and distribute them in a container for further use, apparently I just can’t imagine how it’s possible do differently.