Experience Points Add-On for MacroQuest (v1.0)
Posted: Sun Apr 20, 2003 12:52 am
In the past, EverQuest servers informed the client of the player character's actual experience points at any given time. This information could be extracted from the datastream (and probably from the _CHARINFO struct) and displayed by third party software, most notably by SEQ. Since then, the protocol has been modified to remove such detailed experience information from the client memory space and datastream. Instead, the actual value was replaced by a pseudo-percentage, based on 330 instead of 100. So if you are at 0% of your level, your experience will internally be reported as 0. If you are at 99%, it will be reported as 329. Attaining one more point will ding, and will reset the counter back to 0. This is true both for regular level experience and for alternate advancement (AA) experience. It is theorized that using a 330-based system is probably related to the way in which the new UI draws its graphical elements.
While this means we can't extract your actual experience points from anywhere, it is my opinion that having a resolution of 330 instead of 100 is useful for gameplay in that it gives you slightly more information regarding how much experience a given mob or set of mobs is giving you. This lets you more accurately examine your experience rate, particularly as it pertains to situations like charming, dire charming, and power leveling. Therefore, I have created this add-on for MacroQuest that provides an automatic system for reporting experience gain based on the higher-resolution 330 value, and an extra command for the arbitrary reporting of your current experience values.
I add this code into every new version of the MacroQuest code, as I find it very useful. Whether this should be added to the official codebase is up for debate. If enough people are interested in adding this feature to the codebase, perhaps it should be implemented as:
a) An option in macroquest.ini, such as
Code: Select all
[MacroQuest]
ExpChecker=1Code: Select all
/expchecker on
Experience checker has been ENABLED.http://seq.sourceforge.net/forums/showt ... readid=168
http://seq.sourceforge.net/forums/showt ... eadid=1896
http://seq.sourceforge.net/forums/showt ... eadid=1233
The code checks 5 times a second for any changes to your current level experience and AA experience. It does this by comparing your current experience values to globally saved values. When you first zone into the game, it sets the global values. If you want to see your current experience, or if you suspect that the global experience values have been corrupted somehow (this is not possible unless MQ's mainloop somehow stops working), you may run the /exp command. This displays your current experience, and forces the global values to reset.
(Note that this code requires an accurate _CHARINFO struct, and an accurate CharInfo offset. However, if either of these things are not correct, this code most likely will not generate any crashes. It will just behave rather oddly. Only if the CharInfo offset is somehow outside of eqgame.exe's memory space will this cause an actual crash.)
MQ.h ------
In the DLL export function prototype section, add:
Code: Select all
extern "C" EQLIB_API VOID Exp (PSPAWNINFO, PCHAR);EQLib.cpp ------
Add these two global variables:
Code: Select all
DWORD global_exp, global_aaexp;Code: Select all
VOID ExpChecker();Code: Select all
while (!gbUnload) {
Sleep(1000);
}Code: Select all
while (!gbUnload) {
Sleep(200);
ExpChecker();
}Code: Select all
if (gZoning) {
gDelayZoning += gZoneDelay;
gZoning=FALSE;
}Code: Select all
gbInGame=TRUE;Code: Select all
if (!strncmp(szMsg,"You have entered ",17) && !gbInGame) {
PCHARINFO pCharInfo = NULL;
if ((pCharInfo = GetCharInfo()) != NULL) {
global_exp = pCharInfo->Exp;
global_aaexp = pCharInfo->AAExp;
}
}Code: Select all
{ "/exp", CMD_MQ },Code: Select all
{"/exp", "Exp"},Code: Select all
VOID Exp(PSPAWNINFO pChar, PCHAR szLine)
{
CHAR szBuffer[MAX_STRING] = {0};
PCHARINFO pCharInfo = NULL;
if (NULL == (pCharInfo = GetCharInfo())) return;
sprintf(szBuffer, "You currently have %ld experience and %ld AA experience.", pCharInfo->Exp, pCharInfo->AAExp);
WriteChatColor(szBuffer, USERCOLOR_DUELS);
global_exp = pCharInfo->Exp;
global_aaexp = pCharInfo->AAExp;
}
VOID ExpChecker()
{
CHAR szBuffer[MAX_STRING] = {0};
PCHARINFO pCharInfo = NULL;
long expdiff = 0, aaexpdiff = 0;
if (!gbInGame) return;
if (NULL == (pCharInfo = GetCharInfo())) return;
if (pCharInfo->Exp > global_exp) expdiff = pCharInfo->Exp - global_exp;
if (pCharInfo->Exp < global_exp) expdiff = (330 - global_exp) + pCharInfo->Exp;
if (pCharInfo->AAExp > global_aaexp) aaexpdiff = pCharInfo->AAExp - global_aaexp;
if (pCharInfo->AAExp < global_aaexp) aaexpdiff = (330 - global_aaexp) + pCharInfo->AAExp;
if (expdiff > 0 && expdiff < 340) {
sprintf(szBuffer, "You have gained %ld experience points.", expdiff);
WriteChatColor(szBuffer, USERCOLOR_DUELS);
}
if (aaexpdiff > 0 && aaexpdiff < 340) {
sprintf(szBuffer, "You have gained %ld AA experience points.", aaexpdiff);
WriteChatColor(szBuffer, USERCOLOR_DUELS);
}
global_exp = pCharInfo->Exp;
global_aaexp = pCharInfo->AAExp;
}I have tested this code fairly conclusively, and all appears to work correctly. The SEQ forums report behavior where every time you zone you appear to receive something like negative two million experience points. This is probably the server sending the absolute experience value to the client. In the future, with more analysis, we may be able to make use of this value in some way. For now, the code simply supresses the value, and only reports ordinary experience gains in the 330-resolution frame.
If you have questions, comments, additions or bugs, please post them in this thread.