• 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

MQ2Onecast Plugin

Kyle100

Member
Joined
Jan 8, 2007
RedCents
Purpose: I needed a plugin that would "Cast any single spell over and over as a plugin when a condition is met" It will then sit the toon to med and wait for the condition to be met again. (Thank you odessa for your assistance)


Things I use this for:
  • When Powerleveling a toon I do not want my cleric in group with the PL toon so that I dont steal XP from the toon I am PLing.
  • When I am melee skill training a toon as its skill's advance eventually it will kill the pet that it is fighting. I use this to heal the pet.

Plugin Settings:Used Grouped or Ungrouped
Ensure the mob you want to cast on is targeted:
if you type </onecast npcName % "spellName" target>

(Important Note: if you target something when you do /onecast the plugin will ignore the name and use the target for healing. So even if you write /onecast tankname 45 "heal" but target a pet it will heal the pet)

if you zone you have to redo /onecast because spawnIDs will change

Additonal Options When Grouped
if you type /onecast Name % "spell" (Leave the word target off)
Then after it casts the spell it will untarget the designated mob and again wait for the condition to be met.


Known Bug There is one bug that I can not figure out how to slove. If the "target mob dies" The plugin loses focus and keeps trying to recast the spell on the dead mob. So u have to unload the plugin and start over.


Rich (BB code):
#include "../MQ2Plugin.h"

using namespace std;
PreSetup("MQ2OneCast");

PSPAWNINFO pMyTarget;
char name[MAX_STRING];
int hpPct;
char spell[MAX_STRING];
char temp[MAX_STRING];
char spellgem[MAX_STRING];
bool ready = false;
bool casting = false;
bool untarget = true;

PSPAWNINFO FindTarget(char* _name) {
	PSPAWNINFO pSpawn = (PSPAWNINFO)pSpawnList;
	while (pSpawn) 
	{ 	
		if (GetSpawnType(pSpawn)==PC) {
			if (!stricmp(pSpawn->Name,_name)) return pSpawn;
		}
		pSpawn=pSpawn->pNext;
	}
	return NULL;
}

BOOL InGame() { 
	return(gGameState == GAMESTATE_INGAME && GetCharInfo2() && GetCharInfo()); 
} 

VOID OneCast(PSPAWNINFO pChar, PCHAR szLine) {
	GetArg(name,szLine,1);
	if (pTarget) pMyTarget = (PSPAWNINFO)pTarget;
	else pMyTarget = FindTarget(name);
	CHAR _hpPct[MAX_STRING]; 
	GetArg(_hpPct,szLine,2);
	hpPct=atoi(_hpPct);
	GetArg(spell,szLine,3);
	for (int Index=0;Index<9;Index++) {
      if (GetCharInfo2()->MemorizedSpells[Index]!=0xFFFFFFFF) {
         PCHAR SpellName = GetSpellNameByID(GetCharInfo2()->MemorizedSpells[Index]);
         if (!stricmp(spell,SpellName)) {
            itoa(Index+1,spellgem,10);
         }
      }
	}
	WriteChatf("Casting %s on %s at %d%", spell, pMyTarget->Name, hpPct);
	if (!strncmp(GetArg(temp,szLine,4),"target",6)) {
		untarget = false;
		WriteChatf("Will NOT untarget after cast.");
	} else {
		untarget = true;
		WriteChatf("Will untarget after cast.");
	}
	ready = true;
	
}

// Called once, when the plugin is to initialize
PLUGIN_API VOID InitializePlugin(VOID)
{
	AddCommand("/onecast",OneCast);
}

// Called once, when the plugin is to shutdown
PLUGIN_API VOID ShutdownPlugin(VOID)
{
	RemoveCommand("/onecast");
}

PLUGIN_API VOID OnPulse(VOID)
{
	PSPAWNINFO pChar = GetCharInfo()->pSpawn;
	if (InGame() && ready) {
		if (pMyTarget->HPCurrent<=hpPct) {
			if (pChar->CastingSpellID==-1 && ((PEQCASTSPELLWINDOW)pCastSpellWnd)->SpellSlots[atoi(spellgem)]->spellstate==0) {
				Target(pChar,name);
				if (pTarget) cmdCast(pChar,spellgem);
				if (untarget) pTarget=NULL;
				casting = true;
			}			
		}
		if (pChar->CastingSpellID==-1 && casting) {
				casting = false;
				DoCommand(pChar,"/sit");
			}
	}
}

PLUGIN_API VOID OnBeginZone(VOID) {
	ready = false;
}
 
Just add in a check to the command args. Do something like
Rich (BB code):
/onecast npcName % "spellName" target 0|1

Then
Rich (BB code):
bool StopNoTarg = false;
GetArg(StopNoTarg,szLine,5)

Then in your OnPulse checks:
Rich (BB code):
PLUGIN_API VOID OnPulse(VOID)
{
	PSPAWNINFO pChar = GetCharInfo()->pSpawn;
	if (InGame() && ready) {
                if (StopNoTarg && !pTarget) {
	ready = false;
	casting = false;
	return;
	}
		if (pMyTarget->HPCurrent<=hpPct) {
			if (pChar->CastingSpellID==-1 && ((PEQCASTSPELLWINDOW)pCastSpellWnd)->SpellSlots[atoi(spellgem)]->spellstate==0) {
				Target(pChar,name);
				if (pTarget) cmdCast(pChar,spellgem);
				if (untarget) pTarget=NULL;
				casting = true;
			}			
		}
		if (pChar->CastingSpellID==-1 && casting) {
				casting = false;
				DoCommand(pChar,"/sit");
			}
	}
}

Final suggestion:
Rich (BB code):
#include "../MQ2Plugin.h"

using namespace std;
PreSetup("MQ2OneCast");

PSPAWNINFO pMyTarget;
char name[MAX_STRING];
int hpPct;
char spell[MAX_STRING];
char temp[MAX_STRING];
char spellgem[MAX_STRING];
bool ready = false;
bool casting = false;
bool untarget = true;
bool StopNoTarg = false;

PSPAWNINFO FindTarget(char* _name) {
	PSPAWNINFO pSpawn = (PSPAWNINFO)pSpawnList;
	while (pSpawn) 
	{ 	
		if (GetSpawnType(pSpawn)==PC) {
			if (!stricmp(pSpawn->Name,_name)) return pSpawn;
		}
		pSpawn=pSpawn->pNext;
	}
	return NULL;
}

BOOL InGame() { 
	return(gGameState == GAMESTATE_INGAME && GetCharInfo2() && GetCharInfo()); 
} 

VOID OneCast(PSPAWNINFO pChar, PCHAR szLine) {
	GetArg(name,szLine,1);
	if (pTarget) pMyTarget = (PSPAWNINFO)pTarget;
	else pMyTarget = FindTarget(name);
	CHAR _hpPct[MAX_STRING]; 
	GetArg(_hpPct,szLine,2);
	hpPct=atoi(_hpPct);
	GetArg(spell,szLine,3);
	for (int Index=0;Index<9;Index++) {
      if (GetCharInfo2()->MemorizedSpells[Index]!=0xFFFFFFFF) {
         PCHAR SpellName = GetSpellNameByID(GetCharInfo2()->MemorizedSpells[Index]);
         if (!stricmp(spell,SpellName)) {
            itoa(Index+1,spellgem,10);
         }
      }
	}
	WriteChatf("Casting %s on %s at %d%", spell, pMyTarget->Name, hpPct);
	if (!strncmp(GetArg(temp,szLine,4),"target",6)) {
		untarget = false;
		WriteChatf("Will NOT untarget after cast.");
	} else {
		untarget = true;
		WriteChatf("Will untarget after cast.");
	}
        GetArg(StopNoTarg,szLine,5);
	ready = true;
	
}

// Called once, when the plugin is to initialize
PLUGIN_API VOID InitializePlugin(VOID)
{
	AddCommand("/onecast",OneCast);
}

// Called once, when the plugin is to shutdown
PLUGIN_API VOID ShutdownPlugin(VOID)
{
	RemoveCommand("/onecast");
}

PLUGIN_API VOID OnPulse(VOID)
{
	PSPAWNINFO pChar = GetCharInfo()->pSpawn;
	if (InGame() && ready) {
                if (StopNoTarg && !pTarget) {
	                ready = false;
	                casting = false;
	                return;
	                }
		if (pMyTarget->HPCurrent<=hpPct) {
			if (pChar->CastingSpellID==-1 && ((PEQCASTSPELLWINDOW)pCastSpellWnd)->SpellSlots[atoi(spellgem)]->spellstate==0) {
				Target(pChar,name);
				if (pTarget) cmdCast(pChar,spellgem);
				if (untarget) pTarget=NULL;
				casting = true;
			}			
		}
		if (pChar->CastingSpellID==-1 && casting) {
				casting = false;
				DoCommand(pChar,"/sit");
			}
	}
}

PLUGIN_API VOID OnBeginZone(VOID) {
	ready = false;
}

Thus, the 0 or 1 for the fifth arg acts to tell the plugin whether or not to stop the plugin. As a warning, this is rough code -- no testing for compiling. But even if that doesn't work, it should give you the ideas, code-wise, that you need for finalizing your check.
 
MQ2Onecast Plugin

Users who are viewing this thread

Back
Top
Cart