/Selectitem released (merchant & self listing/select ite

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

Moderator: MacroQuest Developers

EqMule
Developer
Developer
Posts: 2697
Joined: Fri Jan 03, 2003 9:57 pm
Contact:

/Selectitem released (merchant & self listing/select ite

Post by EqMule » Sun Jul 13, 2003 2:33 am

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.
Last edited by EqMule on Wed Jul 16, 2003 10:57 pm, edited 5 times in total.
My status o/
If you like MQ2 and would like to contribute, please do. My goal is 25 donations per month.
So far I've received Image donations for this month's patches.

Bitcoin: 1Aq8ackjQ4f7AUvbUL7BE6oPfT8PmNP4Zq
Krono: PM me.
I can always use characters for testing, PM me if you can donate one.

User avatar
dont_know_at_all
Developer
Developer
Posts: 5450
Joined: Sun Dec 01, 2002 4:15 am
Location: Florida, USA
Contact:

Post by dont_know_at_all » Sun Jul 13, 2003 2:55 am

learn to use diff!

cvs diff will do, too.

EqMule
Developer
Developer
Posts: 2697
Joined: Fri Jan 03, 2003 9:57 pm
Contact:

Post by EqMule » Sun Jul 13, 2003 3:01 am

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!
Last edited by EqMule on Tue Jul 15, 2003 4:04 am, edited 2 times in total.
My status o/
If you like MQ2 and would like to contribute, please do. My goal is 25 donations per month.
So far I've received Image donations for this month's patches.

Bitcoin: 1Aq8ackjQ4f7AUvbUL7BE6oPfT8PmNP4Zq
Krono: PM me.
I can always use characters for testing, PM me if you can donate one.

User avatar
dont_know_at_all
Developer
Developer
Posts: 5450
Joined: Sun Dec 01, 2002 4:15 am
Location: Florida, USA
Contact:

Post by dont_know_at_all » Sun Jul 13, 2003 3:57 am

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).

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

Post by Mckorr » Mon Jul 14, 2003 10:04 am

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.
MQ2: Think of it as Evolution in action.

EqMule
Developer
Developer
Posts: 2697
Joined: Fri Jan 03, 2003 9:57 pm
Contact:

Post by EqMule » Mon Jul 14, 2003 11:44 am

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 :)
My status o/
If you like MQ2 and would like to contribute, please do. My goal is 25 donations per month.
So far I've received Image donations for this month's patches.

Bitcoin: 1Aq8ackjQ4f7AUvbUL7BE6oPfT8PmNP4Zq
Krono: PM me.
I can always use characters for testing, PM me if you can donate one.

wassup
Official Guardian and Writer of TFM
Official Guardian and Writer of TFM
Posts: 1487
Joined: Sat Oct 26, 2002 5:15 pm

Post by wassup » Mon Jul 14, 2003 12:28 pm

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.

EqMule
Developer
Developer
Posts: 2697
Joined: Fri Jan 03, 2003 9:57 pm
Contact:

Post by EqMule » Mon Jul 14, 2003 12:36 pm

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...
My status o/
If you like MQ2 and would like to contribute, please do. My goal is 25 donations per month.
So far I've received Image donations for this month's patches.

Bitcoin: 1Aq8ackjQ4f7AUvbUL7BE6oPfT8PmNP4Zq
Krono: PM me.
I can always use characters for testing, PM me if you can donate one.

wassup
Official Guardian and Writer of TFM
Official Guardian and Writer of TFM
Posts: 1487
Joined: Sat Oct 26, 2002 5:15 pm

Post by wassup » Mon Jul 14, 2003 3:51 pm

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.

EqMule
Developer
Developer
Posts: 2697
Joined: Fri Jan 03, 2003 9:57 pm
Contact:

Post by EqMule » Mon Jul 14, 2003 4:00 pm

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
My status o/
If you like MQ2 and would like to contribute, please do. My goal is 25 donations per month.
So far I've received Image donations for this month's patches.

Bitcoin: 1Aq8ackjQ4f7AUvbUL7BE6oPfT8PmNP4Zq
Krono: PM me.
I can always use characters for testing, PM me if you can donate one.

wassup
Official Guardian and Writer of TFM
Official Guardian and Writer of TFM
Posts: 1487
Joined: Sat Oct 26, 2002 5:15 pm

Post by wassup » Mon Jul 14, 2003 4:27 pm

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.

User avatar
BlueSkies
a ghoul
a ghoul
Posts: 132
Joined: Tue Oct 01, 2002 6:22 pm

Post by BlueSkies » Tue Jul 15, 2003 3:28 am

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.
Live your dreams! Blue Skies everyone

EqMule
Developer
Developer
Posts: 2697
Joined: Fri Jan 03, 2003 9:57 pm
Contact:

/selectitem

Post by EqMule » Wed Jul 16, 2003 10:53 pm

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...
Last edited by EqMule on Mon Jul 21, 2003 8:47 pm, edited 12 times in total.
My status o/
If you like MQ2 and would like to contribute, please do. My goal is 25 donations per month.
So far I've received Image donations for this month's patches.

Bitcoin: 1Aq8ackjQ4f7AUvbUL7BE6oPfT8PmNP4Zq
Krono: PM me.
I can always use characters for testing, PM me if you can donate one.

User avatar
dont_know_at_all
Developer
Developer
Posts: 5450
Joined: Sun Dec 01, 2002 4:15 am
Location: Florida, USA
Contact:

Post by dont_know_at_all » Wed Jul 16, 2003 11:18 pm

fuck -- email me your files

fryfrog
a hill giant
a hill giant
Posts: 271
Joined: Fri Jun 20, 2003 5:37 am

Post by fryfrog » Wed Jul 16, 2003 11:19 pm

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.