Below is the source code and the compiled dll for mq2autoskills
Please Report any bugs
Please Red Cent me if you find this useful
Please Report any bugs
Rich (BB code):
// MQ2AutoSkills.cpp : Auto-activate various skills
//
// version EMU
// 11/22/10 - Reverted code back to 20051116 MQ2Source Compatitble
//
// Project started 8/30/2004 by Cr4zyb4rd
// 9/27/06 - GuildLeader added nils and Drumstix42's fixes for latest zip
// 12/15/05 - DigitalMocking;
// Added a check to use /pet hold if you have the AA during enrage,
// Fixed bash to work properly with the 2 Hand Bash AA
// Fixed a crash bug with bash and equipping a 2handed weapon
// 10/5/05 - DigitalMocking;
// Added /pet back to the enrage and infurate sections of the code
// Added a shield check for the bash ability, ability will no longer fire
// and spam the screen if you don't have a shield equipped.
//
// Commands:
// /autoskills help - lists options
//
// INI file will be auto-created, MQ2AutoSkills_Charname_server.ini
// Syntax is simply Skill=on/off and MeleeRange=distance
//
// Currently suported skills:
// Backstab, Bash, Begging, Disarm, Dragon Punch, Eagle Strike, Flying Kick,
// Frenzy, Evade, Forage, Feign Death, Intimidation, Kick, Mend, Pick Pockets,
// Round Kick, Sense Traps, Slam, Taunt, Tiger Claw
//
// /attack off on mob ENRAGE/infuriate is also supported, treated as the "ENRAGE"
// and "infuriate" skills in the INI.
//
// Known issues: Trade/Vendor windows and possibly some other events may cause some
// skills to fire when not appropriate and spam you
//
//////////////////////////////////////////////////////////////////////////////////////
#include "../MQ2Plugin.h"
#ifndef nSkillsNonInnate
#define nSkillsNonInnate 100
#endif
#ifndef nSkillsMax
#define nSkillsMax 132
#endif
PSPAWNINFO psOldTarget = NULL;
bool MQ2ASenabled = false;
bool DoBackstab = false;
bool DoBash = false;
bool DoBegging = false;
bool DoDisarm = false;
bool DoDragonPunch = false;
bool DoEagleStrike = false;
bool DoENRAGE;
bool DoEvade = false;
bool DoForage = false;
bool DoFeignDeath = false;
bool DoFlyingKick = false;
bool DoFrenzy = false;
bool DoIntimidation = false;
bool DoInfuriate = false;
bool DoKick = false;
bool DoMend = false;
bool DoPickPockets = false;
bool DoRoundKick = false;
bool DoSenseTraps = false;
bool DoSlam = false;
bool DoTaunt = false;
bool DoTigerClaw = false;
bool DoingBegging = false;
bool DoingENRAGE = false;
bool DoingEvade = false;
bool DoingForage = false;
bool DoingInfuriate = false;
bool DoingPickPockets = false;
bool DoingFeignDeath = false;
float MeleeRange = 15;
int BackOffHP = 0;
int DoMendHP = 80;
PreSetup("MQ2AutoSkills");
//shamelessly stolen from MQ2MoveUtils
float angularDistance(float h1, float h2)
{
if( h1 == h2 ) return 0.0;
if( fabs(h1-h2) > 256.0 )
*(h1<h2?&h1:&h2) += 512.0;
return (fabs(h1-h2)>256.0)?(h2-h1):(h1-h2);
}
void ASDoAbility(PCHAR Ability)
{
if (!strncmp(szSkills[112],"Slam",4)) {
DWORD Index, DoIndex, ListIndex = 0xFFFFFFFF;
for (Index=0;Index<10;Index++) {
ListIndex = EQADDR_DOABILITYLIST[Index];
if (ListIndex!= 0xFFFFFFFF) {
if (ListIndex>nSkillsNonInnate) ListIndex++;
if (!strnicmp(Ability,szSkills[ListIndex],strlen(szSkills[ListIndex]))) {
if (Index<4) {
DoIndex = Index+7; // 0-3 = Combat abilities (7-10)
} else {
DoIndex = Index-3; // 4-9 = Abilities (1-6)
}
}
}
}
if (DoIndex!=0xFFFFFFFF) {
CHAR szBuffer[MAX_STRING];
cmdDoAbility(GetCharInfo()->pSpawn,itoa(DoIndex,szBuffer,10));
} else {
WriteChatColor("You do not seem to have that ability on a /doability button",USERCOLOR_DEFAULT);
}
} else DoAbility(GetCharInfo()->pSpawn,Ability);
}
bool BoolFromINI(PCHAR Section, PCHAR Key)
{
char szTemp[MAX_STRING];
GetPrivateProfileString(Section,Key,"off",szTemp,MAX_STRING,INIFileName);
if (!strnicmp(szTemp,"off",3)) {
WritePrivateProfileString(Section,Key,"off",INIFileName);
return false;
}
WritePrivateProfileString(Section,Key,"on",INIFileName);
return true;
}
bool CheckAbilityReady(PCHAR szSkillName)
{
for (DWORD nSkill=0;nSkill<=nSkillsMax;nSkill++) {
if (!stricmp(szSkillName,szSkills[nSkill])) {
if (nSkill>nSkillsNonInnate && !strncmp(szSkills[112],"Slam",4)) nSkill++;
if (nSkill>nSkillsNonInnate)
return gbAltTimerReady?true:false;
else
return EQADDR_DOABILITYAVAILABLE[nSkill]?true:false;
}
}
return false;
}
VOID LoadINI()
{
char szTemp[MAX_STRING];
char MeleeRangeTemp[MAX_STRING];
DoBackstab = BoolFromINI("Skills","Backstab");
DoBash = BoolFromINI("Skills","Bash");
DoBegging = BoolFromINI("Skills","Begging");
DoDisarm = BoolFromINI("Skills","Disarm");
DoDragonPunch = BoolFromINI("Skills","DragonPunch");
DoEagleStrike = BoolFromINI("Skills","EagleStrike");
DoENRAGE = BoolFromINI("Skills","ENRAGE");
DoEvade = BoolFromINI("Skills","Evade");
DoFeignDeath = BoolFromINI("Skills","FeignDeath");
DoForage = BoolFromINI("Skills","Forage");
DoFlyingKick = BoolFromINI("Skills","FlyingKick");
DoFrenzy = BoolFromINI("Skills","Frenzy");
DoIntimidation = BoolFromINI("Skills","Intimidation");
DoInfuriate = BoolFromINI("Skills","Infuriate");
DoKick = BoolFromINI("Skills","Kick");
DoMend = BoolFromINI("Skills","Mend");
DoRoundKick = BoolFromINI("Skills","RoundKick");
DoPickPockets = BoolFromINI("Skills","PickPockets");
DoSenseTraps = BoolFromINI("Skills","SenseTraps");
DoSlam = BoolFromINI("Skills","Slam");
DoTaunt = BoolFromINI("Skills","Taunt");
DoTigerClaw = BoolFromINI("Skills","TigerClaw");
sprintf(MeleeRangeTemp,"%3.3f",MeleeRange);
GetPrivateProfileString("Settings","MeleeRange",MeleeRangeTemp,szTemp,MAX_STRING,INIFileName);
MeleeRange = (float)atof(szTemp);
WritePrivateProfileString("Settings","MeleeRange",szTemp,INIFileName);
BackOffHP = GetPrivateProfileInt("Settings","BackOffHP",0,INIFileName);
sprintf(szTemp,"%d",BackOffHP);
WritePrivateProfileString("Settings","BackOffHP",szTemp,INIFileName);
DoMendHP = GetPrivateProfileInt("Settings","DoMendHP",80,INIFileName);
sprintf(szTemp,"%d",DoMendHP);
WritePrivateProfileString("Settings","DoMendHP",szTemp,INIFileName);
}
VOID DisplayAutoSkillsHelp()
{
WriteChatColor("MQ2AutoSkills - Auto-Use Abilities",USERCOLOR_DEFAULT);
WriteChatColor("Usage:",USERCOLOR_DEFAULT);
WriteChatColor("/autoskills list - List available skills and whether they are enabled",USERCOLOR_DEFAULT);
WriteChatColor("/autoskills settings - List settings/thresholds",USERCOLOR_DEFAULT);
WriteChatColor("/autoskills backoff [#] - %HP at which to not re-engage after FD/Evade",USERCOLOR_DEFAULT);
WriteChatColor("/autoskills melee [#] - Range to be considered 'in melee'",USERCOLOR_DEFAULT);
WriteChatColor("/autoskills mendhp [#] - %HP at which to use the mend ability",USERCOLOR_DEFAULT);
WriteChatColor("/autoskills [skill] - Toggle a skill on/off and update the INI",USERCOLOR_DEFAULT);
WriteChatColor("/autoskills [skill] on - Enable a skill",USERCOLOR_DEFAULT);
WriteChatColor("/autoskills [skill] off - Disable a skill",USERCOLOR_DEFAULT);
}
VOID MQ2AutoSkillsCommand(PSPAWNINFO pChar, PCHAR szLine)
{
char szTemp[MAX_STRING];
char szTemp2[MAX_STRING];
char szArg2[MAX_STRING];
GetArg(szTemp,szLine,1);
if (strlen(szTemp)==0 || !strnicmp(szTemp,"help",4)) {
DisplayAutoSkillsHelp();
return;
}
if (!strnicmp(szTemp,"backoff",7)) {
GetArg(szTemp,szLine,2);
if (strlen(szTemp)) {
BackOffHP=atoi(szTemp);
sprintf(szTemp, "%d",BackOffHP);
WritePrivateProfileString("Settings","BackOffHP",szTemp,INIFileName);
}
WriteChatf("MQ2AutoSkills:: Backing off at %d%%",BackOffHP);
return;
}
if (!strnicmp(szTemp,"mendhp",7)) {
GetArg(szTemp,szLine,2);
if (strlen(szTemp)) {
DoMendHP=atoi(szTemp);
sprintf(szTemp, "%d",DoMendHP);
WritePrivateProfileString("Settings","DoMendHP",szTemp,INIFileName);
}
WriteChatf("MQ2AutoSkills:: Mending at %d%%",DoMendHP);
return;
}
if (!strnicmp(szTemp,"melee",7)) {
GetArg(szTemp,szLine,2);
if (strlen(szTemp)) {
MeleeRange=(float)atof(szTemp);
sprintf(szTemp, "%3.3f",MeleeRange);
WritePrivateProfileString("Settings","MeleeRange",szTemp,INIFileName);
}
WriteChatf("MQ2AutoSkills:: Melee range set to %3.3f%%",MeleeRange);
return;
}
if (!strnicmp(szTemp,"settings",8)) {
WriteChatf("MQ2AutoSkills:: Melee range set to %3.3f%%",MeleeRange);
WriteChatf("MQ2AutoSkills:: Backing off at %d%%",BackOffHP);
WriteChatf("MQ2AutoSkills:: Mending at %d%%",DoMendHP);
return;
}
if (!strnicmp(szTemp,"list", 4)) {
WriteChatColor("MQ2AutoSkills:: Supported abilites and current status",CONCOLOR_RED);
sprintf(szTemp," Backstab (%s)",DoBackstab?"\agon\ax":"\aroff\ax");
WriteChatColor(szTemp,USERCOLOR_WHO);
sprintf(szTemp," Bash (%s)",DoBash?"\agon\ax":"\aroff\ax");
WriteChatColor(szTemp,USERCOLOR_WHO);
sprintf(szTemp," Begging (%s)",DoBegging?"\agon\ax":"\aroff\ax");
WriteChatColor(szTemp,USERCOLOR_WHO);
sprintf(szTemp," Disarm (%s)",DoDisarm?"\agon\ax":"\aroff\ax");
WriteChatColor(szTemp,USERCOLOR_WHO);
sprintf(szTemp," DragonPunch (%s)",DoDragonPunch?"\agon\ax":"\aroff\ax");
WriteChatColor(szTemp,USERCOLOR_WHO);
sprintf(szTemp," EagleStrike (%s)",DoEagleStrike?"\agon\ax":"\aroff\ax");
WriteChatColor(szTemp,USERCOLOR_WHO);
sprintf(szTemp," ENRAGE (%s)",DoENRAGE?"\agon\ax":"\aroff\ax");
WriteChatColor(szTemp,USERCOLOR_WHO);
sprintf(szTemp," Evade (%s)",DoEvade?"\agon\ax":"\aroff\ax");
WriteChatColor(szTemp,USERCOLOR_WHO);
sprintf(szTemp," FeignDeath (%s)",DoFeignDeath?"\agon\ax":"\aroff\ax");
WriteChatColor(szTemp,USERCOLOR_WHO);
sprintf(szTemp," Forage (%s)",DoForage?"\agon\ax":"\aroff\ax");
WriteChatColor(szTemp,USERCOLOR_WHO);
sprintf(szTemp," FlyingKick (%s)",DoFlyingKick?"\agon\ax":"\aroff\ax");
WriteChatColor(szTemp,USERCOLOR_WHO);
sprintf(szTemp," Frenzy (%s)",DoFrenzy?"\agon\ax":"\aroff\ax");
WriteChatColor(szTemp,USERCOLOR_WHO);
sprintf(szTemp," Intimidation (%s)",DoIntimidation?"\agon\ax":"\aroff\ax");
WriteChatColor(szTemp,USERCOLOR_WHO);
sprintf(szTemp," Infuriate (%s)",DoInfuriate?"\agon\ax":"\aroff\ax");
WriteChatColor(szTemp,USERCOLOR_WHO);
sprintf(szTemp," Kick (%s)",DoKick?"\agon\ax":"\aroff\ax");
WriteChatColor(szTemp,USERCOLOR_WHO);
sprintf(szTemp," Mend (%s)",DoMend?"\agon\ax":"\aroff\ax");
WriteChatColor(szTemp,USERCOLOR_WHO);
sprintf(szTemp," PickPockets (%s)",DoPickPockets?"\agon\ax":"\aroff\ax");
WriteChatColor(szTemp,USERCOLOR_WHO);
sprintf(szTemp," RoundKick (%s)",DoRoundKick?"\agon\ax":"\aroff\ax");
WriteChatColor(szTemp,USERCOLOR_WHO);
sprintf(szTemp," SenseTraps (%s)",DoSenseTraps?"\agon\ax":"\aroff\ax");
WriteChatColor(szTemp,USERCOLOR_WHO);
sprintf(szTemp," Slam (%s)",DoSlam?"\agon\ax":"\aroff\ax");
WriteChatColor(szTemp,USERCOLOR_WHO);
sprintf(szTemp," Taunt (%s)",DoTaunt?"\agon\ax":"\aroff\ax");
WriteChatColor(szTemp,USERCOLOR_WHO);
sprintf(szTemp," TigerClaw (%s)",DoTigerClaw?"\agon\ax":"\aroff\ax");
WriteChatColor(szTemp,USERCOLOR_WHO);
return;
}
// Check if entry exists in INI
GetPrivateProfileString("Skills",szTemp,"NULL",szTemp2,MAX_STRING,INIFileName);
if (!strnicmp(szTemp2,"NULL", 4)) { // unsupported skill
WriteChatColor("MQ2AutoSkills::Unsupported argument",CONCOLOR_RED);
WriteChatColor("Use '/autoskills list' for a list",CONCOLOR_RED);
return;
}
GetArg(szArg2,szLine,2);
if ((!strlen(szArg2) && !strnicmp(szTemp2,"off",3)) || !strnicmp(szArg2,"on",2)) {
WritePrivateProfileString("Skills",szTemp,"on",INIFileName);
sprintf(szTemp2,"MQ2AutoSkills::auto %s is now ON",szTemp);
WriteChatColor(szTemp2,CONCOLOR_YELLOW);
} else if ((!strlen(szArg2) && !strnicmp(szTemp2,"on",2)) || !strnicmp(szArg2,"off",3)) {
WritePrivateProfileString("Skills",szTemp,"off",INIFileName);
sprintf(szTemp2,"MQ2AutoSkills::auto %s is now OFF",szTemp);
WriteChatColor(szTemp2,CONCOLOR_YELLOW);
} else {
DisplayAutoSkillsHelp();
return;
}
LoadINI();
}
// Called once, when the plugin is to initialize
PLUGIN_API VOID InitializePlugin(VOID)
{
DebugSpewAlways("Initializing MQ2AutoSkills");
AddCommand("/autoskills",MQ2AutoSkillsCommand);
if (MQ2Globals::gGameState==GAMESTATE_INGAME) {
if (GetCharInfo2()) {
sprintf(INIFileName,"%s\\MQ2AutoSkills_%s_%s.ini",gszINIPath,GetCharInfo()->Name,EQADDR_SERVERNAME);
LoadINI();
MQ2ASenabled=true;
return;
}
} else MQ2ASenabled = false;
}
// Called once, when the plugin is to shutdown
PLUGIN_API VOID ShutdownPlugin(VOID)
{
DebugSpewAlways("Shutting down MQ2AutoSkills");
RemoveCommand("/autoskills");
}
// Called every frame that the "HUD" is drawn -- e.g. net status / packet loss bar
PLUGIN_API VOID OnDrawHUD(VOID)
{
// DONT leave in this debugspew, even if you leave in all the others
// DebugSpewAlways("MQ2AutoSkills::OnDrawHUD()");
}
PLUGIN_API VOID SetGameState(DWORD GameState)
{
DebugSpewAlways("MQ2AutoSkills::SetGameState()");
if (GameState==GAMESTATE_INGAME) {
if (GetCharInfo2()) {
sprintf(INIFileName,"%s\\MQ2AutoSkills_%s_%s.ini",gszINIPath,GetCharInfo()->Name,EQADDR_SERVERNAME);
LoadINI();
MQ2ASenabled=true;
return;
}
} else MQ2ASenabled = false;
}
BOOL IsWindowOpen(PCHAR WindowName)
{
PCSIDLWND pWnd=(PCSIDLWND)FindMQ2Window(WindowName);
if (!pWnd) return false;
return (BOOL)pWnd->Show;
}
PLUGIN_API VOID OnPulse(VOID)
{
if (!MQ2ASenabled) return;
bool mounted;
PSPAWNINFO psTarget = NULL;
PSPAWNINFO pChSpawn = GetCharInfo()->pSpawn;
DWORD MyStandstate = GetCharInfo()->standstate;
int pctHP = pChSpawn->HPCurrent*100/pChSpawn->HPMax;
if (psOldTarget!=(PSPAWNINFO)pTarget && (DoingENRAGE || DoingInfuriate)) {
WriteChatColor("MQ2AutoSkills::Target changed, ENRAGE/Infuriate monitors reset.",CONCOLOR_YELLOW);
DoingENRAGE = false;
DoingInfuriate = false;
}
if (GetCharInfo()->Stunned || MyStandstate==STANDSTATE_DEAD || IsWindowOpen("BigBankWnd") || IsWindowOpen("MerchantWnd") || IsWindowOpen("TradeWnd")) return;
if (DoMend && pctHP < DoMendHP && CheckAbilityReady("Mend")) ASDoAbility("Mend");
//check if stunned, feigned, ducking, dead, binding, sitting
if (MyStandstate==STANDSTATE_FEIGN && DoingFeignDeath) {
if (pctHP > BackOffHP) {
HideDoCommand(pChSpawn,"/stand",FromPlugin);
if (psOldTarget==(PSPAWNINFO)pTarget) HideDoCommand(pChSpawn,"/attack on",FromPlugin);
} else WriteChatf("MQ2AutoSkills::HP lower than %d%%, staying down",BackOffHP);
DoingFeignDeath = 0;
return;
}
// check if not standing
if (MyStandstate!=STANDSTATE_STAND) return;
// check if mounted
mounted = pChSpawn && pChSpawn->pActorInfo->Mount ? true : false;
//check if casting (and not a bard)
if ((pChSpawn->pActorInfo->CastingSpellID!=-1) && strncmp(pEverQuest->GetClassDesc(GetCharInfo2()->Class),"Bard",5)) return;
if (DoSenseTraps && CheckAbilityReady("Sense Traps")) ASDoAbility("\"Sense Traps\"");
if (!mounted && !DoingForage && DoForage && !*EQADDR_ATTACK && CheckAbilityReady("Forage")) {
Sleep(50);
DoAbility(pChSpawn,"Forage");
}
//check for a target
if (ppTarget && pTarget) {
psTarget = (PSPAWNINFO)pTarget;
} else return;
//make sure target isn't me
if (psTarget!=pChSpawn) {
} else return;
//check melee distance
if (GetDistance(pChSpawn,psTarget) < MeleeRange) {
} else return;
//check if in combat
if (*EQADDR_ATTACK) {
} else if (DoingBegging || DoingEvade || DoingPickPockets || DoingFeignDeath || DoingForage) {
if (DoingBegging){
DoAbility(pChSpawn,"Begging");
DoingBegging = 0;
}
if (DoingEvade){
DoAbility(pChSpawn,"Hide");
}
if (DoingPickPockets){
DoAbility(pChSpawn,"\"Pick Pockets\"");
DoingPickPockets =0;
}
if (DoingFeignDeath){
DoAbility(pChSpawn,"\"Feign Death\"");
return; //no attack on here
}
if (DoingForage){
DoAbility(pChSpawn,"Forage");
DoingForage=0;
}
if (psOldTarget==(PSPAWNINFO)pTarget) {
if (DoingEvade && pctHP < BackOffHP) {
WriteChatf("MQ2AutoSkills::HP lower than %d%%, staying hidden",BackOffHP);
} else HideDoCommand(pChSpawn,"/attack on",FromPlugin);
}
DoingEvade =0;
psOldTarget = psTarget;
} else return;
if (DoBash && CheckAbilityReady("Bash") && GetCharInfo2()->InventoryArray[0xe]) {
if (GetCharInfo2()->InventoryArray[0xe]->Item->ItemType==0x8) ASDoAbility("Bash");
} else if (DoBash && CheckAbilityReady("Bash")) {
ASDoAbility("Bash");
}
if (DoDisarm && CheckAbilityReady("Disarm")) ASDoAbility("Disarm");
if (DoDragonPunch && CheckAbilityReady("Dragon Punch")) ASDoAbility("\"Dragon Punch\"");
if (DoEagleStrike && CheckAbilityReady("Eagle Strike")) ASDoAbility("\"Eagle Strike\"");
if (DoFlyingKick && CheckAbilityReady("Flying Kick")) ASDoAbility("\"Flying Kick\"");
if (DoFrenzy && CheckAbilityReady("Frenzy")) ASDoAbility("\"Frenzy\"");
if (DoTaunt && CheckAbilityReady("Taunt")) ASDoAbility("Taunt");
if (DoIntimidation && CheckAbilityReady("Intimidation")) ASDoAbility("Intimidation");
if (DoKick && CheckAbilityReady("Kick")) ASDoAbility("Kick");
if (DoRoundKick && CheckAbilityReady("Round Kick")) ASDoAbility("\"Round Kick\"");
if (DoSlam && CheckAbilityReady("Slam")) ASDoAbility("Slam");
if (DoTigerClaw && CheckAbilityReady("Tiger Claw")) ASDoAbility("\"Tiger Claw\"");
// These skills need attack to be turned off
if (DoBegging && CheckAbilityReady("Begging")) {
HideDoCommand(pChSpawn, "/attack off",FromPlugin);
DoingBegging = 1;
}
if (DoEvade && CheckAbilityReady("Hide") && FindSpeed(pChSpawn)==0) {
HideDoCommand(pChSpawn, "/attack off",FromPlugin);
DoingEvade = 1;
}
if (DoPickPockets && CheckAbilityReady("Pick Pockets")) {
HideDoCommand(pChSpawn, "/attack off",FromPlugin);
DoingPickPockets = 1;
}
if (DoFeignDeath && CheckAbilityReady("Feign Death")) {
HideDoCommand(pChSpawn, "/attack off",FromPlugin);
DoingFeignDeath = 1;
}
if (DoForage && CheckAbilityReady("Forage")) {
HideDoCommand(pChSpawn, "/attack off",FromPlugin);
DoingForage = 1;
}
psOldTarget = psTarget;
//check if behind target
if (fabs(angularDistance(psTarget->Heading,pChSpawn->Heading)) < 45.0) {
} else return;
if (DoBackstab && CheckAbilityReady("Backstab")) ASDoAbility("Backstab");
}
PLUGIN_API DWORD OnIncomingChat(PCHAR Line, DWORD Color)
{
if (MQ2Globals::gGameState != GAMESTATE_INGAME || !MQ2ASenabled) return 0;
// DebugSpewAlways("MQ2AutoSkills::OnIncomingChat(%s)",Line);
if(Color == USERCOLOR_NPC_ENRAGE && (DoENRAGE || DoInfuriate) && ppTarget && pTarget) {
WriteChatColor(Line,CONCOLOR_YELLOW);
PSPAWNINFO psTarget = (PSPAWNINFO)pTarget;
if (strncmp(Line,psTarget->DisplayedName,strlen(psTarget->DisplayedName))||(strstr(Line,"pet")&&!strstr(psTarget->DisplayedName,"pet"))) return 0; // not our target
if (DoENRAGE && strstr(Line,"has become ENRAGED")) {
WriteChatColor("MQ2AutoSkills::\arENRAGE\ax detected, turning attack off.",CONCOLOR_YELLOW);
HideDoCommand(GetCharInfo()->pSpawn, "/attack off",FromPlugin);
if (GetCharInfo()->pSpawn->pActorInfo->PetID) {
HideDoCommand(GetCharInfo()->pSpawn, "/pet back",FromPlugin);
}
DoingENRAGE = true;
psOldTarget = psTarget;
return 0;
}
if (DoInfuriate && strstr(Line,"is infuriated")) {
WriteChatColor("MQ2AutoSkills::\arInfuriate\ax detected, turning attack off.",CONCOLOR_YELLOW);
HideDoCommand(GetCharInfo()->pSpawn, "/attack off",FromPlugin);
if (GetCharInfo()->pSpawn->pActorInfo->PetID) {
HideDoCommand(GetCharInfo()->pSpawn, "/pet back",FromPlugin);
}
DoingInfuriate = true;
psOldTarget = psTarget;
return 0;
}
if (strstr(Line,"is no longer enraged")) {
if (psOldTarget==(PSPAWNINFO)pTarget && DoingENRAGE) {
if (!DoingInfuriate) {
WriteChatColor("MQ2AutoSkills::ENRAGE/infuriate ended, resuming attack.",CONCOLOR_YELLOW);
HideDoCommand(GetCharInfo()->pSpawn, "/attack on",FromPlugin);
if (GetCharInfo()->pSpawn->pActorInfo->PetID) {
HideDoCommand(GetCharInfo()->pSpawn, "/pet kill",FromPlugin);
}
} else {
WriteChatColor("MQ2AutoSkills::\arENRAGE\ax ended, but mob still seems infuriated.",CONCOLOR_YELLOW);
}
DoingENRAGE = false;
}
return 0;
}
if (strstr(Line,"no longer infuriated")) {
if (psOldTarget==(PSPAWNINFO)pTarget && DoingInfuriate) {
if (!DoingENRAGE) {
WriteChatColor("MQ2AutoSkills::ENRAGE/infuriate ended, resuming attack.",CONCOLOR_YELLOW);
HideDoCommand(GetCharInfo()->pSpawn, "/attack on",FromPlugin);
if (GetCharInfo()->pSpawn->pActorInfo->PetID) {
HideDoCommand(GetCharInfo()->pSpawn, "/pet kill",FromPlugin);
}
} else {
WriteChatColor("MQ2AutoSkills::\arInfuriate\ax ended, but mob still seems ENRAGED.",CONCOLOR_YELLOW);
}
DoingInfuriate = false;
}
return 0;
}
}
return 0;
}
Please Red Cent me if you find this useful

