/MEMSPELL FIXED!

A forum for feature requests/discussions and user submitted patches that improve MQ2

Moderator: MacroQuest Developers

EqMule
Developer
Developer
Posts: 2697
Joined: Fri Jan 03, 2003 9:57 pm
Contact:

/MEMSPELL FIXED!

Post by EqMule » Tue Jul 08, 2003 6:26 pm

Ok a while ago, I set out to fix all the non working functions in mq that Plaz once had working, and it was actually thanks to him I was able to fix this good old one! So all say WB to /memspell it was surely missed!

More will come, Im still working on the merchantstuff...

NOTE! the cyan text is the section under which you paste the code, it doesnt mean you can paste it directly under that section, just a pointer to get you started, if you look in the section you will see lines that looks like the code you are going to insert, and you need to paste it under a similar line... also note that some lines might allready exist... just replace them, and you can replace the whole old memspell function in EQLib_Commands.cpp with this new one as well

ok here goes-> (DKAA will hang me for not learning the diff thing yet...)

in EQLib.h :
// ***************************************************************************
// EQ Addresses
// ***************************************************************************

Code: Select all

extern DWORD *EQADDR_SPELLBOOKWND;
//*******************************************************
// EQ Functions
// *******************************************************

Code: Select all

extern fEQMemSpell	      cmdMemSpell;

in EQLib_Commands.cpp :
// ***************************************************************************
// Function: MemSpell
// Description: Our '/MemSpell' command
// Usage: /MemSpell gem# "spell name"
// ***************************************************************************

Code: Select all

VOID MemSpell(PSPAWNINFO pChar, PCHAR szLine) 
{ 
	bRunNextCommand = FALSE;
	DWORD SpellBookWnd = *EQADDR_SPELLBOOKWND; 
	CHAR szBuffer[MAX_STRING] = {0};
	CHAR szGem[MAX_STRING] = {0};
	WORD Gem = -1;
	CHAR SpellName[MAX_STRING] = {0};
	PCHARINFO pCharInfo = NULL;
	DWORD ID,GEMSLOT;

	if (!SpellBookWnd || !cmdMemSpell) return;
	if (NULL == (pCharInfo = GetCharInfo())) return;

	GetArg(szGem,szLine,1);
	GetArg(SpellName,szLine,2);
	Gem = atoi(szGem);
	if (Gem<1 || Gem>8) return;
	Gem--;
	if (pCharInfo->MemorizedSpells[Gem]!=0xFFFFFFFF) return; [color=green]//Im gonna put in dememcode here instead of returning, be patient...[/color]
	
	PSPELLLIST pSpell = GetSpellByName(SpellName);
	if (!pSpell) {
		sprintf(szBuffer,"Unable to find Spell '%s'",SpellName);
		WriteChatBuffer(szBuffer,CONCOLOR_RED);
		return;
	}
	if (pSpell->Level[pChar->Class-1]>pChar->Level) {
		sprintf(szBuffer,"You need to be level '%d' to memorize that spell ",pSpell->Level[pChar->Class-1]);
		WriteChatBuffer(szBuffer,CONCOLOR_RED);
		return;
	}
	ID = (DWORD)pSpell->ID;
	GEMSLOT = (DWORD)Gem;
	sprintf(szBuffer,"Memorizing spell '%d' in slot '%x' ",pSpell->ID, GEMSLOT+1); 
    WriteChatBuffer(szBuffer,USERCOLOR_DEFAULT);
	
	__asm {
	 push ecx; 
	 mov ecx, dword ptr [SpellBookWnd]; 
	 push GEMSLOT; 
	 push ID;
	 call dword ptr [cmdMemSpell]; 
	 pop ecx;
	}
	return;	
}
in EQLib_Interp.cpp :
// ***************************************************************************
// Function: TakeControlOfCommandList
// Description: Creates custom command list with our commands
// Points help/parsing at our list
// ***************************************************************************

Code: Select all

		{"/memspell",	"MemSpell"},
in EQLib_Main.cpp :
// EQ Address Initialization

Code: Select all

DWORD *EQADDR_SPELLBOOKWND;
// EQ Functions Initialization

Code: Select all

fEQMemSpell	      cmdMemSpell	 =  NULL;
// ***************************************************************************
// Function: ParseINIFile
// Description: Parse INI file for memory locations
// ***************************************************************************

Code: Select all

	GetPrivateProfileString("Function Locations","MemSpell","0",szBuffer,MAX_STRING,ClientINI);			cmdMemSpell = (fEQMemSpell)strtoul(szBuffer,NULL,16);

	GetPrivateProfileString("Class Locations","SpellBookWnd","0",szBuffer,MAX_STRING,ClientINI);		EQADDR_SPELLBOOKWND = (DWORD *)strtoul(szBuffer,NULL,16);
in MQ.h :
// ***************************************************************************
// Everquest function typedefs
// ***************************************************************************

Code: Select all

typedef VOID    (__cdecl *fEQMemSpell)(DWORD,DWORD);
// ***************************************************************************
// Exports
// ***************************************************************************

Code: Select all

extern "C" EQLIB_API VOID  MemSpell       (PSPAWNINFO, PCHAR);
in eqgame.ini :

Code: Select all

[Function Locations]
MemSpell=004F626C

[Class Locations]
SpellBookWnd=005FE258 
OK any feedback for making the code cleaner/better will be appreaciated, Im not a mastercoder by any means...

[edit] updated with new offsets for patch on july 10 2003
Last edited by EqMule on Thu Jul 10, 2003 9:16 am, edited 9 times in total.
My status o/
If you like MQ2 and would like to contribute, please do. My goal is 25 donations per month.
So far I've received Image donations for this month's patches.

Bitcoin: 1Aq8ackjQ4f7AUvbUL7BE6oPfT8PmNP4Zq
Krono: PM me.
I can always use characters for testing, PM me if you can donate one.

User avatar
BlueSkies
a ghoul
a ghoul
Posts: 132
Joined: Tue Oct 01, 2002 6:22 pm

Post by BlueSkies » Tue Jul 08, 2003 6:33 pm

Wow, EqMule's on a roll!
Live your dreams! Blue Skies everyone

wassup
Official Guardian and Writer of TFM
Official Guardian and Writer of TFM
Posts: 1487
Joined: Sat Oct 26, 2002 5:15 pm

Post by wassup » Tue Jul 08, 2003 6:46 pm

Added in and get the following errors:

\Compile\macroquest\Release\EQLib.res
Creating library ..\Release/EQLib.lib and object ..\Release/EQLib.exp
EQLib_Commands.obj : error LNK2001: unresolved external symbol "unsigned long * EQADDR_SPELLBOOKWND" (?EQADDR_SPELLBOOKWND@@3PAKA)
EQLib_Main.obj : error LNK2001: unresolved external symbol "unsigned long * EQADDR_SPELLBOOKWND" (?EQADDR_SPELLBOOKWND@@3PAKA)
..\Release/EQLib.dll : fatal error LNK1120: 1 unresolved externals

Tried it 3 times and get the same errors.

Any ideas?

User avatar
BlueSkies
a ghoul
a ghoul
Posts: 132
Joined: Tue Oct 01, 2002 6:22 pm

Post by BlueSkies » Tue Jul 08, 2003 7:26 pm

Are you sure you put everything where he said it should go?

Don't mean to be rude -- but I had very similar problems, and it was because I had misread the text. Once I pulled my eyes back into focus (I really think I need glasses or something), I moved the code to where it needed to go and it compiled fine, and works great! :)

Try it again, and pay very special attention to where you put everything. I was successful by adding the additions to the ends of all the sections he mentioned, not the tops. Give that a try, and see how it goes for you.

Good luck with it. Let us know how it goes.
Live your dreams! Blue Skies everyone

User avatar
dont_know_at_all
Developer
Developer
Posts: 5450
Joined: Sun Dec 01, 2002 4:15 am
Location: Florida, USA
Contact:

Post by dont_know_at_all » Tue Jul 08, 2003 7:42 pm

I'm pretty sure a

Code: Select all

DWORD *EQADDR_SPELLBOOKWND;
is missing from eqlib_main.cpp

User avatar
BlueSkies
a ghoul
a ghoul
Posts: 132
Joined: Tue Oct 01, 2002 6:22 pm

Post by BlueSkies » Tue Jul 08, 2003 8:16 pm

Doesn't

extern DWORD *EQADDR_SPELLBOOKWND;

take care of that though?

Or am I mistaken? Probably am... :P
Live your dreams! Blue Skies everyone

EqMule
Developer
Developer
Posts: 2697
Joined: Fri Jan 03, 2003 9:57 pm
Contact:

Post by EqMule » Tue Jul 08, 2003 8:31 pm

dont_know_at_all wrote:I'm pretty sure a

Code: Select all

DWORD *EQADDR_SPELLBOOKWND;
is missing from eqlib_main.cpp
yeah you are correct, I missed that... damn!, original post updated now...
My status o/
If you like MQ2 and would like to contribute, please do. My goal is 25 donations per month.
So far I've received Image donations for this month's patches.

Bitcoin: 1Aq8ackjQ4f7AUvbUL7BE6oPfT8PmNP4Zq
Krono: PM me.
I can always use characters for testing, PM me if you can donate one.

User avatar
BlueSkies
a ghoul
a ghoul
Posts: 132
Joined: Tue Oct 01, 2002 6:22 pm

Post by BlueSkies » Tue Jul 08, 2003 9:00 pm

Oh I know why it worked for me, then... I had already updated my source with Plaz's, and that must have been in there somewhere. :)
Live your dreams! Blue Skies everyone

User avatar
dont_know_at_all
Developer
Developer
Posts: 5450
Joined: Sun Dec 01, 2002 4:15 am
Location: Florida, USA
Contact:

Post by dont_know_at_all » Tue Jul 08, 2003 9:08 pm

Updated in CVS and on the downloads page.

Untested, since I don't have my EQ machine available at the moment.

wassup
Official Guardian and Writer of TFM
Official Guardian and Writer of TFM
Posts: 1487
Joined: Sat Oct 26, 2002 5:15 pm

Post by wassup » Tue Jul 08, 2003 9:09 pm

Thank you, that did the trick :)

This is a great fix and many thanks...

EqMule
Developer
Developer
Posts: 2697
Joined: Fri Jan 03, 2003 9:57 pm
Contact:

Post by EqMule » Tue Jul 08, 2003 9:40 pm

dont_know_at_all wrote:Updated in CVS and on the downloads page.
Appreciate that, many thanks! :D
My status o/
If you like MQ2 and would like to contribute, please do. My goal is 25 donations per month.
So far I've received Image donations for this month's patches.

Bitcoin: 1Aq8ackjQ4f7AUvbUL7BE6oPfT8PmNP4Zq
Krono: PM me.
I can always use characters for testing, PM me if you can donate one.

Plazmic
The One
The One
Posts: 800
Joined: Fri Jun 14, 2002 12:31 am
Contact:

Post by Plazmic » Tue Jul 08, 2003 10:07 pm

Aww man, I can't post while at work, so i couldn't mention this until now..

The favorite function can be faked, and you can auto-mem a spell using it (fixes unmemming issue)... and it only uses the offsets from my other post ;)

Code: Select all

SPELLFAVORITE MemSpellFavorite;
VOID MemSpell(PSPAWNINFO pChar, PCHAR szLine)
{
	if (!EQADDR_SPELLBOOKWND || !cmdLoadSpells) return;
	DWORD Favorite = (DWORD)&MemSpellFavorite;
	CHAR szGem[MAX_STRING] = {0};
	DWORD sp;
	WORD Gem = -1;
	CHAR SpellName[MAX_STRING] = {0};
	PCHARINFO pCharInfo = NULL;
	DWORD SpellBookWnd = *EQADDR_SPELLBOOKWND;
	if (!SpellBookWnd) return;
	if (NULL == (pCharInfo = GetCharInfo())) return;

	GetArg(szGem,szLine,1);
	GetArg(SpellName,szLine,2);
	Gem = atoi(szGem);
	if (Gem<1 || Gem>8) return;
	Gem--;

	PSPELLLIST pSpell = GetSpellByName(SpellName); 
	if (!pSpell) return;
	if (pSpell->Level[pChar->Class-1]>pChar->Level) return;

	ZeroMemory(&MemSpellFavorite,sizeof(MemSpellFavorite));
	strcpy(MemSpellFavorite.Name,"Mem a Spell");
	MemSpellFavorite.Byte_3A=1;
	for (sp=0;sp<8;sp++) MemSpellFavorite.SpellId[sp]=0xFFFFFFFF;
	MemSpellFavorite.SpellId[Gem] = pSpell->ID;

	__asm {
		push ecx;
		mov ecx, dword ptr [SpellBookWnd];
		push 8;
		push dword ptr [Favorite];
		call dword ptr [cmdLoadSpells];
		pop ecx;
	}
}
- Plazmic

macrotoon
a ghoul
a ghoul
Posts: 106
Joined: Wed Sep 18, 2002 4:38 pm

Post by macrotoon » Tue Jul 08, 2003 10:36 pm

OH MY GOD!

I was coming to this forum to ask how you track things like this in EQ. Meaning how can you find what commands and such are given to the server when you memorize a spell. Im such a newbie when it comes to this kind of stuff, but this little project was gonna keep me busy. DAMN YOU EQ MULE! hehe

Good work!

fwiggles
a hill giant
a hill giant
Posts: 161
Joined: Mon Jun 17, 2002 8:29 pm

Post by fwiggles » Tue Jul 08, 2003 11:35 pm

wow GJ Plaz and EQMule...i don't play a caster, but if i did this would be somethin i would definately use :D
[color=red]Latest survey shows that 3 out of 4 people make up 75% of the world's population.[/color]

wassup
Official Guardian and Writer of TFM
Official Guardian and Writer of TFM
Posts: 1487
Joined: Sat Oct 26, 2002 5:15 pm

Post by wassup » Wed Jul 09, 2003 3:11 am

Both of these functions do the same thing?

If so which is going to be permanent in the CVS?