• You've discovered RedGuides 📕 an EverQuest multi-boxing community 🛡️🧙🗡️. We want you to play several EQ characters at once, come join us and say hello! 👋
  • IS THIS SITE UGLY? Change the look. To dismiss this notice, click the X --->

Plugins (1 Viewer)

forsakenshadow

New member
Joined
Mar 1, 2005
RedCents
Any chance that we can get another section added to the eq1 forums for plugins? Just to help sort it all out.

On a side note of that I finally got around to doing my own complie got it working fine figured out how to make a plugin after tossing a donation to the devs, but now reading though i see that twist and warp are down....warp is nice and makes my afk loot/sell bot work but is mostly just a time saver...twist on the other hand leaves me dead in the water. I didn't see a fix for it yet but then its late and i could be missing something. Only notation i see on the dev's is to go look at a debugger...i dont' mind helping where i can but by nomeans do i have the time/knowledge to be phising though a debug output log. So any help would be great!

I know people are doing complies that work but i'm looking for a working .cpp for twist and warp so that I can continue on my slow arse learning curve... :)
 
try this .cpp
Rich (BB code):
#include "../MQ2Plugin.h" 

PreSetup("MQ2Twist"); 

typedef struct _ITEMCLICK { 
   int cast_time; 
   int recast; 
   long castdue; 
   int disabled; 
   int nousename; 
   CHAR slot[MAX_STRING]; 
   CHAR name[MAX_STRING]; 
} ITEMCLICK; 

int MQ2TwistEnabled = 0; 
const int MAX_SONG=10; 
int LONGSONG_ADJUST=1; // In TICKS, not seconds.  Used for long songs (greater than 3 ticks in duration). See docs. 
int CAST_TIME=33; 
int NumSongs=0; 
int AltNumSongs=0; 
int Song[MAX_SONG*2]; 
int AltSong[MAX_SONG*2]; 
long SongNextCast[MAX_SONG*2]; 
ITEMCLICK ItemClick[MAX_SONG]; 
int CurrSong=0; 
int AltCurrSong=0; 
int PrevSong=0; 
int HoldSong=0; 
long CastDue=0; 
bool bTwist=false; 
bool altTwist=false; 
bool quiet; 

long GetTime(); 
VOID TwistCommand(PSPAWNINFO pChar, PCHAR szLine); 
VOID StopTwistCommand(PSPAWNINFO pChar, PCHAR szLine); 
VOID SingCommand(PSPAWNINFO pChar, PCHAR szLine); 
BOOL dataTwist(PCHAR szIndex, MQ2TYPEVAR &Ret); 
CHAR MQ2TwistTypeTemp[MAX_STRING]={0}; 

//get current timestamp in tenths of a second 
long GetTime() 
{ 
   SYSTEMTIME st; 
   ::GetSystemTime(&st); 
   long lCurrent=0; 
   lCurrent  = st.wDay    * 24 * 60 * 60 * 10; 
   lCurrent += st.wHour        * 60 * 60 * 10; 
   lCurrent += st.wMinute           * 60 * 10; 
   lCurrent += st.wSecond                * 10; 
   lCurrent += (long)(st.wMilliseconds/100); 
   return (lCurrent); 
} 

VOID MQ2TwistDoCommand(PSPAWNINFO pChar, PCHAR szLine) 
{ 
   HideDoCommand(pChar, szLine, FromPlugin); 
} 

VOID Reset_ItemClick_Timers() 
{ 
   int i; 
   for (i=0;i<10;i++) { 
      ItemClick.castdue = 0; 
   } 
   for (i=0;i<MAX_SONG*2;i++) { 
      SongNextCast = 0; 
   } 
} 


VOID Update_INIFileName() { 
   if (GetCharInfo()) { 
      sprintf(INIFileName,"%s\\MQ2Twist_%s.ini",gszINIPath,GetCharInfo()->Name); 
   } else { 
      sprintf(INIFileName,"%s\\MQ2Twist.ini",gszINIPath); 
   } 
} 

VOID Load_MQ2Twist_INI() 
{ 
   CHAR szTemp[MAX_STRING]={0}; 
   CHAR szSection[MAX_STRING]={0}; 

   Update_INIFileName(); 

   CAST_TIME = GetPrivateProfileInt("MQ2Twist","Delay",33,INIFileName); 
   sprintf(szTemp, "%d", CAST_TIME); 
   WritePrivateProfileString("MQ2Twist","Delay",szTemp,INIFileName); 
   quiet = GetPrivateProfileInt("MQ2Twist","Quiet",0,INIFileName)? 1 : 0; 
   sprintf(szTemp, "%d", quiet); 
   WritePrivateProfileString("MQ2Twist","Quiet",szTemp,INIFileName); 
    
   LONGSONG_ADJUST = GetPrivateProfileInt("MQ2Twist","Adjust",1,INIFileName); 
   sprintf(szTemp, "%d", LONGSONG_ADJUST); 
   WritePrivateProfileString("MQ2Twist","Adjust",szTemp,INIFileName); 
    
   for (int i=0;i<10;i++) { 
      sprintf(szSection, "Click_%d", i+10); 
      ItemClick.cast_time = GetPrivateProfileInt(szSection,"CastTime",0,INIFileName); 
      ItemClick.recast = GetPrivateProfileInt(szSection,"ReCastTime",0,INIFileName); 

      GetPrivateProfileString(szSection,"Name","DISABLED",ItemClick.name,MAX_STRING,INIFileName); 
      ItemClick.nousename = !strnicmp("DISABLED", ItemClick.name, 8); 

      GetPrivateProfileString(szSection,"Slot","DISABLED",ItemClick.slot,MAX_STRING,INIFileName); 
      if (ItemClick.nousename) { 
         ItemClick.disabled = !strnicmp("DISABLED", ItemClick.slot, 8); 
      } else ItemClick.disabled = 0; 

      // Write the values above back to disk, mostly to initialize it for easy editing. 
      sprintf(szTemp, "%d", ItemClick.cast_time); 
      WritePrivateProfileString(szSection,"CastTime",szTemp,INIFileName); 
      // If the CastTime is set to -1 in the INI file, use the default. 
      ItemClick.cast_time = ItemClick.cast_time==-1 ? CAST_TIME : ItemClick.cast_time; 

      sprintf(szTemp, "%d", ItemClick.recast); 
      WritePrivateProfileString(szSection,"ReCastTime",szTemp,INIFileName); 
      WritePrivateProfileString(szSection,"Name",ItemClick.name,INIFileName); 
      WritePrivateProfileString(szSection,"Slot",ItemClick.slot,INIFileName); 
      DebugSpewAlways("Initializing MQ2Twist: Processed %s", szSection); 
   } 
} 

VOID SingCommand(PSPAWNINFO pChar, PCHAR szLine) 
{ 
   CHAR szTemp[MAX_STRING]={0}; 
   CHAR szMsg[MAX_STRING]={0}; 
   int i; 

   GetArg(szTemp,szLine,1); 
   i=atoi(szTemp); 

   if (i>=1 && i<=19) { // valid range? 
      HoldSong = i; 
      bTwist=true; 
      CastDue = -1; 
      sprintf(szMsg, "MQ2Twist::Holding Twist and casting gem %d", HoldSong); 
      WriteChatColor(szMsg,USERCOLOR_DEFAULT); 
      MQ2TwistDoCommand(pChar,"/stopsong"); 
      if (i>10) { //item? 
         ItemClick[i-10].castdue = 0; 
      } else SongNextCast = 0; //nope, song 
   } else WriteChatColor("MQ2Twist::Invalid gem specified, ignoring",USERCOLOR_DEFAULT); 
} 

VOID StopTwistCommand(PSPAWNINFO pChar, PCHAR szLine) 
{ 
   bTwist=false; 
   HoldSong=0; 
   MQ2TwistDoCommand(pChar,"/stopsong"); 
   WriteChatColor("MQ2Twist::Stopping Twist",USERCOLOR_DEFAULT); 
} 

VOID PrepNextSong() { 
   if (CurrSong>NumSongs) { 
      if (altTwist) { 
         NumSongs=AltNumSongs; 
         CurrSong=PrevSong=AltCurrSong; 
         for (int i=0; i<NumSongs; i++) Song=AltSong; 
         altTwist=false; 
         if (!quiet) WriteChatColor("MQ2Twist::One-shot twist ended, normal twist will resume next pulse",USERCOLOR_DEFAULT); 
      } else CurrSong=1; 
   } 
} 

VOID DisplayTwistHelp() { 
   WriteChatColor("MQ2Twist - Twist song or songs",USERCOLOR_DEFAULT); 
   WriteChatColor("Usage:   /twist <gem#> - Twists in the order given.",USERCOLOR_DEFAULT); 
   WriteChatColor("  Valid options are 1 thru 8 for song gems, and 10 thru 19 for item clicks.",USERCOLOR_DEFAULT); 
   WriteChatColor("  These may be mixed in any order, and repeats are allowable.",USERCOLOR_DEFAULT); 
   WriteChatColor("Usage: /twist hold <gem #> - Pause twisting and sing only the specified song",USERCOLOR_DEFAULT); 
   WriteChatColor("  /sing <gem#> - alias for /twist hold",USERCOLOR_DEFAULT); 
   WriteChatColor("Usage: /twist or /twist start - Resume the twist after using /twist hold or /twist stop",USERCOLOR_DEFAULT); 
   WriteChatColor("Usage: /twist reset - Reset timers for item clicks and long duration songs",USERCOLOR_DEFAULT); 
   WriteChatColor("Usage: /twist delay # - 10ths of a second, minimum of 30, default 33",USERCOLOR_DEFAULT); 
   WriteChatColor("Usage: /twist adjust # - in ticks, how early to recast long duration songs",USERCOLOR_DEFAULT); 
   WriteChatColor("Usage: /twist stop/end/off - stop twisting, does not clear the twist queue",USERCOLOR_DEFAULT); 
   WriteChatColor("  /stoptwist - alias for /twist stop",USERCOLOR_DEFAULT); 
   WriteChatColor("Usage: /twist reload - reload the INI file to update item clicks",USERCOLOR_DEFAULT); 
   WriteChatColor("Usage: /twist slots - List the slots defined in the INI and their #'s",USERCOLOR_DEFAULT); 
} 

// *************************************************************************** 
// Function:      TwistCommand 
// Description:   Our /twist command. sing for me! 
// *************************************************************************** 
VOID TwistCommand(PSPAWNINFO pChar, PCHAR szLine) 
{ 
   CHAR szTemp[MAX_STRING]={0}; 
   CHAR szMsg[MAX_STRING]={0}; 
   CHAR szChat[MAX_STRING]={0}; 
   PSPELL pSpell; 
   int i; 

   GetArg(szTemp,szLine,1); 

   if (NumSongs && (!strlen(szTemp) || !strnicmp(szTemp,"start", 5))) { 
      WriteChatColor("MQ2Twist::Starting Twist",USERCOLOR_DEFAULT); 
      bTwist=true; 
      HoldSong=0; 
      CastDue = -1; 
      return; 
   } 

   if (!strnicmp(szTemp,"stop", 4) || !strnicmp(szTemp,"end", 3) || !strnicmp(szTemp,"off", 3)) { 
      StopTwistCommand(pChar, szTemp); 
      return; 
   } 

   if (!strnicmp(szTemp,"slots", 5)) { 
      WriteChatColor("MQ2Twist 'Song' Numbers for right click effects:",USERCOLOR_DEFAULT); 
      for (i=0;i<10;i++) { 
         if (ItemClick.disabled) break; 
         if (ItemClick.nousename) { 
            sprintf(szMsg, "  %d = %s (slot)", i+10, ItemClick.slot); 
         } else { 
            sprintf(szMsg, "  %d = %s (name)", i+10, ItemClick.name); 
       } 
         WriteChatColor(szMsg,USERCOLOR_DEFAULT); 
      } 
      WriteChatColor("---",USERCOLOR_DEFAULT); 
      return; 
   } 

   if (!strnicmp(szTemp,"reload", 6)) { 
      WriteChatColor("MQ2Twist::Re-Loading INI Values",USERCOLOR_DEFAULT); 
      Load_MQ2Twist_INI(); 
      return; 
   } 

   if (!strnicmp(szTemp,"delay", 5)) { 
      GetArg(szTemp,szLine,2); 
      if (strlen(szTemp)>0) { 
         i=atoi(szTemp); 
         if (i<=30) { 
            WriteChatColor("MQ2Twist::WARNING delay specified is less than standard song cast time",CONCOLOR_RED); 
         } 
         CAST_TIME=i; 
         Update_INIFileName(); 
         WritePrivateProfileString("MQ2Twist","Delay",itoa(CAST_TIME, szTemp, 10),INIFileName); 
         sprintf(szMsg, "MQ2Twist::Set delay to %d, INI updated", CAST_TIME); 
      } else sprintf(szMsg, "MQ2Twist::Delay %d", CAST_TIME); 
      WriteChatColor(szMsg,USERCOLOR_DEFAULT); 
      return; 
   } 
    
   if (!strnicmp(szTemp,"quiet", 5)) { 
      quiet=!quiet; 
      sprintf(szTemp,"%d",quiet); 
      WritePrivateProfileString("MQ2Twist","Quiet",szTemp,INIFileName); 
      sprintf(szMsg,"MQ2Twist::Now being %s",quiet ? "quiet" : "noisy"); 
      WriteChatColor(szMsg,USERCOLOR_DEFAULT); 
      return; 
   } 
    
   if (!strnicmp(szTemp,"adjust", 6)) { 
      GetArg(szTemp,szLine,2); 
      if (strlen(szTemp)>0) { 
         i=atoi(szTemp); 
         LONGSONG_ADJUST=i; 
         Update_INIFileName(); 
         WritePrivateProfileString("MQ2Twist","Adjust",itoa(LONGSONG_ADJUST, szTemp, 10),INIFileName); 
         sprintf(szMsg, "MQ2Twist::Long song adjustment set to %d, INI updated", LONGSONG_ADJUST); 
      } else sprintf(szMsg, "MQ2Twist::Long song adjustment: %d", LONGSONG_ADJUST); 
      WriteChatColor(szMsg,USERCOLOR_DEFAULT); 
      return; 
   } 

   if (!strnicmp(szTemp,"hold", 4)) { 
      GetArg(szTemp,szLine,2); 
      SingCommand(pChar, szTemp); 
      return; 
   } 

   if (!strnicmp(szTemp,"reset", 5)) { 
      Reset_ItemClick_Timers(); 
      WriteChatColor("MQ2Twist::Timers reset",CONCOLOR_YELLOW); 
      return; 
   } 

   // check help arg, or display if we have no songs defined and /twist was used 
   if (!strlen(szTemp) || !strnicmp(szTemp,"help", 4)) { 
      DisplayTwistHelp(); 
      return; 
   } 

   // if we are "one-shot twisting", save the current song array and current song 
   if (!strnicmp(szTemp,"once", 4)) { 
      WriteChatColor("MQ2Twist one-shot twisting:",CONCOLOR_YELLOW); 
      if (altTwist) { 
         CurrSong=NumSongs+1; 
         PrepNextSong(); // If CurrSong > NumSongs relaod the song list 
      } 
      if (NumSongs) { 
         AltNumSongs=NumSongs; 
         AltCurrSong=CurrSong; 
         for (i=0; i<NumSongs; i++) AltSong=Song; 
      } 
      altTwist=true; 
   } else altTwist=false; 

   DebugSpew("MQ2Twist::TwistCommand Parsing twist order"); 
   NumSongs=0; 
   HoldSong=0; 
   if (!altTwist) { 
      if (!quiet) { 
         WriteChatColor("MQ2Twist Twisting:",CONCOLOR_YELLOW); 
      } else WriteChatColor("MQ2Twist::Starting Twist",USERCOLOR_DEFAULT); 
   } 
   for (i=0 + altTwist ? 1 : 0; i<20; i++) 
   { 
      GetArg(szTemp,szLine,i+1); 
      if (!strlen(szTemp))  break; 

      Song[NumSongs]=atoi(szTemp); 
      if (Song[NumSongs]>=1 && Song[NumSongs]<=19) { 
         if ((Song[NumSongs]>9) && ItemClick[Song[NumSongs]-10].disabled) { 
            sprintf(szChat, " Undefined item specified (%s) - ignoring (see INI file)", szTemp); 
            WriteChatColor(szChat,CONCOLOR_RED); 
         } else { 
            sprintf(szMsg, " %s - ", szTemp); 

            if (Song[NumSongs]<=9) { 
               pSpell=GetSpellByID(GetCharInfo()->MemorizedSpells[Song[NumSongs]-1]); 
               if (altTwist) SongNextCast[NumSongs] = 0; 
               if (pSpell) strcat(szMsg, pSpell->Name); 
            } else { 
               if (ItemClick[Song[NumSongs]-10].nousename) { 
                  strcat(szMsg, ItemClick[Song[NumSongs]-10].slot); 
               } else { 
                  strcat(szMsg, ItemClick[Song[NumSongs]-10].name); 
               } 
               if (altTwist) ItemClick[NumSongs].castdue = 0; 
            } 
            if (!quiet) WriteChatColor(szMsg,COLOR_LIGHTGREY); 
            NumSongs++; 
         } 
      } else { 
         sprintf(szChat, " Invalid gem specified (%s) - ignoring", szTemp); 
         WriteChatColor(szChat,CONCOLOR_RED); 
      } 
   } 

   sprintf(szTemp, "Twisting %d song%s", NumSongs, NumSongs>1 ? "s" : ""); 
   if (!quiet) WriteChatColor(szTemp,CONCOLOR_YELLOW); 

   if (NumSongs>0) bTwist=true; 
   CurrSong = 1; 
   PrevSong = 1; 
   CastDue = -1; 
   MQ2TwistDoCommand(pChar,"/stopsong"); 
   if (!altTwist) Reset_ItemClick_Timers(); 
} 

/* 
Checks to see if character is in a fit state to cast next song/item 

Note 1: Do not try to correct SIT state, or you will have to stop the 
twist before re-memming songs 

Note 2: Since the auto-stand-on-cast bullcrap added to EQ a few patches ago, 
chars would stand up every time it tried to twist a song.  So now 
we stop twisting at sit. 
*/ 
BOOL CheckCharState() { 
   if (!bTwist) return FALSE; 

   if (GetCharInfo()) { 
      if (GetCharInfo()->Stunned==1) return FALSE; 
      switch (GetCharInfo()->standstate) { 
       case STANDSTATE_SIT: 
          WriteChatColor("MQ2Twist::Stopping Twist",USERCOLOR_DEFAULT); 
          bTwist = FALSE; 
          return FALSE; 
          break; 
       case STANDSTATE_FEIGN: 
          MQ2TwistDoCommand(NULL,"/stand"); 
          return FALSE; 
          break; 
       case STANDSTATE_DEAD: 
          WriteChatColor("MQ2Twist::Stopping Twist",USERCOLOR_DEFAULT); 
          bTwist = FALSE; 
          return FALSE; 
          break; 
       default: 
          break; 
      } 
   } 

   if (pCastingWnd) { 
      PCSIDLWND pCastingWindow = (PCSIDLWND)pCastingWnd; 
      if (pCastingWindow->Show == 1) return FALSE; 
      // Don't try to twist if the casting window is up, it implies the previous song 
      // is still casting, or the user is manually casting a song between our twists 
   } 
   return TRUE; 
} 
class MQ2TwistType *pTwistType=0; 

class MQ2TwistType : public MQ2Type 
{ 
public: 
   enum TwistMembers 
   { 
      Twisting=1, 
      Next=2, 
      Current=3, 
      List=4, 
   }; 

   MQ2TwistType():MQ2Type("twist") 
   { 
      TypeMember(Twisting); 
      TypeMember(Next); 
      TypeMember(Current); 
      TypeMember(List); 
   } 
   ~MQ2TwistType() 
   { 
   } 

   bool GetMember(MQ2VARPTR VarPtr, PCHAR Member, PCHAR Index, MQ2TYPEVAR &Dest) 
   { 
      PMQ2TYPEMEMBER pMember=MQ2TwistType::FindMember(Member); 
      if (!pMember) 
         return false; 
      switch((TwistMembers)pMember->ID) 
      { 
      case Twisting: 
         /* Returns: bool 
            0 - Not Twisting 
            1 - Twisting 
         */ 
         Dest.Int=bTwist; 
         Dest.Type=pBoolType; 
         return true; 
      case Next: 
         /* Returns: int 
            0 - Not Twisting 
            -1 - Casting Item 
            1-8 - Current Gem 
         */ 
         Dest.Int=HoldSong ? HoldSong : Song[CurrSong-1]; 
         if (Dest.Int>9) Dest.Int = -1; 
         if (!bTwist) Dest.Int = 0; 

         Dest.Type=pIntType; 
         return true; 
      case Current: 
         Dest.Int=HoldSong ? HoldSong : Song[PrevSong-1]; 
         if (Dest.Int>9) Dest.Int = -1; 
         if (!bTwist) Dest.Int = 0; 

         Dest.Type=pIntType; 
         return true; 
      case List: 
         /* Returns: string 
            Space separated list of gem and item #'s being twisted, in order 
         */ 
         int a; 
         CHAR szTemp[MAX_STRING] = {0}; 

         MQ2TwistTypeTemp[0] = 0; 
         for (a=0; a<NumSongs; a++) { 
            sprintf(szTemp, "%d ", Song[a]); 
            strcat(MQ2TwistTypeTemp, szTemp); 
         } 

         Dest.Ptr=&MQ2TwistTypeTemp[0]; 
         Dest.Type=pStringType; 
         return true; 
      } 
      return false; 
   } 

   bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) 
   { 
      if (bTwist) 
         strcpy(Destination,"TRUE"); 
      else 
         strcpy(Destination,"FALSE"); 
      return true; 
   } 

   bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) 
   { 
      return false; 
   } 
   bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) 
   { 
      return false; 
   } 
}; 

BOOL dataTwist(PCHAR szName, MQ2TYPEVAR &Dest) 
{ 
   Dest.DWord=1; 
   Dest.Type=pTwistType; 
   return true; 
} 


// ****************************** 
// **** MQ2 API Calls Follow **** 
// ****************************** 

PLUGIN_API VOID InitializePlugin(VOID) 
{ 
   DebugSpewAlways("Initializing MQ2Twist"); 

   AddCommand("/twist",TwistCommand,0,1,1); 
   AddCommand("/sing",SingCommand,0,1,1); 
   AddCommand("/stoptwist",StopTwistCommand,0,0,1);; 
    AddMQ2Data("Twist",dataTwist); 

    pTwistType = new MQ2TwistType; 

} 

PLUGIN_API VOID ShutdownPlugin(VOID) 
{ 
   DebugSpewAlways("MQ2Twist::Shutting down"); 

   RemoveCommand("/twist"); 
   RemoveCommand("/sing"); 
   RemoveCommand("/stoptwist"); 
    RemoveMQ2Data("Twist"); 

    delete pTwistType; 
} 

PLUGIN_API VOID OnPulse(VOID) 
{ 
   CHAR szTemp[MAX_STRING] = {0}; 
   PSPELL pSpell; 
   int a,b; 

   if (!MQ2TwistEnabled || !CheckCharState()) return; 

   if ((HoldSong>0) || ((NumSongs==1) && !altTwist)) { 
      DebugSpew("MQ2Twist::Pulse - Single Song"); 
      if ( CastDue<0 || ( ((CastDue-GetTime()) <= 0 ) && (GetCharInfo()->pSpawn->pActorInfo->CastingSpellID == -1) ) ) { 
         int SongTodo = HoldSong ? HoldSong : Song[0]; 
         if (SongTodo <= 9) { 
            DebugSpew("MQ2Twist::Pulse - Single Song (Casting Gem %d)", SongTodo); 
            sprintf(szTemp,"/multiline ; /stopsong ; /cast %d", SongTodo); 
            MQ2TwistDoCommand(NULL,szTemp); 
            CastDue = GetTime()+CAST_TIME; 
         } else { 
            if (ItemClick[SongTodo-10].castdue-GetTime() <= 0) { 
               if (ItemClick[SongTodo-10].nousename) { 
                  DebugSpew("MQ2Twist::Pulse - Single Song (Casting Item %d - %s)", SongTodo, ItemClick[SongTodo-10].slot); 
                  sprintf(szTemp,"/multiline ; /stopsong ; /itemnotify %s rightmouseup", ItemClick[SongTodo-10].slot); 
               } else { 
                  DebugSpew("MQ2Twist::Pulse - Single Song (Casting Item %d - %s)", SongTodo, ItemClick[SongTodo-10].name); 
                  sprintf(szTemp,"/multiline ; /stopsong ; /itemnotify ${FindItem[%s].InvSlot.Name} rightmouseup", ItemClick[SongTodo-10].name); 
               } 
               MQ2TwistDoCommand(NULL,szTemp); 
               ItemClick[SongTodo-10].castdue = ItemClick[SongTodo-10].recast ? (GetTime()+ItemClick[SongTodo-10].cast_time+ItemClick[SongTodo-10].recast) : (GetTime()+CAST_TIME); 
               CastDue = ItemClick[SongTodo-10].castdue; 
            } 
         } 
      } 
   } else { 
      int SongTodo = Song[CurrSong-1]; 
      if (NumSongs && ((CastDue-GetTime()) <= 0)) { 
         if (SongTodo <= 9) { 
            if (SongNextCast[CurrSong-1]-GetTime() <= 0) { 
               DebugSpew("MQ2Twist::OnPulse - Next Song = %s", szTemp); 
               sprintf(szTemp,"/multiline ; /stopsong ; /cast %d", SongTodo); 
               MQ2TwistDoCommand(NULL,szTemp); 
               pSpell=GetSpellByID(GetCharInfo()->MemorizedSpells[Song[CurrSong-1]-1]); 
               if(!pSpell) { 
                  WriteChatColor("Songs not present - suspending twist.  /twist to resume",CONCOLOR_RED); 
                  bTwist = FALSE; 
                  return; 
               } 
               a = pSpell->RecastTime/1000 * 60;                     // recasttime in 10's of a second 
               b = GetSpellDuration(pSpell,GetCharInfo()->pSpawn) * 60;   // duration in 10's of a second 
               if (pSpell->DurationType == 5 && !pSpell->DurationValue1) { 
                  b = 18;   //FIXME - Remove once GetSpellDuration handles duration type5 
               } 
               CastDue = GetTime()+CAST_TIME; 
               if (a > 0 || b > 180) { // We only care about songs with > 3 tick durations or non-0 recast times 
                  SongNextCast[CurrSong-1] = GetTime() + (a > b ? a : b) - CAST_TIME - (LONGSONG_ADJUST*60);   // Cast next after greater of recasttime or duration, minus LONGSONG_ADJUST ticks. 
               } else { 
                  SongNextCast[CurrSong-1] = CastDue; 
               } 
               PrevSong=CurrSong; 
            } // if it's not time for currsong to be re-sung, skip it in the twist 
            CurrSong++; 
            PrepNextSong(); 
         } else { 
            if (ItemClick[SongTodo-10].castdue-GetTime() <= 0) { 
               if (ItemClick[SongTodo-10].nousename) { 
                  DebugSpew("MQ2Twist::Pulse - Next Song (Casting Slot %d - %s)", SongTodo, ItemClick[SongTodo-10].slot); 
                  sprintf(szTemp,"/multiline ; /stopsong ; /itemnotify %s rightmouseup", ItemClick[SongTodo-10].slot); 
               } else { 
                  DebugSpew("MQ2Twist::Pulse - Next Song (Casting Item %d - %s)", SongTodo, ItemClick[SongTodo-10].name); 
                  sprintf(szTemp,"/multiline ; /stopsong ; /itemnotify ${FindItem[%s].InvSlot.Name} rightmouseup", ItemClick[SongTodo-10].name); 
               } 
               MQ2TwistDoCommand(NULL,szTemp); 
               ItemClick[SongTodo-10].castdue = ItemClick[SongTodo-10].recast ? (GetTime()+ItemClick[SongTodo-10].cast_time+ItemClick[SongTodo-10].recast) : (GetTime()+CAST_TIME); 
               CastDue = GetTime()+ItemClick[SongTodo-10].cast_time; 
            } 
            PrevSong=CurrSong;   // Increment twist position even if we didn't do an itemnotify - this might have a long recast 
            CurrSong++;         // interval set, and we just skip it until it's time to recast, rather than keep a separate timer. 
            PrepNextSong(); 
         }    
      } 
   }      
} 

PLUGIN_API DWORD OnIncomingChat(PCHAR Line, DWORD Color) 
{ 
   if (!bTwist || !MQ2TwistEnabled) return 0; 
   DebugSpew("MQ2Twist::OnIncomingChat(%s)",Line); 
    
   if ( !strcmp(Line,"You miss a note, bringing your song to a close!") || 
      !strcmp(Line,"You haven't recovered yet...") || 
      !strcmp(Line,"Your spell is interrupted.") ) { 
         DebugSpew("MQ2Twist::OnIncomingChat - Song Interrupt Event"); 
         if (!HoldSong) CurrSong=PrevSong; 
         CastDue = -1; 
         SongNextCast[CurrSong-1] = -1; 
         return 0; 
      } 

   if (!strcmp(Line,"You can't cast spells while stunned!") ) { 
      DebugSpew("MQ2Twist::OnIncomingChat - Song Interrupt Event (stun)"); 
      if (!HoldSong) CurrSong=PrevSong; 
      CastDue = GetTime() + 10; 
      // Wait one second before trying again, to avoid spamming the trigger text w/ cast attempts 
      return 0; 
   } 
   return 0; 
} 

PLUGIN_API VOID SetGameState(DWORD GameState) 
{ 
   DebugSpew("MQ2Twist::SetGameState()"); 
   if (GameState==GAMESTATE_INGAME) 
   { 
      MQ2TwistEnabled = true; 
      Load_MQ2Twist_INI(); 
   } else { 
      MQ2TwistEnabled = false; 
   } 
} 
 
Plugins

Users who are viewing this thread

Back
Top