Originally mentioned here: 
http://www.projecteq.net/phpBB2/viewtopic.php?t=7289
Summary of above:
Neither quest::me or quest::echo works at the moment. I think quest::me is specific to something, but I can't tell what. 
The quest::echo code - where does this message go exactly? ~line 193 questmgr.cpp:
	Code:
	void QuestManager::echo(const char *str) {
   printf("%s\n", str);
}
 So, I rewrote the quest::echo function to be more like the quest::ze and quest::we functions, meaning it will allow a colour ID. 
I left the quest::me function as it was in case it was intentional:
	Code:
	void QuestManager::me(const char *str) {
   if (!initiator)
      return;
   entity_list.MessageClose(initiator, false, 200, 10, str);
}
  I just made quest::echo work, pretty much identical to the alternative method Trevius posted:
	Code:
	$entity_list->MessageClose($npc, 1, 200, 15, "You hear a whisper in the wind as if something calls to you from the darkness.");
 New usage: quest::echo(#colourID, "Message");
Diffs below. Now, I've had this compiled, tested 
and working, but I am a complete novice at C coding - I tend to stick to script languages. If someone spots something really stupid, please let me know.
questmgr.cpp
	Code:
	--- questmgr.cpp	2009-04-23 11:26:57.000000000 +0100
+++ questmgr.newcpp	2009-04-23 10:43:27.000000000 +0100
@@ -190,8 +190,8 @@ void QuestManager::EndQuest() {
 
 
 //quest perl functions
-void QuestManager::echo(const char *str) {
-	printf("%s\n", str);
+void QuestManager::echo(int colour, const char *str) {
+	entity_list.MessageClose(initiator, false, 200, colour, str);
 }
 
 void QuestManager::say(const char *str) {
 questmgr.h
	Code:
	--- questmgr.h	2009-04-23 11:26:57.000000000 +0100
+++ questmgr.newh	2009-04-23 10:43:40.000000000 +0100
@@ -42,7 +42,7 @@ public:
 	void ClearTimers(Mob *who);
 	
 	//quest perl functions
-	void echo(const char *str);
+	void echo(int colour, const char *str);
 	void say(const char *str);
 	void me(const char *str);
 	void summonitem(int32 itemid, uint8 charges = 0);
 parser.cpp
	Code:
	--- parser.cpp	2009-04-23 11:26:57.000000000 +0100
+++ parser.newcpp	2009-04-23 11:07:54.000000000 +0100
@@ -799,7 +799,7 @@ void Parser::ExCommands(string o_command
 			atof(arglist[3]), atof(arglist[4]), atof(arglist[5]), hdng);
 	}
 	else if (!strcmp(command,"echo")) {
-		quest_manager.echo(parms.c_str());
+		quest_manager.echo(atoi(arglist[0]), parms.c_str());
 	}
 	else if (!strcmp(command,"summonitem")) {
 		quest_manager.summonitem(atoi(arglist[0]));
 perlparser.cpp
	Code:
	--- perlparser.cpp	2009-04-23 11:26:57.000000000 +0100
+++ perlparser.newcpp	2009-04-23 11:07:38.000000000 +0100
@@ -210,10 +210,10 @@ XS(XS__echo); // prototype to pass -Wmis
 XS(XS__echo) {
 	dXSARGS;
 
-	if (items != 1)
-		Perl_croak(aTHX_ "Usage: say(str)");
+	if (items != 2)
+		Perl_croak(aTHX_ "Usage: echo(id#, str)");
 
-	quest_manager.echo(SvPV_nolen(ST(0)));
+	quest_manager.echo(SvUV(ST(0)), SvPV_nolen(ST(1)));
 
 	XSRETURN_EMPTY;
 }