#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;
}
}