Quote:
Originally Posted by spartanfbj
I've scanned through this thread pretty thoroughly over the past few days, and I've seen some mention of debugging and developing practices that were really helpful. I'm coming back to Guild Wars mainly to fix up some bots as a hobby. My main issue is debugging without crashing the Guild Wars client.
What do you guys do to debug issues? Some type of interface between the script and the client to prevent fatal errors? I'm a developer by trade but pretty new to AutoIt scripting outside of manually fixing and improving bugs and UI's.
Edit: Realized that I had made a similar post about this a year ago that was answered by Rifle. I'd still love to hear any suggestions if anyone has any.
|
Types of errors:
1. If its purely a script issue use console messages or output to the gui at every stage of a function printing important values.
2. If its a 007 error and you can reconnect potentially that is caused by performing packet based actions too quickly or malformed packets.
3. Actual gw client crashes are generally from reading/writing invalid memory regions or calling a function improperly or with wrong address.
Debug Technique by error type:
1. verbose script output to look for invalid values or incorrect logic branches while observing the bot. A lot of bots have a function "Out("message") that displays on the gui you can use.
2. Invalid packet header so check it against a known working bot or toolbox's header constants. If your using a packet not listed in those or invalid you can attach ollydbg, immunity, or x32dbg among other dynamic debuggers. Then set a break point on the send packet function that you can find using a byte array pattern from toolbox or find it on your own from tracing back the winsock send function used by the game. Once you have found the packet function right before encryption as it is fully formed minus encryption set a silent logging break point to log the registers and stack parameters to check for header, size, and content. You can also just do a normal breakpoint and manually inspect the stack. To trigger these breakpoints you take the action in game minimizing other actions if possible. Takes some trial and error.
3. Hard crashes stem generally from invalid function calls or memory access so use verbose logging of your script to find the general function or area that crashes the client. Then what you can do is look at what internal engine functions are used by that gwa2 function for example.
3.a. Now that you have some idea of the internal causing the crash you can start debugging it with a few different tools. If it is an invalid memory access being read/write you can check this using cheat engine, reclass, and many other tools to find the data structure in live memory that you are currently accessing to make sure your base address and offsets are correct along with data type. It is also worth doing an array of byte search to confirm your byte pattern is correct for finding the base pointers to the structs your having issues with in this type of crash.
3.b. If it is a function based issue it could be a few things, invalid byte pattern/address to the function, incorrect parameters or call type, in the case of hooking you may not be restoring registers properly, or finally another common one would incorrect thread context. With out digging heavily into thread context switching and process layout you basically want to hook a function that is called a lot and in the same thread as the function you are trying to call.
This is seen easily in toolbox where they hook a gameloop and all functions calls are queued up to be executed in that threads context. Sometimes it is merely enough to inject a .dll or shell code with createremotethread and call but most of the time you need to hook into a game thread for your calls to function because of things like thread local storage.
3.c. So how on earth do you test this stuff? Easiest way imo is to make a simple C/C++ .dll inject that with one goal of hooking the game thread and calling your intended function from it once with console output for feedback. This is more a testing stage but you can also save a lot of time mapping out call type, parameters, call tree, and signatures using static analysis like IDA pro or ghidra.
This is kind of a simplistic overview but in a tl;dr:
Script issues: print debug messages
memory issues: dynamic analysis like cheat engine or reclass to make sure it maps out
Function issues: confirm patterns in static analysis, call type, parameters, and build a test .dll.
I hope this helps at least a little bit.