HardOne
Member
- Joined
- Jan 15, 2006
- RedCents
- 61¢
Rich (BB code):
//==================================================================================//
// MQ2Melee Plugin v0.703 [under developpment]
// based on Cr4zyb4rd MQ2AutoSkills
// by s0rCieR (05/10/06)
//
// Modified by Ebs2002: Added support for Slam. Needs some testing
//----------------------------------------------------------------------------------//
// The goal of this plugin is to use common combat abilities
// at logical times determined by the user
//
// Before an ability fires, a few requirements must be met. The combat ability
// needs to be mapped to a doability button (Ctrl A), you must have at least have 1 point
// in that skill, and any other requirements the ability relies on must be met, ie: bash, you can't bash at
// a target without wearing a shield or disarm a mob if he
// is not holding something...
//
// Right now the engage / validating target part is a litle awkward, i might removes
// some sanity checks to make it smoother if people ask for it. It will engage
// a target if that target is: a NPC, Standing, in Line of Sight, in decent range for
// archery or melee, and in a Line of Sight (ie, it will not engage a target
// that is behind ya) and finally you must have melee or range attack on to confirm
// your intention! (it's designed to be used with some kind of assist macro, as soon
// as you acquire a target, its below percentage you want etc, you will need to turn
// attack on to trigger the engage).
//
// Attack will be turned off if current target does not meet the engage requirements. Any
// newly acquired target will be saved and monitored for enrage/infuriate even if you
// switch targets (ie to a NPC or PET to heal or buff). As soon as you switch back to
// the saved target, it will auto-resume.
//
// You can toggle between melee/range mode as needed
//
// The plugin monitors engaged target for enrage/infuriate conditions and will react to them.
// It will also watch for a failed feign death message and automatically issue /stand.
//
// If you are a pet class, have a pet up, and use the pet
// assist setting, it will auto-send pet to attack on engage and back him off
// on enrage/infuriate. If you have /pet hold or /pet focus those commands will be
// used on attack / backoff.
//
// There is a parameter called "aggro" that could be toggled on/off and will react to
// skills and how the plugin operates. When in aggro mode: taunt & provoke will
// will be used if they are "on", you will never backoff a fight because of
// low health. When aggro is off, taunt/provoke will never
// be used, but now you will backoff if the ini includes this setting.
//
// Currently supported abilities:
// BackStab, Bash, Begging, Disarm, Dragon Punch, Eagle Strike, Feign Death, Flying
// Kick, Forage, Frenzy, Hide, Intimidation, Kick, Mend, Pick Pockets, Round Kick,
// Sense Traps, Sneak, Taunt and Tiger Claw.
//
// Currently supported alt abilities:
// FeralSwipe, Pet Discipline, and Advanced Pet Discipline.
//
// Currently supported combat abilities:
// Throw Stone, Bazu Bellow, Ancient Chaos Cry, Bellow of the Mastruq, Incite,
// Berate, Below, Provoke, Destroyer's Volley, Rage Volley, Dragon Fang and Leopard
// Claw.
//
//----------------------------------------------------------------------------------//
// COMMAND: /melee
// /melee on aggro=on taunt=on kick=1 bash=0 intimidation=false disarm=true
//
// In other words, you may use on/off, 1/0, or true/false
//
// /melee will only list and report abilities and setting that are available to you.
//
// Note: /melee just changes the values in the INI. If you begin with /melee
// aggro=on kick=on, but want to stop taunting, you must use /melee aggro=off, not
// /melee kick=on (in other words, your settings are NOT reset with each use of /melee
//----------------------------------------------------------------------------------//
// on/off : Turn On/Off features.
// aggro : [On/Off] Means that you want to keep aggro on target, it will use
// aggro abilities/disciplines(enabled) and will keep on going until
// either you or the target dies.
// melee : [0+] This is the maximum melee distance for abilities that require
// a target to be used. (0=off)
// range : [0+] This is the minimum distance to be considered in archery/throwing
// range (0=off). You must have bow/arrow or throwing item equipped
// for /ranged to activate.
//----------------------------------------------------------------------------------//
// enrage : [On/Off] Watch for enrage messages and turn off/on
// attack if needed. Attack will be turned back on if you are standing behind
// the target during enrage.
// infuriate : [On/Off] Watch for infuriate messages and turns off/on attack.
// petassist : [On/Off] Will send pet attack on engage and backoff on enrage/infuriate
// if those skills are on. The plugin will also use /pet focus or /pet hold
// if you have those AAs.
//----------------------------------------------------------------------------------//
// mend : [0-100] Mend your wound if your life percentage goes below the designated value.
// backoff : [0-100] Turns attack off if your life percentage goes below the designated value.
// (0=off) If you are in aggro mode, you will never back off due to low health.
// evade : [0-100] Turn off Attack and Hide if your life percentage goes below
// the designated value. Will never happen if you are in aggro mode. (Needs more testing)
// feigndeath : [0-100] Feigns death if your life percentage goes below this value. Will
// never happen if you are in aggro mode. (Needs more testing)
// resume : [0-100] Stand Up and turn back attack on if your life percentage
// goes above this value. Used with /melee feigndeath
//----------------------------------------------------------------------------------//
// backstab : [0-180] Will try to backstab if you wielding a piercing weapon in main
// hand and you are within X degrees +/- of the targets back (ie 45 is a good
// angle for just backstabbing, 180 will backstab from all directions.
// bash : [On/Off] Will try to bash target if you have a shield equipped.
// begging : [On/Off] Will turn attack off and beg target if not in aggro mode.
// disarm : [On/Off] Will try to disarm target if target is wielding something.
// dragonpunch : [On/Off] Will use dragon punch if available.
// eaglestrike : [On/Off] Will use eagle strike if available.
// flyingkick : [On/Off] Will use flying kick if available.
// forage : [On/Off] Will try to forage up food/water if not in combat.
// frenzy : [On/Off] Will try to use frenzy if available.
// hide : [On/Off] Will try to hide if you're not in a combat and not moving.
// intimidation : [On/Off] Will use intimidation if available.
// kick : [On/Off] Will use kick as often as possible.
// pickpockets : [On/Off] Turn off attack & try to pickpocket if not in aggro mode.
// roundkick : [On/Off] Will use round kick if available.
// sensetraps : [On/Off] Will try to sense traps if not in combat.
// slam : [On/Off] Will use kick as often as possible.
// sneak : [On/Off] Will try to sneak if not in combat.
// taunt : [On/Off] Will push taunt button if aggro is on and you're not hott.
// tigerclaw : [On/Off] Will try to use tiger claw if available.
//----------------------------------------------------------------------------------//
// feralswipe : [On/Off] Will trigger feral swipe AA as it refreshes.
// provoke : [0-100] Will use best provoke discipline once per target if you are
// in aggro mode and your endurance percentage above this.
// 0=off.
// throwstone : [0-100] Will use throw stone disc when ready and target in range.
// (Will not use in aggro/provoke mode if provoke has not been
// used yet).
// ragevolley : [0-100] Will use best ragevolley discipline available and ready.
// leopardclaw : [0-100] Will use "leopard claw" or "dragon fang" discipline when
// your endurace is above X%. If not operating in aggro mode it
// will wait till target hp get below 70% before firing up
// this.
//==================================================================================//
#include "../MQ2Plugin.h"
PreSetup("MQ2Melee");
// debug 1 1=output action taken, should always be on during beta test
// aabug 0 0=altabilities functions still not broken so dont need to disbale them
// cabug 0 0=combat abilities function still not broken so dont need to disable
#define debug 1
#define aabug 0
#define cabug 0
//================================================================//
int doSKILL =0; // Plugin Support?
int doAGGRO =0; // Aggro? (enable/disable taunt/evades)?
int doMELEE =15; // Melee? Consider Melee if Target dist < this?
int doRANGE =40; // Range? Consider Range if Target dist > this?
int doBACKSTAB =0; // BackStab?
int doBASH =0; // Bash?
int doBEGGING =0; // Begging?
int doDISARM =0; // Disarm?
int doDRAGONPUNCH =0; // Dragon Punch?
int doEAGLESTRIKE =0; // Eagle Strike?
int doFLYINGKICK =0; // Flying Kick?
int doFORAGE =0; // Forage?
int doFRENZY =0; // Fenzy?
int doHIDE =0; // Hide?
int doINTIMIDATION =0; // Intimidation?
int doKICK =0; // Kick?
int doPICKPOCKETS =0; // Pick Pockets?
int doROUNDKICK =0; // Round Kick?
int doSENSETRAPS =0; // Sense Traps?
int doSLAM =0; // Slam?
int doSNEAK =0; // Sneak?
int doTAUNT =0; // Taunt?
int doTIGERCLAW =0; // Tiger Claw?
int doENRAGE =1; // watch for enrage?
int doINFURIATE =1; // watch for infuriate?
int doPETASSIST =1; // pet in assist?
int doMENDS =40; // Mend? if My Life Below This?
int doBKOFF =40; // BackOff? if My Life Below This?
int doEVADE =40; // Evade? if My Life Below This?
int doFEIGN =30; // Feign? if My Life Below This?
int doSTAND =70; // Stand? Resume Meleeing if My Life Above This?
int doFERAL =1; // Feral Swipe AA? if My Endu > This?
int doPROVOKE =25; // Provoke? if Endu above This?
int doTHROWSTONE =50; // ThrowStone if Endu above This?
int doRAGEVOLLEY =25; // RageVolley if Endu above This?
int doLEOPARDCLAW =50; // Leopard Claw if Endu above This?
eSpawnType TarType =NONE; // Target SpawnType
PSPAWNINFO TarKill =0; // Target Kill Struct
float TarBack =0.0f; // Target Behind
float TarDist =0.0f; // Target Distance
long TarLife =100; // Target Life
int CurEndu =0; // MySelf Endurance
int PctEndu =0; // MySelf % Endu
int PctLife =0; // MySelf % Life
DWORD onCLOCK =0; // Clock Timers
DWORD onTIMER =0; // Timed Delays
int onENRAGE =0; // Enrage Event?
int onINFURIATE =0; // Infuriate Event?
int onEVADE =0; // Evading Event?
int onSTEAL =0; // Begging/PickPockets Event?
int onPROVOKE =0; // Incite Flag?
int onHOLD =0; // Pet On Hold?
char Fallen[MAX_STRING]="+|HACKED|+";
//================================================================//
// return pointer to abilities search only for aa that i own!
PALTABILITY AltByName(PCHAR ID) {
for(DWORD nAbility=0; nAbility<AA_CHAR_MAX_REAL; nAbility++) {
if(!GetCharInfo2()->AAList[nAbility].AAIndex) break;
if(PALTABILITY pAbility=pAltAdvManager->GetAltAbility(GetCharInfo2()->AAList[nAbility].AAIndex))
if(PCHAR pName=pCDBStr->GetString(pAbility->nName,1,NULL))
if(!stricmp(ID,pName)) return pAbility;
}
return NULL;
}
// return true if we own that aa.
int AltAvail(PCHAR ID) {
if(aabug || !ID[0]) return 0;
PALTABILITY pAbility=AltByName(ID);
return (pAbility)?1:0;
}
// return timer left or -1 if not found/available.
int AltTimer(PCHAR ID) {
int Result=-1;
if(!cabug && ID[0]) if(PALTABILITY pAbility=AltByName(ID))
if(pAltAdvManager->GetCalculatedTimer(pPCData,pAbility)>0) {
pAltAdvManager->IsAbilityReady(pPCData,pAbility,&Result);
if(Result<0) Result=0;
}
return (Result);
}
// trigger that aa.
void AltPress(PCHAR ID) {
if(aabug && !ID[0]) return;
char Buffer[MAX_STRING];
if(PALTABILITY pAbility=AltByName(ID)) {
if(debug) WriteChatf("MQ2Melee:: <\ay%s\ax>.",ID);
sprintf(Buffer,"/alt act %d",pAbility->ID);
HideDoCommand(GetCharInfo()->pSpawn,Buffer,FromPlugin);
}
}
//================================================================//
// return pointer to spells corresponding to that abilities.
PSPELL CABByName(PCHAR ID) {
for(DWORD nCombat=0; nCombat<NUM_COMBAT_ABILITIES; nCombat++)
if(PSPELL pSpell=GetSpellByID(GetCharInfo2()->CombatAbilities[nCombat]))
if(!stricmp(ID,pSpell->Name)) return pSpell;
return NULL;
}
// return true if combat abilities available.
int CABAvail(PCHAR ID) {
if(!cabug && ID[0]) if(PSPELL pSpell=CABByName(ID)) return 1;
return 0;
}
// return 0 if ready, -1 if not found, 1+ timeleft
int CABTimer(PCHAR ID) {
long Result=-1;
if(!cabug && ID[0])
if(PSPELL pSpell=CABByName(ID))
if(pSpell->CARecastTimerID) {
Result=(GetCharInfo2()->CombatAbilityTimes[pSpell->CARecastTimerID]-(DWORD)time(NULL));
if(Result<0) Result=0;
}
return Result;
}
// fire that discipline.
void CABPress(PSPELL DiscName) {
if(cabug || !DiscName) return;
pCharData->DoCombatAbility(DiscName->ID);
if(debug) WriteChatf("MQ2Melee:: <\ay%s\ax>.",DiscName->Name);
}
//================================================================//
// return true if windowname is open.
BOOL WindowOpen(PCHAR WindowName) {
PCSIDLWND pWnd=(PCSIDLWND)FindMQ2Window(WindowName);
return (!pWnd)?false:(BOOL)pWnd->Show;
}
// return true if i get a window that interfere with actions.
bool Windows() {
if(!WindowOpen("SpellBookWnd")) // not medding spells
if(!WindowOpen("LootWnd")) // not looting stuffs
if(!WindowOpen("TradeWnd")) // not trading stuffs
if(!WindowOpen("MerchantWnd")) // not selling stuffs
if(!WindowOpen("BigBankWnd")) // not banking stuffs
if(!WindowOpen("BankWnd")) // not banking stuffs
return true; // all good so return true
return false; // else return false
}
// return true if im stunned or dead.
bool Stunned() {
return (GetCharInfo()->Stunned || GetCharInfo()->standstate==STANDSTATE_DEAD);
}
// return the spawntype (if pet and owner not a pc respond its a npc)
eSpawnType SpawnType (PSPAWNINFO pSpawn) {
eSpawnType eST=(pSpawn)?GetSpawnType(pSpawn):NONE;
return (eST!=PET)?eST:(GetSpawnType((PSPAWNINFO)GetSpawnByID(pSpawn->MasterID))!=PC)?NPC:PET;
}
// return true if skill is trained
bool SkillTrain(PCHAR szSkillName) {
if(szSkillName=="Slam") {
if(GetCharInfo2()->Race==9 || GetCharInfo2()->Race==2 || GetCharInfo2()->Race==10) {
return true;
}
}
for(DWORD idx=0;idx<100;idx++)
if(GetCharInfo2()->Skill[idx] && !stricmp(szSkillName,szSkills[idx]))
return true;
return false;
}
// return true if skill found trained and ready to use.
BOOL SkillReady(PCHAR szSkillName) {
DWORD btn, idx;
for(btn=0;btn<10;btn++) {
idx=EQADDR_DOABILITYLIST[btn];
if(idx<100 && GetCharInfo2()->Skill[idx] && !stricmp(szSkillName,szSkills[idx]))
return(SkillDict[idx]->AltTimer==2)?gbAltTimerReady:EQADDR_DOABILITYAVAILABLE[idx];
}
return false;
}
// press the doability button corresponging to skillname
void SkillPress(PCHAR szSkillName) {
DWORD btn, idx, skl = 0xFFFFFFFF;
for(btn=0;btn<10;btn++)
if((idx=EQADDR_DOABILITYLIST[btn])!=0xFFFFFFFF)
if(!stricmp(szSkillName,szSkills[idx]))
skl=(btn<4)?btn+7:btn-3;
if(skl!=0xFFFFFFFF) {
if(debug) WriteChatf("MQ2Melee:: <\ay%s\ax>.",(szSkillName=="111")?"Slam":szSkillName);
char Buffers[MAX_STRING];
cmdDoAbility(GetCharInfo()->pSpawn,itoa(skl,Buffers,10));
}
}
// return true if skill available on a doability
bool SkillAvail(PCHAR szSkillName) {
if(szSkillName=="Slam") {
if(GetCharInfo2()->Race==9 || GetCharInfo2()->Race==2 || GetCharInfo2()->Race==10) {
return true;
}
}
DWORD btn, idx;
for(btn=0;btn<10;btn++) {
idx=EQADDR_DOABILITYLIST[btn];
if(idx<100 && !stricmp(szSkillName,szSkills[idx]))
return true;
}
return false;
}
// send pet this command if i have one!
void PetCommand(PCHAR Cmd) {
if(!doPETASSIST || !pPetInfoWnd || !GetCharInfo()->pSpawn->pActorInfo->PetID ||
!ClassInfo[GetCharInfo2()->Class & 0xff].PetClass) return;
if(!strnicmp(Cmd,"focus",5) && !AltAvail("Advanced Pet Discipline")) return;
if(!strnicmp(Cmd,"hold",4)) {
onHOLD=true;
if(!AltAvail("Pet Discipline")) return;
} else onHOLD=false;
char Pet[MAX_STRING]; sprintf(Pet,"/pet %s",Cmd);
if(debug) WriteChatf("MQ2Melee:: <\ay%s\ax>.",Pet);
HideDoCommand(GetCharInfo()->pSpawn,Pet,FromPlugin);
}
// return value 1/0 (on/off/toggle or default)
int OnOff(PCHAR Set, int Def, int Cur) {
char Val[MAX_STRING]; GetArg(Val,Set,1);
if(!strlen(Val)) return (Cur)?0:1;
if(!strnicmp(Val,"true" ,4)) return 1;
if(!strnicmp(Val,"on" ,2)) return 1;
if(!strnicmp(Val,"1" ,1)) return 1;
if(!strnicmp(Val,"false",5)) return 0;
if(!strnicmp(Val,"off" ,3)) return 0;
if(!strnicmp(Val,"0" ,1)) return 0;
return Def;
}
// load settings from ini files.
void LoadINI() {
if(debug) WriteChatf("MQ2Melee:: Loading INI.");
sprintf(Fallen,"%s has fallen to the ground.",GetCharInfo()->Name);
doSKILL =GetPrivateProfileInt(GetCharInfo()->Name,"Plugin" ,0,INIFileName);
doAGGRO =GetPrivateProfileInt(GetCharInfo()->Name,"Aggro" ,0,INIFileName);
doMELEE =GetPrivateProfileInt(GetCharInfo()->Name,"Melee" ,0,INIFileName);
doRANGE =GetPrivateProfileInt(GetCharInfo()->Name,"Range" ,0,INIFileName);
doBACKSTAB =GetPrivateProfileInt(GetCharInfo()->Name,"BackStab" ,0,INIFileName);
doBASH =GetPrivateProfileInt(GetCharInfo()->Name,"Bash" ,0,INIFileName);
doBEGGING =GetPrivateProfileInt(GetCharInfo()->Name,"Begging" ,0,INIFileName);
doDISARM =GetPrivateProfileInt(GetCharInfo()->Name,"Disarm" ,0,INIFileName);
doDRAGONPUNCH =GetPrivateProfileInt(GetCharInfo()->Name,"DragonPunch" ,0,INIFileName);
doEAGLESTRIKE =GetPrivateProfileInt(GetCharInfo()->Name,"EagleStrike" ,0,INIFileName);
doFLYINGKICK =GetPrivateProfileInt(GetCharInfo()->Name,"FlyingKick" ,0,INIFileName);
doFORAGE =GetPrivateProfileInt(GetCharInfo()->Name,"Forage" ,0,INIFileName);
doFRENZY =GetPrivateProfileInt(GetCharInfo()->Name,"Frenzy" ,0,INIFileName);
doHIDE =GetPrivateProfileInt(GetCharInfo()->Name,"Hide" ,0,INIFileName);
doINTIMIDATION=GetPrivateProfileInt(GetCharInfo()->Name,"Intimidation",0,INIFileName);
doKICK =GetPrivateProfileInt(GetCharInfo()->Name,"Kick" ,0,INIFileName);
doPICKPOCKETS =GetPrivateProfileInt(GetCharInfo()->Name,"PickPockets" ,0,INIFileName);
doROUNDKICK =GetPrivateProfileInt(GetCharInfo()->Name,"RoundKick" ,0,INIFileName);
doSENSETRAPS =GetPrivateProfileInt(GetCharInfo()->Name,"SenseTraps" ,0,INIFileName);
doSLAM =GetPrivateProfileInt(GetCharInfo()->Name,"Slam" ,0,INIFileName);
doSNEAK =GetPrivateProfileInt(GetCharInfo()->Name,"Sneak" ,0,INIFileName);
doTAUNT =GetPrivateProfileInt(GetCharInfo()->Name,"Taunt" ,0,INIFileName);
doTIGERCLAW =GetPrivateProfileInt(GetCharInfo()->Name,"TigerClaw" ,0,INIFileName);
doFERAL =GetPrivateProfileInt(GetCharInfo()->Name,"FeralSwipe" ,0,INIFileName);
doENRAGE =GetPrivateProfileInt(GetCharInfo()->Name,"Enrage" ,1,INIFileName);
doINFURIATE =GetPrivateProfileInt(GetCharInfo()->Name,"Infuriate" ,1,INIFileName);
doPETASSIST =GetPrivateProfileInt(GetCharInfo()->Name,"PetAssist" ,1,INIFileName);
doMENDS =GetPrivateProfileInt(GetCharInfo()->Name,"Mend" ,0,INIFileName);
doBKOFF =GetPrivateProfileInt(GetCharInfo()->Name,"BackOff" ,0,INIFileName);
doEVADE =GetPrivateProfileInt(GetCharInfo()->Name,"Evade" ,0,INIFileName);
doFEIGN =GetPrivateProfileInt(GetCharInfo()->Name,"FeignDeath" ,0,INIFileName);
doSTAND =GetPrivateProfileInt(GetCharInfo()->Name,"Resume" ,0,INIFileName);
doFERAL =GetPrivateProfileInt(GetCharInfo()->Name,"FeralSwipe" ,0,INIFileName);
doPROVOKE =GetPrivateProfileInt(GetCharInfo()->Name,"Provoke" ,0,INIFileName);
doTHROWSTONE =GetPrivateProfileInt(GetCharInfo()->Name,"ThrowStone" ,0,INIFileName);
doRAGEVOLLEY =GetPrivateProfileInt(GetCharInfo()->Name,"RageVolley" ,0,INIFileName);
doLEOPARDCLAW =GetPrivateProfileInt(GetCharInfo()->Name,"LeopardClaw" ,0,INIFileName);
}
// return true if im ingame and have access to all characters informations.
bool InGames() {
if(MQ2Globals::gGameState==GAMESTATE_INGAME) // currently ingame
if(GetCharInfo()) // get charinfo1 structure
if(GetCharInfo()->pSpawn) // get spawninfo structure
if(GetCharInfo()->pSpawn->pActorInfo) // get actorinfo structure
if(GetCharInfo2()) // get charinfo2 structure
return true; // got all return true
return false; // else return false
}
// return angle dif heading in radiants from source facing destination
float HeadingAngle(PSPAWNINFO s, PSPAWNINFO d) {
double Head=atan2(d->X-s->X,d->Y-s->Y)*256.0/PI;
if(Head<0.0f)Head += 512.0f; else if(Head>= 512.0f) Head -= 512.0f;
return fabs(s->Heading-Head);
}
// return true if i am grouped
BOOL Grouped() {
return GetCharInfo()->GroupLeader[0];
}
// experimental gotaggro test
bool GotAggro() {
PSPAWNINFO MySelf=GetCharInfo()->pSpawn;
PSPAWNINFO CurTar=(ppTarget && pTarget)?(PSPAWNINFO)pTarget:NULL;
if(CurTar && SpawnType(CurTar)==NPC) {
if(MySelf==MySelf->pActorInfo->pTargetOfTarget) return true;
if(HeadingAngle(CurTar,MySelf)<8.0f) return true;
}
return false;
}
// return true if iam casting and not a bard class.
bool Casting() {
return (GetCharInfo()->pSpawn->pActorInfo->CastingSpellID!=-1 && strncmp(pEverQuest->GetClassDesc
(GetCharInfo2()->Class & 0xff),"Bard",5));
}
// return true if i get equipped throwing ammo or archery items.
bool CanRange() {
PCONTENTS aSlot=GetCharInfo2()->Inventory.Ammo;
if(PCONTENTS rSlot=GetCharInfo2()->Inventory.Range) {
if((rSlot->Item->ItemType==7 || rSlot->Item->ItemType==19) &&
(!aSlot || aSlot->Item->ItemNumber==rSlot->Item->ItemNumber)) return true;
if(rSlot->Item->ItemType==5 && aSlot && aSlot->Item->ItemType==27) return true;
}
return false;
}
// return true if i have a poker equipped in primary hand.
bool CanStab() {
PCONTENTS pItem=GetCharInfo2()->Inventory.Primary;
return (!pItem)?false:(pItem->Item->ItemType==2);
}
// return true if you could bash (have a shield in secondary or a 2h weapon in primary with 2 hand
bool CanBash() {
PCONTENTS pItem=GetCharInfo2()->Inventory.Secondary;
if(pItem) return (pItem->Item->ItemType==8);
pItem=GetCharInfo2()->Inventory.Primary;
return (pItem && (pItem->Item->ItemType==1 || pItem->Item->ItemType==4 || pItem->Item->ItemType==35) && AltAvail("2 Hand Bash"));
}
// turn off attack
void AttackOFF(PCHAR DisplayWhy, bool PassToPet) {
if(*EQADDR_ATTACK) HideDoCommand(GetCharInfo()->pSpawn,"/attack off",FromPlugin);
if(PassToPet) {
PetCommand("hold");
PetCommand("back off");
}
if(strlen(DisplayWhy)) WriteChatColor(DisplayWhy,CONCOLOR_YELLOW);
}
// turn on attack
void AttackON(PCHAR DisplayWhy, bool PassToPet) {
if(strlen(DisplayWhy)) WriteChatColor(DisplayWhy,CONCOLOR_YELLOW);
PSPAWNINFO CurrTar=(ppTarget && pTarget)?(PSPAWNINFO)pTarget:NULL;
if(CurrTar!=TarKill) return;
if(!*EQADDR_ATTACK) HideDoCommand(GetCharInfo()->pSpawn,"/attack on",FromPlugin);
if(PassToPet) {
PetCommand("attack");
PetCommand("focus");
}
}
// 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);
}
//================================================================//
int SetSkillOnOff(PCHAR SkillName, PCHAR SkillCheck, PCHAR Setting, int Cur) {
char Buffer[MAX_STRING];
int Result=OnOff(Setting,strlen(SkillCheck)?SkillTrain(SkillCheck):0,Cur);
WriteChatf("MQ2Melee:: %s (%s)%s",SkillName,Result?"\agon\ax":"\aroff\ax",!strlen
(SkillCheck)?".":SkillAvail(SkillCheck)?" \agMAPPED\ax.":" \arNOTMAPPED\ax.");
WritePrivateProfileString(GetCharInfo()->Name,SkillName,itoa(Result,Buffer,10),INIFileName);
return Result;
}
int SetSkillValue(PCHAR SkillName, PCHAR SkillCheck, PCHAR Setting, int Cur) {
char Buffer[MAX_STRING];
int Result=atoi(Setting);
if(Result) sprintf(Buffer,"\ag%d\ax",Result); else sprintf(Buffer,"\aroff\ax");
WriteChatf("MQ2Melee:: %s (%s)%s",SkillName,Buffer,!strlen(SkillCheck)?".":SkillAvail
(SkillCheck)?" \agMAPPED\ax.":" \arNOTMAPPED\ax.");
WritePrivateProfileString(GetCharInfo()->Name,SkillName,itoa(Result,Buffer,10),INIFileName);
return Result;
}
void PutSkillOnOff(PCHAR SkillName, PCHAR SkillCheck, int Cur, PCHAR ShowHelp) {
if(strlen(SkillCheck) && !SkillTrain(SkillCheck)) return;
WriteChatf("MQ2Melee:: %s (%s) <%s>%s",SkillName,Cur?"\agon\ax":"\aroff\ax",ShowHelp,!strlen
(SkillCheck)?".":SkillAvail(SkillCheck)?" \agMAPPED\ax.":" \arNOTMAPPED\ax.");
}
void PutSkillValue(PCHAR SkillName, PCHAR SkillCheck, int Cur, PCHAR ShowHelp) {
if(strlen(SkillCheck) && !SkillTrain(SkillCheck)) return;
char Buffer[MAX_STRING]; sprintf(Buffer,"\ag%d\ax",Cur);
WriteChatf("MQ2Melee:: %s (%s) <%s>%s",SkillName,Cur?Buffer:"\aroff\ax",ShowHelp,!strlen
(SkillCheck)?".":SkillAvail(SkillCheck)?" \agMAPPED\ax.":" \arNOTMAPPED\ax.");
}
void MeleeCmd(PSPAWNINFO pCHAR, PCHAR Cmd) {
char Tmp[MAX_STRING]; BYTE Parm=1;
char Var[MAX_STRING]; bool Help=0;
char Set[MAX_STRING];
char Err[MAX_STRING]; sprintf(Err," \arNOT MAPPED\ax");
char Dot[MAX_STRING]; sprintf(Dot,".");
do {
GetArg(Tmp,Cmd,Parm++);
GetArg(Var,Tmp,1,FALSE,FALSE,FALSE,'=');
GetArg(Set,Tmp,2,FALSE,FALSE,FALSE,'=');
if(!strlen(Tmp)) {
if(Parm==2) Help=1;
} else if(!strnicmp(Tmp,"on",2) || !strnicmp(Tmp,"off",3)) { doSKILL=SetSkillOnOff
("Plugin","",Tmp,doSKILL);
} else if(!strnicmp(Var,"aggro",5)) {
doAGGRO=SetSkillOnOff("Aggro","",Set,doAGGRO);
if(doAGGRO) onPROVOKE=(doPROVOKE && doAGGRO && Grouped())?true:false;
} else if(!strnicmp(Var,"Provoke",7)) {
doPROVOKE=SetSkillValue("Provoke","",Set,doPROVOKE);
if(doPROVOKE) onPROVOKE=(doPROVOKE && doAGGRO && Grouped())?true:false;
} else if(!strnicmp(Var,"Melee",5)) { doMELEE=SetSkillValue("Melee","",Set,doMELEE);
} else if(!strnicmp(Var,"Range",5)) { doRANGE=SetSkillValue("Range","",Set,doRANGE);
} else if(!strnicmp(Var,"BackStab",8)) { doBACKSTAB=SetSkillValue
("BackStab","BackStab",Set,doBACKSTAB);
} else if(!strnicmp(Var,"Bash",4)) { doBASH=SetSkillOnOff("Bash","Bash",Set,doBASH);
} else if(!strnicmp(Var,"Begging",7)) { doBEGGING=SetSkillOnOff
("Begging","Begging",Set,doBEGGING);
} else if(!strnicmp(Var,"Disarm",6)) { doDISARM=SetSkillOnOff("Disarm","Disarm",Set,doDISARM);
} else if(!strnicmp(Var,"DragonPunch",11)) { doDRAGONPUNCH=SetSkillOnOff("DragonPunch","DragonPunch",Set,doDRAGONPUNCH);
} else if(!strnicmp(Var,"EagleStrike",11)) { doEAGLESTRIKE=SetSkillOnOff("EagleStrike","EagleStrike",Set,doEAGLESTRIKE);
} else if(!strnicmp(Var,"FlyingKick",10)) { doFLYINGKICK=SetSkillOnOff("FlyingKick","FlyingKick",Set,doFLYINGKICK);
} else if(!strnicmp(Var,"Forage",6)) { doFORAGE=SetSkillOnOff("Forage","Forage",Set,doFORAGE);
} else if(!strnicmp(Var,"Frenzy",6)) { doFRENZY=SetSkillOnOff("Frenzy","Frenzy",Set,doFRENZY);
} else if(!strnicmp(Var,"Hide",4)) { doHIDE=SetSkillOnOff("Hide","Hide",Set,doHIDE);
} else if(!strnicmp(Var,"Intimidation",12)) { doINTIMIDATION=SetSkillOnOff("Intimidation","Intimidation",Set,doINTIMIDATION);
} else if(!strnicmp(Var,"Kick",4)) { doKICK=SetSkillOnOff("Kick","Kick",Set,doKICK);
} else if(!strnicmp(Var,"Slam",4)) { doSLAM=SetSkillOnOff("Slam","111",Set,doSLAM);
} else if(!strnicmp(Var,"PickPockets",11)) { doPICKPOCKETS=SetSkillOnOff("PickPockets","PickPockets",Set,doPICKPOCKETS);
} else if(!strnicmp(Var,"RoundKick",9)) { doROUNDKICK=SetSkillOnOff("RoundKick","RoundKick",Set,doROUNDKICK);
} else if(!strnicmp(Var,"SenseTraps",10)) { doSENSETRAPS=SetSkillOnOff("SenseTraps","SenseTraps",Set,doSENSETRAPS);
} else if(!strnicmp(Var,"Sneak",5)) { doSNEAK=SetSkillOnOff("Sneak","Sneak",Set,doSNEAK);
} else if(!strnicmp(Var,"Taunt",5)) { doTAUNT=SetSkillOnOff("Taunt","Taunt",Set,doTAUNT);
} else if(!strnicmp(Var,"TigerClaw",9)) { doTIGERCLAW=SetSkillOnOff("TigerClaw","TigerClaw",Set,doTIGERCLAW);
} else if(!strnicmp(Var,"Enrage",6)) { doENRAGE=SetSkillOnOff("Enrage","",Set,doENRAGE);
} else if(!strnicmp(Var,"Infuriate",9)) { doINFURIATE=SetSkillOnOff("Infuriate","",Set,doINFURIATE);
} else if(!strnicmp(Var,"Mend",4)) { doMENDS=SetSkillValue("Mend","Mend",Set,doMENDS);
} else if(!strnicmp(Var,"BackOff",7)) { doBKOFF=SetSkillValue("BackOff","",Set,doBKOFF);
} else if(!strnicmp(Var,"Evade",5)) { doEVADE=SetSkillValue("Evade","Hide",Set,doEVADE);
} else if(!strnicmp(Var,"FeignDeath",10)) { doFEIGN=SetSkillValue("FeignDeath","FeignDeath",Set,doFEIGN);
} else if(!strnicmp(Var,"Resume",6)) { doSTAND=SetSkillValue("Resume","",Set,doSTAND);
} else if(!strnicmp(Var,"PetAssist",9)) { doPETASSIST=SetSkillOnOff("PetAssist","",Set,doPETASSIST);
} else if(!strnicmp(Var,"FeralSwipe",10)) { doFERAL=SetSkillOnOff("FeralSwipe","",Set,doFERAL);
} else if(!strnicmp(Var,"ThrowStone",10)) { doTHROWSTONE=SetSkillValue("ThrowStone","",Set,doTHROWSTONE);
} else if(!strnicmp(Var,"RageVolley",10)) { doRAGEVOLLEY=SetSkillValue("RageVolley","",Set,doRAGEVOLLEY);
} else if(!strnicmp(Var,"LeopardClaw",11)) { doLEOPARDCLAW=SetSkillValue("LeopardClaw","",Set,doLEOPARDCLAW);
} else {
WriteChatf("MQ2Melee:: Unsupported Argument <\ar%s\ax>",Tmp);
Help++;
}
} while(strlen(Tmp));
if(Help) {
WriteChatf("MQ2Melee:: ABILITIES LIST & SETTING");
WriteChatf("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-");
PutSkillOnOff("Plugin","",doSKILL,"Turn On/Off Entire Plugin");
PutSkillValue("Melee","",doMELEE,"Max Range to be in 'MELEE'");
PutSkillValue("Range","",doRANGE,"Min Range to be in 'ARCHERY'");
PutSkillOnOff("Aggro","",doAGGRO,"Aggro=ON BackOff/Evade/Feign=OFF");
WriteChatf("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-");
PutSkillValue("BackStab","BackStab",doBACKSTAB,"+-Angle Back or Off|Need Poker");
PutSkillOnOff("Bash","Bash",doBASH,"On/Off|Need Shield");
PutSkillOnOff("Begging","Begging",doBEGGING,"On/Off");
PutSkillOnOff("Disarm","Disarm",doDISARM,"On/Off");
PutSkillOnOff("DragonPunch","Dragon Punch",doDRAGONPUNCH,"On/Off");
PutSkillOnOff("EagleStrike","Eagle Strike",doEAGLESTRIKE,"On/Off");
PutSkillOnOff("FlyingKick","Flying Kick",doFLYINGKICK,"On/Off");
PutSkillOnOff("Forage","Forage",doFORAGE,"On/Off");
PutSkillOnOff("Frenzy","Frenzy",doFRENZY,"On/Off");
PutSkillOnOff("Hide","Hide",doHIDE,"On/Off");
PutSkillOnOff("Intimidation","Intimidation",doINTIMIDATION,"On/Off");
PutSkillOnOff("Kick","Kick",doKICK,"On/Off");
PutSkillOnOff("Slam","Slam",doSLAM,"On/Off");
PutSkillOnOff("PickPockets","Pick Pockets",doPICKPOCKETS,"On/Off");
PutSkillOnOff("RoundKick","Round Kick",doROUNDKICK,"On/Off");
PutSkillOnOff("SenseTraps","Sense Traps",doSENSETRAPS,"On/Off");
PutSkillOnOff("Sneak","Sneak",doSNEAK,"On/Off");
PutSkillOnOff("Taunt","Taunt",doTAUNT,"On/Off");
PutSkillOnOff("TigarClaw","Tiger Claw",doTIGERCLAW,"On/Off");
WriteChatf("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-");
PutSkillOnOff("Enrage","",doENRAGE,"On/Off");
PutSkillOnOff("Infuriate","",doINFURIATE,"On/Off");
if(ClassInfo[GetCharInfo2()->Class & 0xff].PetClass)
PutSkillOnOff("PetAssist","",doPETASSIST,"Assist on Engage/Enrage");
PutSkillValue("Mend","Mend",doMENDS,"Mend Wound if Life% Below/Off");
PutSkillValue("BackOff","",doBKOFF,"Attack Off if Life% Below/Off");
PutSkillValue("Evade","Hide",doEVADE,"Attack Off && Hide if Life% Below/Off");
PutSkillValue("Feign Death","Feign Death",doFEIGN,"Feign if Life% Below/Off");
PutSkillValue("Resume","",doSTAND,"Stand & Attack if Life% Above/Off");
WriteChatf("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-");
if(AltAvail("Feral Swipe")) PutSkillOnOff("FeralSwipe","",doFERAL,"On/Off");
if(CABAvail("Throw Stone")) PutSkillValue("ThrowStone","",doTHROWSTONE,"Throw Stone if Endu%Above/Off");
if(CABAvail("Bazu Bellow") || CABAvail("Ancient Chaos Cry") || CABAvail("Bellow of the Mastruq")||
CABAvail("Incite") || CABAvail("Berate") || CABAvail("Bellow") || CABAvail("Provoke"))
PutSkillValue("Provoke","",doPROVOKE,"Provoke (once) if Endu% Above/Off");
if(CABAvail("Rage Volley") ||
CABAvail("Destroyer's Volley"))
PutSkillValue("RageVolley","",doRAGEVOLLEY,"Rage Volley if Endu% Above/Off");
if(CABAvail("Leopard Claw") ||
CABAvail("Dragon Fang"))
PutSkillValue("LeopardCalw","",doLEOPARDCLAW,"Leopard Claw Disc if Endu% Above/Off");
}
}
//================================================================//
PLUGIN_API VOID InitializePlugin(VOID) {
AddCommand("/Melee",MeleeCmd);
}
PLUGIN_API VOID ShutdownPlugin(VOID) {
RemoveCommand("/Melee");
}
PLUGIN_API VOID SetGameState(DWORD GameState) {
if(InGames()) LoadINI();
}
PLUGIN_API VOID OnPulse(VOID) {
if(!doSKILL || !InGames() || Stunned() || Casting() || !Windows()) return;
PctLife=GetCurHPS()*100/GetMaxHPS();
if(GetCharInfo()->standstate!=STANDSTATE_FEIGN) {
if(onEVADE && PctLife>=doSTAND) onEVADE=false;
} else if(doAGGRO || (!onEVADE && PctLife>=doSTAND)) HideDoCommand(GetCharInfo()->pSpawn,"/stand",FromPlugin);
if(GetCharInfo()->standstate!=STANDSTATE_STAND) return;
if(doMENDS && PctLife<doMENDS && SkillReady("Mend")) SkillPress("Mend");
// NPC on Target?
PSPAWNINFO CurrTar=(ppTarget && pTarget)?(PSPAWNINFO)pTarget:NULL;
if((TarType=SpawnType(CurrTar))==NPC) {
TarDist=DistanceToSpawn(GetCharInfo()->pSpawn,CurrTar);
// target is a NPC, in Range, Standing, in Line of Sight? in good Angle?
if(TarDist<175.0f && CurrTar->StandState &&
LineOfSight(GetCharInfo()->pSpawn,CurrTar) &&
HeadingAngle(GetCharInfo()->pSpawn,CurrTar)<42.5f ) {
// check we engage a brand new target?
if(!gbRangedAttackReady && CurrTar!=TarKill) {
WriteChatf("MQ2Melee:: <\ay%s\ax>",CurrTar->DisplayedName);
TarKill=CurrTar;
onENRAGE=false;
onINFURIATE=false;
onEVADE=false;
onSTEAL=false;
onPROVOKE=(doPROVOKE && doAGGRO && Grouped())?true:false;
PetCommand("attack");
PetCommand("focus");
}
// Kill this target if we not evading/backoff/feigning?
if(CurrTar==TarKill && !onEVADE) {
// target in archery range
if(doRANGE && TarDist>=doRANGE && gbRangedAttackReady && CanRange())
HideDoCommand(GetCharInfo()->pSpawn,"/ranged",FromPlugin);
// target in melee range
if(doMELEE && TarDist<=doMELEE) {
TarBack=fabs(AngularDistance(CurrTar->Heading,GetCharInfo()->pSpawn->Heading));
// pickpockets/begging required a target and attack off
if(doPICKPOCKETS && SkillReady("Pick Pockets") && !doAGGRO) {
onSTEAL=false;
if(*EQADDR_ATTACK) onSTEAL=true;
else SkillPress("Pick Pockets");
} else if(doBEGGING && SkillReady("Begging") && !doAGGRO) {
onSTEAL=false;
if(*EQADDR_ATTACK) onSTEAL=true;
else SkillPress("Begging");
}
// attack is off should we turn it on?
if(!*EQADDR_ATTACK && !onSTEAL) {
if((!onENRAGE && !onINFURIATE) || (TarBack<60.0f && !onINFURIATE)) AttackON("",false);
}
// those skills need attack on
if(*EQADDR_ATTACK) {
if(doTAUNT && doAGGRO && !GotAggro() && SkillReady("Taunt")) SkillPress("Taunt");
if(doBASH && SkillReady("Bash") && CanBash()) SkillPress("Bash");
if(doBACKSTAB && SkillReady("BackStab") && CanStab() && TarBack<doBACKSTAB) SkillPress
("BackStab");
if(doDISARM && SkillReady("Disarm") && CurrTar->Holding) SkillPress("Disarm");
if(doFRENZY && SkillReady("Frenzy")) SkillPress("Frenzy");
if(doFLYINGKICK && SkillReady("Flying Kick")) SkillPress("Flying Kick");
if(doDRAGONPUNCH && SkillReady("Dragon Punch")) SkillPress("Dragon Punch");
if(doEAGLESTRIKE && SkillReady("Eagle Strike")) SkillPress("Eagle Strike");
if(doTIGERCLAW && SkillReady("Tiger Claw")) SkillPress("Tiger Claw");
if(doROUNDKICK && SkillReady("Round Kick")) SkillPress("Round Kick");
if(doKICK && SkillReady("Kick")) SkillPress("Kick");
if(doSLAM && (SkillReady("Kick") || SkillReady("Bash"))) SkillPress("111");
if(doINTIMIDATION && SkillReady("Intimidation")) SkillPress("Intimidation");
}
}
// time to use some alt/combat abilities?
if((onCLOCK=GetCharInfo()->pSpawn->pActorInfo->TimeStamp)>onTIMER) {
// Beast Feral Swipe
if(!aabug && doFERAL && TarDist<50.0f && !AltTimer("Feral Swipe")) {
AltPress("Feral Swipe");
onTIMER=onCLOCK+3000;
return;
}
// combat abilities
if(!cabug) {
TarLife=((PSPAWNINFO)pTarget)->HPCurrent;
CurEndu=GetCharInfo2()->Endurance;
PctEndu=CurEndu*100/GetMaxEndurance();
PSPELL pSpell=NULL;
// Monk Leopard Claw / Dragon Fang Discipline
if(!pSpell && doLEOPARDCLAW && PctEndu>doLEOPARDCLAW && CurEndu>240 && TarDist<50.0f &&
(doAGGRO || (!doAGGRO && TarLife<70)) && !CABTimer("Leopard Claw")) {
pSpell=CABByName("Dragon Fang");
if(!pSpell) pSpell=CABByName("Leopard Claw");
}
// Warrior Provoke Discipline
if(!pSpell && onPROVOKE && PctEndu>doPROVOKE && CurEndu>=350 && TarDist<100.0f && !
CABTimer("Provoke")) {
pSpell=CABByName("Bazu Bellow");
if(!pSpell) pSpell=CABByName("Ancient Chaos Cry");
if(!pSpell) pSpell=CABByName("Bellow of the Mastruq");
if(!pSpell) pSpell=CABByName("Incite");
if(!pSpell) pSpell=CABByName("Berate");
if(!pSpell) pSpell=CABByName("Bellow");
if(!pSpell) pSpell=CABByName("Provoke");
}
// Berserker Rage Volley / Destroyer's Volley Discipline
if(!pSpell && doRAGEVOLLEY && PctEndu>doRAGEVOLLEY && CurEndu>=95 && TarDist<175.0f &&
!CABTimer("Rage Volley")) {
pSpell=CABByName("Destroyer's Volley");
if(!pSpell) pSpell=CABByName("Rage Volley");
}
// Monk/Warrior/Rogue/Berserker Throw Stone Discipline
if(!pSpell && !onPROVOKE && doTHROWSTONE && PctEndu>doTHROWSTONE && CurEndu>=10 &&
TarDist<50.0f && !CABTimer("Throw Stone"))
pSpell=CABByName("Throw Stone");
// Did we find a Combat Abilities to Use?
if(pSpell) {
CABPress(pSpell);
onTIMER=onCLOCK+3000;
return;
}
}
}
}
}
}
// time to feign/evade or backoff if we bleeding too much and not tanking?
if(!doAGGRO && (doBKOFF || doEVADE || doFEIGN)) {
if(GetCharInfo()->standstate!=STANDSTATE_FEIGN) {
if(doFEIGN && PctLife<doFEIGN && SkillReady("Feign Death")) {
SkillPress("Feign Death");
onEVADE=true;
return;
}
} else if(!GetCharInfo()->pSpawn->HideMode) {
if(doEVADE && PctLife<doEVADE && SkillReady("Hide") && FindSpeed(GetCharInfo()->pSpawn)==0 &&
!gbMoving) {
if(!*EQADDR_ATTACK) SkillPress("Hide");
onEVADE=true;
}
} else if(doBKOFF && PctLife<doBKOFF) {
onEVADE=true;
}
}
// check time to fire non combat skills?
if(!*EQADDR_ATTACK) {
if(SpawnType(TarKill)!=NPC && gbRangedAttackReady && !gbMoving && FindSpeed(GetCharInfo()->pSpawn)==0) {
if(doSENSETRAPS && SkillReady("Sense Traps")) SkillPress("Sense Traps");
if(doHIDE && SkillReady("Hide") && GetCharInfo()->pSpawn->HideMode) SkillPress("Hide");
if(doSNEAK && SkillReady("Sneak") && !GetCharInfo()->pSpawn->Sneak) SkillPress("Sneak");
if(doFORAGE && SkillReady("Forage") && !GetCharInfo()->pSpawn->pActorInfo->Mount) SkillPress("Forage");
if(!onHOLD && doPETASSIST) PetCommand("hold");
}
// should we turn off attack so i could fire some skills?
} else if (onEVADE || onSTEAL || TarType!=NPC || CurrTar!=TarKill || (CurrTar && TarDist>30.0f &&
doRANGE && CanRange())) AttackOFF("",false);
}
PLUGIN_API DWORD OnIncomingChat(PCHAR Line, DWORD Color) {
if(!doSKILL || MQ2Globals::gGameState!=GAMESTATE_INGAME) return 0;
// check has fallen to the ground message
if(Color==USERCOLOR_DEFAULT && !strncmp(Line,Fallen,strlen(Fallen))) {
HideDoCommand(GetCharInfo()->pSpawn,"/stand",FromPlugin);
return 0;
}
// check for enrage/infuriate message
if(Color==USERCOLOR_NPC_ENRAGE && (doENRAGE || doINFURIATE) && TarKill) {
// make sure it's our target!
if(strncmp(Line,TarKill->DisplayedName,strlen(TarKill->DisplayedName)) ||
(strstr(Line,"pet") && !strstr(TarKill->DisplayedName,"pet"))) return 0;
// turn off attack on enrage
if(doENRAGE && strstr(Line,"has become ENRAGED")) {
AttackOFF("MQ2Melee::\arENRAGE\ax detected, turning attack off.",true);
onENRAGE=true;
return 0;
}
// turn off attack on infuriate
if(doINFURIATE && strstr(Line,"is infuriated")) {
AttackOFF("MQ2Melee::\arINFURIATE\ax detected, turning attack off.",true);
onINFURIATE=true;
return 0;
}
// turn back on attack if no longer enrage and not infuriated
if(strstr(Line,"is no longer enraged")) {
if(!onINFURIATE) AttackON("MQ2Melee::ENRAGE/INFURIATE ended resuming attack.",true);
onENRAGE=false;
return 0;
}
// turn back on attack if no longer infuriated and not enrage
if(strstr(Line,"no longer infuriated")) {
if(!onENRAGE) AttackON("MQ2Melee::ENRAGE/INFURIATE ended resuming attack.",true);
onINFURIATE=false;
return 0;
}
}
return 0;
}

