Chat functionality update

A forum for feature requests/discussions and user submitted patches that improve MQ2

Moderator: MacroQuest Developers

Lax
We're not worthy!
We're not worthy!
Posts: 3524
Joined: Thu Oct 17, 2002 1:01 pm
Location: ISBoxer
Contact:

Chat functionality update

Post by Lax » Fri Oct 31, 2003 12:10 pm

EQLib_UI.cpp

Code: Select all

void CChatWindow__AddOutputText(PEQCHATWINDOW pWnd, const char *Text, int RGBA=0)
{
   if (!pWnd || !Text)
      return;

   char out[MAX_STRING];
   DWORD saddr   =(DWORD)&out[0];
   if (RGBA)
      sprintf(&out[0],"<c \"#%06X\">%s</c><br>",RGBA &0xFFFFFF,Text);
   else
      sprintf(&out[0],"%s<br>",Text);

   PCXSTR stri=0;
   DWORD outwnd=(DWORD)pWnd->OutputWnd;
   __asm{
      push ecx;
      push eax;
      push saddr;
      lea ecx, [stri];
      call [EQADDR_CXSTRCONSTRUCTOR];
      pop eax;
      pop ecx;
   };
[color=red]
   // Convert item tags
   saddr=(DWORD)&stri;
   __asm{
      push ecx;
      push eax;
	  push 1;
	   push [saddr];
	   call [EQADDR_CONVERTITEMTAGS];
	   pop eax;
	   pop ecx;
   };
[/color]
   struct _rect{ 
      DWORD l,r,t,b; 
   } temp; 
   DWORD atemp=(DWORD)&temp; 
.
.
.
}
.
.
.
VOID Chat(PCHAR Text, DWORD Color)
{
   PEQCHATMGR pChatManager= *(PEQCHATMGR*)EQADDR_CHATMANAGER;
   if (!MQChatWnd) {
      MakeChatWindow();
   }

   if (!MQChatWnd) {
      return;
   }
   char out[MAX_STRING];
   MQToSTML(Text,&out[0]);

   CChatWindow__AddOutputText(MQChatWnd,&out[0],Color);
   if (gTelnetServer && gTelnetConnection && !gPauseTelnetOutput) {
		StripMQChat(&Text[0],&out[0]);
      TelnetServer_Write(Text); 
   } 
}



VOID Chat(PCHAR Text) 
{ 
   DebugSpew("Chat(%s)",Text); 
   PEQCHATMGR pChatManager= *(PEQCHATMGR*)EQADDR_CHATMANAGER; 
   if (!MQChatWnd) { 
      MakeChatWindow(); 
   } 

   if (!MQChatWnd) { 
      return; 
   } 
   char out[MAX_STRING]; 
   MQToSTML(Text,&out[0]);
   DebugSpew("Chat() output \"%s\"",&out[0]); 
   CChatWindow__AddOutputText(MQChatWnd,&out[0],0); 

   if (gTelnetServer && gTelnetConnection && !gPauseTelnetOutput) {
 		StripMQChat(&Text[0],&out[0]);
     TelnetServer_Write(Text); 
   } 
}
Note: Telnet server writes were moved to Chat()

Replace in EQLib_Utilities.cpp. Note: the telnet write should ONLY be handled by these if Chat() is not called, because Chat() writes to telnet.

Code: Select all

VOID WriteChatColor(PCHAR Line, DWORD Color) { 
   if (!gbInGame) return; 
   if (gFilterMacro != FILTERMACRO_NONE) { 
   PEQCHATMGR pChatManager=*(PEQCHATMGR*)EQADDR_CHATMANAGER; 
   __asm 
   { 
      push eax; 
      push ecx; 
      mov ecx, pChatManager; 
      push Color; 
      call [EQADDR_CCHATMANAGERGETRGBAFROMINDEX]; 
      mov [Color], eax; 
      pop ecx; 
      pop eax; 
   }; 
   Chat(Line,Color); 
	} else if (gTelnetServer && gTelnetConnection && !gPauseTelnetOutput) {
		char out[MAX_STRING];
		StripMQChat(Line,&out[0]);
        TelnetServer_Write(&out[0]);
    }
};

VOID WriteChatBuffer(PCHAR szText, DWORD Color)
{
    if (gFilterMacro == FILTERMACRO_ALL) {
        WriteChatColor(szText,Color);
	} else if (gTelnetServer && gTelnetConnection && !gPauseTelnetOutput) {
		char out[MAX_STRING];
		StripMQChat(szText,&out[0]);
        TelnetServer_Write(&out[0]);
    }
}
Add to EQLib_Utilities.cpp

Code: Select all

#define InsertColor(text,color) sprintf(text,"<c \"#%06X\">",color);TotalColors++; 
#define InsertStopColor(text)   sprintf(text,"</c>");TotalColors--; 

VOID StripMQChat(PCHAR in, PCHAR out)
{
	int i = 0;
	int o = 0;
	int len=strlen(in);
	while(in[i]<len)
	{
		if (in[i]=='\a')
		{
			if(in[i]=='-')
			{
				i++;
			}
			else if (in[i]=='#')
			{
				i+=6;
			}
			i++;
		}
		else if (in[i]=='\n')
		{
		}
		else
			out[o++]=in[i];
		i++;
	}
	out[o++]=0;
}

DWORD MQToSTML(PCHAR in, PCHAR out, DWORD maxlen)
{
	// 1234567890123
	// <c "#123456">
	if (maxlen>13)
		maxlen-=13; // huh...
   int i = 0;
   int o = 0;
   bool bFirstColor=false;
   int CurrentColor=0xFFFFFFFF; // -1
   int TotalColors=0;
   while(in[i]!=0 && o<maxlen)
   {
      switch(in[i])
      {
	  case '\a':
		  // HANDLE COLOR
		  bFirstColor=true;
		  i++;
		  if (in[i]=='x')
		  {
			  CurrentColor=-1;
			  o+=InsertStopColor(&out[o]);
		  }
		  else
		  if (in[i]=='#')
		  {
			  i++;
			  char temp[7];
			  for (int x = 0 ; x < 6 ; x++)
			  {
				temp[x++]=in[i++];
			  }
			  i--;
			  temp[6]=0;
			  CurrentColor=-1;
			  o+=sprintf(&out[o],"<c \"#%s\">",&temp[0]);
			  TotalColors++;
		  }
		  else
		  {
			bool Dark=false;
			if (in[i]=='-')
			{
				Dark=true;	
				i++;
			}
			int LastColor=CurrentColor;
			switch(in[i])
			{
				case 'y': // yellow (green/red)
					if (Dark)
						CurrentColor=0x999900;
					else
						CurrentColor=0xFFFF00;
					break;
				case 'o': // orange (green/red)
					if (Dark)
						CurrentColor=0x996600;
					else
						CurrentColor=0xFF9900;
					break;
				case 'g': // green   (green)
					if (Dark)
						CurrentColor=0x009900;
					else
	  					CurrentColor=0x00FF00;
					break;
				case 'u': // blue   (blue)
					if (Dark)
						CurrentColor=0x000099;
					else
  						CurrentColor=0x0000FF;
					break;
				case 'r': // red     (red)
					if (Dark)
						CurrentColor=0x990000;
					else
	  					CurrentColor=0xFF0000;
					break;
				case 't': // teal (blue/green)
					if (Dark)
  						CurrentColor=0x009999;
					else
  						CurrentColor=0x00FFFF;
					break;
				case 'b': // black   (none)
  					CurrentColor=0x000000;
					break;
				case 'm': // magenta (blue/red)
					if (Dark)
	  					CurrentColor=0x990099;
					else
	  					CurrentColor=0xFF00FF;
					break;
				case 'p': // purple (blue/red)
					if (Dark)
						CurrentColor=0x660099;
					else
	  					CurrentColor=0x9900FF;
					break;
				case 'w': // white   (all)
					if (Dark)
						CurrentColor=0x999999;
					else
	  					CurrentColor=0xFFFFFF;
					break;
				}
				if (CurrentColor!=LastColor)
				{
					o+=InsertColor(&out[o],CurrentColor);
				}
			}
		  break;
      case '&':
         out[o++]='&';
         out[o++]='A';
         out[o++]='M';
         out[o++]='P';
         out[o++]=';';
         break;
      case '%':
         out[o++]='&';
         out[o++]='P';
         out[o++]='C';
         out[o++]='T';
         out[o++]=';';
         break;
      case '<':
         out[o++]='&';
         out[o++]='L';
         out[o++]='T';
         out[o++]=';';
         break;
      case '>':
         out[o++]='&';
         out[o++]='G';
         out[o++]='T';
         out[o++]=';';
         break;
      case '"':
         out[o++]='&';
         out[o++]='Q';
         out[o++]='U';
         out[o++]='O';
         out[o++]='T';
         out[o++]=';';
         break;
	  case '\n':
		 out[o++]='<';
		 out[o++]='B';
		 out[o++]='R';
		 out[o++]='>';
		 break;
      default:
		  if (!bFirstColor)
		  {
			  bFirstColor=true;
			  CurrentColor=0xFFFFFF; // white
			  o+=InsertColor(&out[o],CurrentColor);
		  }
         out[o++]=in[i];
         break;
      }
      i++;
   }
   for (TotalColors ; TotalColors>0 ; TotalColors--)
   {
	  o+=InsertStopColor(&out[o]);
   }
	out[o++]=0;
	return o;
}
EQLib_Main.cpp

Code: Select all

DWORD EQADDR_CONVERTITEMTAGS=0;
.
.
.
    GetPrivateProfileString("Function Locations","ConvertItemTags","0",szBuffer,MAX_STRING,ClientINI);   EQADDR_CONVERTITEMTAGS = (DWORD)strtoul(szBuffer,NULL,16);
EQLib.h

Code: Select all

extern DWORD MQToSTML(PCHAR in, PCHAR out, DWORD maxlen=MAX_STRING);
extern VOID StripMQChat(PCHAR in, PCHAR out);
.
.
.
extern DWORD EQADDR_CONVERTITEMTAGS;
eqgame.ini

Code: Select all

ConvertItemTags=00453F20
That should do it.

WriteChatColor will now accept MQ chat codes, and \n is now considered a special character and replaced with a stml <BR> if you want to do two lines in one call.. item tags are converted.. the StripMQChat will remove special characters so the text can be sent to telnet without confusing anyone, since WriteChatColor can accept the codes now.. MQToSTML is the single conversion routine that folks were asking for.. I think that's about it. Note: don't call MQToSTML twice on the same text, this will make the STML tags visible instead of doing what you want :)

Example color usage for the DisplayZem function:

Code: Select all

      sprintf(out, "\awZone experience modifier: \ag%.1f%%\ax (\a%c%.1f%% %s\ax)", zem, (bonus<0) ? 'r' : 't', (bonus<0) ? 0-bonus : bonus, (bonus<0) ? "penalty" : "bonus" );
Lax Lacks
Master of MQ2 Disaster
Purveyor of premium, EULA-safe MMORPG Multiboxing Software
* Multiboxing with ISBoxer: Quick Start Video
* EQPlayNice, WinEQ 2.0

Mckorr
Developer
Developer
Posts: 2326
Joined: Fri Oct 18, 2002 1:16 pm
Location: Texas

Post by Mckorr » Fri Oct 31, 2003 12:21 pm

So CVS it in already :D
MQ2: Think of it as Evolution in action.

Lax
We're not worthy!
We're not worthy!
Posts: 3524
Joined: Thu Oct 17, 2002 1:01 pm
Location: ISBoxer
Contact:

Post by Lax » Fri Oct 31, 2003 12:22 pm

Wish i could bud! ;)
Lax Lacks
Master of MQ2 Disaster
Purveyor of premium, EULA-safe MMORPG Multiboxing Software
* Multiboxing with ISBoxer: Quick Start Video
* EQPlayNice, WinEQ 2.0

Mckorr
Developer
Developer
Posts: 2326
Joined: Fri Oct 18, 2002 1:16 pm
Location: Texas

Post by Mckorr » Fri Oct 31, 2003 12:25 pm

Can't help you right now, I'm still working on getting this cantankerous machine at the office to load the compiler.
MQ2: Think of it as Evolution in action.