Page 1 of 2

/Selectitem released (merchant & self listing/select ite

Posted: Sun Jul 13, 2003 2:33 am
by EqMule
UPDATE2, I implemented list and selection for the char as well, but to not confuse anyone, it has its own post, so if you are new to this thread, skip this and jump directly here:
http://macroquest2.com/phpBB2/viewtopic ... 7902#17902


UPDATE! ok implemented /selectitem slot <slotnumber> and put in a few checkas against unruly merchants that couldnt keep their items in order...
NOTE! that I changed EQWINDOW struct so you need to use this one.

ok here is the fix for /merchant.
This version will take /selectitem list || "item name" || slot <slotnumber> and select that item for buying. I will release the /sellitem as well, thats why I wanted this command to be called selectitem and not merchant, because in the next version we will be able to specify where to select from, for example your own bags... or inventory i.e /selectitem "item name" self || merchant , if someone feels up for the finetuning, feel free to paste some code in this thread I could use some ideas and help. The list prints IDs maybe /selectitem <ID> ? or /selectitem <slot> ? post code or feedback.
someone wanted $merchant(has,"item name") and $corpse(has,"item name") that shouldnt be hard to fix now since the function works again...


NOTE! the cyan text is the section under which you paste the code, it doesnt mean you can paste it directly under that section, just a pointer to get you started, if you look in the section you will see lines that looks like the code you are going to insert, and you need to paste it under a similar line... also note that some lines might allready exist... just replace them

ok here goes->

in EQLib.h :
// ***************************************************************************
// EQ Addresses
// ***************************************************************************

Code: Select all

extern DWORD *EQADDR_CLASSMERCHWND;
extern DWORD *EQADDR_CLASSTEXTUREANIMATION; 
//*******************************************************
// EQ Functions
// *******************************************************

Code: Select all

extern fEQSelectItem	  cmdSelectItem; 

in EQLib_Commands.cpp :

Code: Select all

 [color=green]// ***************************************************************************
// Function:    SelectItem
// Description: Our '/selectitem' command
//              targets an item.
// Usage:       /selectitem list || "item name" || slot <slotnumber>
// ***************************************************************************
// uses public: void __thiscall CMerchantWnd::SelectBuySellSlot(int,class CTextureAnimation *)
// ***************************************************************************[/color]
VOID SelectItem(PSPAWNINFO pChar, PCHAR szLine) 
{ 
	bRunNextCommand = FALSE;
	
	PEQWINDOW pMainWindow = (PEQWINDOW)*EQADDR_CLASSMERCHWND;
	PEQCURRENTSELECTION pSelectedSlot = (PEQCURRENTSELECTION)*EQADDR_CLASSTEXTUREANIMATION;
	PEQWINDOW pCurSlot = NULL;
	PEQWINDOW pDestSlot = NULL;

	DWORD MerchTraderWnd = *EQADDR_CLASSMERCHWND; 
	BOOL Found;
	CHAR szBuffer[MAX_STRING] = {0};
	CHAR szArg1[MAX_STRING] = {0};
	CHAR szArg2[MAX_STRING] = {0};
	int SelectSlot, i;
	if (!MerchTraderWnd || !cmdSelectItem) return;
	GetArg(szArg1,szLine,1);
	GetArg(szArg2,szLine,2);
	Found = FALSE;
	
	if ((!_stricmp(szArg1,"slot") && (szArg2[0]!=0)))
	{	
		i = atoi(szArg2);
		i--;
		if (pMainWindow->ItemDesc[i] == NULL)
			return;
		SelectSlot = (int)pMainWindow->SlotsHandles[i]->SlotID;
		Found = TRUE;
	}

	if ((!_stricmp(szArg1,"list") && (szArg2[0]==0) && (Found == FALSE)))
	{
		WriteChatBuffer("Merchant Inventory:",USERCOLOR_DEFAULT);
		WriteChatBuffer("--------------------------",USERCOLOR_DEFAULT);
		i=0;
		while (i < 79)
		{
			if (!_stricmp(szArg1,"list"))// && (szArg2[0]==0))
			{
				if (pMainWindow->ItemDesc[i] != NULL)
				{
					sprintf(szBuffer,"%d:'%s' : (slot %d)",pMainWindow->ItemDesc[i]->ItemNumber,pMainWindow->ItemDesc[i]->Name,(pMainWindow->SlotsHandles[i]->SlotID-5999));
					WriteChatBuffer(szBuffer,CONCOLOR_YELLOW);
				}else
					i=80;
			}
			i++;
		}
	}
	if ((_stricmp(szArg1,"list") && (szArg1[0]!=0) && (Found == FALSE)))
	{
		i=0;
		while (i < 79 && Found == FALSE)
		{
			if (pMainWindow->ItemDesc[i] != NULL)
			{
				if (!_stricmp(pMainWindow->ItemDesc[i]->Name , szArg1))
				{
					sprintf(szBuffer,"'%s' Found in slot '%d'",pMainWindow->ItemDesc[i]->Name,(pMainWindow->SlotsHandles[i]->SlotID-5999));
					WriteChatBuffer(szBuffer,USERCOLOR_DEFAULT);
					SelectSlot = (int)pMainWindow->SlotsHandles[i]->SlotID;
					Found = TRUE;
					i--;
				}
			}else
				i=80;
			i++;
		}
	}
	if (Found == TRUE)
	{	
		if (pMainWindow->ItemDesc[i] != NULL)
		{
			pCurSlot = (PEQWINDOW)((int *)pSelectedSlot->SelectedWnd);
			pDestSlot = (PEQWINDOW)((int *)pMainWindow->SlotsHandles[i]);//(PEQMERCHANT)(DWORD)TextureAnim;
			pCurSlot->Selector = 0;
			pDestSlot->Selector = 1;
			*((int *)EQADDR_CLASSTEXTUREANIMATION) = ((int)pDestSlot->PushToSelector);
			int TextureAnim = (int)pMainWindow->SlotsHandles[i]->InvDecription;
			__asm {
				push ecx;
				push TextureAnim;
				mov ecx, dword ptr [MerchTraderWnd];
				push SelectSlot;
				call dword ptr [cmdSelectItem];
				pop ecx;
			}
		}
	}else
	{
		if(_stricmp(szArg1,"list"))
		{
			WriteChatBuffer("Item not found.",CONCOLOR_RED);
		}
	}
	return;	
}
in EQLib_Interp.cpp
// ***************************************************************************
// Function: TakeControlOfCommandList
// Description: Creates custom command list with our commands
// Points help/parsing at our list
// ***************************************************************************

Code: Select all

 		{"/selectitem",	"SelectItem"},
in EQLib_Main.cpp :
// EQ Functions Initialization

Code: Select all

fEQSelectItem	  cmdSelectItem	 =	NULL; 
// EQ Address Initialization

Code: Select all

DWORD *EQADDR_CLASSMERCHWND;
DWORD *EQADDR_CLASSTEXTUREANIMATION; 
// ***************************************************************************
// Function: ParseINIFile
// Description: Parse INI file for memory locations
// ***************************************************************************

Code: Select all

GetPrivateProfileString("Function Locations","SelectItem","0",szBuffer,MAX_STRING,ClientINI);		cmdSelectItem = (fEQSelectItem)strtoul(szBuffer,NULL,16);

	GetPrivateProfileString("Class Locations","ClassMerchWnd","0",szBuffer,MAX_STRING,ClientINI);		EQADDR_CLASSMERCHWND = (DWORD *)strtoul(szBuffer,NULL,16);
	GetPrivateProfileString("Class Locations","ClassTextureAnim","0",szBuffer,MAX_STRING,ClientINI);	EQADDR_CLASSTEXTUREANIMATION = (DWORD *)strtoul(szBuffer,NULL,16);
in MQ.h :
// ***************************************************************************
// Everquest function typedefs
// ***************************************************************************

Code: Select all

typedef VOID    (__cdecl *fEQSelectItem)(int,DWORD); [color=green]//public: void __thiscall CMerchantWnd::SelectBuySellSlot(int,class CTextureAnimation *)[/color]

 
// ***************************************************************************
// Exports
// ***************************************************************************

Code: Select all

extern "C" EQLIB_API VOID  SelectItem     (PSPAWNINFO, PCHAR);
 
in eqgame.ini :

Code: Select all

[Function Locations]
SelectItem=004E932D

[Class Locations]
ClassMerchWnd=005FE270
ClassTextureAnim=0077BF04 
ok last but not least the updated version of the EQWINDOW struct...
replace the one in MQ.h with theese two:

Code: Select all

//7-7-2003   eqmule 
typedef struct _EQWINDOWINFO { 
   DWORD   WindowStyle;            //if it is style then 04 = Window 01 = button 
   DWORD   Unknown1; 
   DWORD   Unknown2; 
   DWORD   Unknown3; 
   DWORD   Unknown4; 
   CHAR    WindowTitle[140]; 
   BYTE    Unknown5[12]; 
   DWORD   pNextAddress;            //most likely pointers to another structure... 
   DWORD   pPrevAddress; 
} EQWINDOWINFO, *PEQWINDOWINFO;         //ok it goes on and there are plenty more to pick up here, but I just need the name for now... 

typedef struct _EQWINDOW {
			DWORD   WindowID; 
			DWORD   TimeMouseOver;         //how many ms the window has had the mouse over it... 
			DWORD   Unknown0x008;      // 2000 seems a common value 
			DWORD   Unknown0x00c;      //500 seems a common value 
			BYTE    Flag; 
			BYTE    MouseOver;         //01 yes 00 no 
			BYTE    Unknown0x012; 
			BYTE    Unknown0x013; 
			BYTE    Unknown0x014[12]; 
			struct  _EQWINDOW *pDownTheTreeOnSameWindow; 
			struct  _EQWINDOW *pNextWindow; 
			DWORD   Flags4; 
			DWORD   Z;               //not sure but its logical to assume it at this point... 
			DWORD   X; 
			DWORD   Y; 
			DWORD   Height; 
			DWORD   Width; 
            DWORD   Depth;            //hmmm... 
            BYTE    Unknown0x040[12]; 
            BYTE    Open;            //1 open 0 closed 
            BYTE    Unknown0x051[7]; 
            DWORD   somekindofID; 
            DWORD   *pUnknownStruct0x060; 
            struct  _EQWINDOWINFO *Info; 
			BYTE	Unknown[84];
			union{
		PITEMINFO	Item;//only when structure is filled with a slot...
			struct	_EQWINDOW	*InvDecription;
			};
			BYTE	Unknown1[68];
			DWORD	SlotID;			//merchantslots start at 1770h bags at 16 and bagslots at fb inventory start at 0.
			BYTE	Unknown2[16];
			BYTE	Selector;		//this graphically selects an item on/off
			BYTE	Unknown3[3];
			DWORD	PushToSelector;
			BYTE	Unknown4[36];//364
		PITEMINFO	ItemDesc[80];	//the mainwindow has pointers directly to the items in the slots...
			DWORD	Unknown5;
			DWORD	FirstSlotIDforWindow;
			DWORD	AddressToPointerForSelectedItem;//
			DWORD	Unknown6;
			DWORD	ItemIconwnd;
			DWORD	Unknown7;
			DWORD	SellBuyButton;
			struct _EQWINDOW	*SlotsHandles[80];
			DWORD	DoneButton;
			DWORD	WindowFace;
} EQWINDOW, *PEQWINDOW;

typedef struct _EQCURRENTSELECTION {
			DWORD	Unknown;
			DWORD	SelectedWnd;//address to selection in tree
} EQCURRENTSELECTION, *PEQCURRENTSELECTION;

OK any feedback for making the code cleaner/better will be appreaciated, Im not a mastercoder by any means...

I will expand on this theeme making buying, selling, trading, possible by commandline only. /autoloot is comming as well as the new windowscanner, so we dont need so many damn offsets...
Play nice.

[edit] ok everything works now.

Posted: Sun Jul 13, 2003 2:55 am
by dont_know_at_all
learn to use diff!

cvs diff will do, too.

Posted: Sun Jul 13, 2003 3:01 am
by EqMule
haha I never know if my code makes it to the cvs, so I post it this way for the newbs who cant figure out a diff...

heck next time I post Ill PM you a diff :)

[edit] code posted works just fine!

Posted: Sun Jul 13, 2003 3:57 am
by dont_know_at_all
if they can't figure out a context diff, they won't be able to make your changes.

If you use a [cvs] diff -u, I can run patch and I don't have to do any work (other than testing).

Posted: Mon Jul 14, 2003 10:04 am
by Mckorr
There's a problem with items right now. ap50 claims the offset is valid, so it looks like a struct change of some sort. That might be causing your bug.

Posted: Mon Jul 14, 2003 11:44 am
by EqMule
hmm maybe something changed in the _ITEMINFO struct, I will take a look at it, and Amadeus if you see this, please give me a hand :)

Posted: Mon Jul 14, 2003 12:28 pm
by wassup
This is working for me, at least when I test it in game with

Code: Select all

/selectitem "<itemname>" merchant


the mouse doesn't move but the item gets selected if the vendor has one.

I'm not sure how to get it to actually click the location and enter numbers into the Quantity text boxes though... that may be a bit much to expect MQ to do.

Posted: Mon Jul 14, 2003 12:36 pm
by EqMule
Wassup wrote:I'm not sure how to get it to actually click the location and enter numbers into the Quantity text boxes though... that may be a bit much to expect MQ to do.
why do you want to do that? just use /buyitem <qty>

for example /buyitem 13 will by 13 of the selected item... /buyitem 1 will buy 1 of the selected item...

anyway, yeah the code works sometimes, but its buggy because at some merchants it will crash, Im looking into it...

Posted: Mon Jul 14, 2003 3:51 pm
by wassup
EqMule00 wrote:
Wassup wrote:I'm not sure how to get it to actually click the location and enter numbers into the Quantity text boxes though... that may be a bit much to expect MQ to do.
why do you want to do that? just use /buyitem <qty>

for example /buyitem 13 will by 13 of the selected item... /buyitem 1 will buy 1 of the selected item...

anyway, yeah the code works sometimes, but its buggy because at some merchants it will crash, Im looking into it...
Ah... I keep relying on the documentation for commands. Thanks for the tip.

If I could get a valid file for the current commands I would be happy to keep it updated as new commands/updates are added.

Posted: Mon Jul 14, 2003 4:00 pm
by EqMule
oh heh I must have mistaken you for someone else lol, thought you allready had /buyitem working, its not in cvs I think, you need to manually paste in that command, but if you did it with selectitem im sure you can do it with buyitem, here is the link to it : http://macroquest2.com/phpBB2/viewtopic.php?t=2643

Posted: Mon Jul 14, 2003 4:27 pm
by wassup
Yeah, I must have missed the post. I used search and found it, just finished the compile to go do some testing.

Thanks.

BTW, I meand the readme.html that comes with MQ, it didn't have a reference to /buyitem, but I just added it in to my own version here.

Posted: Tue Jul 15, 2003 3:28 am
by BlueSkies
I'm currently working on a new Manual that will be both more current (as in, everything correct as of right now), and more reference-like, with an index of all commands that are hyperlinks, etc. Watch for that in the near future.

/selectitem

Posted: Wed Jul 16, 2003 10:53 pm
by EqMule
edit: updated july 21 2003 ok... FINALLY got the #%$#%$^ Animation in... selectitem will now properly display the selected items "texture" in the littel window on the merchantitemwindow... this hopefully will fix the random crash, and make this function really usefull again. Anyway Im posting this now, and will post a cleaned up version later, because I have alot of debugstuff in it. and I think I can speed up the slotcounting as well, give me some time... Note that the _EQCURRENTSELECTION struct changed as well... and FORGET about doing a /selectitem "item name" self if the item you are trying to select are in a bag that is closed, mkay! I am working on a solution for that, but this is not it...

edit: updated July 19 2003 for slotcounting, had a problem, since bags are only updated upon zoning... thus SlotID wouldnt be valid for newly created items for example...

ok since some people allready use what I posted in my initial post, I think it would be messy to edit that post, and also hard for non coders to understand the differences, so instead of starting a new post, I bump it, and the few lucky ones that actually reads this, gets the new features...

and they are:
/selectitem slot <Number> merchant || self
/selectitem "item name" merchant || self
/selectitem list merchant || self

examples:
/selectitem slot 10 merchant :selects slot 10 in the merchant window
/selectitem slot 14 self :selects slot 14 in your characters bags
/selectitem list self :lists all your items and slots they are in, this is useful if you want to select something to sell by slotID...
/selectitem "Manastone" self :Will select your manastone but dont press sell now!

I noticed a weird behaviour with what /sellitem can do, so I need to make a security check on it, before I post it, but I will do that later today, expect it within a few hours...

The /selectitem code will be very useful in combination with /buyitem and /sellitem. Play nice.




in EQLib.h :
// ***************************************************************************
// EQ Addresses
// ***************************************************************************

Code: Select all

extern DWORD *EQADDR_CLASSMERCHWND;
extern DWORD *EQADDR_CLASSTEXTUREANIMATION; 
//*******************************************************
// EQ Functions
// *******************************************************

Code: Select all

extern fEQSelectItem	  cmdSelectItem; 

in EQLib_Commands.cpp :

Code: Select all

 [color=green] // ***************************************************************************
// Function:    SelectItem
// Description: Our '/SelectItem' command
//              targets an item.
// Usage:       /SelectItem list || "item name" || slot <slotnumber> && merchant || self
// ***************************************************************************
// uses public: void __thiscall CMerchantWnd::SelectBuySellSlot(int,class CTextureAnimation *)
// ***************************************************************************[/color]
DWORD SelectFind(char* szSearch, char* szOption )
{
//	int j;
	UCHAR PriSlot;
	CHAR szBuffer[MAX_STRING] = {0};
	BOOL Exact= TRUE;
	PCHARINFO pCharInfo = NULL;
	DWORD slotcounter = 250;
	DWORD BagCounter = 21;
	PEQSLOTLIST pSlotList = (PEQSLOTLIST)*(int *)0x005FE2D4;
	PEQCURRENTSELECTION CurrentSelection = NULL;
//	PEQWINDOW Slot;
	if (NULL == (pCharInfo = GetCharInfo())) return (0);
	for (PriSlot=0;PriSlot<8;PriSlot++)
	{
		PITEMINFO pSlot = pCharInfo->Inventory[22+PriSlot];
		CHAR szTemp[MAX_STRING] = {0};
		BagCounter++;//first bag set counter to 22
		DebugSpew("SelectFind - real bag is %d)",BagCounter);
		if (!pSlot)
		{
			continue;
		}
		if (!stricmp(szOption,"list"))
		{
			if (pSlot->Type == ITEMTYPE_NORMAL)
			{
				slotcounter = slotcounter+10;
				sprintf(szBuffer,"%d:	'%s'	:(slot %d)",pSlot->ItemNumber,pSlot->Name,BagCounter);
				WriteChatBuffer(szBuffer,CONCOLOR_YELLOW);
			}
		}
		else
		{
			_strlwr(strcpy(szTemp,pSlot->Name));
			DebugSpew("pSlot->Name %s - szSearch %s",pSlot->Name,szSearch);
			if (((!Exact) && (strstr(szTemp,szSearch))) || ((Exact) && (!_stricmp(szTemp,szSearch))))
			{
				gLastFind = LASTFIND_PRIMARY;
				DebugSpew("SelectFind - Found '%s' in primary inventory slot %d real slot is %d",pSlot->Name,pSlot->SlotID,BagCounter);
				gLastError[0]=0;
				return (BagCounter);
			}
		}
		if (pSlot->Type == ITEMTYPE_PACK)
		{	
			UCHAR BagSlot;
			DebugSpew("SelectFind - Looking inside pack %d: '%s' %d slots, real slot is %d",PriSlot,pSlot->Name,pSlot->Container.Slots,BagCounter);
			for (BagSlot=0;BagSlot<10;BagSlot++)
			{
				
				PITEMINFO pItem = pSlot->Container.Contents[BagSlot];
				slotcounter++;
				DebugSpew("SelectFind - real slot is %d)",slotcounter);
				if (!pItem)
				{
					continue;
				}

				if (!stricmp(szOption,"list"))
				{
					sprintf(szBuffer,"%d:	'%s'	:(slot %d)",pItem->ItemNumber,pItem->Name,slotcounter);
					WriteChatBuffer(szBuffer,CONCOLOR_YELLOW);
				}
				else
				{
					DebugSpew("pSlot->Name %s - szSearch %s",pItem->Name,szSearch);
					_strlwr(strcpy(szTemp,pItem->Name));
					if (((!Exact) && (strstr(szTemp,szSearch))) || ((Exact) && (!_stricmp(szTemp,szSearch))))
					{
						DebugSpew("SelectFind - Found '%s' in slot %d of '%s' (primary slot %d real slot is %d)",pItem->Name,pSlot->SlotID,pSlot->Name,PriSlot,slotcounter);
						gLastError[0]=0;
					/*	for (j=281;j<362;j++)
						{
							if (pSlotList->InvSlots[j])
							{
								DebugSpew("%d address to selector %x",j,pSlotList->InvSlots[j]);
								CurrentSelection = (PEQCURRENTSELECTION)pSlotList->InvSlots[j];
								Slot = (PEQWINDOW)CurrentSelection->SelectedWnd;
								DebugSpew("%x CurrentSelection %x Slot%x",j,CurrentSelection,Slot);
								if (Slot->SlotID == slotcounter)
								{
									DebugSpew("Slot->SlotID == slotcounter at address %x",CurrentSelection);
								}
							}
						}*/
						return (slotcounter);
					}
				}
			}
		}
	}
	return (0);
}
VOID SelectItem(PSPAWNINFO pChar, PCHAR szLine) 
{ 
	bRunNextCommand = FALSE;
	PEQSLOTLIST pSlotList = (PEQSLOTLIST)*(int *)0x005FE2D4;
	PEQCURRENTSELECTION CurrentSelection = NULL;
	PEQCURRENTSELECTION FixedSelection = NULL;
	PEQWINDOW Slot = NULL;
	PEQWINDOW FixedSlot = NULL;

	PEQWINDOW pMainWindow = (PEQWINDOW)*EQADDR_CLASSMERCHWND;
	PEQCURRENTSELECTION pSelectedSlot = (PEQCURRENTSELECTION)*EQADDR_CLASSTEXTUREANIMATION;
	PEQWINDOW pCurSlot = NULL;
	PEQWINDOW pDestSlot = NULL;
	PCHARINFO pCharInfo = NULL;
	PITEMINFO pItemInfo = NULL;
	DWORD MerchTraderWnd = *EQADDR_CLASSMERCHWND;
	BOOL Found;
	CHAR szBuffer[MAX_STRING] = {0};
	CHAR szArg1[MAX_STRING] = {0};
	CHAR szArg2[MAX_STRING] = {0};
	CHAR szArg3[MAX_STRING] = {0};
	int SelectSlot, i;
	DebugSpew("/selectitem : yes the command works at least to this point");
	if (szLine[0] == 0) {
		WriteChatBuffer("Usage: /selectitem 'item name' merchant || self : slot <number> merchant || self : list merchant || self",USERCOLOR_DEFAULT);
		strcpy(gLastError,"FIND_NOTFOUND");
		return;
	}
	if (NULL == (pCharInfo = GetCharInfo())) return;
	if (!MerchTraderWnd || !cmdSelectItem) return;
	GetArg(szArg1,szLine,1);
	GetArg(szArg2,szLine,2);
	GetArg(szArg3,szLine,3);
	Found = FALSE;
	BOOL PlayerSelection = FALSE;

	if ((!_stricmp(szArg1,"slot") && (szArg2[0]!=0) && (!_stricmp(szArg3,"merchant"))))
	{	
		i = atoi(szArg2);
		i--;
		if (pMainWindow->ItemDesc[i] == NULL)
			return;
		SelectSlot = (int)pMainWindow->SlotsHandles[i]->SlotID;
		Found = TRUE;
	}

	if ((!_stricmp(szArg1,"slot") && (szArg2[0]!=0) && (!_stricmp(szArg3,"self"))))
	{	
		i = atoi(szArg2);
		//i--;
		SelectSlot = (int)i;//+250;
		Found = TRUE;
		PlayerSelection = TRUE;
		i=0;
	}
	//list merchant inventory
	if ((!_stricmp(szArg1,"list") && (!_stricmp(szArg2,"merchant") && (Found == FALSE))))
	{
		WriteChatBuffer("Merchant Inventory:",USERCOLOR_DEFAULT);
		WriteChatBuffer("--------------------------",USERCOLOR_DEFAULT);
		i=0;
		while (i < 79)
		{
			if (pMainWindow->ItemDesc[i] != NULL)
			{
				sprintf(szBuffer,"%d:'%s' : (slot %d)",pMainWindow->ItemDesc[i]->ItemNumber,pMainWindow->ItemDesc[i]->Name,(pMainWindow->SlotsHandles[i]->SlotID-5999));
				WriteChatBuffer(szBuffer,CONCOLOR_YELLOW);
			}else
				return;
			i++;
		}
		
	}
	//list characters inventory
	if ((!_stricmp(szArg1,"list") && (!_stricmp(szArg2,"self") && (Found == FALSE))))
	{
		WriteChatBuffer("Your Inventory:",USERCOLOR_DEFAULT);
		WriteChatBuffer("--------------------------",USERCOLOR_DEFAULT);
		SelectFind("list","list");
		return;
	}
	//search merchant inventory
	if ((_stricmp(szArg1,"list") && (!_stricmp(szArg2,"merchant") && (Found == FALSE))))
	{
		i=0;
		while (i < 79 && Found == FALSE)
		{
			if (pMainWindow->ItemDesc[i] != NULL)
			{
				if (!_stricmp(pMainWindow->ItemDesc[i]->Name , szArg1))
				{
					sprintf(szBuffer,"'%s' Found in slot '%d'",pMainWindow->ItemDesc[i]->Name,(pMainWindow->SlotsHandles[i]->SlotID-5999));
					WriteChatBuffer(szBuffer,USERCOLOR_DEFAULT);
					SelectSlot = (int)pMainWindow->SlotsHandles[i]->SlotID;
					Found = TRUE;
					i--;
				}
			}else
			{
				i=80;
			}
			i++;
		}
	}
	//search character bags 
	if ((_stricmp(szArg1,"list") && (!_stricmp(szArg2,"self") && (Found == FALSE))))
	{
		i = (DWORD)SelectFind(szArg1,"self");
		if (i != 0)
		{

			int j=0;
			SelectSlot = (int)i;
			PlayerSelection = TRUE;
			for (j=281;j<362;j++)
			{
				if (pSlotList->InvSlots[j])
				{
					DebugSpew("%d address to selector %x",j,pSlotList->InvSlots[j]);
					CurrentSelection = (PEQCURRENTSELECTION)pSlotList->InvSlots[j];
					Slot = (PEQWINDOW)CurrentSelection->SelectedWnd;
					DebugSpew("%x CurrentSelection %x Slot%x",j,CurrentSelection,Slot);
					if ((int)Slot->SlotID == SelectSlot)
					{
						DebugSpew("Slot->SlotID == SelectSlot at address %x",CurrentSelection);
						FixedSelection=CurrentSelection;
						FixedSlot = Slot;
						Found = TRUE;
						break;
					}
				}
			}
			i = 0;
			DebugSpew("SelectItem - SelectSlot %d",SelectSlot);
		}else return;
	}
	if (Found == TRUE)
	{	int TextureAnim;
		if (pMainWindow->ItemDesc[i])
		{
			pCurSlot = (PEQWINDOW)((int *)pSelectedSlot->SelectedWnd);
			pCurSlot->Selector = 0;
			if (PlayerSelection == FALSE)
			{
				pDestSlot = (PEQWINDOW)((int *)pMainWindow->SlotsHandles[i]);
				pDestSlot->Selector = 1;
				*((int *)EQADDR_CLASSTEXTUREANIMATION) = ((int)pDestSlot->PushToSelector);
				FixedSelection = (PEQCURRENTSELECTION)pDestSlot->PushToSelector;
				TextureAnim = FixedSelection->TextureAnim;
			}
			else
			{
				pDestSlot = FixedSlot;
				pDestSlot->Selector = 1;
				*((int *)EQADDR_CLASSTEXTUREANIMATION) = ((int)FixedSelection);
				TextureAnim = (int)FixedSelection->TextureAnim;
				DebugSpew("TextureAnim = %x",TextureAnim);
				DebugSpew("FixedSelection = %x",FixedSelection);
				DebugSpew("SelectSlot = %x",SelectSlot);
				DebugSpew("FixedSlot = %x",FixedSlot);
				SelectSlot = FixedSlot->SlotID;

			}
			__asm {
				push ecx;
				push TextureAnim;
				mov ecx, dword ptr [MerchTraderWnd];
				push SelectSlot;
				call dword ptr [cmdSelectItem];
				pop ecx;
			}
		}
	}
	return;	
}
in EQLib_Interp.cpp
// ***************************************************************************
// Function: TakeControlOfCommandList
// Description: Creates custom command list with our commands
// Points help/parsing at our list
// ***************************************************************************

Code: Select all

 		{"/selectitem",	"SelectItem"},
in EQLib_Main.cpp :
// EQ Functions Initialization

Code: Select all

fEQSelectItem	  cmdSelectItem	 =	NULL; 
// EQ Address Initialization

Code: Select all

DWORD *EQADDR_CLASSMERCHWND;
DWORD *EQADDR_CLASSTEXTUREANIMATION; 
// ***************************************************************************
// Function: ParseINIFile
// Description: Parse INI file for memory locations
// ***************************************************************************

Code: Select all

GetPrivateProfileString("Function Locations","SelectItem","0",szBuffer,MAX_STRING,ClientINI);		cmdSelectItem = (fEQSelectItem)strtoul(szBuffer,NULL,16);

	GetPrivateProfileString("Class Locations","ClassMerchWnd","0",szBuffer,MAX_STRING,ClientINI);		EQADDR_CLASSMERCHWND = (DWORD *)strtoul(szBuffer,NULL,16);
	GetPrivateProfileString("Class Locations","ClassTextureAnim","0",szBuffer,MAX_STRING,ClientINI);	EQADDR_CLASSTEXTUREANIMATION = (DWORD *)strtoul(szBuffer,NULL,16);
in MQ.h :
// ***************************************************************************
// Everquest function typedefs
// ***************************************************************************

Code: Select all

typedef VOID    (__cdecl *fEQSelectItem)(int,DWORD); [color=green]//public: void __thiscall CMerchantWnd::SelectBuySellSlot(int,class CTextureAnimation *)[/color]

 
// ***************************************************************************
// Exports
// ***************************************************************************

Code: Select all

extern "C" EQLIB_API VOID  SelectItem     (PSPAWNINFO, PCHAR);
 
in eqgame.ini :

Code: Select all

[Function Locations]
SelectItem=004E932D

[Class Locations]
ClassMerchWnd=005FE270
ClassTextureAnim=0077BF04 
ok last but not least the updated version of the EQWINDOW struct...
replace the one in MQ.h with theese two:

Code: Select all

//7-7-2003   eqmule 
typedef struct _EQWINDOWINFO { 
   DWORD   WindowStyle;            //if it is style then 04 = Window 01 = button 
   DWORD   Unknown1; 
   DWORD   Unknown2; 
   DWORD   Unknown3; 
   DWORD   Unknown4; 
   CHAR    WindowTitle[140]; 
   BYTE    Unknown5[12]; 
   DWORD   pNextAddress;            //most likely pointers to another structure... 
   DWORD   pPrevAddress; 
} EQWINDOWINFO, *PEQWINDOWINFO;         //ok it goes on and there are plenty more to pick up here, but I just need the name for now... 

typedef struct _EQWINDOW {
			DWORD   WindowID; 
			DWORD   TimeMouseOver;         //how many ms the window has had the mouse over it... 
			DWORD   Unknown0x008;      // 2000 seems a common value 
			DWORD   Unknown0x00c;      //500 seems a common value 
			BYTE    Flag; 
			BYTE    MouseOver;         //01 yes 00 no 
			BYTE    Unknown0x012; 
			BYTE    Unknown0x013; 
			BYTE    Unknown0x014[12]; 
			struct  _EQWINDOW *pDownTheTreeOnSameWindow; 
			struct  _EQWINDOW *pNextWindow; 
			DWORD   Flags4; 
			DWORD   Z;               //not sure but its logical to assume it at this point... 
			DWORD   X; 
			DWORD   Y; 
			DWORD   Height; 
			DWORD   Width; 
            DWORD   Depth;            //hmmm... 
            BYTE    Unknown0x040[12]; 
            BYTE    Open;            //1 open 0 closed 
            BYTE    Unknown0x051[7]; 
            DWORD   somekindofID; 
            DWORD   *pUnknownStruct0x060; 
            struct  _EQWINDOWINFO *Info; 
			BYTE	Unknown[84];
			union{
		PITEMINFO	Item;//only when structure is filled with a slot...
			struct	_EQWINDOW	*InvDecription;
			};
			BYTE	Unknown1[68];
			DWORD	SlotID;			//merchantslots start at 1770h bags at 16 and bagslots at fb inventory start at 0.
			BYTE	Unknown2[16];
			BYTE	Selector;		//this graphically selects an item on/off
			BYTE	Unknown3[3];
			DWORD	PushToSelector;
			BYTE	Unknown4[36];//364
		PITEMINFO	ItemDesc[80];	//the mainwindow has pointers directly to the items in the slots...
			DWORD	Unknown5;
			DWORD	FirstSlotIDforWindow;
			DWORD	AddressToPointerForSelectedItem;//
			DWORD	Unknown6;
			DWORD	ItemIconwnd;
			DWORD	Unknown7;
			DWORD	SellBuyButton;
			struct _EQWINDOW	*SlotsHandles[80];
			DWORD	DoneButton;
			DWORD	WindowFace;
} EQWINDOW, *PEQWINDOW;

typedef struct _EQCURRENTSELECTION {
			DWORD	Unknown;
			DWORD	SelectedWnd;//address to selection in tree
			DWORD	TextureAnim;
} EQCURRENTSELECTION, *PEQCURRENTSELECTION;

typedef struct _EQSLOTLIST {
			DWORD	Parent;
			DWORD	InvSlots[372];//0-21 inv 22-30 bags
} EQSLOTLIST, *PEQSLOTLIST;
and

Code: Select all

// 7-07-2003	Eqmule
#define ITEM_NAME_LEN         64
#define LORE_NAME_LEN         80
typedef struct _ITEMINFO {
/*0x0*/    BYTE      Unknown0x00; //placeholder
/*0x1*/    BYTE       Weight;
/*0x2*/    BYTE      NoRent;
/*0x3*/    BYTE      NoDrop;
/*0x4*/    BYTE      Size;
/*0x5*/    BYTE      Type;
/*0x6*/    BYTE      Unknown0x06[10];
/*0x10*/   CHAR      IDFile[30];
/*0x2e*/   CHAR      LoreName[LORE_NAME_LEN];
/*0x7e*/   BYTE      Unknown0x7e[14];
/*0x8c*/   DWORD     Cost;
/*0x90*/   CHAR      Name[ITEM_NAME_LEN];
/*0xd0*/   DWORD    IconNumber;
/*0xd4*/   DWORD    [b]SlotID;[/b]
/*0xd8*/   DWORD    Unknown0xd8;         
/*0xdc*/   DWORD    Unknown0xdc;   // -1 ?         
/*0xe0*/   DWORD    Unknown0xe0;   // -1 ?         
/*0xe4*/   DWORD    Unknown0xe4;            
/*0xe8*/   DWORD    Unknown0xe8;            
/*0xec*/   DWORD     ItemNumber;
/*0xf0*/   DWORD    Tradeskill; 

         union   {
/*0xf4*/   COMMON    Common;
/*0xf4*/   CONTAINER Container;
/*0xf4*/   BOOK      Book;
               };
} ITEMINFO, *PITEMINFO;
note that this _ITEMINFO struct is needed because I needed the slotID for my findcode...

Posted: Wed Jul 16, 2003 11:18 pm
by dont_know_at_all
fuck -- email me your files

Posted: Wed Jul 16, 2003 11:19 pm
by fryfrog
Perhaps I missed something, but I am getting the following error when trying to compile. I searched the entire thread for "EQADDR_INVENTORYWND" and only found two occurances, inside your MQ.h mods.

Code: Select all

EQLib_Commands.cpp(153) : error C2065: 'EQADDR_INVENTORYWND' : undeclared identifier
I commented those two lines out... lets see what happens :)

with the two lines commented out, it seems to work... but i am testing over vnc and telnet so i could be quite wrong :)

the item listing DOES work, but i never made it to a merchant remotely.