Hi enigma first of thanks for your work its realy good to look up stuff.
But i have a Question about the Containers. (Container, ExContainer)
As far as i understand it now Container is something like List in C# and ExContainer is like a Dictionary.
Anyway my problem is when im searching SceneSNOs.
I have to do this very often and the SNOGroup contains many entries, so it takes me relatively long to find the right one about(50ms).
So the main question is ther a way to get an Item in the Container with a Specific SNOId?
The thing that makes me curious is that you write something about Djb hash. I mean this must be good for something ^^
Would be nice if i could trade my linear search to a faster way.
If you want high performance reading, you may use approch number 3 on this link :
Reading Unmanaged Data Into Structures - CodeProject
it took me 3ms to enumerate all actors with all ACDs and navigation distance for each one using this kind of struct serialization.
For examle to optimze, you can read a data block of 0x44C * actor count, and serialize all actors with slices of byte[0x44C].
Container is indeed something like List in C#, or better called ArrayList. It uses a single array as backing store and if running out of space a bigger allocation is made to replace it.
"ExContainer" on the other hand uses multiple arrays. If space runs out, a new array is allocated to fit more items. For a fast growing/shrinking collection that is a much more efficient way as you don't have to reallocate the array all the time. That's pretty much how StringBuilder in .NET is implemented as well.
"ExContainer" is not at all similar to a Dictionary. The typical IDs in those collection are [hash][index], where hash (starts as hash of container name) is incremented for every new item (kinda, subtracting original hash doesn't quite equal how many items that has been created in total) and index is, well index. I don't think there is much too it, it's just a way to generate unique IDs.
If you're repeatedly going though all scene SNOs, maybe you could benefit from some caching. If you're using Enigma.D3 then you can use TakeSnapshot() on a MemoryObject in order to save the entire blob of memory for that object. That way when accessing the properties you read from your own memory instead of from D3. Also there is no need to update that snapshot as SNOs doesn't change (at least I can't imagine that, them being read from MPQs and all).
This is a good tip! It's actually the kind of solution I'm currently working on, combining large reads with the Snapshot feature I've mentioned. It's pretty fast, but obviously not as fast as casting to structs as there is overhead when reading the bytes into proper types. For pure performance always go with structs!
Awsome work enigma can't wait for the Map hack, quick question are you able to read the map information from d3? If so can you post some sample code, thanks!
lol, like you have any idea what you're talking about
By map information, you mean how the map looks right? What is walk-able and whatnot, and what is there that haven't been discovered yet by the player? I don't have much, but some of what the UI uses you can see in Enigma.D3.LevelArea and what I had for 1.0.8 is in Enigma.D3.Legacy.LevelArea
Thanks enigma, I got the basic map down for items, actors (monsers, players, doors, portals, chests) all ofset by the current player and drawn up. The last part I would like to know is the world details like what is off bounds similar to the mini map details without just taking a screenshot of it and imposing the data onto it.
I will look into level area info thanks for the suggestion.
Also do you have any information on the mouse data such as objects it's touching or coordinates? Is there a helper or some structure for this?
hi enigma,
I've been fiddling around with the code and its been working great. I was wondering if there was something in place for tracking bounties?
thanks,
moe
Can anyone tell me how to use this engine in my project.
Is there a sample to view?
Thanks.
ok thanks for the long explanation
i have already structs but for every struct i have to make an additional memoryread to get the snoid and that makes it timeconsuming
however now i found a method to get them faster.
even if no one interested in it i post it anyway ^^
It probably works with any SNO but i can now only confirm for SceneSno.
!!!'EDITED THE CODE*!!!
!!!'EDITED THE CODE*!!!Code:public static IntPtr GetSnoLinkFromId(SNOGroup baseAddr, int snoId) { int dwMainOffset = D3.ReadInt((int)baseAddr); int test = D3_SnoFromId(dwMainOffset, snoId, 0); int snoPointer = D3.ReadInt(test + 0x10); // Nur zum Test. //int snoID = D3.ReadInt(snoPointer); return (IntPtr)snoPointer; } public static int D3_SnoFromId(int snoGroupPointer, int snoId, int a3) { int v4; // eax@2 int v6; // edi@5 int v7; // eax@6 int v8; // eax@7 if ((D3.m.ReadInt((byte)(snoGroupPointer + 24)) & 2) == 0) { v7 = D3_SnoFromIdGetIndex(snoId); if (v7 == -1) { if (snoId < 0) { //v8 = sub_10B40B0(snoId, 0, a3); //goto LABEL_10; } } else { int PointerContainer2 = D3.m.ReadInt((snoGroupPointer + 16)); int PointerSnoArray = D3.m.ReadInt(PointerContainer2 + 284); v8 = PointerSnoArray + 20 * (UInt16)v7; return v8; //if ( v8 != 0 ) //{ // LABEL_9: // *(_DWORD *)(v8 + 4) = dword_1CEF8C4; // LABEL_10: // if ( v8 == 0) // { // return 0; // } // return sub_10B2530(*(_DWORD *)(v8 + 16)); //} } //v8 = sub_10BAB00(snoId, 0, a3); //if ( !v8 ) // return 0; //goto LABEL_9; } //sub_10B3C10(); //v4 = sub_10B8FD0(snoId, 0, a3); //if ( !v4 ) //{ // sub_825D80(*(_DWORD *)(snoGroupPointer + 124) + 72); // return 0; //} //v6 = sub_10B2530(*(_DWORD *)(v4 + 16)); //sub_825D80(*(_DWORD *)(snoGroupPointer + 124) + 72); //return v6; throw new Exception("rest implementieren."); } public static int D3_SnoFromIdGetIndex(int a1) { int result; // eax@5 int v2; // eax@7 if (a1 < D3.m.ReadInt(0x1D019C4)) { result = D3.m.ReadInt(D3.m.ReadInt(0x1D019C8) + 4 * a1); return result; } throw new Exception("Code unterhalb implementieren."); //else //{ // if ( a1 >= 0xFFFFD8EF ) // { // if ( a1 != -1 && a1 != -2 ) // return dword_1CFE9A4[a1]; // return -1; // } // v2 = *(_DWORD *)(qword_1D01A50 // + 4 // * (dword_1D01A40 & 16777619 // * (BYTE3(a1) ^ 16777619 // * (BYTE2(a1) ^ 16777619 // * (BYTE1(a1) ^ 16777619 // * ((unsigned __int8)a1 ^ 0x811C9DC5)))))); // if ( !v2 ) // return -1; // while ( *(_DWORD *)(v2 + 4) != a1 ) // { // v2 = *(_DWORD *)v2; // if ( !v2 ) // return -1; // } // result = *(_DWORD *)(v2 + 8); //} //return result; }
In cases of the Exception you could use the iteratingmethod als fallback or implement the rest. Im to lazy rigth now becaus it works without problems so far.
Last edited by Dakoon; 04-28-2014 at 05:14 PM.
Bounties are basically the same as quests, you can get a list of them with QuestManager.cs and they look like Quest.cs. If you need more info about a specific quest then you have to look up its SNO ID but I don't really have an example of this. Where the objectives are stored I don't know either.
Engine.Create() and you can start using it as long as it's not null (no D3 found) How to use it depends on what information you need from it. Most stuff is in ObjectManager and Storage that is inside that. See the *Helper classes for some ideas. Also keep in mind that this library is more for proof of concept projects and might not give the performance or reliability that you might desire.
Last edited by enigma32; 04-27-2014 at 09:44 AM.
hi there m8 first of all you have done an amazing work here...you give us a dll that literally strips down d3 ...my problem is that i'm new to d3 botting and i want to try making a simple bot that opens chest and loots items (not the pixel search way) but i don't know how the d3 structure work here or where the data are stored and how to fetch them with your dll...any more in-depth help on how to start or if you know any other thread to help me start understanding how d3 works would be very helpful! i have done in the past a fishing and gathering bot in wow relaying only on memory reading though it took me some months since i get into it but i did it at the end... of course i could not do a shit if the ownedcore community was not existing which gave me a lot of information and guides to understand how things work... Thanks in advance and again as KillerJohn said your code is a truly state of art!