Page 4 of 6

Posted: Tue Oct 28, 2003 2:34 pm
by Lax
Nah I mean there's a function in the CSidlWnd virtual function table to call that stores to the ini, and one that reads from the ini..

Posted: Tue Oct 28, 2003 2:57 pm
by vzmule
Would be nice to make this able to be toggled. Like simply having a setting in the ini file to toggle this on and off.

Like
MQwindow=0/1

Posted: Tue Oct 28, 2003 5:17 pm
by Lax
crash bug, when you camp out the MQ window variable needs to be reset... need to find best way to tell if we're in game or not.

Posted: Tue Oct 28, 2003 5:19 pm
by Mckorr
Lax wrote:Nah I mean there's a function in the CSidlWnd virtual function table to call that stores to the ini, and one that reads from the ini..
Ah. Well, let me know, so we can update the mouse parser code as well. My method is brute force, because that's all we had at the time :D

Posted: Tue Oct 28, 2003 6:08 pm
by Plazmic
Ok, I've fixed camping out by calling CChatManager::FreeChatWindow (which is solved incorrectly in the .IDC) during CDisplay::CleanGameUI.
This frees up our window when camping to charselect or out of game, and during a /loadskin.

I also added ini storage of the window location in Macroquest.ini with a [servername.charname] section. I really don't want to start editing files in the EQ directory... that would give them SOE/VI something more to snoop for...

Looking for alpha settings right now so I can save those also, then I'll make a diff...

Posted: Tue Oct 28, 2003 6:12 pm
by Lax
post your code for fixing the camp problem

Posted: Tue Oct 28, 2003 6:14 pm
by Plazmic
detours not posted or global var defines...

CleanGameUI=0040EFEC

Code: Select all

CHAR szChatINISection[MAX_STRING] = {0};
void LoadChatFromINI(PCSIDLWND pWindow)
{
    sprintf(szChatINISection,"%s.%s",(*EQADDR_CHAR_INFO)->Server,(*EQADDR_CHAR_INFO)->Name);
	pWindow->Location.top		= GetPrivateProfileInt(szChatINISection,"ChatTop",    10,gszINIFilename);
	pWindow->Location.bottom	= GetPrivateProfileInt(szChatINISection,"ChatBottom",210,gszINIFilename);
	pWindow->Location.left		= GetPrivateProfileInt(szChatINISection,"ChatLeft",   10,gszINIFilename);
	pWindow->Location.right 	= GetPrivateProfileInt(szChatINISection,"ChatRight", 410,gszINIFilename);
}

void SaveChatToINI(PCSIDLWND pWindow)
{
	CHAR szTemp[MAX_STRING] = {0};
	WritePrivateProfileString(szChatINISection,"ChatTop",	itoa(pWindow->Location.top,		szTemp,10),gszINIFilename);
	WritePrivateProfileString(szChatINISection,"ChatBottom",itoa(pWindow->Location.bottom,	szTemp,10),gszINIFilename);
	WritePrivateProfileString(szChatINISection,"ChatLeft",	itoa(pWindow->Location.left,	szTemp,10),gszINIFilename);
	WritePrivateProfileString(szChatINISection,"ChatRight",	itoa(pWindow->Location.right,	szTemp,10),gszINIFilename);
}

void MakeChatWindow()
{
   ...
   // should be ok now, set style etc
   BitOff(MQChatWnd->Wnd.WindowStyle,CWS_CLOSE); 
   for (int n = 0 ; n < 0x20 ; n++) 
   { 
      if (pChatManager->ChannelMap[n]==0 || pChatManager->ChannelMap[n]==MQChatWnd) 
         pChatManager->ChannelMap[n]=pChatManager->ChatWnd[0]; 
   } 
   LoadChatFromINI(&MQChatWnd->Wnd);
   SetCXSTRText(MQChatWnd->Wnd.WindowText,"MQ");
}

VOID FreeChatWindow()
{
	if (!MQChatWnd) return;
	SaveChatToINI(&MQChatWnd->Wnd);

   PEQCHATMGR pChatManager= *(PEQCHATMGR*)EQADDR_CHATMANAGER;
   for (int n = 0 ; n < 0x20 ; n++) 
   { 
      if (pChatManager->ChannelMap[n]==0 || pChatManager->ChannelMap[n]==MQChatWnd) 
         pChatManager->ChannelMap[n]=pChatManager->ChatWnd[0]; 
   } 

	DWORD destructor=(DWORD)MQChatWnd->Wnd.pvfTable->vector_deleting_destructor; 
	__asm { 
		push ecx; 
		mov ecx, MQChatWnd; 
		push 1; 
		call [destructor]; 
		pop ecx; 
	}; 

	MQChatWnd = NULL;
}
and

Code: Select all

class CDisplay
{ 
public: 
	VOID Trampoline_CleanGameUI(VOID); 
	VOID Detour_CleanGameUI(VOID) 
	{ 
		FreeChatWindow();
		Trampoline_CleanGameUI();
	}
};

Posted: Tue Oct 28, 2003 6:26 pm
by Lax
Bout the same as I was about to work on for CleanGameUI :) One thing though, we need to make sure it gets destroyed in the "cant" instance in removal, which would happen if someone has max # of chat windows open. Should call the destructor like so:

Code: Select all

DWORD destructor=MQChatWnd->Wnd.pvfTable->vector_deleting_destructor;
__asm {
  push ecx;
  mov ecx, MQChatWnd;
  push 1;
  call [destructor];
  pop ecx;
};
the push 1 tells the destructor to call delete on the object, which we want to do since it's dynamic

toss that in there and it should be good to go

Also, put this in

Code: Select all

	BitOff(MQChatWnd->Wnd.WindowStyle,CWS_CLOSE);
	for (int n = 0 ; n < 0x2b ; n++)
	{
		if (pChatManager->ChannelMap[n]==0 || pChatManager->ChannelMap[n]==MQChatWnd)
			pChatManager->ChannelMap[n]=pChatManager->ChatWnd[0];
	}
to replace

Code: Select all

MQChatWnd->Wnd.WindowStyle=CWS_TITLE|CWS_MINIMIZE|CWS_BORDER|CWS_RESIZEALL; 
This makes sure the usual style is preserved other than the close box, and also makes sure the EQ chat filters wont crash us :)

For that to compile without casting, the chat manager struct needs to be fixed so that

Code: Select all

/*0x090*/ DWORD ChannelMap[0x2a];   // channel map
is now

Code: Select all

/*0x090*/ struct _EQCHATWINDOW* ChannelMap[0x2a];   // channel map

Posted: Tue Oct 28, 2003 6:31 pm
by Plazmic
the stupid destructor has a 1 param? that's why I was hanging when trying that way ;(

Posted: Tue Oct 28, 2003 6:31 pm
by Lax
Err.. that's supposed to work to fix the channel map but it doesn't ;) working on it...

Posted: Tue Oct 28, 2003 6:33 pm
by Lax
Yes I think that's standard for all destructors, for future reference :)
It can probably be set in the struct as a function of type void * (bool bDelete)

Posted: Tue Oct 28, 2003 6:43 pm
by Plazmic
Thanks, I originally had it that way, but it hung on logout without the push 1... Updated to be much cleaner ;)

When you figure out the channel cleanup, I'll modify that also

Posted: Tue Oct 28, 2003 6:52 pm
by Lax
Ok, the problem was in the struct. oops. it had 0x2a available chat channels and threw off the struct.

First part of the struct fixed:

Code: Select all

typedef struct _EQCHATMGR
{
/*0x000*/ struct _EQCHATWINDOW* ChatWnd[0x20];
/*0x080*/ DWORD NumWindows; 
/*0x084*/ DWORD ActiveWindow; // CChatManager::GetActiveChatWindow
/*0x088*/ DWORD LockedWindow; // CChatManager::GetActiveChatWindow
/*0x08c*/ DWORD Unknown0x08c;
/*0x090*/ struct _EQCHATWINDOW* ChannelMap[0x20];   // channel map
/*0x110*/ BYTE  Unknown0x110;
/*0x138*/ DWORD Unknown0x138;
The channel map integrity check should use < 0x20 instead of 0x2b

Posted: Tue Oct 28, 2003 6:53 pm
by Plazmic
My final diff is going to change the way Pulse is called also.
I moved all of the pulse related stuff in the keyboard hook to a ProcessGameEvents detour.
Additionally, (gDelay) is only going to delay macros now, not map updates, /face slow, etc like it does now.

Posted: Tue Oct 28, 2003 6:56 pm
by Plazmic
Lax wrote:Ok, the problem was in the struct. oops. it had 0x2a available chat channels and threw off the struct.

First part of the struct fixed:

Code: Select all

typedef struct _EQCHATMGR
{
..
/*0x110*/ BYTE  Unknown0x110;
/*0x138*/ DWORD Unknown0x138;
The channel map integrity check should use < 0x20 instead of 0x2b
Do we need to pad between 110 and 138 to keep the menus correct?