Spell Favorites

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

Moderator: MacroQuest Developers

Amadeus
The Maestro
The Maestro
Posts: 2036
Joined: Sat Jun 29, 2002 3:51 pm

Spell Favorites

Post by Amadeus » Tue Jun 17, 2003 2:33 am

Yea, well, I'm not sure how useful this is going to be to our little project...I can't seem to find any pointers to it..however, I could find the list of 'favorites' in memory ..hehe

I'm not adding it to any patches or anything...but, just in case anyone wants to dick around with it ..the struct is something like this:

Code: Select all

typedef struct _SPELLLOADERLIST {
/*0x00*/	DWORD	SpellIDs[8];
/*0x20*/	CHAR	 Name[24];
/*0x38*/	DWORD	Unknown0x38;
} SPELLLOADERLIST, *PSPELLLOADERLIST;
Current offset as of 6/11/2003 is 0075e2ac

merkzu
a ghoul
a ghoul
Posts: 99
Joined: Wed May 14, 2003 2:08 pm

Post by merkzu » Tue Jun 17, 2003 8:23 pm

sure would be nice to be able to /loadlist spelllist

cybernerd
a lesser mummy
a lesser mummy
Posts: 38
Joined: Tue May 13, 2003 11:05 pm

Post by cybernerd » Thu Jun 19, 2003 6:36 am

How the heck do you load those pesky favorites? Or even save them for that matter? I can't find that feature anywhere by clicking/right clicking on the spell bar. I saw a screenshot of it before it went live, but I can't seem to figure it out... Thanks!

-The Nerd :lol:

Glasscoin
a lesser mummy
a lesser mummy
Posts: 55
Joined: Mon Jan 13, 2003 8:57 am

Post by Glasscoin » Thu Jun 19, 2003 8:17 am

Right click on the spellbook icon on your spellbar

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

Post by Plazmic » Tue Jul 08, 2003 2:06 am

Minor struct fixup
typedef struct _SPELLLOADERLIST {
/*0x00*/ DWORD SpellIDs[8];
/*0x20*/ CHAR Name[25];
/*0x39*/ BYTE Byte_39; // set to 1
/*0x3A*/ BYTE Byte_3A; // set to 1
/*0x3B*/ BYTE Byte_3B; // unknown
} SPELLLOADERLIST, *PSPELLLOADERLIST;


Want to actually use this?

LoadSpellFavorites=004466EB
typedef VOID (__cdecl *fEQLoadSpells)(PSPELLLOADERLIST,DWORD);

Oh, and it's a spellbook window class function...
SpellBookWnd=005e545c


I'd CVS my /loadspells command, but I never got CVS syncing to work from Windows ;(
Last edited by Plazmic on Tue Jul 08, 2003 2:30 am, edited 2 times in total.
- Plazmic

User avatar
grimjack
Macro Author
Macro Author
Posts: 525
Joined: Thu Nov 07, 2002 6:51 am
Contact:

Post by grimjack » Tue Jul 08, 2003 2:17 am

Plazmic wrote:Minor struct fixup
typedef struct _SPELLLOADERLIST {
/*0x00*/ DWORD SpellIDs[8];
/*0x20*/ CHAR Name[25];
/*0x39*/ BYTE Byte_39; // set to 1
/*0x3A*/ BYTE Byte_3A; // set to 1
/*0x3B*/ BYTE Byte_3B; // unknown
} SPELLLOADERLIST, *PSPELLLOADERLIST;


Want to actually use this?

LoadSpellFavorites=004466EB
typedef VOID (__cdecl *fEQLoadSpells)(PSPELLLOADERLIST,DWORD);


I'd CVS my /loadspells command, but I never got CVS syncing to work from Windows ;(
drool

This would make my life sooo much easier.
When they come to me, they're in trouble, or they want some. I bust people out of prison, hunt down vampires, fight alien gods -- All the fun jobs people are too squeamish or too polite to do themselves.

Call me a mercenary. Call me an assassin. Call me a villain. I am all that and more.

My name's John Gaunt, but out on the streets of Cynosure, I am called...
GrimJack

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

All of it in one post

Post by Plazmic » Tue Jul 08, 2003 2:50 am

Ok... here's everything important... you can add the non-externs and read them from the ini yourself.
Oh, and don't forget to add it to the command list ;)

Code: Select all

LoadSpells=004466EB
SpellFavorites=0075E2AC
SpellBookWnd=005E545C

Code: Select all

typedef struct _SPELLLOADERLIST { 
/*0x00*/ DWORD SpellIDs[8]; 
/*0x20*/ CHAR Name[25]; 
/*0x39*/ BYTE Byte_39; // set to 1 
/*0x3A*/ BYTE Byte_3A; // set to 1 
/*0x3B*/ BYTE Byte_3B; // unknown 
} SPELLLOADERLIST, *PSPELLLOADERLIST; 
typedef VOID    (__cdecl *fEQLoadSpells)(PSPELLLOADERLIST,DWORD);

extern PSPELLLOADERLIST EQADDR_SPELLFAVORITES;
extern DWORD *EQADDR_SPELLBOOKWND;
extern fEQLoadSpells      cmdLoadSpells;

Code: Select all

// ***************************************************************************
// Function:    LoadSpells
// Description: Our '/loadspells' command
//              Loads (or lists) a spell favorite list
// Usage:       /loadspells [list|"name"]
// ***************************************************************************
DWORD FindSpellListByName(PCHAR szName)
{
	DWORD Index;
	for (Index=0;Index<10;Index++) {
		if (!stricmp(EQADDR_SPELLFAVORITES[Index].Name,szName)) return Index;
	}
	return -1;
}

VOID LoadSpells(PSPAWNINFO pChar, PCHAR szLine)
{
	if (!cmdLoadSpells || !EQADDR_SPELLFAVORITES || !EQADDR_SPELLBOOKWND || szLine[0]==0) return;

	DWORD Index, DoIndex = 0xFFFFFFFF;
	CHAR szArg1[MAX_STRING] = {0};
	CHAR szArg2[MAX_STRING] = {0};
	CHAR szBuffer[MAX_STRING] = {0};
	DWORD SpellBookWnd = *EQADDR_SPELLBOOKWND;

	if (!SpellBookWnd) return;

	GetArg(szArg1,szLine,1);
	GetArg(szArg2,szLine,2);

	if ((!stricmp(szArg1,"list")) && (szArg2[0]==0)) {
		WriteChatBuffer("Spell favorites list:",USERCOLOR_DEFAULT);
		WriteChatBuffer("--------------------------",USERCOLOR_DEFAULT);
		for (Index=0;Index<10;Index++) {
			if (EQADDR_SPELLFAVORITES[Index].Name[0]!=0) {
				WriteChatBuffer(EQADDR_SPELLFAVORITES[Index].Name,USERCOLOR_DEFAULT);
			}
		}
		return;
	}

	if (!stricmp(szArg1,"list")) {
		DoIndex = FindSpellListByName(szArg2);
		if (DoIndex==-1) {
			sprintf(szBuffer,"Unable to find favorite list '%s'",szArg2);
			WriteChatBuffer(szBuffer,USERCOLOR_DEFAULT);
			return;
		}
		sprintf(szBuffer,"Favorite list '%s':",szArg2);
		WriteChatBuffer(szBuffer,USERCOLOR_DEFAULT);
		for (Index=0;Index<8;Index++) {
			if (EQADDR_SPELLFAVORITES[DoIndex].SpellId[Index]!=0xFFFFFFFF) {
				sprintf(szBuffer,"%d) %s",Index,GetSpellByID(EQADDR_SPELLFAVORITES[DoIndex].SpellId[Index]));
				WriteChatBuffer(szBuffer,USERCOLOR_DEFAULT);
			}
		}
		return;
	}

	DoIndex = FindSpellListByName(szArg1);
	if (DoIndex!=-1) {
		Index = (DWORD)&EQADDR_SPELLFAVORITES[DoIndex];
		
		__asm {
			push ecx;
			mov ecx, dword ptr [SpellBookWnd];
			push 8;
			push dword ptr [Index];
			call dword ptr [cmdLoadSpells];
			pop ecx;
		}
	} else {
		sprintf(szBuffer,"Unable to find favorite list '%s'",szArg1);
		WriteChatBuffer(szBuffer,USERCOLOR_DEFAULT);
	}
}
- Plazmic

User avatar
grimjack
Macro Author
Macro Author
Posts: 525
Joined: Thu Nov 07, 2002 6:51 am
Contact:

Spell list meming.

Post by grimjack » Tue Jul 08, 2003 3:11 am

Thanks a million Plaz. This will be a great help.

Thanks
GrimJack
When they come to me, they're in trouble, or they want some. I bust people out of prison, hunt down vampires, fight alien gods -- All the fun jobs people are too squeamish or too polite to do themselves.

Call me a mercenary. Call me an assassin. Call me a villain. I am all that and more.

My name's John Gaunt, but out on the streets of Cynosure, I am called...
GrimJack

kagonis
a hill giant
a hill giant
Posts: 228
Joined: Sat May 24, 2003 8:48 pm

Post by kagonis » Tue Jul 08, 2003 4:33 am

:?
Hmm, the first one I can kinda quess where goes in, eqclient.ini right?
The second and third goes in? EQLib_MacroParser.cpp?

I'm dumb, please help me here.
I wanna go from "Kagonis drools -- something must have him excited" to "Kagonis gets a mad look in his eyes: Muahahahaha it's aliiive"

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

Post by BlueSkies » Tue Jul 08, 2003 1:13 pm

Very cool Plaz. :) Got this working with about 15 minutes of work :)

Had to fix one of your typos though :P

In LoadSpells, you have the following:

Code: Select all

  if (!stricmp(szArg1,"list")) { 
      DoIndex = FindSpellListByName(szArg2); 
      if (DoIndex==-1) { 
         sprintf(szBuffer,"Unable to find favorite list '%s'",szArg2); 
         WriteChatBuffer(szBuffer,USERCOLOR_DEFAULT); 
         return; 
      } 
      sprintf(szBuffer,"Favorite list '%s':",szArg2); 
      WriteChatBuffer(szBuffer,USERCOLOR_DEFAULT); 
      for (Index=0;Index<8;Index++) { 
         [b]if (EQADDR_SPELLFAVORITES[DoIndex].SpellId[Index]!=0xFFFFFFFF) { 
            sprintf(szBuffer,"%d) %s",Index,GetSpellByID(EQADDR_SPELLFAVORITES[DoIndex].SpellId[Index])); [/b]
            WriteChatBuffer(szBuffer,USERCOLOR_DEFAULT); 
         } 
      } 
      return; 
   }
Replace the bold lines with:

Code: Select all

if (EQADDR_SPELLFAVORITES[DoIndex].SpellIDs[Index]!=0xFFFFFFFF) { 
            sprintf(szBuffer,"%d) %s",Index,GetSpellByID(EQADDR_SPELLFAVORITES[DoIndex].SpellIDs[Index]));
Not a big deal -- gods know I've done the same (and worse) about a million times. :P

Thanks for the LoadSpells function, and the opportunity to give my MQ knowledge a workout :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 2:22 pm

can we get this function cvsed in? DKAA? someone?
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.