Ok so I am working to bring bard support to MQ2Cast and disable MQ2Twist/Medley usage. I can then trigger the songs needed by using holyshits in mq2melee. Currently I have ${Cast.Ready} fixed for bard so it will determine if you are currently singing a song or not. I DO NOT however have ${Cast.Ready[Requiem of Time]} working same for mezes as well. I can bypass this with a workaround timer variable but would rather get it fixed at the source. Here is my modified MQ2Cast source any help would be appreciated. I suppose this might need to go in the MQ2 forums but thought I'd try my luck here first.
- - - Updated - - -
Ok so I combined Cast.Ready with ${Me.GemTimer[Song Name]} which works great for my Bard INI. Doing some more testing but here is the alpha of what i'm using so far.
Rich (BB code):
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=//
// Projet: MQ2Cast.cpp | Set DEBUGGING to true for DEBUGGING msg
// Author: s0rCieR |
// A_Enchanter_00 |
// htw |
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=//
// Last edited by: devestator 10/30/2010 Updated for HoT & MQ2BagWindow
// Last edited by: Maskoi 4/15/2011 ->item changes
// 10.0 edited by: EqMule 12/14/2013 Removed MQ2BagWindow dependecy - Sponsored by RedGuides.com
// Since a recent patch, I think that there are very few items that require a swap/must equip to be cast.
// Therefore, this version does NOT swap stuff in and out of bags and/or use bandolier anymore.
// If you need that in your macro, use mq2exchange or /itemnotify to move/swap things. (or a version prior to 9.11)
// I also, made this plugin debugable again.
// Please future editors, keep the {} in the if's and while's
// Cause debugging without them is a total pain. (cant set bps if the return is on same line for example)
// 10.02 edited by: three-p-o 1/12/2014 switched over item casting to use EQ's own /cast command.
// Fixed issue in CastHandle with {} not matching up properly. Resolves issue with cast returning before casting is completed.
// Also added in my changes to return CAST_UNKNOWN if you are trying to cast or memorize a spell that is not in your book.
// 10.03 edited by: three-p-o 3/23/2014 Updated for MQ2-20140322
// 10.04 edited by: trev 3/28/2014 Fixed: spells not getting memmed
// Last edited by: noobhaxor 11/17/2015 Bard support work
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=//
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=//
bool DEBUGGING = false;
#ifndef PLUGIN_API
#include "../MQ2Plugin.h"
#include "../Blech/Blech.h"
PreSetup("MQ2Cast");
PLUGIN_VERSION(10.04);
#endif
#define DELAY_CAST 13000
#define DELAY_STOP 4000
#define DELAY_PULSE 125
#define CAST_SUCCESS 0
#define CAST_INTERRUPTED 1
#define CAST_RESIST 2
#define CAST_COLLAPSE 3
#define CAST_RECOVER 4
#define CAST_FIZZLE 5
#define CAST_STANDING 6
#define CAST_STUNNED 7
#define CAST_INVISIBLE 8
#define CAST_NOTREADY 9
#define CAST_OUTOFMANA 10
#define CAST_OUTOFRANGE 11
#define CAST_NOTARGET 12
#define CAST_CANNOTSEE 13
#define CAST_COMPONENTS 14
#define CAST_OUTDOORS 15
#define CAST_TAKEHOLD 16
#define CAST_IMMUNE 17
#define CAST_DISTRACTED 18
#define CAST_ABORTED 19
#define CAST_UNKNOWN 20
#define CAST_MEZIMMUNE 21
#define CAST_SLOWIMMUNE 22
#define CAST_SNAREIMMUNE 23
#define FLAG_COMPLETE 0
#define FLAG_REQUEST -1
#define FLAG_PROGRESS1 -2
#define FLAG_PROGRESS2 -3
#define FLAG_PROGRESS3 -4
#define FLAG_PROGRESS4 -5
#define DONE_COMPLETE -3
#define DONE_ABORTED -2
#define DONE_PROGRESS -1
#define DONE_SUCCESS 0
#define TYPE_SPELL 1
#define TYPE_ALT 2
#define TYPE_ITEM 3
#define RECAST_DEAD 2
#define RECAST_LAND 1
#define RECAST_ZERO 0
#define NOID -1
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=//
long DELAY_MEMO=10000;
bool BardBeta = false; // Removed BardBeta = true; --Noobhaxor Edit
bool Immobile = false; // Immobile?
bool Invisible= false; // Invisibility Check?
bool Twisting = false; // Twisting?
bool Casting = false; // Casting Window was opened?
long Resultat = CAST_SUCCESS; // Resultat
ULONGLONG ImmobileT=0; // Estimate when it be immobilized!
long CastingD=NOID; // Casting Spell Detected
long CastingC=NOID; // Casting Current ID
long CastingE=CAST_SUCCESS; // Casting Current Result
long CastingL=NOID; // Casting LastOne ID
long CastingX=CAST_SUCCESS; // Casting LastOne Result
ULONGLONG CastingT=0; // Casting Timeout
long CastingO=NOID; // Casting OnTarget
ULONGLONG CastingP=0; // Casting Pulse
long TargI=0; // Target ID
long TargC=0; // Target Current
long StopF=FLAG_COMPLETE; // Stop Event Flag Progress?
long StopE=DONE_SUCCESS; // Stop Event Exit Value
ULONGLONG StopM=0; // Stop Event Mark
long MoveA=FLAG_COMPLETE; // Move Event AdvPath?
long MoveS=FLAG_COMPLETE; // Move Event Stick?
long MoveF=FLAG_COMPLETE; // Move Event MQ2AdvPath Following?
long MoveP=FLAG_COMPLETE; // Move Event MQ2AdvPath Pathing?
long MemoF=FLAG_COMPLETE; // Memo Event Flag
long MemoE=DONE_SUCCESS; // Memo Event Exit
ULONGLONG MemoM=0; // Memo Event Mark
long ItemF=FLAG_COMPLETE; // Item Flag
long ItemA[NUM_INV_SLOTS]; // Item Arrays
long DuckF=FLAG_COMPLETE; // Duck Flag
ULONGLONG DuckM=0; // Duck Time Stamp
long CastF=FLAG_COMPLETE; // Cast Flag
long CastE=CAST_SUCCESS; // Cast Exit Return value
long CastG=NOID; // Cast Gem ID
void *CastI=NULL; // Cast ID [spell/alt/item]
long CastK=NOID; // Cast Kind [spell/alt/item]
long CastT=0; // Cast Time [spell/alt/item]
ULONGLONG CastM=0; // Cast TimeMark Start Casting
long CastR=0; // Cast Retry Counter
long CastW=0; // Cast Retry Type
char CastB[MAX_STRING]; // Cast Bandolier In
char CastC[MAX_STRING]; // Cast SpellType
char CastN[MAX_STRING]; // Cast SpellName
PSPELL CastS=NULL; // Cast Spell Pointer
char zOutputDly[MAX_STRING]={0}; //Delayed command for item casting
const unsigned long EX_DELAY = 125; //The amount of time to delay for the item casting
ULONGLONG ulTimer = 0; //Delay timer
unsigned long ulTimerR = 0; //Delay timer 2
bool cPendingEq = false; //Pending equipment cast
bool Parsed=false; // BTree List Found Flags
Blech LIST013('#'); // BTree List for OnChat Message on Color 13
Blech LIST264('#'); // BTree List for OnChat Message on Color 264
Blech LIST289('#'); // BTree List for OnChat Message on Color 289
Blech UNKNOWN('#'); // BTree List for OnChat Message on UNKNOWN Yet Color
Blech SUCCESS('#'); // BTree List for OnChat Message on SUCCESS Detection
PCONTENTS fPACK=0; // ItemFound/ItemSearch - Find Pack Contents
PCONTENTS fITEM=0; // ItemFound/ItemSearch - Find Item Contents
long fSLOT=0; // ItemFound/ItemSearch - Find Item SlotID
long SwapSlot=0; // Item Swapped to slot#
int PulseCount=0;
PSPELL fFIND; // SpellFind - Casting Spell Effect
void *fINFO; // SpellFind - Casting Type Structure
int fTYPE; // SpellFind - Casting Type
int fTIME; // SpellFind - Casting Time
PCHAR fNAME; // SpellFind - Casting Name
SPELLFAVORITE SpellToMemorize; // Favorite Spells Array
long SpellTotal; // Favorite Spells Total
void WinClick(CXWnd *Wnd, PCHAR ScreenID, PCHAR ClickNotification, DWORD KeyState) ;
void ClickBack();
PCHAR ListGems[]={"1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=//
#define aCastEvent(List,Value,Filter) List.AddEvent(Filter,CastEvent,(void*)Value);
void __stdcall CastEvent(unsigned int ID, void *pData, PBLECHVALUE pValues)
{
Parsed=true;
if(CastingE<(long)pData) {
CastingE=(long)pData;
}
if(DEBUGGING) {
WriteChatf("[%I64u] MQ2Cast:[OnChat]: Result=[%d] Called=[%d].",GetTickCount642(),CastingE,(long)pData);
}
}
PALTABILITY AltAbility(PCHAR ID)
{
if(ID[0]) {
int Number=IsNumber(ID);
int Values=atoi(ID);
for(DWORD nAbility=0; nAbility < AA_CHAR_MAX_REAL; nAbility++) {
if(GetCharInfo2()->AAList[nAbility].AAIndex) {
if(PALTABILITY pAbility=pAltAdvManager->GetAAById(GetCharInfo2()->AAList[nAbility].AAIndex)) {
if(Number) {
if(pAbility->ID == Values) {
return pAbility;
}
} else {
if(PCHAR pName=pCDBStr->GetString(pAbility->nName,1,NULL)) {
if(!stricmp(ID,pName)) {
return pAbility;
}
}
}
}
}
}
}
return NULL;
}
bool BardClass()
{
return (strncmp(pEverQuest->GetClassDesc(GetCharInfo()->pSpawn->Class & 0xFF),"Bard",5))?false:true;
}
void Cast(PCHAR zFormat, ...)
{
char zOutput[MAX_STRING]={0}; va_list vaList; va_start(vaList,zFormat);
vsprintf(zOutput,zFormat,vaList);
if(!zOutput[0]) {
return;
}
// WriteChatf("Cast = %s : zOutput %s Line 222 - Cast()",GetCharInfo()->pSpawn,zOutput);
Cast(GetCharInfo()->pSpawn,zOutput);
}
long CastingLeft()
{
long CL=0;
if(pCastingWnd && (PCSIDLWND)pCastingWnd->dShow) {
CL=GetCharInfo()->pSpawn->CastingData.SpellETA - GetCharInfo()->pSpawn->TimeStamp;
if(CL<1) {
CL=1;
}
}
return CL;
}
long Evaluate(PCHAR zFormat, ...)
{
char zOutput[MAX_STRING]={0}; va_list vaList; va_start(vaList,zFormat);
vsprintf(zOutput,zFormat,vaList);
if(!zOutput[0]) {
return 1;
}
ParseMacroData(zOutput);
return atoi(zOutput);
}
void CastTimer(int TargetID,int SpellID,long TickE)
{
typedef VOID (__cdecl *CastTimerCALL) (int,int,long);
PMQPLUGIN pLook=pPlugins;
while(pLook && strnicmp(pLook->szFilename,"MQ2Casttimer",11)) {
pLook=pLook->pNext;
}
if(pLook && pLook->fpVersion>1.1100) {
if(CastTimerCALL Request=(CastTimerCALL)GetProcAddress(pLook->hModule,"TimerCastHandle")) {
Request(TargetID, SpellID, TickE);
}
}
}
void Execute(PCHAR zFormat, ...)
{
char zOutput[MAX_STRING]={0}; va_list vaList; va_start(vaList,zFormat);
vsprintf(zOutput,zFormat,vaList);
if(!zOutput[0]) {
return;
}
DoCommand(GetCharInfo()->pSpawn,zOutput);
}
void ExecuteDly(PCHAR zFormat, ...)
{
//char zOutput[MAX_STRING]={0};
if(cPendingEq) {
MacroError("MQ2Cast: There is already an item pending to cast.");
return;
}
va_list vaList; va_start(vaList,zFormat);
vsprintf(zOutputDly,zFormat,vaList);
if(!zOutputDly[0]) {
return;
}
ulTimer = GetTickCount642() + EX_DELAY;
cPendingEq = true;
//DoCommand(GetCharInfo()->pSpawn,zOutput);
}
bool Flags()
{
//if(!BardClass() && pCastingWnd && (PCSIDLWND)pCastingWnd->dShow) { ----Noobhaxor Edit
if(pCastingWnd && (PCSIDLWND)pCastingWnd->dShow) {
if(DEBUGGING) {
WriteChatf("MQ2Cast: pCastingWnd=TRUE");
}
return true;
}
if(CastF!=FLAG_COMPLETE) { if(DEBUGGING) WriteChatf("MQ2Cast: CastF!=FLAG_COMPLETE"); return true; }
if(DuckF!=FLAG_COMPLETE) { if(DEBUGGING) WriteChatf("MQ2Cast: DuckF!=FLAG_COMPLETE"); return true; }
if(ItemF!=FLAG_COMPLETE) { if(DEBUGGING) WriteChatf("MQ2Cast: ItemF!=FLAG_COMPLETE"); return true; }
if(MemoF!=FLAG_COMPLETE) { if(DEBUGGING) WriteChatf("MQ2Cast: MemoF!=FLAG_COMPLETE"); return true; }
if(StopF!=FLAG_COMPLETE) { if(DEBUGGING) WriteChatf("MQ2Cast: StopF!=FLAG_COMPLETE"); return true; }
if(MoveS!=FLAG_COMPLETE) { if(DEBUGGING) WriteChatf("MQ2Cast: MoveS!=FLAG_COMPLETE"); return true; }
if(MoveF!=FLAG_COMPLETE) { if(DEBUGGING) WriteChatf("MQ2Cast: MoveF!=FLAG_COMPLETE"); return true; }
if(MoveP!=FLAG_COMPLETE) { if(DEBUGGING) WriteChatf("MQ2Cast: MoveP!=FLAG_COMPLETE"); return true; }
if(MoveA!=FLAG_COMPLETE) { if(DEBUGGING) WriteChatf("MQ2Cast: MoveA!=FLAG_COMPLETE"); return true; }
return false;
}
long GEMID(DWORD ID)
{
for(int GEM=0; GEM < NUM_SPELL_GEMS; GEM++) {
if(GetCharInfo2()->MemorizedSpells[GEM] == ID) {
return GEM;
}
}
return NOID;
}
bool GEMReady(DWORD ID)
{
if(pCastSpellWnd && ID < NUM_SPELL_GEMS) {
if((long)((PEQCASTSPELLWINDOW)pCastSpellWnd)->SpellSlots[ID]->spellicon!=NOID) {
if((long)((PEQCASTSPELLWINDOW)pCastSpellWnd)->SpellSlots[ID]->spellstate!=1) {
return true;
}
}
}
return false;
}
bool GiftOfMana()
{
for (unsigned long nBuff=0 ; nBuff < 35 ; nBuff++) {
if (PSPELL pSpell=GetSpellByID(GetCharInfo2()->ShortBuff[nBuff].SpellID)) {
if (!stricmp("Gift of Mana",pSpell->Name)) {
return true;
}
}
}
return false;
}
void MemoLoad(long Gem, PSPELL Spell)
{
if(!Spell || Spell->ClassLevel[GetCharInfo()->pSpawn->Class]>GetCharInfo()->pSpawn->Level) {
return;
}
for(int sp=0;sp<NUM_SPELL_GEMS;sp++) {
if(SpellToMemorize.SpellId[sp]==Spell->ID) {
SpellToMemorize.SpellId[sp]=0xFFFFFFFF;
}
}
SpellToMemorize.SpellId[((DWORD)Gem<NUM_SPELL_GEMS)?Gem:4]=Spell->ID;
}
float Speed()
{
float MySpeed=0.0f;
if(PSPAWNINFO Self=GetCharInfo()->pSpawn) {
MySpeed=Self->SpeedRun;
if(PSPAWNINFO Mount=FindMount(Self)) {
MySpeed=Mount->SpeedRun;
}
}
return MySpeed;
}
void Success(PSPELL Cast)
{
SUCCESS.Reset();
// WriteChatf("Success(Cast) = %d",Cast);
if(Cast) {
char Temps[MAX_STRING];
bool Added=false;
if(Cast->CastOnYou[0]) {
sprintf(Temps,"%s#*#",Cast->CastOnYou);
aCastEvent(SUCCESS,CAST_SUCCESS,Temps);
Added=true;
}
if(Cast->CastOnAnother[0]) {
sprintf(Temps,"#*#%s#*#",Cast->CastOnAnother);
aCastEvent(SUCCESS,CAST_SUCCESS,Temps);
Added=true;
}
//removed 3 commented lines below here -- Noobhaxor Edit
if(BardClass() && GetCharInfo()->pSpawn->CastingData.SpellID) {
Added=true;
}
if(!Added) {
aCastEvent(SUCCESS,CAST_SUCCESS,"You begin casting#*#");
}
}
}
bool Moving()
{
ULONGLONG MyTimer=GetTickCount642();
if(Speed()!=0.0f) {
ImmobileT=MyTimer+500;
}
return (!MQ2Globals::gbMoving && (!ImmobileT || MyTimer>ImmobileT));
}
BOOL Open(PCHAR WindowName)
{
PCSIDLWND pWnd=(PCSIDLWND)FindMQ2Window(WindowName);
return (!pWnd)?false:(BOOL)pWnd->dShow;
}
BOOL Paused()
{
if(BardClass()) {
return false;
}
if(pLootWnd && (PCSIDLWND)pLootWnd->dShow) {
return true;
}
if(pBankWnd && (PCSIDLWND)pBankWnd->dShow) {
return true;
}
if(pMerchantWnd && (PCSIDLWND)pMerchantWnd->dShow) {
return true;
}
if(pTradeWnd && (PCSIDLWND)pTradeWnd->dShow) {
return true;
}
if(pGiveWnd && (PCSIDLWND)pGiveWnd->dShow) {
return true;
}
if(Open("TributeMasterWnd")) {
return true;
}
if(Open("GuildTributeMasterWnd")) {
return true;
}
if(Open("GuildBankWnd")) {
return true;
}
return false;
}
void Reset() {
TargI=0; // Target ID
TargC=0; // Target Check ID
StopF=FLAG_COMPLETE; // Stop Event Flag Progress?
StopE=DONE_SUCCESS; // Stop Event Exit Value
MoveA=FLAG_COMPLETE; // Stop Event AdvPath?
MoveS=FLAG_COMPLETE; // Stop Event Stick?
MoveF=FLAG_COMPLETE; // Stop Event MQ2AdvPath Following?
MoveP=FLAG_COMPLETE; // Stop Event MQ2AdvPath Pathing?
MemoF=FLAG_COMPLETE; // Memo Event Flag
MemoE=DONE_SUCCESS; // Memo Event Exit
ItemF=FLAG_COMPLETE; // Item Flag
DuckF=FLAG_COMPLETE; // Duck Flag
CastF=FLAG_COMPLETE; // Cast Flag
CastE=CAST_SUCCESS; // Cast Exit Return value
CastG=NOID; // Cast Gem ID
CastI=NULL; // Cast ID [spell/alt/item/disc]
CastK=NOID; // Cast Kind [spell/alt/item/disc] [-1=unknown]
CastT=0; // Cast Time [spell/alt/item/disc]
CastB[0]=0; // Cast Bandolier In
CastB[0]=0; // Cast Bandolier Out
CastC[0]=0; // Cast SpellType
CastN[0]=0; // Cast SpellName
CastR=1; // Cast Retry Counter
CastW=0; // Cast Retry Type
Invisible=false; // Invisibility Check?
ZeroMemory(&SpellToMemorize,sizeof(SPELLFAVORITE));
strcpy(SpellToMemorize.Name,"Mem a Spell");
SpellToMemorize.inuse=1;
for(int sp=0;sp<NUM_SPELL_GEMS;sp++) {
SpellToMemorize.SpellId[sp]=0xFFFFFFFF;
}
SpellTotal=0;
}
long SlotID(PCHAR ID)
{
long Search=IsNumber(ID);
DWORD Number=atoi(ID);
if(Search) {
return (Number<NUM_INV_SLOTS)?Number:NOID;
}
for(Number=0; szItemSlot[Number]; Number++) {
if(!stricmp(ID,szItemSlot[Number])) {
return Number;
}
}
return NOID;
}
PSPELL SpellBook(PCHAR ID)
{
if(ID[0]) {
if(IsNumber(ID)) {
int Number=atoi(ID);
for(DWORD nSpell=0; nSpell < NUM_BOOK_SLOTS; nSpell++) {
if(GetCharInfo2()->SpellBook[nSpell]==Number) {
return GetSpellByID(Number);
}
}
} else {
for(DWORD nSpell=0; nSpell < NUM_BOOK_SLOTS; nSpell++) {
if(PSPELL pSpell=GetSpellByID(GetCharInfo2()->SpellBook[nSpell])) {
if(!stricmp(ID,pSpell->Name)) {
return pSpell;
}
}
}
}
}
return NULL;
}
//returns true if an item has a clicky effect equal to szItemName
bool ItemSearch(PCHAR szItemName, long B, long E)
{
//can it ever be a number?
//I dont see any calls to it where it is...
PCONTENTS pItem = 0;
if(IsNumber(szItemName)) {
pItem = FindItemByID(atoi(szItemName));
//return ItemFound(atoi(szItemName),B,E);
} else {
pItem = FindItemByName(szItemName,1);
}
if(pItem) {
fSLOT=pItem->ItemSlot;
fITEM=pItem;
fPACK=NULL;
if(PCONTENTS pPack = FindItemBySlot(pItem->ItemSlot)) {
if(GetItemFromContents(pPack)->Type==ITEMTYPE_PACK) {
fPACK=pPack;
}
}
return true;
}
fSLOT=0;
fITEM=0;
fPACK=0;
return false;
}
bool SpellFind(PCHAR szSpellorAltorItemName, PCHAR szTYPE) {
DWORD n=0;
if(szSpellorAltorItemName[0]) {
// is it an alt ability?
if(!szTYPE[0] || !strnicmp(szTYPE,"alt",3)) {
if(PALTABILITY Search=AltAbility(szSpellorAltorItemName)) {
if(PSPELL spell=GetSpellByID(Search->SpellID)) {
fFIND=spell;
fINFO=Search;
fTIME=fFIND->CastTime;
fNAME=(PCHAR)fFIND->Name;
fTYPE=TYPE_ALT;
return true;
}
}
}
// nope was'nt an altability, so is it a spell?
if(!szTYPE[0] || !strnicmp(szTYPE,"gem",3) || IsNumber(szTYPE)) {
if(PSPELL Search=SpellBook(szSpellorAltorItemName)) {
fFIND=Search;
fINFO=Search;
fTIME=pCharData1->GetAACastingTimeModifier((EQ_Spell*)fFIND)+
pCharData1->GetFocusCastingTimeModifier((EQ_Spell*)fFIND,(EQ_Equipment**)&n,0)+
fFIND->CastTime;
fNAME=(PCHAR)fFIND->Name;
fTYPE=TYPE_SPELL;
return true;
}
}
// ok... ehm, not a spell, is it a clicky then?
if(ItemSearch(szSpellorAltorItemName,0,NUM_INV_SLOTS)) {
//if(GetItemFromContents(fITEM)->Clicky.SpellID) {
if(GetSpellByID(GetItemFromContents(fITEM)->Clicky.SpellID)) {
fFIND=GetSpellByID(GetItemFromContents(fITEM)->Clicky.SpellID);
fINFO=fITEM;
fTIME=GetItemFromContents(fITEM)->Clicky.CastTime;
fNAME=(PCHAR)GetItemFromContents(fITEM)->Name;
fTYPE=TYPE_ITEM;
return true;
}
}
}
fFIND=NULL;
fINFO=NULL;
fTYPE=0;
return false;
}
long SpellTimer(long Type, void *Data)
{
int Ready = 0;
switch(Type) {
case TYPE_SPELL:
{
if(GEMReady(GEMID(((PSPELL)Data)->ID))) {
return 0;
}
if(BardClass()) {
return 2;
}
if(GetCharInfo()->pSpawn->Level<4) {
return (long)((PSPELL)Data)->FizzleTime*2;
}
return (long)((PSPELL)Data)->FizzleTime;
}
case TYPE_ALT:
{
if(pAltAdvManager->GetCalculatedTimer(pPCData,(PALTABILITY)Data)>0) {
pAltAdvManager->IsAbilityReady(pPCData,(PALTABILITY)Data,&Ready);
return (Ready<1)?0:Ready*1000;
}
return 999999;
}
case TYPE_ITEM:
{
return GetItemTimer((PCONTENTS)Data)*1000;
}
}
return 999999;
}
bool SpellReady(PCHAR szSpellName)
{
if(szSpellName[0]==0) {
return true;
}
if(IsNumber(szSpellName)) {
long number=atoi(szSpellName)-1;
if((DWORD)number<NUM_SPELL_GEMS) {
return GEMReady(number);
}
}
if(szSpellName[0]=='M' && strlen(szSpellName)==1) {
return !(Twisting=Evaluate("${If[${Twist.Twisting},1,0]}")?true:false);
}
char zName[MAX_STRING];
GetArg(zName,szSpellName,1,FALSE,FALSE,FALSE,'|');
char zType[MAX_STRING];
GetArg(zType,szSpellName,2,FALSE,FALSE,FALSE,'|');
if(SpellFind(zName,zType)) {
if(!SpellTimer(fTYPE,fINFO)) {
return true;
}
}
return false;
}
void Stick(PCHAR zFormat, ...)
{
typedef VOID (__cdecl *StickCALL) (PSPAWNINFO,PCHAR);
char zOutput[MAX_STRING]; va_list vaList; va_start(vaList,zFormat);
vsprintf(zOutput,zFormat,vaList);
PMQPLUGIN pLook=pPlugins;
while(pLook && strnicmp(pLook->szFilename,"MQ2MoveUtils",12)) {
pLook=pLook->pNext;
}
if(pLook && pLook->fpVersion>0.9999 && pLook->RemoveSpawn) {
if(StickCALL Request=(StickCALL)GetProcAddress(pLook->hModule,"StickCommand")) {
Request(GetCharInfo()->pSpawn,zOutput);
}
}
}
void FollowPath(PCHAR zFormat, ...)
{
typedef VOID (__cdecl *FollowCALL) (PSPAWNINFO,PCHAR);
char zOutput[MAX_STRING]; va_list vaList; va_start(vaList,zFormat);
vsprintf(zOutput,zFormat,vaList);
PMQPLUGIN pLook=pPlugins;
while(pLook && strnicmp(pLook->szFilename,"MQ2AdvPath",10)) {
pLook=pLook->pNext;
}
if(pLook && pLook->fpVersion>0.999 && pLook->RemoveSpawn) {
if(FollowCALL Request=(FollowCALL)GetProcAddress(pLook->hModule,"MQFollowCommand")) {
Request(GetCharInfo()->pSpawn,zOutput);
}
}
}
void Path(PCHAR zFormat, ...)
{
typedef VOID (__cdecl *FollowCALL) (PSPAWNINFO,PCHAR);
char zOutput[MAX_STRING]; va_list vaList; va_start(vaList,zFormat);
vsprintf(zOutput,zFormat,vaList);
PMQPLUGIN pLook=pPlugins;
while(pLook && strnicmp(pLook->szFilename,"MQ2AdvPath",10)) {
pLook=pLook->pNext;
}
if(pLook && pLook->fpVersion>0.999 && pLook->RemoveSpawn) {
if(FollowCALL Request=(FollowCALL)GetProcAddress(pLook->hModule,"MQPlayCommand")) {
Request(GetCharInfo()->pSpawn,zOutput);
}
}
}
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=//
class MQ2CastType *pCastType=0;
class MQ2CastType : public MQ2Type
{
private:
char Temps[MAX_STRING];
public:
enum CastMembers {
Active=1,
Effect=2,
Stored=3,
Result=4,
Return=5,
Status=6,
Timing=7,
Taken=8,
Ready=9,
};
MQ2CastType():MQ2Type("Cast") {
TypeMember(Active);
TypeMember(Effect);
TypeMember(Stored);
TypeMember(Result);
TypeMember(Return);
TypeMember(Status);
TypeMember(Timing);
TypeMember(Taken);
TypeMember(Ready);
}
bool GetMember(MQ2VARPTR VarPtr, PCHAR Member, PCHAR Index, MQ2TYPEVAR &Dest) {
PMQ2TYPEMEMBER pMember=MQ2CastType::FindMember(Member);
if(pMember) {
switch((CastMembers)pMember->ID)
{
case Active:
Dest.DWord=(gbInZone);
Dest.Type=pBoolType;
return true;
case Effect:
Dest.DWord=GetCharInfo()->pSpawn->CastingData.SpellID;
if((long)Dest.DWord==NOID && CastF!=FLAG_COMPLETE) {
Dest.DWord=CastS->ID;
}
if((long)Dest.DWord!=NOID) {
Dest.Ptr=GetSpellByID(Dest.DWord);
Dest.Type=pSpellType;
}
return true;
case Stored:
if(CastingL!=NOID) {
Dest.Ptr=GetSpellByID(CastingL);
Dest.Type=pSpellType;
}
return true;
case Timing:
Dest.DWord=(DWORD)CastingLeft();
Dest.Type=pIntType;
return true;
case Status:
Temps[0] = '\0';
if(CastingC!=NOID || CastF!=FLAG_COMPLETE || (pCastingWnd && (PCSIDLWND)pCastingWnd->dShow)) {
strcat(Temps,"C");
}
if(StopF!=FLAG_COMPLETE) strcat(Temps,"S");
if(MoveA!=FLAG_COMPLETE) strcat(Temps,"A");
if(MoveS!=FLAG_COMPLETE) strcat(Temps,"F");
if(MoveF!=FLAG_COMPLETE) strcat(Temps,"P");
if(MoveP!=FLAG_COMPLETE) strcat(Temps,"P");
if(MemoF!=FLAG_COMPLETE) strcat(Temps,"M");
if(DuckF!=FLAG_COMPLETE) strcat(Temps,"D");
if(ItemF!=FLAG_COMPLETE) strcat(Temps,"E");
if(!Temps[0]) {
strcat(Temps,"I");
}
Dest.Ptr=Temps;
Dest.Type=pStringType;
return true;
case Result:
case Return:
switch((pMember->ID==Result)?CastingX:Resultat)
{
case DONE_PROGRESS:
case CAST_SUCCESS: strcpy(Temps,"CAST_SUCCESS"); break;
case CAST_INTERRUPTED: strcpy(Temps,"CAST_INTERRUPTED"); break;
case CAST_RESIST: strcpy(Temps,"CAST_RESIST"); break;
case CAST_COLLAPSE: strcpy(Temps,"CAST_COLLAPSE"); break;
case CAST_RECOVER: strcpy(Temps,"CAST_RECOVER"); break;
case CAST_FIZZLE: strcpy(Temps,"CAST_FIZZLE"); break;
case CAST_STANDING: strcpy(Temps,"CAST_STANDING"); break;
case CAST_STUNNED: strcpy(Temps,"CAST_STUNNED"); break;
case CAST_INVISIBLE: strcpy(Temps,"CAST_INVISIBLE"); break;
case CAST_NOTREADY: strcpy(Temps,"CAST_NOTREADY"); break;
case CAST_OUTOFMANA: strcpy(Temps,"CAST_OUTOFMANA"); break;
case CAST_OUTOFRANGE: strcpy(Temps,"CAST_OUTOFRANGE"); break;
case CAST_NOTARGET: strcpy(Temps,"CAST_NOTARGET"); break;
case CAST_CANNOTSEE: strcpy(Temps,"CAST_CANNOTSEE"); break;
case CAST_COMPONENTS: strcpy(Temps,"CAST_COMPONENTS"); break;
case CAST_OUTDOORS: strcpy(Temps,"CAST_OUTDOORS"); break;
case CAST_TAKEHOLD: strcpy(Temps,"CAST_TAKEHOLD"); break;
case CAST_IMMUNE: strcpy(Temps,"CAST_IMMUNE"); break;
case CAST_DISTRACTED: strcpy(Temps,"CAST_DISTRACTED"); break;
case CAST_ABORTED: strcpy(Temps,"CAST_CANCELLED"); break;
case CAST_UNKNOWN: strcpy(Temps,"CAST_UNKNOWN"); break;
case CAST_MEZIMMUNE: strcpy(Temps,"CAST_MEZIMMUNE"); break;
case CAST_SNAREIMMUNE: strcpy(Temps,"CAST_SNAREIMMUNE"); break;
case CAST_SLOWIMMUNE: strcpy(Temps,"CAST_SLOWIMMUNE"); break;
default: strcpy(Temps,"CAST_NEEDFIXTYPE"); break;
}
Dest.Ptr=Temps;
Dest.Type=pStringType;
return true;
case Ready:
Dest.DWord=(gbInZone && !Flags() && !Paused() && !Open("SpellBookWnd") && !(GetCharInfo()->Stunned) && SpellReady(Index));
Dest.Type=pBoolType;
return true;
case Taken:
Dest.DWord=(CastingX==CAST_TAKEHOLD);
Dest.Type=pBoolType;
return true;
}
}
strcpy(Temps,"NULL");
Dest.Type=pStringType;
Dest.Ptr=Temps;
return true;
}
bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) {
strcpy(Destination,"TRUE");
return true;
}
bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) {
return false;
}
bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) {
return false;
}
~MQ2CastType() {}
};
BOOL dataCast(PCHAR szName, MQ2TYPEVAR &Dest)
{
Dest.DWord=1;
Dest.Type=pCastType;
return true;
}
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=//
void StopEnding()
{
if(MoveS!=FLAG_COMPLETE) {
if(DEBUGGING) {
WriteChatf("[%I64u] MQ2Cast:[Immobilize]: Stick UnPause Request.",GetTickCount642());
}
Stick("unpause");
MoveS=FLAG_COMPLETE;
}
if(MoveA!=FLAG_COMPLETE) {
if(DEBUGGING) {
WriteChatf("[%I64u] MQ2Cast:[Immobilize]: AdvPath UnPause Request.",GetTickCount642());
}
Execute("/varcalc PauseFlag 0");
MoveA=FLAG_COMPLETE;
}
if(MoveF!=FLAG_COMPLETE) {
if(DEBUGGING) {
WriteChatf("[%I64u] MQ2Cast:[Immobilize]: MQ2AdvPath UnPause Request.",GetTickCount642());
}
FollowPath("unpause");
MoveF=FLAG_COMPLETE;
}
if(MoveP!=FLAG_COMPLETE) {
if(DEBUGGING) {
WriteChatf("[%I64u] MQ2Cast:[Immobilize]: MQ2AdvPath UnPause Request.",GetTickCount642());
}
Path("unpause");
MoveP=FLAG_COMPLETE;
}
}
void StopHandle()
{
if(StopF==FLAG_REQUEST) {
if(DEBUGGING) {
WriteChatf("[%I64u] MQ2Cast:[Immobilize]: Request.",GetTickCount642());
}
StopM=GetTickCount642()+DELAY_STOP;
StopF=FLAG_PROGRESS1;
StopE=DONE_PROGRESS;
}
if(Evaluate("${If[${Stick.Status.Equal[ON]},1,0]}")) {
if(DEBUGGING) {
WriteChatf("[%I64u] MQ2Cast:[Immobilize]: Stick Pause Request.",GetTickCount642());
}
Stick("pause");
MoveS=FLAG_PROGRESS1;
}
if(Evaluate("${If[${Bool[${FollowFlag}]},1,0]}")) {
if(DEBUGGING) {
WriteChatf("[%I64u] MQ2Cast:[Immobilize]: AdvPath Pause Request.",GetTickCount642());
}
Execute("/varcalc PauseFlag 1");
MoveA=FLAG_PROGRESS1;
}
if(Evaluate("${If[${AdvPath.Following} && !${AdvPath.Paused},1,0]}")) {
if(DEBUGGING) {
WriteChatf("[%I64u] MQ2Cast:[Immobilize]: MQ2AdvPath Pause Request.",GetTickCount642());
}
FollowPath("pause");
MoveF=FLAG_PROGRESS1;
}
if(Evaluate("${If[${AdvPath.Playing} && !${AdvPath.Paused},1,0]}")) {
if(DEBUGGING) {
WriteChatf("[%I64u] MQ2Cast:[Immobilize]: MQ2AdvPath Pause Request.",GetTickCount642());
}
Path("pause");
MoveP=FLAG_PROGRESS1;
}
if(Immobile=Moving()) {
if(DEBUGGING) {
WriteChatf("[%I64u] MQ2Cast:[Immobilize]: Complete.",GetTickCount642());
}
StopF=FLAG_COMPLETE;
StopE=DONE_SUCCESS;
}
if(GetTickCount642() > StopM) {
WriteChatf("[%I64u] MQ2Cast:[Immobilize]: Aborting!",GetTickCount642());
StopF=FLAG_COMPLETE;
StopE=DONE_ABORTED;
return;
}
if(StopF==FLAG_PROGRESS1) {
StopF=FLAG_PROGRESS2;
if(Speed()!=0.0f) {
MQ2Globals::ExecuteCmd(FindMappableCommand("back"),1,0);
MQ2Globals::ExecuteCmd(FindMappableCommand("back"),0,0);
}
}
}
void MemoHandle()
{
if(!pSpellBookWnd) {
MemoE=DONE_ABORTED;
} else {
bool Complete=true;
for(int sp=0; sp<NUM_SPELL_GEMS; sp++) {
if(SpellToMemorize.SpellId[sp]!=0xFFFFFFFF && SpellToMemorize.SpellId[sp]!=GetCharInfo2()->MemorizedSpells[sp]) {
Complete=false;
break;
}
}
if(!Complete) {
if(MemoF==FLAG_REQUEST) {
if(DEBUGGING) {
WriteChatf("[%I64u] MQ2Cast:[Memorize]: Immobilize.",GetTickCount642());
}
MemoF=FLAG_PROGRESS1;
MemoE=DONE_PROGRESS;
if(GetCharInfo()->pSpawn->Level<4 && DELAY_MEMO<15000) {
DELAY_MEMO=15000;
}
MemoM=GetTickCount642()+DELAY_STOP+DELAY_MEMO*SpellTotal;
if(StopF==FLAG_COMPLETE) {
StopE=DONE_SUCCESS;
}
if(StopF==FLAG_COMPLETE) {
StopF=FLAG_REQUEST;
}
if(StopF!=FLAG_COMPLETE) {
StopHandle();
}
}
if(MemoF==FLAG_PROGRESS1 && StopE==DONE_SUCCESS) {
if(DEBUGGING) {
WriteChatf("[%I64u] MQ2Cast:[Memorize]: Spell(s).",GetTickCount642());
}
MemoF=FLAG_PROGRESS2;
DWORD Favorite=(DWORD)&SpellToMemorize;
pSpellBookWnd->MemorizeSet((int*)Favorite,NUM_SPELL_GEMS);
}
if(StopE==DONE_ABORTED || GetTickCount642()>MemoM) {
MemoE=DONE_ABORTED;
}
} else {
if(DEBUGGING) {
WriteChatf("[%I64u] MQ2Cast:[Memorize]: Complete.",GetTickCount642());
}
MemoF=FLAG_COMPLETE;
MemoE=DONE_SUCCESS;
}
}
if(MemoE==DONE_ABORTED || !pSpellBookWnd) {
WriteChatf("[%I64u] MQ2Cast:[Memorize]: Aborting!",GetTickCount642());
MemoF=FLAG_COMPLETE;
}
if(MemoF==FLAG_COMPLETE && (pSpellBookWnd && (PCSIDLWND)pSpellBookWnd->dShow)) {
if(DEBUGGING) {
WriteChatf("[%I64u] MQ2Cast:[Memorize]: Closebook.",GetTickCount642());
}
Execute("/book");
}
}
void DuckHandle(int flag)
{
if(DEBUGGING) {
WriteChatf("[%I64u] MQ2Cast:[Duck]: StopCast.",GetTickCount642());
}
Execute("/stopcast");
CastingE=CAST_ABORTED;
DuckF=FLAG_COMPLETE;
}
void CastHandle()
{
// we got the casting request cookies, request immobilize/memorize if needed.
if(CastF==FLAG_REQUEST) {
if(DEBUGGING) {
WriteChatf("[%I64u] MQ2Cast:[Casting]: Request.",GetTickCount642());
}
CastF=FLAG_PROGRESS1;
if(StopF==FLAG_COMPLETE) {
StopF=DONE_SUCCESS;
}
if(StopF==FLAG_COMPLETE && CastT>100 && !BardClass()) {
StopF=FLAG_REQUEST;
}
if(MemoF!=FLAG_COMPLETE) {
MemoHandle();
} else {
if(StopF!=FLAG_COMPLETE) {
StopHandle();
}
}
}
// waiting on the casting results to take actions.
if(CastF==FLAG_PROGRESS3 && CastingE!=DONE_PROGRESS) {
CastF=FLAG_PROGRESS4;
if(CastR) {
CastR--;
}
if(CastR) {
if((CastingE==CAST_SUCCESS && CastW!=RECAST_LAND) || (CastingE==CAST_COLLAPSE) || (CastingE==CAST_FIZZLE) ||
(CastingE==CAST_INTERRUPTED) || (CastingE==CAST_RECOVER) || (CastingE==CAST_RESIST)) {
if(DEBUGGING) {
WriteChatf("[%I64u] MQ2Cast:[Casting]: AutoRecast [%d].",GetTickCount642(),CastingE);
}
if(CastW!=RECAST_ZERO && !TargC) {
TargC=(pTarget)?((PSPAWNINFO)pTarget)->SpawnID:0;
}
CastM=GetTickCount642()+DELAY_CAST;
CastF=FLAG_REQUEST;
}
}
}
// casting is over, grab latest casting results and exit.
if(CastF==FLAG_PROGRESS4) {
if(CastE>CastingE) {
CastingE=CastE;
}
CastF=FLAG_COMPLETE;
}
// evaluate if we are taking too long, or immobilize/memorize event failed.
if(CastF!=FLAG_COMPLETE) {
if(StopE==DONE_ABORTED || MemoE==DONE_ABORTED || GetTickCount642()>CastM) {
WriteChatf("[%I64u] MQ2Cast:[Casting]: Aborting! (%s)",GetTickCount642(), StopE==DONE_ABORTED?"StopE":(MemoE==DONE_ABORTED?"MemoE":"CastM"));
CastF=FLAG_PROGRESS4;
CastE=CAST_NOTREADY;
}
}
// waiting for opportunity to start casting, end if conditions not favorables.
if(CastF==FLAG_PROGRESS1) {
if(pCastingWnd && (PCSIDLWND)pCastingWnd->dShow) {
return; // casting going on
}
CastingC=CastS->ID;
CastF=FLAG_PROGRESS4;
if(TargC && (!pTarget || (pTarget && ((PSPAWNINFO)pTarget)->SpawnID!=TargC))) {
if(CastW==RECAST_DEAD) {
CastE=CAST_NOTARGET;
} else if(CastW==RECAST_LAND) {
CastE=CAST_ABORTED;
}
} else {
if(Invisible && GetCharInfo()->pSpawn->HideMode) {
CastE=CAST_INVISIBLE;
} else if(GetCharInfo()->Stunned) {
CastE=CAST_STUNNED;
} else if(StopF!=FLAG_COMPLETE || MemoF!=FLAG_COMPLETE) {
CastF=FLAG_PROGRESS1;
} else {
long TimeReady=SpellTimer(CastK,CastI); // get estimate time before it's ready.
if(TimeReady>3000) {
CastE=CAST_NOTREADY; // if estimate higher then 3 seconds, abort.
} else if(!TimeReady) {
CastF=FLAG_PROGRESS2; // estimate says it's ready, so cast it
} else {
CastF=FLAG_PROGRESS1; // otherwise give it some time to be ready.
}
}
}
}
// we got the final approbation to cast, so lets do it.
//this is where it breaks
if(CastF==FLAG_PROGRESS2) {
if(DEBUGGING) {
WriteChatf("[%I64u] MQ2Cast:[Casting]: Cast.",GetTickCount642());
}
Success(CastS);
//ItemHandle(true);
CastF=FLAG_PROGRESS3;
CastE=DONE_PROGRESS;
CastingT=GetTickCount642()+CastT+250+(pConnection->Last)*4;
CastingE=DONE_PROGRESS;
CastingC=CastS->ID;
if((long)GetCharInfo()->pSpawn->CastingData.SpellID>0) {
CastingX=(CastingE<CAST_SUCCESS)?CAST_SUCCESS:CastingE;
CastingL=CastingC;
if(CastK==TYPE_SPELL) {
Execute("/multiline ; /stopsong ; /cast \"%s\"",CastN);
} else if(CastK==TYPE_ITEM) {
if(!BardBeta) {
Execute("/multiline ; /stopsong ; /useitem \"%s\"",CastN);
} else {
Execute("/useitem \"%s\"",CastN);
}
} else if(CastK==TYPE_ALT) {
if(!BardBeta) {
Execute("/multiline ; /stopsong ; /alt activate %d",((PALTABILITY)CastI)->ID);
} else {
Execute("/alt activate %d",((PALTABILITY)CastI)->ID);
}
}
} else {
if(CastK==TYPE_SPELL) {
Cast("\"%s\"",CastN);
} else if(CastK==TYPE_ITEM) {
if(DEBUGGING) {
WriteChatf("/useitem \"%s\"",CastN);
}
Execute("/useitem \"%s\"",CastN);
} else if(CastK==TYPE_ALT) {
Execute("/alt activate %d",((PALTABILITY)CastI)->ID);
}
}
}
}
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=//
PLUGIN_API VOID CastDebug(PSPAWNINFO pChar, PCHAR Cmd)
{
char zParm[MAX_STRING];
GetArg(zParm,Cmd,1);
if(zParm[0]==0) {
DEBUGGING=!DEBUGGING;
} else if(!strnicmp(zParm,"on",2)) {
DEBUGGING=true;
} else if(!strnicmp(zParm,"off",2)) {
DEBUGGING=false;
} else {
DEBUGGING=!DEBUGGING;
}
WriteChatf("\arMQ2Cast\ax::\amDEBUGGING is now %s\ax.",DEBUGGING?"\aoON":"\agOFF");
}
PLUGIN_API VOID CastCommand(PSPAWNINFO pChar, PCHAR Cmd)
{
Resultat=CAST_DISTRACTED;
if(!gbInZone || Flags() || Paused() || (pSpellBookWnd && (PCSIDLWND)pSpellBookWnd->dShow)) {
if(DEBUGGING) {
WriteChatf("[%I64u] MQ2Cast:[Casting]: Complete. [%d][%s%s%s%s]",GetTickCount642(),Resultat,
gbInZone?" ZONE ":"",Flags()?" FLAGS ":"",Paused()?" PAUSED ":"",(pSpellBookWnd && (PCSIDLWND)pSpellBookWnd->dShow)?" SHOW ":"");
}
return;
}
Reset();
char zParm[MAX_STRING];
long iParm=0;
do {
GetArg(zParm,Cmd,++iParm);
if(zParm[0]==0) {
break;
} else if(!strnicmp(zParm,"-targetid|",10)) {
TargI=atoi(&zParm[10]);
} else if(!strnicmp(zParm,"-kill",5)) {
CastW=RECAST_DEAD; CastR=9999;
} else if(!strnicmp(zParm,"-maxtries|",10)) {
CastW=RECAST_LAND; CastR=atoi(&zParm[10]);
} else if(!strnicmp(zParm,"-recast|",8)) {
CastW=RECAST_ZERO; CastR=atoi(&zParm[8]);
} else if(!strnicmp(zParm,"-setin|",6)) {
GetArg(CastB,zParm,2,FALSE,FALSE,FALSE,'|');
} else if(!strnicmp(zParm,"-invis",6)) {
Invisible=true;
} else if(zParm[0]!='-' && CastN[0]==0) {
GetArg(CastN,zParm,1,FALSE,FALSE,FALSE,'|');
GetArg(CastC,zParm,2,FALSE,FALSE,FALSE,'|');
} else if(zParm[0]!='-' && CastC[0]==0) {
GetArg(CastC,zParm,1,FALSE,FALSE,FALSE,'|');
}
} while(true);
Resultat=CAST_SUCCESS;
if(GetCharInfo()->Stunned) {
Resultat=CAST_STUNNED;
} else if(Invisible && GetCharInfo()->pSpawn->HideMode) {
Resultat=CAST_INVISIBLE;
} else if(!SpellFind(CastN,CastC)) {
Resultat=CAST_UNKNOWN;
} else if(fTYPE!=TYPE_SPELL && SpellTimer(fTYPE,fINFO)) {
Resultat=CAST_NOTREADY;
} else if(TargI) {
if(PSPAWNINFO Target=(PSPAWNINFO)GetSpawnByID(TargI)) {
*(PSPAWNINFO*)ppTarget=Target;
} else {
Resultat=CAST_NOTARGET;
}
}
if(Resultat==CAST_SUCCESS && fTYPE==TYPE_SPELL) {
if(BardClass()) {
if(Twisting) {
Execute("/stoptwist");
}
if(GetCharInfo()->pSpawn->CastingData.SpellID) {
Execute("/stopsong");
}
}
CastG=GEMID(fFIND->ID);
if(CastG==NOID) {
CastG=atoi(&CastC[(strnicmp(CastC,"gem",3))?0:3])-1;
MemoLoad(CastG,fFIND);
SpellTotal=1;
MemoF=FLAG_REQUEST;
MemoE=DONE_SUCCESS;
}
}
if(Resultat!=CAST_SUCCESS) {
if(DEBUGGING) {
WriteChatf("[%I64u] MQ2Cast:[Casting]: Complete. [%d]",GetTickCount642(),Resultat);
}
return;
}
CastF=FLAG_REQUEST;
CastI=fINFO;
CastK=fTYPE;
CastT=fTIME;
CastS=fFIND;
CastM=GetTickCount642()+DELAY_CAST;
strcpy(CastN,fNAME);
if(DEBUGGING) {
WriteChatf("[%I64u] MQ2Cast:[Casting]: Name<%s> Type<%d>.",GetTickCount642(),CastN,CastK);
}
CastHandle();
}
PLUGIN_API VOID DuckCommand(PSPAWNINFO pChar, PCHAR Cmd)
{
if(gbInZone) {
if(CastF!=FLAG_COMPLETE) {
CastR=0;
}
if((pCastingWnd && (PCSIDLWND)pCastingWnd->dShow) && CastingLeft()>500) {
DuckF=FLAG_REQUEST;
DuckHandle(DuckF);
}
}
Resultat=CAST_SUCCESS;
}
PLUGIN_API VOID MemoCommand(PSPAWNINFO pChar, PCHAR zLine)
{
Resultat=CAST_DISTRACTED;
if(!gbInZone || Flags() || Paused() || !pSpellBookWnd) {
return;
}
if(GetCharInfo()->Stunned) {
Resultat=CAST_STUNNED;
return;
}
Reset();
long iParm=0;
char zParm[MAX_STRING];
char zTemp[MAX_STRING];
CastingX=CAST_SUCCESS;
do {
GetArg(zParm,zLine,++iParm);
if(!zParm[0]) {
break;
}
GetArg(zTemp,zParm,1,FALSE,FALSE,FALSE,'|');
if(PSPELL Search=SpellBook(zTemp)) {
if(DEBUGGING) {
WriteChatf("[%d] MQ2Cast:[Memorize]: Spell Found.",(long)GetTickCount642());
}
GetArg(zTemp,zParm,2,FALSE,FALSE,FALSE,'|');
long Gem=atoi(&zTemp[(strnicmp(zTemp,"gem",3))?0:3])-1;
if(!((DWORD)Gem<NUM_SPELL_GEMS)) {
GetArg(zTemp,zLine,1+iParm);
Gem=atoi(&zTemp[(strnicmp(zTemp,"gem",3))?0:3])-1;
if((DWORD)Gem<NUM_SPELL_GEMS) {
iParm++;
}
}
MemoLoad(Gem,Search);
}
else {
CastingX=CAST_UNKNOWN;
if(DEBUGGING) {
WriteChatf("[%d] MQ2Cast:[Memorize]: Spell Not Found. %d",(long)GetTickCount642(),CastingX);
}
return;
}
} while(true);
for(int sp=0;sp<NUM_SPELL_GEMS;sp++) {
if(SpellToMemorize.SpellId[sp] != 0xFFFFFFFF && SpellToMemorize.SpellId[sp] != GetCharInfo2()->MemorizedSpells[sp]) {
SpellTotal++;
}
}
if(SpellTotal) {
MemoF=FLAG_REQUEST;
MemoE=DONE_SUCCESS;
MemoHandle();
}
}
PLUGIN_API VOID SpellSetDelete(PSPAWNINFO pChar,PCHAR Cmd)
{
Resultat=CAST_ABORTED;
if(!gbInZone) {
return;
} else if(!Cmd[0]) {
MacroError("Usage: /ssd setname");
} else {
Resultat=CAST_SUCCESS;
sprintf(INIFileName,"%s\\%s_%s.ini",gszINIPath,EQADDR_SERVERNAME,GetCharInfo()->Name);
WritePrivateProfileString("MQ2Cast(SpellSet)",Cmd,NULL,INIFileName);
}
}
PLUGIN_API VOID SpellSetList(PSPAWNINFO pChar, PCHAR Cmd)
{
Resultat=CAST_SUCCESS;
if(!gbInZone)
return;
char Keys[MAX_STRING*NUM_SPELL_GEMS]={0};
char Temp[MAX_STRING];
PCHAR pKeys=Keys;
long Disp=0;
Resultat=CAST_SUCCESS;
sprintf(INIFileName,"%s\\%s_%s.ini",gszINIPath,EQADDR_SERVERNAME,GetCharInfo()->Name);
WriteChatf("MQ2Cast:: SpellSet [\ay Listing... \ax].",Disp);
GetPrivateProfileString("MQ2Cast(SpellSet)",NULL,"",Keys,MAX_STRING*10,INIFileName);
while(pKeys[0]) {
GetPrivateProfileString("MQ2Cast(SpellSet)",pKeys,"",Temp,MAX_STRING,INIFileName);
if(Temp[0]) {
if(!Disp)
WriteChatf("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-");
WriteChatf("\ay%s\ax",pKeys);
Disp++;
}
pKeys+=strlen(pKeys)+1;
}
if(Disp)
WriteChatf("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-");
WriteChatf("MQ2Cast:: SpellSet [\ay %d Displayed\ax ].",Disp);
}
PLUGIN_API VOID SpellSetMemorize(PSPAWNINFO pChar, PCHAR Cmd)
{
Resultat=CAST_UNKNOWN;
if(!gbInZone) {
return;
} else if(!Cmd[0]) {
MacroError("Usage: /ssm setname");
} else {
char List[MAX_STRING];
Resultat=CAST_SUCCESS;
sprintf(INIFileName,"%s\\%s_%s.ini",gszINIPath,EQADDR_SERVERNAME,GetCharInfo()->Name);
GetPrivateProfileString("MQ2Cast(SpellSet)",Cmd,"",List,MAX_STRING,INIFileName);
if(List[0])
MemoCommand(GetCharInfo()->pSpawn,List);
}
}
PLUGIN_API VOID SpellSetSave(PSPAWNINFO pChar, PCHAR Cmd)
{
if(!gbInZone) {
return;
}
char zSet[MAX_STRING]; GetArg(zSet,Cmd,1);
char zGem[MAX_STRING]; GetArg(zGem,Cmd,2);
Resultat=CAST_ABORTED;
if(!zSet[0]) {
MacroError("Usage: /sss setname <gemlist>");
return;
}
if(!zGem[0]) {
sprintf(zGem,"123456789ABC");
}
char zLst[MAX_STRING]={0};
char zTmp[MAX_STRING];
long find=0;
for(int g=0;g<NUM_SPELL_GEMS;g++)
if((long)GetCharInfo2()->MemorizedSpells[g]>0) {
if(strstr(zGem,ListGems[g])) {
sprintf(zTmp,"%d|%d",GetCharInfo2()->MemorizedSpells[g],g+1);
if(find) {
strcat(zLst," ");
}
strcat(zLst,zTmp);
find++;
}
}
Resultat=CAST_UNKNOWN;
if(find) {
Resultat=CAST_SUCCESS;
sprintf(INIFileName,"%s\\%s_%s.ini",gszINIPath,EQADDR_SERVERNAME,GetCharInfo()->Name);
WritePrivateProfileString("MQ2Cast(SpellSet)",Cmd,zLst,INIFileName);
}
}
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=//
PLUGIN_API VOID InitializePlugin(VOID)
{
CHAR BetaSwitch[MAX_STRING]={0};
if(GetPrivateProfileString("Settings","Normal","",BetaSwitch,MAX_STRING,INIFileName)) {
BardBeta=false;
}
aCastEvent(LIST289, CAST_COLLAPSE ,"Your gate is too unstable, and collapses#*#");
aCastEvent(LIST289, CAST_CANNOTSEE ,"You cannot see your target#*#");
aCastEvent(LIST289, CAST_COMPONENTS ,"You are missing some required components#*#");
aCastEvent(UNKNOWN, CAST_COMPONENTS ,"Your ability to use this item has been disabled because you do not have at least a gold membership#*#");
aCastEvent(LIST289, CAST_COMPONENTS ,"You need to play a#*#instrument for this song#*#");
aCastEvent(LIST289, CAST_DISTRACTED ,"You are too distracted to cast a spell now#*#");
aCastEvent(LIST289, CAST_DISTRACTED ,"You can't cast spells while invulnerable#*#");
aCastEvent(LIST289, CAST_DISTRACTED ,"You *CANNOT* cast spells, you have been silenced#*#");
aCastEvent(LIST289, CAST_IMMUNE ,"Your target has no mana to affect#*#");
aCastEvent(UNKNOWN, CAST_IMMUNE ,"Your target looks unaffected#*#");
aCastEvent(LIST264, CAST_INTERRUPTED ,"Your spell is interrupted#*#");
aCastEvent(UNKNOWN, CAST_INTERRUPTED ,"Your casting has been interrupted#*#");
aCastEvent(LIST289, CAST_FIZZLE ,"Your spell fizzles#*#");
aCastEvent(LIST289, CAST_FIZZLE ,"You miss a note, bringing your song to a close#*#");
aCastEvent(LIST289, CAST_MEZIMMUNE ,"Your target cannot be mesmerized#*#");
aCastEvent(LIST289, CAST_NOTARGET ,"You must first select a target for this spell#*#");
aCastEvent(LIST289, CAST_NOTARGET ,"This spell only works on#*#");
aCastEvent(LIST289, CAST_NOTARGET ,"You must first target a group member#*#");
aCastEvent(LIST289, CAST_NOTREADY ,"Spell recast time not yet met#*#");
aCastEvent(LIST289, CAST_OUTOFMANA ,"Insufficient Mana to cast this spell#*#");
aCastEvent(LIST289, CAST_OUTOFRANGE ,"Your target is out of range, get closer#*#");
aCastEvent(LIST289, CAST_OUTDOORS ,"This spell does not work here#*#");
aCastEvent(LIST289, CAST_OUTDOORS ,"You can only cast this spell in the outdoors#*#");
aCastEvent(LIST289, CAST_OUTDOORS ,"You can not summon a mount here#*#");
aCastEvent(LIST289, CAST_OUTDOORS ,"You must have both the Horse Models and your current Luclin Character Model enabled to summon a mount#*#");
aCastEvent(LIST264, CAST_RECOVER ,"You haven't recovered yet#*#");
aCastEvent(LIST289, CAST_RECOVER ,"Spell recovery time not yet met#*#");
aCastEvent(LIST289, CAST_RESIST ,"Your target resisted the#*#spell#*#");
aCastEvent(LIST013, CAST_SLOWIMMUNE ,"Your target is immune to changes in its attack speed#*#");
aCastEvent(LIST013, CAST_SNAREIMMUNE ,"Your target is immune to changes in its run speed#*#");
aCastEvent(LIST289, CAST_STANDING ,"You must be standing to cast a spell#*#");
aCastEvent(LIST289, CAST_STUNNED ,"You can't cast speI think lls while stunned#*#");
aCastEvent(LIST289, CAST_SUCCESS ,"You are already on a mount#*#");
aCastEvent(LIST289, CAST_TAKEHOLD ,"Your spell did not take hold#*#");
aCastEvent(LIST289, CAST_TAKEHOLD ,"Your spell would not have taken hold#*#");
aCastEvent(LIST289, CAST_TAKEHOLD ,"Your spell is too powerfull for your intended target#*#");
aCastEvent(LIST289, CAST_TAKEHOLD ,"You need to be in a more open area to summon a mount#*#");
aCastEvent(LIST289, CAST_TAKEHOLD ,"You can only summon a mount on dry land#*#");
aCastEvent(LIST289, CAST_TAKEHOLD ,"This pet may not be made invisible#*#");
pCastType= new MQ2CastType;
AddMQ2Data("Cast",dataCast);
AddCommand("/castdebug",CastDebug);
AddCommand("/casting" ,CastCommand);
AddCommand("/interrupt",DuckCommand);
AddCommand("/memorize" ,MemoCommand);
AddCommand("/ssd",SpellSetDelete);
AddCommand("/ssl",SpellSetList);
AddCommand("/ssm",SpellSetMemorize);
AddCommand("/sss",SpellSetSave);
}
PLUGIN_API void SetGameState(unsigned long ulGameState)
{
if (GetGameState() != GAMESTATE_INGAME)
{
cPendingEq=false;
ulTimer = 0;
ulTimerR = 0;
}
}
PLUGIN_API VOID ShutdownPlugin(VOID)
{
RemoveMQ2Data("Cast");
delete pCastType;
RemoveCommand("/castdebug");
RemoveCommand("/casting");
RemoveCommand("/interrupt");
RemoveCommand("/memorize");
RemoveCommand("/ssd");
RemoveCommand("/ssl");
RemoveCommand("/ssm");
RemoveCommand("/sss");
}
PLUGIN_API VOID OnEndZone(VOID)
{
Reset();
CastingO=NOID;
CastingC=NOID;
CastingE=CAST_SUCCESS;
CastingT=0;
ImmobileT=0;
}
PLUGIN_API DWORD OnIncomingChat(PCHAR Line, DWORD Color)
{
if(gbInZone) {
if(CastingC!=NOID && !Twisting) {
Parsed=false;
if(Color==264) {
LIST264.Feed(Line);
SUCCESS.Feed(Line);
} else if(Color==289) {
LIST289.Feed(Line);
} else if(Color==13) {
LIST013.Feed(Line);
}
if(!Parsed) {
UNKNOWN.Feed(Line);
if(Parsed) {
WriteChatf("\arMQ2Cast::Note for Author[\ay%s\ar]=(\ag%d\ar)\ax",Line,Color);
}
}
}
}
return 0;
}
PLUGIN_API VOID OnPulse(VOID)
{
if(gbInZone && GetTickCount642()>CastingP && GetCharInfo() && GetCharInfo()->pSpawn) {
CastingP=GetTickCount642()+DELAY_PULSE;
// evaluate immobile flag and handle immobilize request
Immobile=Moving();
if(StopF!=FLAG_COMPLETE) {
StopHandle();
}
CastingD=GetCharInfo()->pSpawn->CastingData.SpellID;
// casting window currently openened?
if(pCastingWnd && (PCSIDLWND)pCastingWnd->dShow) {
Casting=true;
if(CastingO==NOID) {
CastingO=(pTarget)?((long)((PSPAWNINFO)pTarget)->SpawnID):0;
}
// was this an unecpected cast?
if(CastingD!=CastingC && CastingD!=NOID) {
CastingE=DONE_PROGRESS;
CastingC=CastingD;
CastingT=GetCharInfo()->pSpawn->CastingData.SpellETA - GetCharInfo()->pSpawn->TimeStamp +
GetTickCount642()+450+(pConnection->Last)*4;
Success(GetSpellByID(CastingD));
}
// are we attempting to interrupt this?
if(DuckF!=FLAG_COMPLETE) {
DuckHandle(DuckF);
}
return;
}
// wait for incoming chat, timers, and windows to be closed.
DuckF=FLAG_COMPLETE;
Twisting=Evaluate("${If[${Twist.Twisting},1,0]}")?true:false;
if(Casting) {
if(CastingC==CastingD) {
if(PSPELL Spell=GetSpellByID(CastingC))
{
switch(Spell->TargetType)
{
case 18: // Uber Dragons
case 17: // Uber Giants
case 16: // Plant
case 15: // Corpse
case 14: // Pet
case 11: // Summoned
case 10: // Undead
case 9: // Animal
case 5: // Single
if(!pTarget) {
CastingE=CAST_NOTARGET;
}
break;
}
}
}
// re-evaluate casting timer after cast window close
CastingT=GetTickCount642()+450+(pConnection->Last)*2;
Casting=false;
}
if(CastingE==DONE_PROGRESS) {
if(GetTickCount642()>CastingT) {
CastingE=CAST_SUCCESS;
} else if(!Twisting) {
return;
}
}
if(Paused()) {
if((long)GetCharInfo()->pSpawn->CastingData.SpellID>0) {
Execute("/stopsong");
}
return;
}
// give time to proceed other casting events
if(MemoF!=FLAG_COMPLETE)
MemoHandle();
if(MemoF!=FLAG_COMPLETE)
return;
if(CastF!=FLAG_COMPLETE)
CastHandle();
// make sure we get final casting results
if((CastF==FLAG_COMPLETE && CastingC!=NOID && CastingD==NOID) || (BardClass() && CastingC!=NOID && (CastingD!=NOID))) {
CastingX=(CastingE<CAST_SUCCESS)?CAST_SUCCESS:CastingE;
CastingL=CastingC;
CastingE=DONE_COMPLETE;
if(!Twisting) {
if(DEBUGGING) {
WriteChatf("[%I64u] MQ2Cast:: Casting Complete ID[%d] Result=[%d]",GetTickCount642(),CastingL,CastingX);
}
CastTimer(CastingO,CastingC,CastingX); // patches for ae but sound illogicials
}
CastingC=NOID;
CastingO=NOID;
}
// make sure we finish other casting events
if(CastF==FLAG_COMPLETE) {
StopEnding();
if(PulseCount) {
PITEMINFO pCursor = GetItemFromContents(GetCharInfo2()->pInventoryArray->Inventory.Cursor);
if(PulseCount>5 && !pCursor) {
PulseCount=0;
return;
}
if(GetCharInfo2()->pInventoryArray->Inventory.Cursor && PulseCount) {
ClickBack();
}
if(PulseCount && PulseCount<7) {
PulseCount++;
}
}
}
}
}
void WinClick(CXWnd *Wnd, PCHAR ScreenID, PCHAR ClickNotification, DWORD KeyState)
{
if(Wnd) {
if(CXWnd *Child=Wnd->GetChildItem(ScreenID)) {
BOOL KeyboardFlags[4];
*(DWORD*)&KeyboardFlags=*(DWORD*)&((PCXWNDMGR)pWndMgr)->KeyboardFlags;
*(DWORD*)&((PCXWNDMGR)pWndMgr)->KeyboardFlags=KeyState;
SendWndClick2(Child,ClickNotification);
*(DWORD*)&((PCXWNDMGR)pWndMgr)->KeyboardFlags=*(DWORD*)&KeyboardFlags;
}
}
return;
}
void ClickBack()
{
if(!GetCharInfo2()->pInventoryArray->Inventory.Cursor || (pCastingWnd && (PCSIDLWND)pCastingWnd->dShow) ||
(pSpellBookWnd && (PCSIDLWND)pSpellBookWnd->dShow)) {
return;
}
if(GetCharInfo2()->pInventoryArray->Inventory.Cursor && PulseCount) {
PITEMINFO pCursor = GetItemFromContents(GetCharInfo2()->pInventoryArray->Inventory.Cursor);
if (pCursor && pCursor->Type == ITEMTYPE_PACK) {
//if(GetCharInfo2()->pInventoryArray->Inventory.Cursor->Item->Type==ITEMTYPE_PACK) {
WriteChatf("Pack Type");
WinClick((CXWnd*)pInventoryWnd,"InvSlot30","leftmouseup",0);
PulseCount=1;
return;
}
PITEMINFO pCursor2 = GetItemFromContents(GetCharInfo2()->pInventoryArray->Inventory.Cursor);
if (pCursor2->Type != ITEMTYPE_PACK) {
//if(GetCharInfo2()->pInventoryArray->Inventory.Cursor->Item->Type!=ITEMTYPE_PACK) {
WriteChatf("Not a pack");
WinClick((CXWnd*)pInventoryWnd,"IW_CharacterView","leftmouseup",0);
PulseCount=0;
return;
}
return;
}
}
- - - Updated - - -
Ok so I combined Cast.Ready with ${Me.GemTimer[Song Name]} which works great for my Bard INI. Doing some more testing but here is the alpha of what i'm using so far.
Rich (BB code):
[MQ2Melee]
enrage=1
facing=1
infuriate=1
melee=1
plugin=1
resume=75
stickrange=75
stickbreak=1
stickmode=on
stickcmd=${If[${Math.Calc[${Target.MaxRangeTo}*0.8]} > 19,15,${Math.Calc[${Target.MaxRangeTo}*0.8]}]} hold moveback loose
synergy=0
downflag0=1
downflag1=1
downflag2=1
downflag3=1
downflag4=1
downshit0=/if (!${Defined[mezcheck1]}) /multiline ; /declare mezcheck1 timer outer 0 ; /declare mezcheck2 timer outer 0 ; /declare mezcheck3 timer outer 0 ; /declare mezcheck4 timer outer 0 ; /declare slowd timer outer 0 ; /declare bardregen timer outer 0
downshit1=/if (!${Spell[${Me.Aura[1]}].ID} && !${Me.Moving} && !${Me.Invis} && !${Me.Sitting} && ${Me.State.NotEqual[FEIGN]}&&${Cast.Ready}&&${bardregen}==0) /casting "Aura of Va'Ker" 12
downshit2=/if (${Me.PctMana}>80&&${Group}&&${Cast.Ready}&&${bardregen}==0&&!${Me.Invis}&& !${Me.Sitting}) /multiline ; /melody ${Me.Gem[Silisia's Lively Crescendo]} ; /delay 35 ${Cast.Ready} ; /stopcast ; /varset bardregen 450
downshit3=/if (${Spell[Selo's Sonata].Stacks} &&(!${Me.Buff[Selo's Sonata].ID})&& !${Me.Invis}&& !${Me.Sitting} && ${Me.AltAbilityReady[Selo's Sonata]}) /docommand /alt act 3704
downshit4=/if (${Select[${Me.Casting.ID},${Spell[War March of Jocelyn].ID},${Spell[Aria of Maetanrus].ID},${Spell[Fjilnauk's Song of Suffering].ID}]}>0) /stopcast
holyflag0=1
holyflag1=1
holyflag2=1
holyflag3=1
holyflag4=1
holyflag5=1
holyflag6=1
holyflag7=1
holyflag8=1
holyflag9=1
holyflag10=1
holyflag11=1
holyflag12=1
holyshit0=/if (${Spell[Selo's Sonata].Stacks} &&!${Me.Buff[Selo's Sonata].ID}&& !${Me.Invis} && ${Me.AltAbilityReady[3704]} && ${Me.State.NotEqual[FEIGN]}) /docommand /alt act 3704
holyshit1=/if (${Me.AltAbilityReady[Banestrike]} && ${Target.Type.Equal[NPC]} && ${Me.CombatState.Equal[COMBAT]} && ${Me.State.NotEqual[FEIGN]}) /docommand /alt act 15073
holyshit2=/if (${FindItem[Vicious Rabbit].Timer}==0 && ${Target.Type.Equal[NPC]} && ${Me.CombatState.Equal[COMBAT]} && ${Me.State.NotEqual[FEIGN]}) /multiline ; /docommand /useitem "Vicious Rabbit" ; /delay 10
holyshit3=/if (${Me.AltAbilityReady[Selo's Kick]} && ${Target.Type.Equal[NPC]} && ${Me.CombatState.Equal[COMBAT]} && ${Me.State.NotEqual[FEIGN]}) /docommand /alt act 8205
holyshit4=/if (${Me.Combat} && ${Target.Type.Equal[NPC]} && ${Target.Distance}<150&&${Me.GemTimer[Requiem of Time]}==0&& ${Spell[${Target.Buff}].ID} && !${Spell[${Target.Buff[Requiem of Time]}].ID}) /multiline ; /if (${Me.Casting.ID}) /stopcast ; /melody ${Me.Gem[Requiem of Time]} ; /delay 35 ${Cast.Ready}
holyshit5=/if (${Me.Combat} && ${Me.XTarget[1].ID} && ${SpawnCount[npc radius 35]}>1 && ${mezcheck1}==0 && ${Spawn[${Me.XTarget[1].ID}].PctHPs}>99&&${Cast.Ready}) /multiline ; /casting "Slumber of Silisia" -targetid|${Me.XTarget[1].ID} ; /delay 35 ${Cast.Ready} ; /if (${Cast.Result.Equal[CAST_SUCCESS]}||${Cast.Result.Equal[CAST_TAKEHOLD]}) /varset mezcheck1 120
holyshit6=/if (${Me.Combat} && ${Me.XTarget[2].ID} && ${SpawnCount[npc radius 35]}>1 && ${mezcheck2}==0 && ${Spawn[${Me.XTarget[2].ID}].PctHPs}>99&&${Cast.Ready}) /multiline ; /casting "Slumber of Silisia" -targetid|${Me.XTarget[2].ID} ; /delay 35 ${Cast.Ready} ; /if (${Cast.Result.Equal[CAST_SUCCESS]}||${Cast.Result.Equal[CAST_TAKEHOLD]}) /varset mezcheck2 120
holyshit7=/if (${Me.Combat} && ${Me.XTarget[3].ID} && ${SpawnCount[npc radius 35]}>1 && ${mezcheck3}==0 && ${Spawn[${Me.XTarget[3].ID}].PctHPs}>99&&${Cast.Ready}) /multiline ; /casting "Slumber of Silisia" -targetid|${Me.XTarget[3].ID} ; /delay 35 ${Cast.Ready} ; /if (${Cast.Result.Equal[CAST_SUCCESS]}||${Cast.Result.Equal[CAST_TAKEHOLD]}) /varset mezcheck3 120
holyshit8=/if (${Me.Combat} && ${Me.XTarget[4].ID} && ${SpawnCount[npc radius 35]}>1 && ${mezcheck4}==0 && ${Spawn[${Me.XTarget[4].ID}].PctHPs}>99&&${Cast.Ready}) /multiline ; /casting "Slumber of Silisia" -targetid|${Me.XTarget[4].ID} ; /delay 35 ${Cast.Ready} ; /if (${Cast.Result.Equal[CAST_SUCCESS]}||${Cast.Result.Equal[CAST_TAKEHOLD]}) /varset mezcheck4 120
holyshit9=/if (${Me.Combat} && ${Target.Type.Equal[NPC]} && ${Cast.Ready} && ${Me.Song[War March of Jocelyn].Duration}<6000) /melody ${Me.Gem[War March of Jocelyn]} ${Me.Gem[Aria of Maetanrus]} ${Me.Gem[Fjilnauk's Song of Suffering]} ${Me.Gem[Chorus of Sionachie]}
holyshit10=/if (${Me.Combat} && ${Target.Type.Equal[NPC]} && ${Cast.Ready} && ${Me.Song[Aria of Maetanrus].Duration}<6000 && ${Me.Song[War March of Jocelyn].Duration}>=12000) /melody ${Me.Gem[Aria of Maetanrus]} ${Me.Gem[Fjilnauk's Song of Suffering]} ${Me.Gem[War March of Jocelyn]} ${Me.Gem[Chorus of Sionachie]}
holyshit11=/if (${Me.Combat} && ${Target.Type.Equal[NPC]} && ${Cast.Ready} && ${Me.Song[Fjilnauk's Song of Suffering].Duration}<6000 && ${Me.Song[Aria of Maetanrus].Duration}>=6000 && ${Me.Song[War March of Jocelyn].Duration}>=6000) /melody ${Me.Gem[Fjilnauk's Song of Suffering]} ${Me.Gem[War March of Jocelyn]} ${Me.Gem[Aria of Maetanrus]} ${Me.Gem[Chorus of Sionachie]}
holyshit12=/if (${Me.Combat} && ${Target.Type.Equal[NPC]} && !${Me.Casting.ID}) /melody ${Me.Gem[War March of Jocelyn]} ${Me.Gem[Aria of Maetanrus]} ${Me.Gem[Fjilnauk's Song of Suffering]} ${Me.Gem[Chorus of Sionachie]}
version=7.050

