• 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 --->

Compiled - Just use VS2015 (1 Viewer)

Joined
Mar 29, 2017
RedCents
167¢
Hello all, new user here, and had a little advice for other new users.

The MQ2 wiki states that VS version 2013+ will work for building the solution, so I fired up 2013 and tried it. I had several issues, even after building and re-building several times, fixing my projects' toolkits, etc... Finally I deleted it all, unpacked the zip again and tried it using 2015. Literally my first build everything compiled with no errors or warnings.

My advice, if you don't want the headache of figuring out what is wrong when using 2013 is: just don't. Use 2015 instead.

Thanks,
Skadoosh
 
On the wiki here the first option is 2015. I personally always use a higher version unless otherwise stated for most things.

Community member etheralmist,
First off your handle sounds like an exotic drink you would buy a babe at a pickup bar............ I like it!!!!!
Thirdly the hyperlink "here" sends me to Visual Studio 2017. I am new to this and most likely got it unright. Something less than correct. A result at odds with a satisfactory conclusion. A cursory root cause analysis would indicate operator error. All right I could not figure it out. So where is the 2015 thingy?
Every time I learn something new I am just a little closer to Effing something up in a major way.

Already thanked you..... but,
Thank you,
As always,
Playbetter
 
Community member etheralmist,
First off your handle sounds like an exotic drink you would buy a babe at a pickup bar............ I like it!!!!!
Thirdly the hyperlink "here" sends me to Visual Studio 2017. I am new to this and most likely got it unright. Something less than correct. A result at odds with a satisfactory conclusion. A cursory root cause analysis would indicate operator error. All right I could not figure it out. So where is the 2015 thingy?
Every time I learn something new I am just a little closer to Effing something up in a major way.

Already thanked you..... but,
Thank you,
As always,
Playbetter

The link on the wiki is probably a default link to whatever the current new version of VB studio community is.
 
You want to use 2015 at a minimum. Thats the requirement.

I highly recommend you use 2017 though. Its much improved over 2015 and is backwards compatible with 2015 (even includes 2015 compiler if you check the box during installation)
 
On the wiki here the first option is 2015. I personally always use a higher version unless otherwise stated for most things.

True, I guess I should have noticed that.

Community member etheralmist,
First off your handle sounds like an exotic drink you would buy a babe at a pickup bar............ I like it!!!!!
Thirdly the hyperlink "here" sends me to Visual Studio 2017. I am new to this and most likely got it unright. Something less than correct. A result at odds with a satisfactory conclusion. A cursory root cause analysis would indicate operator error. All right I could not figure it out. So where is the 2015 thingy?
Every time I learn something new I am just a little closer to Effing something up in a major way.

Already thanked you..... but,
Thank you,
As always,
Playbetter

Even though you directly addressed etherealmist, I thought you were talking to me at first... and all I could think was, "I would never drink something called a 'Skadoosh'." LOL

The link on the wiki is probably a default link to whatever the current new version of VB studio community is.

I didn't even notice; I'm a software developer so I already had both non-community versions installed, and as such didn't bother following either link.

You want to use 2015 at a minimum. Thats the requirement.

I highly recommend you use 2017 though. Its much improved over 2015 and is backwards compatible with 2015 (even includes 2015 compiler if you check the box during installation)

The wiki itself says that 2013 is the minimum requirement. And I've found that VS in particular as an IDE is pretty fickle with versioning, and it's usually best to use the version on which the solution you're editing/building was written, which appears to be 2015 in this case. But whatever works, I'm sure 2017 works just as well. I'll make sure to get it and try it out, thanks for the recommendation!
 
True, I guess I should have noticed that.



Even though you directly addressed etherealmist, I thought you were talking to me at first... and all I could think was, "I would never drink something called a 'Skadoosh'." LOL



I didn't even notice; I'm a software developer so I already had both non-community versions installed, and as such didn't bother following either link.



The wiki itself says that 2013 is the minimum requirement. And I've found that VS in particular as an IDE is pretty fickle with versioning, and it's usually best to use the version on which the solution you're editing/building was written, which appears to be 2015 in this case. But whatever works, I'm sure 2017 works just as well. I'll make sure to get it and try it out, thanks for the recommendation!

I tried to compile last night with VS2017 and got a ton of errors. I am sure it was something I was doing, but I can't imagine what. There isn't a lot to it. Run MQ2Auth.exe. Open MacroQuest2.sln in VS. Build.
I hope you have better luck than I do friend!
 
I tried to compile last night with VS2017 and got a ton of errors. I am sure it was something I was doing, but I can't imagine what. There isn't a lot to it. Run MQ2Auth.exe. Open MacroQuest2.sln in VS. Build.
I hope you have better luck than I do friend!

Same. Tried compiling on another box using a fresh install of 2017, and it was worse than when I tried 2013. Think I'll stick with 2015 for the time being.
 
If you happen to have a good link to an install of VS2015 let me know. Apparently the official website has it, but you have to have some sort of subscription to download it.

Yeah, it looks like you have to have a subscription to MSDN in order to get older versions of VS Community. That sucks, especially considering VS has always had backward compatibility issues.
 
I did a fresh run yesterday on a win 10 machine.
I downloaded vs 2017 community and installed it.
Now the problem with 2017 is that Microsoft decided to "add power" to the installer by making every single thing a custom option.

So unless you know what you need, it makes life incredibly complicated, because just clicking next,next won't cut it.

I don't have time to screenshot the process right now, but a tutorial is definitely needed at some point.
You need the c++ stuff but NOT mfc for example... You need the sdk, might wanna check winxp support as well as the vs 2015 sdk etc, it's a pita to figure out all the checkboxes.

Bottomline, I suppose you could check every single one and get all the .net crap as well and I *think* that would work...

Either way, after a successful install opening the mq solution it wanted to change the toolset to 2017 I just clicked no, and it used the 2015 one, built just fine without warnings or errors...

When people install a community edition and mq compile gives errors it's 100% likely they either didn't run mq2auth.exe first, OR they missed a checkbox in the install of something needed, like the toolset or the actual c compiler itself, maybe they just installed .NET (Microsoft default that crap and push hard for people to use it when in fact they SHOULD default to native...)

Also, as a side note, EVERYONE has access to edit the wiki, so go for it, change the recommended to vs 2015 if you like.
 
I've been able to build with vs 2017. Here are the steps I took. Feel free to copy/paste directly to a forum post, I just put it up on my own site so that I could share with friends.

http://wwccs.com/mq.html

edit: This doesn't include theh m2auth step, so do that as normal before following the tut.
 
The method Jhxetc mentioned works perfectly but I found that Platform Toolset 2017 also works for the main pack compile.

But I found some erros when I tried to compile this plugin MQ2Chatevents (I use the crazybard version in the replies)

http://www.macroquest2.com/phpBB3/viewtopic.php?f=50&t=18906&hilit=mq2chatevents

The errors are from EQClass.h and MQ2Chatevent.cpp, screenshot is like this
Errors.jpg

Rich (BB code):
Error (active)		return type may not be specified on a conversion function	MQ2Main	e:\MQ2\MQ2Main\EQClasses.h	450

Rich (BB code):
Error	C2660	'ParseMacroData': function does not take 1 arguments	MQ2Chatevents	E:\MQ2\MQ2Chatevents\MQ2Chatevents.cpp	306

My properties of the CPP is like this:
Prop.jpg
 
I don't have access to the link you posted to download the plugin source. The EQClasses.h errors show up for me as well, but will still compile. It's some C++ syntax stuff that VS wants to fix, but doesn't prevent it from working. The chat plugin though appears to be passing an argument to a function that does not take one.
 
I've been using Windows SDK 8.1 instead of 10.0.14393.0, guess that doesn't matter though?

Thanks jhxetc sir~

Here is the source code of altered version of MQ2Chatevent

Rich (BB code):
/*
MQ2ChatEvents.cpp
2006-08-05   Created by Persnickety/BustedPretext
Credit to Kuv for his MQ2CustomSound plugin on which some of this was based
2013-05-07   Updated to allow multiple commands to execute on a match
2013-05-15   Updated to allow in-game variables to be used in Match strings and Commands
2013-05-24   Moved commands into a command queue for asyncronous execution from the chat matching

-----------------
Usage: /ce <Sound|Popup|MissedChat|MissedChatEcho|Commands|verbose|on|off|reload|help>
Sound         : Toggles playing of custom sounds
Popup         : Toggles displaying of custom popups
MissedChat      : Toggles popup notification after missing chat while zoning
MissedChatEcho   : Toggles echoing of missed chat to MQ window
Commands      : Toggles executing custom commands
On            : Turns plugin On
Off            : Turns plugin Off
Reload         : Reload INI file
Help            : Displays the in game commands and show the current settings

Usage /playsound <EventKey>
Plays sound file associated with given key
*/

#include "../MQ2Plugin.h"
#include <mmsystem.h>
#include <vector>
#include <queue>

#pragma comment(lib,"winmm.lib")

void ChatEventsHelp(void);
DWORD TextToColor(char[]);
void ToggleOption(char[], bool *);
string GetOnOffLabel(bool);
void HandleChat(PCHAR, DWORD);
void AddEvents(char[]);

#define MAX_KEYLINES 100      // not max keys, but max number of EventKey# lines, each capable of containing multiple keys
#define MATCHABLE_STRINGS 100
#define MATCHABLE_COLORS 10
#define MAX_COMMANDS 100
#define SKIP_PULSES 5

typedef struct {
	char key[MAX_STRING];
	char matchStrings[MATCHABLE_STRINGS][MAX_STRING];
	char matchColors[MATCHABLE_COLORS][MAX_STRING];
	char soundFile[MAX_STRING];
	char popupText[MAX_STRING];
	char popupColor[MAX_STRING];
	char popupDuration[MAX_STRING];
	char command[MAX_COMMANDS][MAX_STRING];
	int    commandCount;
	int  matchCount;
	int    matchColorCount;
} ChatEvent;
vector<ChatEvent> eventVector;

char commandBuffer[MAX_STRING];
queue<string> commandQueue;

char CESection[MAX_STRING] = "MQ2ChatEvents";
bool popupsEnabled = true;
bool soundsEnabled = true;
bool missedChatPopup = true;
bool missedChatEcho = true;
bool commandsEnabled = true;
bool verboseCommands = false;
bool pluginEnabled = true;
bool tellFlag = false;
int  pulseCounter = 0;
bool processFlag = true;

PreSetup("MQ2ChatEvents");

// InitEvents - loads custom events and match strings from INI file
void InitEvents()
{
	//DebugSpewAlways("MQ2ChatEvents - Enter InitEvents");
	gbInZone = true;
	CHAR tempSetting[MAX_STRING];
	eventVector.clear();

	// return if character not yet in game
	if (strcmp(CESection, "MQ2ChatEvents") == 0) return;

	sprintf_s(CESection, "%s_%s", GetCharInfo()->Name, EQADDR_SERVERNAME);

	GetPrivateProfileString(CESection, "PluginEnabled", "MQ2ChatEvents_Error", tempSetting, MAX_STRING, INIFileName);
	//WriteChatColor(tempSetting);
	if (strcmp(tempSetting, "MQ2ChatEvents_Error") == 0) {
		WritePrivateProfileString(CESection, "PluginEnabled", "TRUE", INIFileName);
		sprintf_s(tempSetting, "TRUE");
	}
	if (!_strnicmp(tempSetting, "true", 4) || !_strnicmp(tempSetting, "on", 2) || !_strnicmp(tempSetting, "1", 1)) pluginEnabled = true;
	else pluginEnabled = false;
	if (!pluginEnabled) return;

	GetPrivateProfileString(CESection, "PopupsEnabled", "MQ2ChatEvents_Error", tempSetting, MAX_STRING, INIFileName);
	if (strcmp(tempSetting, "MQ2ChatEvents_Error") == 0) {
		WritePrivateProfileString(CESection, "PopupsEnabled", "TRUE", INIFileName);
		sprintf_s(tempSetting, "TRUE");
	}
	if (!_strnicmp(tempSetting, "true", 4) || !_strnicmp(tempSetting, "on", 2) || !_strnicmp(tempSetting, "1", 1)) popupsEnabled = true;
	else popupsEnabled = false;

	GetPrivateProfileString(CESection, "SoundsEnabled", "MQ2ChatEvents_Error", tempSetting, MAX_STRING, INIFileName);
	if (strcmp(tempSetting, "MQ2ChatEvents_Error") == 0) {
		WritePrivateProfileString(CESection, "SoundsEnabled", "TRUE", INIFileName);
		sprintf_s(tempSetting, "TRUE");
	}
	if (!_strnicmp(tempSetting, "true", 4) || !_strnicmp(tempSetting, "on", 2) || !_strnicmp(tempSetting, "1", 1)) soundsEnabled = true;
	else soundsEnabled = false;

	GetPrivateProfileString(CESection, "MissedChatEcho", "MQ2ChatEvents_Error", tempSetting, MAX_STRING, INIFileName);
	if (strcmp(tempSetting, "MQ2ChatEvents_Error") == 0) {
		WritePrivateProfileString(CESection, "MissedChatEcho", "FALSE", INIFileName);
		sprintf_s(tempSetting, "FALSE");
	}
	if (!_strnicmp(tempSetting, "true", 4) || !_strnicmp(tempSetting, "on", 2) || !_strnicmp(tempSetting, "1", 1)) missedChatEcho = true;
	else missedChatEcho = false;

	GetPrivateProfileString(CESection, "MissedChatPopup", "MQ2ChatEvents_Error", tempSetting, MAX_STRING, INIFileName);
	if (strcmp(tempSetting, "MQ2ChatEvents_Error") == 0) {
		WritePrivateProfileString(CESection, "MissedChatPopup", "FALSE", INIFileName);
		sprintf_s(tempSetting, "FALSE");
	}
	if (!_strnicmp(tempSetting, "true", 4) || !_strnicmp(tempSetting, "on", 2) || !_strnicmp(tempSetting, "1", 1)) missedChatPopup = true;
	else missedChatPopup = false;

	GetPrivateProfileString(CESection, "CommandsEnabled", "MQ2ChatEvents_Error", tempSetting, MAX_STRING, INIFileName);
	if (strcmp(tempSetting, "MQ2ChatEvents_Error") == 0) {
		WritePrivateProfileString(CESection, "CommandsEnabled", "TRUE", INIFileName);
		sprintf_s(tempSetting, "TRUE");
	}
	if (!_strnicmp(tempSetting, "true", 4) || !_strnicmp(tempSetting, "on", 2) || !_strnicmp(tempSetting, "1", 1)) commandsEnabled = true;
	else commandsEnabled = false;

	GetPrivateProfileString(CESection, "VerboseCommands", "MQ2ChatEvents_Error", tempSetting, MAX_STRING, INIFileName);
	if (strcmp(tempSetting, "MQ2ChatEvents_Error") == 0) {
		WritePrivateProfileString(CESection, "VerboseCommands", "FALSE", INIFileName);
		sprintf_s(tempSetting, "FALSE");
	}
	if (!_strnicmp(tempSetting, "true", 4) || !_strnicmp(tempSetting, "on", 2) || !_strnicmp(tempSetting, "1", 1)) verboseCommands = true;
	else verboseCommands = false;

	CHAR szAllKeys[MAX_KEYLINES][MAX_STRING] = { 0 };

	// Get event keys : EventKeys=
	GetPrivateProfileString(CESection, "EventKeys", "MQ2ChatEvents_Error", szAllKeys[0], MAX_STRING, INIFileName);
	if (strcmp(szAllKeys[0], "MQ2ChatEvents_Error") == 0) {
		WritePrivateProfileString(CESection, "EventKeys", "test123|", INIFileName);
	}
	AddEvents(szAllKeys[0]);

	// Add event keys : EventKeys#=
	char tmpEventKeysLine[MAX_STRING];
	char tmpEventKeysKey[MAX_STRING];
	for (int i = 0; i < MAX_KEYLINES; i++) {
		sprintf_s(tmpEventKeysKey, "EventKeys%d", i);
		GetPrivateProfileString(CESection, tmpEventKeysKey, "MQ2ChatEvents_Error", tmpEventKeysLine, MAX_STRING, INIFileName);
		//DebugSpewAlways("\tReading INI: [%s]=%s", tmpEventKeysKey, tmpEventKeysLine);
		if (strcmp(tmpEventKeysLine, "MQ2ChatEvents_Error") == 0) continue;
		strcpy_s(szAllKeys, tmpEventKeysLine);
		//DebugSpewAlways("\tAdding Valid EventKeys String: [%s]=%s", tmpEventKeysKey, tmpEventKeysLine);
	}

	for (int keyIndex = 0; keyIndex < MAX_KEYLINES; keyIndex++) {
		AddEvents(szAllKeys[keyIndex]);
	}

	// Validate events
	/*
	for( unsigned int eventIndex = 0; eventIndex < eventVector.size(); eventIndex++ ) {
	DebugSpewAlways("Event: %s", eventVector[eventIndex].key );
	for( int matchStringIndex = 0; matchStringIndex < eventVector[eventIndex].matchCount; matchStringIndex++ ){
	DebugSpewAlways("[%s]MatchString%d=%s", eventVector[eventIndex].key, matchStringIndex, eventVector[eventIndex].matchStrings[matchStringIndex] );
	}
	//for( int matchColorIndex = 0; matchColorIndex < eventVector[eventIndex].matchColorCount; matchColorIndex++ ){
	//   DebugSpewAlways("[%s]MatchColor%d=%d", eventVector[eventIndex].key, matchColorIndex, eventVector[eventIndex].matchColors[matchColorIndex] );
	//}
	for( int cmdIndex = 0; cmdIndex < eventVector[eventIndex].commandCount; cmdIndex++ ){
	DebugSpewAlways("[%s]Command%d=%s", eventVector[eventIndex].key, cmdIndex, eventVector[eventIndex].command[cmdIndex] );
	}
	DebugSpewAlways("[%s]SoundFile=%s", eventVector[eventIndex].key, eventVector[eventIndex].soundFile );
	DebugSpewAlways("[%s]PopupText=%s", eventVector[eventIndex].key, eventVector[eventIndex].popupText );
	//DebugSpewAlways("[%s]PopupColor=%d", eventVector[eventIndex].key, eventVector[eventIndex].popupColor );
	DebugSpewAlways("[%s]PopupDuration=%d", eventVector[eventIndex].key, eventVector[eventIndex].popupDuration );
	DebugSpewAlways("[%s]CommandCount=%d", eventVector[eventIndex].key, eventVector[eventIndex].commandCount );
	DebugSpewAlways("[%s]MatchCount=%d", eventVector[eventIndex].key, eventVector[eventIndex].matchCount );
	DebugSpewAlways("[%s]matchColorCount=%d", eventVector[eventIndex].key, eventVector[eventIndex].matchColorCount );
	}
	*/
}

void AddEvents(char KeyLine[MAX_STRING])
{
	string strAllKeys(KeyLine);
	string::size_type pos = strAllKeys.find("|", 0);
	while (pos != string::npos)
	{
		if (strlen(strAllKeys.substr(0, pos).c_str()) == 0) {
			// Erase key from AllKeys variable (so we process the next one on next loop)
			strAllKeys.erase(0, pos + 1);
			pos = strAllKeys.find("|");
			continue;
		}

		//Create new event structure
		ChatEvent *newEvent = new ChatEvent;
		//Add event name to events structure
		sprintf_s(newEvent->key, "%s", strAllKeys.substr(0, pos).c_str());

		// Get event match strings from INI
		char tmpMatchString[MAX_STRING];
		char tmpMatchStringKey[MAX_STRING];
		newEvent->matchCount = 0;
		for (int i = 0; i < MATCHABLE_STRINGS; i++) {
			sprintf_s(tmpMatchStringKey, "MatchString%d", i);
			GetPrivateProfileString(newEvent->key, tmpMatchStringKey, "MQ2ChatEvents_Error", tmpMatchString, MAX_STRING, INIFileName);
			//DebugSpewAlways( "\tReading INI: [%s]matchString[%d]=%s", newEvent->key, i, tmpMatchString );
			if (strcmp(tmpMatchString, "MQ2ChatEvents_Error") == 0) continue;
			strcpy_s(newEvent->matchStrings[newEvent->matchCount], tmpMatchString);
			//DebugSpewAlways("\tAdding Valid Match String: [%d] = %s", newEvent->matchCount, newEvent->matchStrings[newEvent->matchCount] );
			newEvent->matchCount++;
		}

		// Get matchColors from INI
		char tmpMatchColor[MAX_STRING];
		char tmpMatchColorKey[MAX_STRING];
		newEvent->matchColorCount = 0;
		for (int i = 0; i < MATCHABLE_COLORS; i++) {
			sprintf_s(tmpMatchColorKey, "MatchColor%d", i);
			GetPrivateProfileString(newEvent->key, tmpMatchColorKey, "MQ2ChatEvents_Error", tmpMatchColor, MAX_STRING, INIFileName);
			//DebugSpewAlways( "\tReading INI: [%s]matchColor[%d]=%s", newEvent->key, i, tmpMatchColor );
			if (strcmp(tmpMatchColor, "MQ2ChatEvents_Error") == 0) continue;
			strcpy_s(newEvent->matchColors[newEvent->matchColorCount], tmpMatchColor);
			//DebugSpewAlways("\tAdding Valid Match Color: [%d] = %s", newEvent->matchColorCount, newEvent->matchColors[newEvent->matchColorCount] );
			newEvent->matchColorCount++;
		}

		// Get sound file from INI
		GetPrivateProfileString(newEvent->key, "SoundFile", "MQ2ChatEvents_Error", newEvent->soundFile, MAX_STRING, INIFileName);
		if (strlen(newEvent->soundFile) == 0) strcpy_s(newEvent->soundFile, "MQ2ChatEvents_Error");

		// Get popup message from INI
		GetPrivateProfileString(newEvent->key, "PopupText", "MQ2ChatEvents_Error", newEvent->popupText, MAX_STRING, INIFileName);
		if (strlen(newEvent->popupText) == 0) strcpy_s(newEvent->popupText, "MQ2ChatEvents_Error");

		// Get popup text color from INI
		CHAR szPopupColor[MAX_STRING] = { 0 };
		GetPrivateProfileString(newEvent->key, "PopupColor", "CONCOLOR_YELLOW", newEvent->popupColor, MAX_STRING, INIFileName);
		if (strlen(newEvent->popupColor) == 0) strcpy_s(newEvent->popupColor, "CONCOLOR_YELLOW");

		// Get popup display duration from INI
		GetPrivateProfileString(newEvent->key, "PopupDuration", "3000", newEvent->popupDuration, MAX_STRING, INIFileName);
		if (strlen(newEvent->popupDuration) == 0) strcpy_s(newEvent->popupDuration, "3000");

		// Get commands from INI
		char tmpCommandKey[MAX_STRING];
		char tmpCommandString[MAX_STRING];
		newEvent->commandCount = 0;   // Used as both a count and an index for commands found      
		for (int i = 0; i < MAX_COMMANDS; i++) {
			sprintf_s(tmpCommandKey, "Command%d", i);
			GetPrivateProfileString(newEvent->key, tmpCommandKey, "MQ2ChatEvents_Error", tmpCommandString, MAX_STRING, INIFileName);
			//DebugSpewAlways( "\tReading INI: [%s]command[%d]=%s", newEvent->key, i, tmpCommandString );
			if (strcmp(tmpCommandString, "MQ2ChatEvents_Error") == 0) continue;
			strcpy_s(newEvent->command[newEvent->commandCount], tmpCommandString);
			//DebugSpewAlways("\tAdding Valid Command: [%d] = %s", newEvent->commandCount, newEvent->command[newEvent->commandCount] );
			newEvent->commandCount++;
		}

		// Add the event to the vector 
		eventVector.push_back(*newEvent);
		delete newEvent;

		// Erase current key from AllKeys variable (so we process the next one on next loop)
		strAllKeys.erase(0, pos + 1);
		pos = strAllKeys.find("|");
	}
}
// Cycle through events looking for a string (and color) match
// Returns the index of the event where the match is found
// Returns -1 if no match found
int FindMatch(PCHAR Line, DWORD Color){
	string strLine(Line);
	string::size_type pos;
	bool skip = false;
	bool matchFound = false;
	bool NoColorCheck = false;
	char expandedString[MAX_STRING] = { 0 };

	//DebugSpewAlways("Entering FindMatch: %s", Line );
	if (Color == NULL) NoColorCheck = true;

	for (unsigned int eventIndex = 0; eventIndex < eventVector.size(); eventIndex++)
	{
		//for each MatchString# entry in the event   
		for (int matchStringIndex = 0; matchStringIndex < eventVector[eventIndex].matchCount; matchStringIndex++){
			//DebugSpewAlways("\t\tMQ2ChatEvents Inside for matchStringIndex = 0; %d < eventVector[eventIndex].matchCount (%d); matchStringIndex++ ", matchStringIndex, eventVector[eventIndex].matchCount);
			//DebugSpewAlways("Comparing strings: %s  <==>  %s", Line, eventVector[eventIndex].matchStrings[matchStringIndex]);

			strcpy_s(expandedString, eventVector[eventIndex].matchStrings[matchStringIndex]);
			// Expand any variables in the match string         
			ParseMacroData(expandedString);

			pos = strLine.find(expandedString, 0);
			if (pos != string::npos){
				//DebugSpewAlways("\tFound Match, checking color");            
				//string match found, scan for matched colors if specified

				//DebugSpewAlways("Color is null: %s",(NoColorCheck)?"true":"false");
				// If no color check, successful match
				if (NoColorCheck) return eventIndex;

				//If no colors specified, successful match for all colors
				if (eventVector[eventIndex].matchColorCount == 0) return eventIndex;

				// for each MatchColor# entry in the event
				for (int matchColorIndex = 0; matchColorIndex < eventVector[eventIndex].matchColorCount; matchColorIndex++){
					//DebugSpewAlways("\t\t\tMQ2ChatEvents Inside for matchColorIndex = 0; %d < eventVector[eventIndex].matchColorCount (%d); matchColorIndex++", matchColorIndex, eventVector[eventIndex].matchColorCount);
					//DebugSpewAlways("\tComparing colors: Index %d ", matchColorIndex );
					if (Color == TextToColor(eventVector[eventIndex].matchColors[matchColorIndex])){
						// Color specified and found, match successful
						//DebugSpewAlways("\tColor specified and found, match successful");
						return eventIndex;
					}
				}
			}
		}
	}
	// No match found
	//DebugSpewAlways("Leaving FindMatch, no match found for %s", Line);
	return -1;
}

void ProcessPopups(PCHAR Line, unsigned int i)
{
	DWORD popupColor = 0;
	DWORD popupTransparency = 100;
	DWORD popupFadeIn = 500;
	DWORD popupFadeOut = 500;
	DWORD popupHold = 3000;
	string::size_type pos;
	char popupText[MAX_STRING];

	if (popupsEnabled && strcmp(eventVector.popupText, "MQ2ChatEvents_Error") != 0){
		popupColor = TextToColor(eventVector.popupColor);
		popupHold = (DWORD)atoi(eventVector.popupDuration); //convert string to int, cast as dword

		// Replace placeholder #FULLTEXT# with the entire line that was matched
		string popupString(eventVector.popupText);
		pos = popupString.find("#FULLTEXT#");
		if (pos != string::npos) {
			//found a match on FULLTEXT
			popupString.replace(pos, strlen("#FULLTEXT#"), Line);
		}
		sprintf_s(popupText, "%s", popupString.c_str());

		DisplayOverlayText(popupText, popupColor, popupTransparency, popupFadeIn, popupFadeOut, popupHold);
	}
}

void ProcessSounds(unsigned int i)
{
	if (soundsEnabled && strcmp(eventVector.soundFile, "MQ2ChatEvents_Error") != 0){
		CHAR szTemp[MAX_STRING] = { 0 };
		sprintf_s(szTemp, "%s\\%s", gszINIPath, eventVector.soundFile);
		PlaySound(szTemp, NULL, SND_FILENAME | SND_ASYNC);
	}
}

void ProcessCommands(PCHAR Line, unsigned int eventIndex, unsigned int commandIndex)
{
	CHAR commandText[MAX_STRING];
	string::size_type pos;
	string strLine(Line);

	//DebugSpewAlways("Entering ProcessCommands = Line:%s |eventIndex:%d |commandIndex:%d |processFlag:%s |command:%s", Line, eventIndex, commandIndex, (processFlag)?"true":"false", eventVector[eventIndex].command[commandIndex] );
	//DebugSpewAlways("\tCommand %d : %s", commandIndex, eventVector[eventIndex].command[commandIndex] );
	if (!commandsEnabled) return;

	strcpy_s(commandText, eventVector[eventIndex].command[commandIndex]);

	// Replace placeholder #FULLTEXT# with the entire line that was matched
	string commandString(commandText);
	pos = commandString.find("#FULLTEXT#");
	if (pos != string::npos) {
		//found a match on FULLTEXT
		commandString.replace(pos, strlen("#FULLTEXT#"), strLine);
	}
	sprintf_s(commandText, "%s", commandString.c_str());

	if (strcmp(commandText, "MQ2ChatEvents_Error") != 0){
		commandQueue.push(commandText);
	}
	//DebugSpewAlways("Leaving ProcessCommands = Line:%s |eventIndex:%d |commandIndex:%d |processFlag:%s |command:%s", Line, eventIndex, commandIndex, (processFlag)?"true":"false", eventVector[eventIndex].command[commandIndex] );
	return;
}

PLUGIN_API DWORD OnWriteChatColor(PCHAR Line, DWORD Color, DWORD Filter)
{
	//DebugSpewAlways("Entering OnWriteChatColor: Line:%s |processFlag:%s", Line, (processFlag)?"true":"false" );
	if (processFlag && pluginEnabled) HandleChat(Line, Color);
	return 0;
}
PLUGIN_API DWORD OnIncomingChat(PCHAR Line, DWORD Color)
{
	//DebugSpewAlways("Entering OnIncomingChat: Line:%s |processFlag:%s", Line, (processFlag)?"true":"false" );
	if (processFlag && pluginEnabled) HandleChat(Line, Color);
	return 0;
}

void CheckMissedChat(PCHAR Line, DWORD Color){
	// Check if you received any tells or group chat while zoning
	string strLine(Line);
	string::size_type pos;

	//DebugSpewAlways("gbInZone: %s  --- missedChatEcho: %s --- %s", (gbInZone)?"true":"false", (missedChatEcho)?"true":"false", Line );
	if (!gbInZone && missedChatEcho) {
		pos = strLine.find(" tells ", 0);
		if (pos != string::npos) {
			processFlag = false;
			DebugSpewAlways("Missed chat: %s", Line);
			WriteChatColor(Line, Color);
			processFlag = true;
			tellFlag = true;
		}
		pos = strLine.find(" told ", 0);
		if (pos != string::npos) {
			processFlag = false;
			DebugSpewAlways("Missed chat: %s", Line);
			WriteChatColor(Line, Color);
			processFlag = true;
			tellFlag = true;
		}
	}

	if (tellFlag && missedChatPopup) {
		DisplayOverlayText("You missed some chat while zoning!  Check MQ window.",
			CONCOLOR_YELLOW, 100, 500, 500, 10000);
		tellFlag = false;
	}
}

void HandleChat(PCHAR Line, DWORD Color){
	/* ****************************************************************************************
	Be very careful writing anything to the EQ or MQ chat windows inside this function!
	It can create an infinite recursive loop by re-calling HandleChat for any line that is written!
	**************************************************************************************** */
	//DebugSpewAlways("MQ2ChatEvents entering HandleChat (proccessFlag=%s) = %s", (processFlag)?"true":"false", Line);   
	int eventIndex = -1;   // Index of the event vector where the match was found

	if (!pluginEnabled || !processFlag) return;

	CheckMissedChat(Line, Color);
	// Cycle through events looking for a match.  If match is found, that event's index is returned
	eventIndex = FindMatch(Line, Color);
	if (eventIndex < 0 || eventIndex >= (int)eventVector.size()) return;
	//DebugSpewAlways("\tHandleChat Match Found [%s]: Index=%d", eventVector[eventIndex].key, matchFound );

	// Found a matching chat line.  Now process all defined events for that match
	ProcessPopups(Line, eventIndex);
	ProcessSounds(eventIndex);

	for (int cmdIndex = 0; cmdIndex < eventVector[eventIndex].commandCount; cmdIndex++){
		//DebugSpewAlways("\t\tMQ2ChatEvents Inside for cmdIndex = 0; %d < eventVector[eventIndex].commandCount %d; cmdIndex++", cmdIndex, eventVector[eventIndex].commandCount );
		//DebugSpewAlways("\t\tLine:%s |eventIndex:%d |cmdIndex:%d", Line, eventIndex, cmdIndex);
		ProcessCommands(Line, eventIndex, cmdIndex);
	}

	//DebugSpewAlways("MQ2ChatEvents exiting HandleChat");
	return;
}

// Handle commands passed through /ce
void ChatEventsCmd(PSPAWNINFO pChar, PCHAR szLine)
{
	char Arg[MAX_STRING];
	CHAR tempString[MAX_STRING];

	GetArg(Arg, szLine, 1);

	if (!strlen(Arg) ||
		!_strnicmp(Arg, "help", strlen(Arg)) ||
		!_strnicmp(Arg, "?", strlen(Arg))){
		ChatEventsHelp();
		return;
	}
	if (!_strnicmp(Arg, "sound", strlen(Arg)) ||
		!_strnicmp(Arg, "sounds", strlen(Arg)) ||
		!_strnicmp(Arg, "togglesound", strlen(Arg)) ||
		!_strnicmp(Arg, "togglesounds", strlen(Arg))){
		ToggleOption("SoundsEnabled", &soundsEnabled);
		return;
	}
	if (!_strnicmp(Arg, "popup", strlen(Arg)) ||
		!_strnicmp(Arg, "popups", strlen(Arg)) ||
		!_strnicmp(Arg, "togglepopup", strlen(Arg)) ||
		!_strnicmp(Arg, "togglepopups", strlen(Arg))){
		ToggleOption("PopupsEnabled", &popupsEnabled);
		return;
	}
	if (!_strnicmp(Arg, "missedchat", strlen(Arg)) ||
		!_strnicmp(Arg, "missedchatecho", strlen(Arg)) ||
		!_strnicmp(Arg, "togglemissedchat", strlen(Arg)) ||
		!_strnicmp(Arg, "togglemissedchatecho", strlen(Arg))){
		ToggleOption("MissedChatEcho", &missedChatEcho);
		return;
	}
	if (!_strnicmp(Arg, "missedchatpopup", strlen(Arg)) ||
		!_strnicmp(Arg, "togglemissedchatpopup", strlen(Arg))){
		ToggleOption("MissedChatPopup", &missedChatPopup);
		return;
	}
	if (!_strnicmp(Arg, "command", strlen(Arg)) ||
		!_strnicmp(Arg, "commands", strlen(Arg)) ||
		!_strnicmp(Arg, "togglecommand", strlen(Arg)) ||
		!_strnicmp(Arg, "togglecommands", strlen(Arg))){
		ToggleOption("CommandsEnabled", &commandsEnabled);
		return;
	}
	if (!_strnicmp(Arg, "verbose", strlen(Arg)) ||
		!_strnicmp(Arg, "verbosecommands", strlen(Arg)) ||
		!_strnicmp(Arg, "toggleverbose", strlen(Arg)) ||
		!_strnicmp(Arg, "togglerverbosecommands", strlen(Arg))){
		ToggleOption("VerboseCommands", &verboseCommands);
		return;
	}
	if (!_strnicmp(Arg, "on", strlen(Arg))){
		WritePrivateProfileString(CESection, "PluginEnabled", "TRUE", INIFileName);
		pluginEnabled = true;
		string enabledTxt = GetOnOffLabel(pluginEnabled);
		sprintf_s(tempString, "ChatEvents: Plugin = %s", enabledTxt.c_str());
		WriteChatColor(tempString);
		InitEvents();
		return;
	}
	if (!_strnicmp(Arg, "off", strlen(Arg))){
		WritePrivateProfileString(CESection, "PluginEnabled", "FALSE", INIFileName);
		pluginEnabled = false;
		string enabledTxt = GetOnOffLabel(pluginEnabled);
		sprintf_s(tempString, "ChatEvents: Plugin = %s", enabledTxt.c_str());
		WriteChatColor(tempString);
		return;
	}
	if (!_strnicmp(Arg, "reload", strlen(Arg)) ||
		!_strnicmp(Arg, "reloadini", strlen(Arg))){
		InitEvents();
		WriteChatColor("ChatEvents INI reloaded");
		return;
	}
	else {
		ChatEventsHelp();
		return;
	}

}
void ToggleOption(char optionName[MAX_STRING], bool *optionVal)
{
	CHAR tempString[MAX_STRING];

	*optionVal = !(*optionVal);
	if (*optionVal) sprintf_s(tempString, "TRUE");
	else sprintf_s(tempString, "FALSE");
	WritePrivateProfileString(CESection, optionName, tempString, INIFileName);

	string enabledTxt = GetOnOffLabel(*optionVal);
	sprintf_s(tempString, "ChatEvents: %s = %s", optionName, enabledTxt.c_str());
	WriteChatColor(tempString);

	InitEvents();
}

void ChatEventsHelp()
{
	char szTemp[MAX_STRING];
	string tempStr;

	WriteChatColor(" --------------------------------", CONCOLOR_LIGHTBLUE);
	WriteChatColor("MQ2ChatEvents    ", CONCOLOR_LIGHTBLUE);
	WriteChatColor(" --------------------------------", CONCOLOR_LIGHTBLUE);
	tempStr = GetOnOffLabel(pluginEnabled);
	sprintf_s(szTemp, "[%s] Plugin", tempStr.c_str());
	WriteChatColor(szTemp);
	tempStr = GetOnOffLabel(popupsEnabled);
	sprintf_s(szTemp, "[%s] Popups", tempStr.c_str());
	WriteChatColor(szTemp);
	tempStr = GetOnOffLabel(soundsEnabled);
	sprintf_s(szTemp, "[%s] Sounds", tempStr.c_str());
	WriteChatColor(szTemp);
	tempStr = GetOnOffLabel(missedChatPopup);
	sprintf_s(szTemp, "[%s] MissedChatPopup", tempStr.c_str());
	WriteChatColor(szTemp);
	tempStr = GetOnOffLabel(missedChatEcho);
	sprintf_s(szTemp, "[%s] MissedChatEcho", tempStr.c_str());
	WriteChatColor(szTemp);
	tempStr = GetOnOffLabel(commandsEnabled);
	sprintf_s(szTemp, "[%s] Commands", tempStr.c_str());
	WriteChatColor(szTemp);
	tempStr = GetOnOffLabel(verboseCommands);
	sprintf_s(szTemp, "[%s] Verbose Commands", tempStr.c_str());
	WriteChatColor(szTemp);
	WriteChatColor(" --------------------------------", CONCOLOR_LIGHTBLUE);
	SyntaxError("Usage: /ce <Sound|Popup|MissedChat|MissedChatEcho|Commands|verbose|on|off|reload>");
}

string GetOnOffLabel(bool val)
{
	string s;

	if (val) s = "\agON\ax";
	else s = "\auOFF\ax";

	return s;
}


DWORD TextToColor(char colorText[MAX_STRING])
{
	if (!strcmp(colorText, "COLOR_DEFAULT"))                  return COLOR_DEFAULT;
	if (!strcmp(colorText, "COLOR_DARKGREY"))                 return COLOR_DARKGREY;
	if (!strcmp(colorText, "COLOR_DARKGREEN"))                return COLOR_DARKGREEN;
	if (!strcmp(colorText, "COLOR_DARKBLUE"))                 return COLOR_DARKBLUE;
	if (!strcmp(colorText, "COLOR_PURPLE"))                   return COLOR_PURPLE;
	if (!strcmp(colorText, "COLOR_LIGHTGREY"))                return COLOR_LIGHTGREY;

	if (!strcmp(colorText, "CONCOLOR_GREEN"))                 return CONCOLOR_GREEN;
	if (!strcmp(colorText, "CONCOLOR_LIGHTBLUE"))             return CONCOLOR_LIGHTBLUE;
	if (!strcmp(colorText, "CONCOLOR_BLUE"))                  return CONCOLOR_BLUE;
	if (!strcmp(colorText, "CONCOLOR_BLACK"))                 return CONCOLOR_BLACK;
	if (!strcmp(colorText, "CONCOLOR_YELLOW"))                return CONCOLOR_YELLOW;
	if (!strcmp(colorText, "CONCOLOR_RED"))                   return CONCOLOR_RED;

	if (!strcmp(colorText, "USERCOLOR_SAY"))                  return USERCOLOR_SAY;               //  1  - Say
	if (!strcmp(colorText, "USERCOLOR_TELL"))                 return USERCOLOR_TELL;               //  2  - Tell
	if (!strcmp(colorText, "USERCOLOR_GROUP"))                return USERCOLOR_GROUP;               //  3  - Group
	if (!strcmp(colorText, "USERCOLOR_GUILD"))                return USERCOLOR_GUILD;               //  4  - Guild
	if (!strcmp(colorText, "USERCOLOR_OOC"))                  return USERCOLOR_OOC;               //  5  - OOC
	if (!strcmp(colorText, "USERCOLOR_AUCTION"))              return USERCOLOR_AUCTION;            //  6  - Auction
	if (!strcmp(colorText, "USERCOLOR_SHOUT"))                return USERCOLOR_SHOUT;               //  7  - Shout
	if (!strcmp(colorText, "USERCOLOR_EMOTE"))                return USERCOLOR_EMOTE;               //  8  - Emote
	if (!strcmp(colorText, "USERCOLOR_SPELLS"))               return USERCOLOR_SPELLS;            //  9  - Spells (meming, scribing, casting, etc.)
	if (!strcmp(colorText, "USERCOLOR_YOU_HIT_OTHER"))        return USERCOLOR_YOU_HIT_OTHER;         //  10 - You hit other
	if (!strcmp(colorText, "USERCOLOR_OTHER_HIT_YOU"))        return USERCOLOR_OTHER_HIT_YOU;         //  11 - Other hits you
	if (!strcmp(colorText, "USERCOLOR_YOU_MISS_OTHER"))       return USERCOLOR_YOU_MISS_OTHER;      //  12 - You miss other
	if (!strcmp(colorText, "USERCOLOR_OTHER_MISS_YOU"))       return USERCOLOR_OTHER_MISS_YOU;      //  13 - Other misses you
	if (!strcmp(colorText, "USERCOLOR_DUELS"))                return USERCOLOR_DUELS;               //  14 - Some broadcasts (duels)
	if (!strcmp(colorText, "USERCOLOR_SKILLS"))               return USERCOLOR_SKILLS;            //  15 - Skills (ups, non-combat use, etc.)
	if (!strcmp(colorText, "USERCOLOR_DISCIPLINES"))          return USERCOLOR_DISCIPLINES;         //  16 - Disciplines or special abilities
	if (!strcmp(colorText, "USERCOLOR_UNUSED001"))            return USERCOLOR_UNUSED001;            //  17 - Unused at this time
	if (!strcmp(colorText, "USERCOLOR_DEFAULT"))              return USERCOLOR_DEFAULT;            //  18 - Default text and stuff you type
	if (!strcmp(colorText, "USERCOLOR_UNUSED002"))            return USERCOLOR_UNUSED002;            //  19 - Unused at this time
	if (!strcmp(colorText, "USERCOLOR_MERCHANT_OFFER"))       return USERCOLOR_MERCHANT_OFFER;      //  20 - Merchant Offer Price
	if (!strcmp(colorText, "USERCOLOR_MERCHANT_EXCHANGE"))    return USERCOLOR_MERCHANT_EXCHANGE;      //  21 - Merchant Buy/Sell
	if (!strcmp(colorText, "USERCOLOR_YOUR_DEATH"))           return USERCOLOR_YOUR_DEATH;         //  22 - Your death message
	if (!strcmp(colorText, "USERCOLOR_OTHER_DEATH"))          return USERCOLOR_OTHER_DEATH;         //  23 - Others death message
	if (!strcmp(colorText, "USERCOLOR_OTHER_HIT_OTHER"))      return USERCOLOR_OTHER_HIT_OTHER;      //  24 - Other damage other
	if (!strcmp(colorText, "USERCOLOR_OTHER_MISS_OTHER"))     return USERCOLOR_OTHER_MISS_OTHER;      //  25 - Other miss other
	if (!strcmp(colorText, "USERCOLOR_WHO"))                  return USERCOLOR_WHO;               //  26 - /who command
	if (!strcmp(colorText, "USERCOLOR_YELL"))                 return USERCOLOR_YELL;               //  27 - yell for help
	if (!strcmp(colorText, "USERCOLOR_NON_MELEE"))            return USERCOLOR_NON_MELEE;            //  28 - Hit for non-melee
	if (!strcmp(colorText, "USERCOLOR_SPELL_WORN_OFF"))       return USERCOLOR_SPELL_WORN_OFF;      //  29 - Spell worn off
	if (!strcmp(colorText, "USERCOLOR_MONEY_SPLIT"))          return USERCOLOR_MONEY_SPLIT;         //  30 - Money splits
	if (!strcmp(colorText, "USERCOLOR_LOOT"))                 return USERCOLOR_LOOT;               //  31 - Loot message
	if (!strcmp(colorText, "USERCOLOR_RANDOM"))               return USERCOLOR_RANDOM;            //  32 - Dice Roll (/random)
	if (!strcmp(colorText, "USERCOLOR_OTHERS_SPELLS"))        return USERCOLOR_OTHERS_SPELLS;         //  33 - Others spells
	if (!strcmp(colorText, "USERCOLOR_SPELL_FAILURE"))        return USERCOLOR_SPELL_FAILURE;         //  34 - Spell Failures (resists, fizzles, missing component, bad target, etc.)
	if (!strcmp(colorText, "USERCOLOR_CHAT_CHANNEL"))         return USERCOLOR_CHAT_CHANNEL;         //  35 - Chat Channel Messages
	if (!strcmp(colorText, "USERCOLOR_CHAT_1"))               return USERCOLOR_CHAT_1;;            //  36 - Chat Channel 1
	if (!strcmp(colorText, "USERCOLOR_CHAT_2"))               return USERCOLOR_CHAT_2;            //  37 - Chat Channel 2
	if (!strcmp(colorText, "USERCOLOR_CHAT_3"))               return USERCOLOR_CHAT_3;            //  38 - Chat Channel 3
	if (!strcmp(colorText, "USERCOLOR_CHAT_4"))               return USERCOLOR_CHAT_4;            //  39 - Chat Channel 4
	if (!strcmp(colorText, "USERCOLOR_CHAT_5"))               return USERCOLOR_CHAT_5;            //  40 - Chat Channel 5
	if (!strcmp(colorText, "USERCOLOR_CHAT_6"))               return USERCOLOR_CHAT_6;            //  41 - Chat Channel 6
	if (!strcmp(colorText, "USERCOLOR_CHAT_7"))               return USERCOLOR_CHAT_7;            //  42 - Chat Channel 7
	if (!strcmp(colorText, "USERCOLOR_CHAT_8"))               return USERCOLOR_CHAT_8;            //  43 - Chat Channel 8
	if (!strcmp(colorText, "USERCOLOR_CHAT_9"))               return USERCOLOR_CHAT_9;            //  44 - Chat Channel 9
	if (!strcmp(colorText, "USERCOLOR_CHAT_10"))              return USERCOLOR_CHAT_10;            //  45 - Chat Channel 10
	if (!strcmp(colorText, "USERCOLOR_MELEE_CRIT"))           return USERCOLOR_MELEE_CRIT;         //  46 - Melee Crits
	if (!strcmp(colorText, "USERCOLOR_SPELL_CRIT"))           return USERCOLOR_SPELL_CRIT;         //  47 - Spell Crits
	if (!strcmp(colorText, "USERCOLOR_TOO_FAR_AWAY"))         return USERCOLOR_TOO_FAR_AWAY;         //  48 - Too far away (melee)
	if (!strcmp(colorText, "USERCOLOR_NPC_RAMPAGE"))          return USERCOLOR_NPC_RAMPAGE;         //  49 - NPC Rampage
	if (!strcmp(colorText, "USERCOLOR_NPC_FLURRY"))           return USERCOLOR_NPC_FLURRY;         //  50 - NPC Furry
	if (!strcmp(colorText, "USERCOLOR_NPC_ENRAGE"))           return USERCOLOR_NPC_ENRAGE;         //  51 - NPC Enrage
	if (!strcmp(colorText, "USERCOLOR_ECHO_SAY"))             return USERCOLOR_ECHO_SAY;            //  52 - say echo
	if (!strcmp(colorText, "USERCOLOR_ECHO_TELL"))            return USERCOLOR_ECHO_TELL;            //  53 - tell echo
	if (!strcmp(colorText, "USERCOLOR_ECHO_GROUP"))           return USERCOLOR_ECHO_GROUP;         //  54 - group echo
	if (!strcmp(colorText, "USERCOLOR_ECHO_GUILD"))           return USERCOLOR_ECHO_GUILD;         //  55 - guild echo
	if (!strcmp(colorText, "USERCOLOR_ECHO_OOC"))             return USERCOLOR_ECHO_OOC;            //  56 - group echo
	if (!strcmp(colorText, "USERCOLOR_ECHO_AUCTION"))         return USERCOLOR_ECHO_AUCTION;         //  57 - auction echo
	if (!strcmp(colorText, "USERCOLOR_ECHO_SHOUT"))           return USERCOLOR_ECHO_SHOUT;         //  58 - shout echo
	if (!strcmp(colorText, "USERCOLOR_ECHO_EMOTE"))           return USERCOLOR_ECHO_EMOTE;         //  59 - emote echo
	if (!strcmp(colorText, "USERCOLOR_ECHO_CHAT_1"))          return USERCOLOR_ECHO_CHAT_1;         //  60 - chat 1 echo
	if (!strcmp(colorText, "USERCOLOR_ECHO_CHAT_2"))          return USERCOLOR_ECHO_CHAT_2;         //  61 - chat 2 echo
	if (!strcmp(colorText, "USERCOLOR_ECHO_CHAT_3"))          return USERCOLOR_ECHO_CHAT_3;         //  62 - chat 3 echo
	if (!strcmp(colorText, "USERCOLOR_ECHO_CHAT_4"))          return USERCOLOR_ECHO_CHAT_4;         //  63 - chat 4 echo
	if (!strcmp(colorText, "USERCOLOR_ECHO_CHAT_5"))          return USERCOLOR_ECHO_CHAT_5;         //  64 - chat 5 echo
	if (!strcmp(colorText, "USERCOLOR_ECHO_CHAT_6"))          return USERCOLOR_ECHO_CHAT_6;         //  65 - chat 6 echo
	if (!strcmp(colorText, "USERCOLOR_ECHO_CHAT_7"))          return USERCOLOR_ECHO_CHAT_7;         //  66 - chat 7 echo
	if (!strcmp(colorText, "USERCOLOR_ECHO_CHAT_8"))          return USERCOLOR_ECHO_CHAT_8;         //  67 - chat 8 echo
	if (!strcmp(colorText, "USERCOLOR_ECHO_CHAT_9"))          return USERCOLOR_ECHO_CHAT_9;         //  68 - chat 9 echo
	if (!strcmp(colorText, "USERCOLOR_ECHO_CHAT_10"))         return USERCOLOR_ECHO_CHAT_10;         //  69 - chat 10 echo
	if (!strcmp(colorText, "USERCOLOR_RESERVED"))             return USERCOLOR_RESERVED;            //  70 - "unused at this time" ))
	if (!strcmp(colorText, "USERCOLOR_LINK"))                 return USERCOLOR_LINK;               //  71 - item links 
	if (!strcmp(colorText, "USERCOLOR_RAID"))                 return USERCOLOR_RAID;               //  72 - raid 
	if (!strcmp(colorText, "USERCOLOR_PET"))                  return USERCOLOR_PET;               //  73 - my pet 
	if (!strcmp(colorText, "USERCOLOR_DAMAGESHIELD"))         return USERCOLOR_DAMAGESHIELD;         //  74 - damage shields 
	if (!strcmp(colorText, "USERCOLOR_LEADER"))               return USERCOLOR_LEADER;            //  75 - LAA-related messages 
	if (!strcmp(colorText, "USERCOLOR_PETRAMPFLURRY"))        return USERCOLOR_PETRAMPFLURRY;         //  76 - pet rampage/flurry 
	if (!strcmp(colorText, "USERCOLOR_PETCRITS"))             return USERCOLOR_PETCRITS;            //  77 - pet's critical hits 
	if (!strcmp(colorText, "USERCOLOR_FOCUS"))                return USERCOLOR_FOCUS;               //  78 - focus item activation 
	if (!strcmp(colorText, "USERCOLOR_XP"))                   return USERCOLOR_XP;               //  79 - xp gain/loss 
	if (!strcmp(colorText, "USERCOLOR_SYSTEM"))               return USERCOLOR_SYSTEM;            //  80 - system broadcasts etc 
	return 0;
}
// PlaySound - plays sound events when using the /playsound command
// Inspired by the MQ2PlaySound plug-in by Digitalxero
void PlaySoundCmd(PSPAWNINFO pChar, PCHAR szLine)
{
	CHAR Arg[MAX_STRING] = { 0 };
	CHAR szSoundFile[MAX_STRING] = { 0 };
	bool matchFound = false;
	unsigned int i = 0;

	// Get sound file from INI
	GetArg(Arg, szLine, 1);
	if (!stricmp(Arg, "stop")) {
		PlaySound(NULL, NULL, SND_ASYNC);
		return;
	}
	// Get sound file from INI
	GetArg(Arg, szLine, 1);
	for (i = 0; i < eventVector.size(); i++){
		if (!_strnicmp(Arg, eventVector.key, strlen(Arg))){
			GetPrivateProfileString(eventVector.key, "SoundFile", "MQ2ChatEvents_Error", szSoundFile, MAX_STRING, INIFileName);
			if (!stricmp(szSoundFile, "MQ2ChatEvents_Error")) return;
			CHAR szTemp[MAX_STRING] = { 0 };
			sprintf_s(szTemp, "%s\\%s", gszINIPath, eventVector.soundFile);
			PlaySound(szTemp, NULL, SND_FILENAME | SND_ASYNC);
			break;
		}
	}
	return;
}

PLUGIN_API VOID SetGameState(DWORD GameState)
{
	if (GameState == GAMESTATE_INGAME)
		sprintf_s(CESection, "%s_%s", GetCharInfo()->Name, EQADDR_SERVERNAME);
	else
		strcpy_s(CESection, "MQ2ChatEvents");

	InitEvents();
}

PLUGIN_API VOID OnPulse(VOID)
{
	/*
	pulseCounter++;
	if ( pulseCounter <= SKIP_PULSES ) {
	//DebugSpewAlways("\tpulseCounter <= SKIP_PULSES, returning : %d <= %d", pulseCounter, SKIP_PULSES);
	return ;
	}
	else {
	pulseCounter = 0 ;
	}
	*/

	// Execute one command per pulse
	// If there are commands in the queue, turn off chat line processing until the queue is empty again 
	if (!commandQueue.empty()) {
		processFlag = false;
		char commandText[MAX_STRING];
		// Expand any variables in the command string         
		sprintf_s(commandText, "%s", commandQueue.front().c_str());
		ParseMacroData(commandText);

		if (verboseCommands) {
			char verboseMessage[MAX_STRING];
			sprintf_s(verboseMessage, "MQ2ChatEvents::Executing command=\ag%s\ax", commandText);
			WriteChatColor(verboseMessage);
		}
		//DebugSpewAlways("Executing command: %s", commandQueue.front().c_str() );
		//DebugSpewAlways("Executing command: %s", commandText );
		DoCommand(((PCHARINFO)pCharData)->pSpawn, commandText);
		commandQueue.pop();
	}
	else {
		processFlag = true;
	}
	return;
}

PLUGIN_API VOID InitializePlugin(VOID)
{
	DebugSpewAlways("Initializing MQ2ChatEvents");
	AddCommand("/chatevents", ChatEventsCmd);
	AddCommand("/ce", ChatEventsCmd);
	AddCommand("/playsound", PlaySoundCmd);
	InitEvents();
}

PLUGIN_API VOID ShutdownPlugin(VOID)
{
	DebugSpewAlways("Shutting down MQ2ChatEvents");
	RemoveCommand("/chatevents");
	RemoveCommand("/ce");
	RemoveCommand("/playsound");
}
 
I'm able to build it with no problems. More than likely it can't find MQ2Plugin.h. Try this: create a folder called 'MQ2ChatEvents' inside of your MQ2 source folder. So for example: create folder c:\users\yourname\Documents\Visual Studio 2017\Projects\MQ2\MQ2ChatEvents and copy MQ2ChatEvents.cpp into it. Then, right click "Solution 'MacroQuest2'" (on the right hand side) in VS and say "Add Existing Item" and add your MQ2ChatEvents.cpp file you put into the MQ2ChatEvents folder. When you build the whole solution, your MQ2ChatEvents DLL should build with it and show up in the release folder.
 
I'm able to build it with no problems. More than likely it can't find MQ2Plugin.h. Try this: create a folder called 'MQ2ChatEvents' inside of your MQ2 source folder. So for example: create folder c:\users\yourname\Documents\Visual Studio 2017\Projects\MQ2\MQ2ChatEvents and copy MQ2ChatEvents.cpp into it. Then, right click "Solution 'MacroQuest2'" (on the right hand side) in VS and say "Add Existing Item" and add your MQ2ChatEvents.cpp file you put into the MQ2ChatEvents folder. When you build the whole solution, your MQ2ChatEvents DLL should build with it and show up in the release folder.

Well, I've tried to do it as you said, but first
MQ2Chatevents.cpp is source C++ file, so if itself get added in a Solution, which shows like this
Cpp.jpg

Which I believe it's not right.

Where to add a "existing project" instead of "existing item" to the solution right?? Aka the vcxproj file to the solution? It should be add the MQ2Chatevents.vcxproj to the Solution "Macroquest" right?
It should show like this :
proj.png

Anyway thanks a lot for the help and discussion

- - - Updated - - -

And after adding the existing project file who generated by the "mkplugin" command, I always get the errors as above.

Maybe is the SDK differences? I use 8.1 instead of 10.0.14393.0??
 
Yes, sorry, forgot about the mkplugin part. Was trying to go off memory and I knew you had to add it to the project somehow. I also opened up an older version of MQ2 as I re-downloaded the latest version and see the same issue as you.

I can see he problem:

ChatEvents is calling a function with 1 argument:
Rich (BB code):
ParseMacroData(expandedString);

In my older version of code, that function only required 1 argument:
Rich (BB code):
BOOL ParseMacroData(PCHAR szOriginal)

In the latest version it requires 2:
Rich (BB code):
BOOL ParseMacroData(PCHAR szOriginal, SIZE_T BufferSize)

I don't know enough to be able to supply the function with the buffersize it is looking for - or what the ramifications would be of getting it wrong :confused:
 
Compiled - Just use VS2015

Users who are viewing this thread

Back
Top