this is a little tool I've been working on lately. I have always been interested in adding an actual ingame menu for my tools, as a well integrated tool makes for much easier usage and a better overall 'feel' to using it.
The easiest way to manage this (as far as I know) is by injecting a dll into the elementclient process. You can do this on startup, or while a process is running. I picked the 'Inject the dll on startup' method as described in detail on here. On that page you can also download an easy to use example for injection, which I used pretty much verbatim in my own injector. No need to reinvent the weel
Having created the injector, we now need a dll to inject. The injector will call a function 'Initialize()' from this dll, wait for it to return, and then exit. So in the dll we will have a function Initialize() spawn a new thread, so it can return as soon as possible, which will contain our main loop. Before initializing everything the thread waits for the main window to be created; it does this by checking for the hWnd in memory. You need the hWnd of the window for any win32 API calls you wish to make.
A game using Direct3D for its graphics will render all the objects between calls to BeginScene and EndScene. So if you want to render your own objects you hook the function call to endscene and add your own objects just before it is called. This way your own objects will be rendered in every frame (and on top for the menus). Luckily there are a lot of guides on how to hook the EndFrame function for the different versions of D3D. PWI uses D3D8 so you just google for a method to hook that if you aren't interested in learning how it works precisely (which I wasn't). As I will be posting the source code for this little tool, you can simply look in there.
Having done that we can simply create some wrapper classes to create the different controls necessary for a basic window (like buttons, labels, checkboxes, etc.). So.... now we can draw a menu, but we still have to somehow detect when a user clicks on a button for example, or drags the menu around. You also don't want the clicks intended for your controls to fall through to the basic game, so it is important to intercept them before that happens. Luckily the win32 API provides us with an easy method:
Where WndProc is your own function for handling any windows messages such as mousebuttons / keys, and wpOrigEditProc is PWI's function. What you then do is check whether any messages sent to PWI are likely intended for your own controls, and if not you call wpOrigEditProc with the same parameters, so the game receives all the necessary messages for running normally.Code:WNDPROC wpOrigEditProc = (WNDPROC)SetWindowLong(hwnd, GWL_WNDPROC, (LONG) WndProc);
Well, those are the basic building blocks for creating ingame menus. For the rest simply look at the source code to see how it works (the actual functionality is of course moot, as a 2 minute autoIt script could do the same thing). The structures were created with a program called "ReClass" which can be found here. It's a nifty tool for exploring the game's structures in memory.
The attached AutoPot.rar contains the injector + dll + resources necessary for drawing the ingame menu. Simply extract it in the element directory (the one that contains elementclient.exe)
Note: To actually compile the Dll you will need the D3D8 SDK
- Please extract the AutoPot.rar into the ..\element directory of your PWI install. For example: C:\Program Files\Perfect World Entertainment\Perfect World International\element
- After extracting the files "AutoPot.exe" and "PWdll.dll" should be in the same directory as your "elementclient.exe" file. Apart from these two files, a folder named "Resources" should have been created in this same directory.
- The "Resources" folder contains the images necessary for displaying the buttons and menu in the game, as well as the basic PWI fonts, in case they are not registered on your system.
- After unpacking the rar file, you should now run the "AutoPot.exe" file for every instance of PWI you wish to have the AutoPot enabled. It will inject the "PWdll.dll" on starting of the PWI client, which will enable a button next to your chat screen.
- By pressing this button (which looks like the cleric icon) you will open a menu in which you can select the options necessary for the AutoPot to function. These are very basic options so it shouldn't be too difficult
Note: This program uses hardcoded offsets and addresses, it might not work soon after any patches. This program is merely created in order to learn basic menu creation within the game via EndScene hooking.