• You've discovered RedGuides, an EverQuest multi-boxing and scripting community 🧙‍♀️⚙️. We want you to play several EQ characters at once, come join us and say hello! 👋

  • A TLP without truebox has thawed (Very Vanilla ready)
    Frostreaver

Request - Spell/Skill/Disc checking Macro

Joined
Dec 31, 2005
RedCents
1,008¢
I had a thought for those that have all the database tables and ability for a spell checker type macro. We all use and love Scribe to get spells and such from the vendors but how about seeing what you are missing? What would it take to create a macro that would look at your class then go through your spell book, disc's and skills to see what you're missing. At the higher levels, you have to do some running around to get certain spells like Alarith, West Etherene Karana, etc. Just a thought! :)
 
I second this.

As we/you know, scribe merely looks at the spells/tomes available at the vendor you have open (yes there is a mod somewhere that will checked nearest NPC). You almost have to check your spells against Alla's to know what you might be missing (which sadly, is exactly what I do).
 
It would take making a list of every fucking class spells, songs or discs and saving it somewhere to check against your toon.
 
I'm not so sure, couldn't it just do a search on Alla's, grab all spells for your class <= lvl, and do a compare with what is in your spellbook?

Yes it's possible Alla's has restrictions against outside domain searches, would have to look at that, but then could always use Magelo. Perhaps can't be done with a mac what with the out-of-game URL processing, but maybe could be done with that .NET scripting engine I can't remember the name of right now.

Hell, you could even create your own list using /outputfile spellbook on a 105 toon of the same class you knew had them all to use as your database.

That outputfile could be posted for others to use, a mac could then read it like an INI, compare it to what's in spellbook, output list of missing spells.

I nominate Raz to upload the 105 all-spell txt file for wizzies, just sayin.
 
Actually.. it is pretty doable with existing data and not much effort but it would require a plugin to not take forever. Macro could certainly do it automatically but it would take a minute or so as my guesstimate.
 
The more I think about this the more I could swear this was done, mighta been back 10 yrs ago... I remember running something against my SHM and seeing I was only missing the Imbue crap that I didn't want... maybe that was the old Magelo App?

Sp Pete, point me in the right direction for an -in- memory spell dump and I will look at this. I will go look at the MQ2 docos now and see what I can find.
 
Your correct Inc, there was as i used it for all my casters. Maybe still on eqm2 site. I'll look when i get home.
 
- - - Updated - - -
edit: went ahead and coded a draft version out. youd need to make this a /command to use.
So the brute force version would look something like this (for spells only atm):
Rich (BB code):
void MissingSpells(PSPAWNINFO pChar, PCHAR szLine)
{
	for (int i = 0; i < 50000; i++)
	{
		if (PSPELL pSpell = GetSpellByID(i))
			if (pSpell->ClassLevel[GetCharInfo()->pSpawn->Class] <= GetCharInfo2()->Level)
			{
				int z = 0;
				for (int x = 0; x < NUM_BOOK_SLOTS; x++)
					if (PSPELL pBookSpell = GetSpellByID(GetCharInfo2()->SpellBook[x]))
					{
						if (pSpell == pBookSpell || strstr(pSpell->Name, pBookSpell->Name) || strstr(pBookSpell->Name, pSpell->Name))
						{
							z = 1;
							continue;
						}
					}
				if(z==0)
					WriteChatf("Missing: %s - Level %d", pSpell->Name, pSpell->ClassLevel[GetCharInfo()->pSpawn->Class]);
			}
	}
}

Now you could make that a lot more efficient by just loading all your discs and spells into a vector/array/map and compare to that rather than search the entire book every time. and as you detect something you could remove it so your map gets smaller and smaller as you go. Then what you are searching for is a lot less information and it would run much faster. i might write it out later.
 
I have never been able to find a way to access the class object from the Spell TLO, in a macro anyway. I have had times where I have needed to look at the classes that could use a spell and have never found a way to tell if a certain spell can be used by a specific class, when looking at the Spell TLO.
 
So i cant seem to create plugins atm due to 64 bit windows issue. but this compiles correctly into my bot plugin if someone would like to try it. it would either list all the spells you have or all the ones you are missing depending on what you choose. default is to list missing. i made it this way so that you could add other options that i hadnt thought of, such as specific types. ive chopped it out of my other plugin, so if some variable or type isnt declared, you may have to add something. it should be smart enough to only list the spell group once, instead of rank 1,2,3,etc. so in theory it will list only the rank 1 of everything you are missing.

/myspells
/myspells missing
/myspells have
Rich (BB code):
#include "../MQ2Plugin.h"
#include <vector>

PreSetup("MQ2SpellList");
char INISection[MAX_STRING];

bool FindSpell(PSPELL pSpell, vector<PSPELL> &v)
{
	for (int i = 0; i < v.size();i++)
	{
		if (v->SpellGroup == pSpell->SpellGroup)
			return true;
	}
	return false;
}

void MySpells(PSPAWNINFO pChar, PCHAR szLine)
{
	if (GetGameState() == GAMESTATE_INGAME && GetCharInfo() && GetCharInfo()->pSpawn && GetCharInfo2())
	{
		int option = 0;
		if (strlen(szLine) != 0)
		{
			CHAR Arg1[MAX_STRING] = { 0 };
			GetArg(Arg1, szLine, 1);
			if (!_stricmp(Arg1, "have"))
			{
				option = 1;
			}
			if (!_stricmp(Arg1, "missing"))
			{
				option = 0;
			}
		}
		vector<PSPELL> MySpells, HaveSpells, MissingSpells;
		for (unsigned long nCombatAbility = 0; nCombatAbility < NUM_COMBAT_ABILITIES; nCombatAbility++)
		{
			if (pCombatSkillsSelectWnd->ShouldDisplayThisSkill(nCombatAbility)) {
				if (PSPELL pSpell = GetSpellByID(pPCData->GetCombatAbility(nCombatAbility)))
				{
					MySpells.push_back(pSpell);
				}
			}
		}
		for (unsigned long nAbility = 0; nAbility < NUM_ALT_ABILITIES; nAbility++)
		{
			if (PALTABILITY pAbility = pAltAdvManager->GetAAById(nAbility)) {
				if (char *pName = pCDBStr->GetString(pAbility->nName, 1, NULL))
				{
					if (pAbility->SpellID != -1) {
						if (PSPELL pSpell = GetSpellByID(pAbility->SpellID))
						{
							MySpells.push_back(pSpell);
						}
					}
				}
			}
		}
		for (DWORD nSpell = 0; nSpell < NUM_BOOK_SLOTS; nSpell++)
		{
			if (GetCharInfo2()->SpellBook[nSpell] != 0xFFFFFFFF)
			{
				if (PSPELL pSpell = GetSpellByID((GetCharInfo2()->SpellBook[nSpell])))
				{
					MySpells.push_back(pSpell);
				}
			}
		}
		{
			for (int i = 0; i < 50000; i++)
			{
				if (PSPELL pSpell = GetSpellByID(i))
				{
					if (pSpell->ClassLevel[GetCharInfo()->pSpawn->Class] <= GetCharInfo2()->Level)
					{
						if (FindSpell(pSpell, MySpells))
							HaveSpells.push_back(pSpell);
						else
						{
							if (!FindSpell(pSpell, MissingSpells))
								MissingSpells.push_back(pSpell);
							else
								continue;
						}
					}
				}
			}
		}
		char key[MAX_STRING]={ 0 }, total[MAX_STRING]={ 0 },spellName[MAX_STRING] = { 0 };
		if (option == 0)
		{
			::sprintf(total,"%d",MissingSpells.size());
			WritePrivateProfileString(INISection, "MissingTotal", total,INIFileName);
			for (int i = 0; i < MissingSpells.size();i++)
			{
				::sprintf(key, "Missing%d", i);
				::sprintf(spellName, "%s|%d", MissingSpells->Name, MissingSpells->ClassLevel[GetCharInfo()->pSpawn->Class]);
				WritePrivateProfileString(INISection, key, spellName, INIFileName);
			}
		}
		if (option == 1)
		{
			::sprintf(total,"%d",HaveSpells.size());
			WritePrivateProfileString(INISection, "HaveTotal", total,INIFileName);
			for (int i = 0; i < HaveSpells.size(); i++)
			{
				::sprintf(key, "Have%d", i);
				::sprintf(spellName, "%s|%d", HaveSpells->Name, HaveSpells->ClassLevel[GetCharInfo()->pSpawn->Class]);
				WritePrivateProfileString(INISection, key, spellName, INIFileName);
			}
		}
                WriteChatf("Spell output complete");
		return;
	}
}

PLUGIN_API VOID InitializePlugin(VOID)
{
	::sprintf(INIFileName, "%s\\%s_%s.ini", gszINIPath, EQADDR_SERVERNAME, GetCharInfo()->Name);
	::sprintf(INISection, "%s_%d_%s_%s", PLUGIN_NAME, Level, pEverQuest->GetRaceDesc(Races), pEverQuest->GetClassDesc(Class));
	DWORD Shrouded=false;
	Shrouded = GetCharInfo2()->Shrouded;
		if (!Shrouded)
			INISection[strlen(PLUGIN_NAME)] = 0;
	AddCommand("/myspells", MySpells);
}

PLUGIN_API VOID ShutdownPlugin(VOID)
{
	RemoveCommand("/myspells");
}


- - - Updated - - -

I edited the output to not use /mq2log because why bother. instead it will make it more macro friendly and output them as into your main mq2 folder in your server_name.ini under [MQ2SpellList] (assuming you name the plugin that) as:
[MQ2SpellList]
MissingTotal=#
Missing0=Spell name|Level

HaveTotal=#
Have0=Blah Rk. II|75
Have1=This spell Rk. III|101
 
Last edited:
Request - Spell/Skill/Disc checking Macro

Users who are viewing this thread

Back
Top
Cart