[1.10] Gamble Screen Refresh

This forum is for discussions on how to edit what can not be edited through the txt files, needless to say this isn't about battle net hacking.

Moderators: Nefarius, Havvoric

User avatar
weapon-x
Forum Legend
Arch-Angel
Posts: 1047
Joined: Wed Mar 18, 2009 4:52 am
Location: Mindanao, Philippines
Philippines

[1.10] Gamble Screen Refresh

Post by weapon-x » Mon Nov 14, 2016 1:17 am

howdy everyone,

i am currently messing with C->S stuff and am planning to add a gamble refresh button.

i found functions related to vendor-store-item generation but sadly i left the func address and defs at home, what happens is that when the server receives a 0x38 with a parameter of 0D, it passes it to a table then calls the item-generate function (feel free to correct me if i am wrong, haha)

i'll post em first thing tomorrow...

i tried to replicate what the server does but could not seem to do so...

i also tried via client-side but still no luck... what happened in the client-side approach was it removed all other store tabs (armor, weapon, misc) just like how it appears in the gamble screen, but if you click the items to buy em, the are labeled "This item is already Traded"...

anyhow... will post em tomorrow

any help will be greatly appreciated :)

thanks
" It's not the size of the dog in the fight, it's the size of the fight in the dog. "

~Mark Twain

User avatar
Necrolis
Senior Admin
Throne
Posts: 9125
Joined: Sat Mar 25, 2006 1:22 pm
Location: The Land of the Dead
South Africa

Hand-picked

Re: [1.10] Gamble Screen Refresh

Post by Necrolis » Mon Nov 14, 2016 12:42 pm

A gamble refresh from what I remember doesn't need to much, basically you need to delete the entire gamble inventory, then refresh the unit to sync with the client, then create it again and sync the new items:

Code: Select all

/* 
	Date: Sat Jun 20 07:00:34 2009
	Author: Necrolis
	Function: STORES_FreeGamble
	Address: D2Game.0x6FCCD190
	Comments:
*/

void __fastcall STORES_FreeGamble(D2GameStrc* pGame, D2UnitStrc* pPlayer, D2UnitStrc* pNPC, D2NPCRecordStrc* pRecord)
//the above shouldn't be needed as the function that fills the gamble inv will flush old items itself.


/* 
	Date: Sat Jun 20 07:00:44 2009
	Author: Necrolis
	Function: STORES_FillGamble
	Address: D2Game.0x6FCCA9F0
	Comments:
*/

void __fastcall STORES_FillGamble(D2GameStrc* pGame, D2UnitStrc* pPlayer, D2UnitStrc* pNPC, D2NPCRecordStrc* pRecord)
{
	if(pGame == NULL || pPlayer == NULL || pNPC == NULL || pRecord == NULL)
		return;

	DWORD dwGUID = pPlayer->dwGUID;
	D2NPCGambleStrc* pGamble = pRecord->pGamble;
	while(pGamble != NULL)
	{
		D2NPCGambleStrc* pNext = pGamble->pNext;
		if(pGamble->dwGUID == dwGUID)
		{
			D2InventoryStrc* pInventory = pGamble->pInventory;

			if(pInventory)
			{
				STORES_DeleteAllGambleItems(pGame,pInventory);
				INVENTORY_Free(pInventory);
			}

			pGamble->dwGUID = INVALID_GUID;
			pGamble->pInventory = NULL;
		}

		pGamble = pNext;
	}

	STORES_CreateGambleInventory(pGame,pPlayer,pNPC,pRecord);
} 

//this is need after the function above
	UNITS_RefreshInventory(pNPC,TRUE);
	STORES_UpdateItems(pNPC,(bGamble) ? STORES_GetGambleInventory(pGame,pPlayer,pNPC) : pNPC->pInventory);

/* 
	Date: Sat Jun 20 07:01:16 2009
	Author: Necrolis
	Function: STORES_UpdateItems
	Address:
	Comments:
*/

void __fastcall STORES_UpdateItems(D2UnitStrc* pNPC, D2InventoryStrc* pInventory)
{
	if(pNPC == NULL || !GOODINV(pInventory))
		return;

	D2UnitStrc* pItem = INVENTORY_GetFirstItem(pInventory);
	while(pItem != NULL)
	{
		if(INVENTORY_CheckInvItem(pItem))
		{
			pItem->fUnitFlagsEx |= UNITFLAG_SHOPITEM;
			if(ITEMS_HasSockets(pItem))
				ITEMS_SetFlag(pItem,ITEMFLAG_NEWITEM,TRUE);

			ITEMS_UpdateTrade(pNPC->pInventory,pItem);
		}

		pItem = INVENTORY_GetNextItem(pItem);
	}
}
Image
Netiquette, Do you USE it?!?! | Nefarius' Fixed TXT Files | Terms Of Service
Blackened | Day of Death | D2GFEx
"What was yours is mine. Your land, your people, and now your life." - Lim-Dul, the Necromancer
Judgement is Final, Death is Eternal

User avatar
weapon-x
Forum Legend
Arch-Angel
Posts: 1047
Joined: Wed Mar 18, 2009 4:52 am
Location: Mindanao, Philippines
Philippines

Re: [1.10] Gamble Screen Refresh

Post by weapon-x » Tue Nov 15, 2016 12:55 am

Necrolis" wrote:A gamble refresh from what I remember doesn't need to much, basically you need to delete the entire gamble inventory, then refresh the unit to sync with the client, then create it again and sync the new items:

Code: Select all

/* 
	Date: Sat Jun 20 07:00:34 2009
	Author: Necrolis
	Function: STORES_FreeGamble
	Address: D2Game.0x6FCCD190
	Comments:
*/

void __fastcall STORES_FreeGamble(D2GameStrc* pGame, D2UnitStrc* pPlayer, D2UnitStrc* pNPC, D2NPCRecordStrc* pRecord)
//the above shouldn't be needed as the function that fills the gamble inv will flush old items itself.


/* 
	Date: Sat Jun 20 07:00:44 2009
	Author: Necrolis
	Function: STORES_FillGamble
	Address: D2Game.0x6FCCA9F0
	Comments:
*/

void __fastcall STORES_FillGamble(D2GameStrc* pGame, D2UnitStrc* pPlayer, D2UnitStrc* pNPC, D2NPCRecordStrc* pRecord)
{
	if(pGame == NULL || pPlayer == NULL || pNPC == NULL || pRecord == NULL)
		return;

	DWORD dwGUID = pPlayer->dwGUID;
	D2NPCGambleStrc* pGamble = pRecord->pGamble;
	while(pGamble != NULL)
	{
		D2NPCGambleStrc* pNext = pGamble->pNext;
		if(pGamble->dwGUID == dwGUID)
		{
			D2InventoryStrc* pInventory = pGamble->pInventory;

			if(pInventory)
			{
				STORES_DeleteAllGambleItems(pGame,pInventory);
				INVENTORY_Free(pInventory);
			}

			pGamble->dwGUID = INVALID_GUID;
			pGamble->pInventory = NULL;
		}

		pGamble = pNext;
	}

	STORES_CreateGambleInventory(pGame,pPlayer,pNPC,pRecord);
} 

//this is need after the function above
	UNITS_RefreshInventory(pNPC,TRUE);
	STORES_UpdateItems(pNPC,(bGamble) ? STORES_GetGambleInventory(pGame,pPlayer,pNPC) : pNPC->pInventory);

/* 
	Date: Sat Jun 20 07:01:16 2009
	Author: Necrolis
	Function: STORES_UpdateItems
	Address:
	Comments:
*/

void __fastcall STORES_UpdateItems(D2UnitStrc* pNPC, D2InventoryStrc* pInventory)
{
	if(pNPC == NULL || !GOODINV(pInventory))
		return;

	D2UnitStrc* pItem = INVENTORY_GetFirstItem(pInventory);
	while(pItem != NULL)
	{
		if(INVENTORY_CheckInvItem(pItem))
		{
			pItem->fUnitFlagsEx |= UNITFLAG_SHOPITEM;
			if(ITEMS_HasSockets(pItem))
				ITEMS_SetFlag(pItem,ITEMFLAG_NEWITEM,TRUE);

			ITEMS_UpdateTrade(pNPC->pInventory,pItem);
		}

		pItem = INVENTORY_GetNextItem(pItem);
	}
}
woah, thank you for sharing sir...

sadly, i am quite unfamiliar with this new data structs

Code: Select all

D2NPCRecordStrc*
D2NPCGambleStrc*
edit: while searching the keep i found senior mod-maker Nefarius' post on NPCs

here
viewtopic.php?f=8&t=47132&hilit=NPCRecord

Code: Select all

struct NpcRecord
{
int npcNo;
Inventory* pInventory;
DWORD uk1;
BOOL bGambleInit;
DWORD uk2[4];
bool bools[9];
DWORD dwTicks;
UnitProxy proxy;
DWORD uk3[2];
};

Code: Select all

struct UnitProxy
{
ItemCache* cache;
int nItems;
DWORD* permCodes;
int nPerms;
};
is UnitProxy = pGamble? or a separate member of the NPCRecordStructure? :mrgreen:

On a side note, these functions that i was trying to analyze, during my attempts :lol:

Code: Select all

ClientSide
{
*D2CLIENT_6FBB5C3B = 3;   //seems to be a global dword
*D2CLIENT_6FBB5D7C = 1;  //a global dword

D2CLIENT_6FB23260(0x0C, 0, 0);  //seems to be ui related? perhaps this removes that vendor tabs?
D2CLIENT_6FAADA70(0x38, 2, NPCGUID, 0); //2 = gamble_transaction_type

*D2CLIENT_6FBB5DA0 = pPlayer;   //D2UnitStrc* global, a deeper client_function might be fetching this -_-
*D2CLIENT_6FBB5DA4 = 0;   //i have no idea :D
}
and the server functions:

Code: Select all

D2GAME_6FCC9F40, void, __fastcall, (D2GameStrc* pGame, D2UnitStrc* pPlayer, DWORD dwTransactionType, DWORD dwNPCGUID, DWORD dwZero)

D2GAME_6FCC74F0, void, __fastcall, (D2GameStrc* pGame, D2UnitStrc* pPlayer, D2UnitStrc* pNPC, D2UnitStrc* pPlayer2, BOOL bOneZero), 0x974F0) //NPC Item Generation Related last arg is 1 for gamble and 0 for normal trade

D2GAME_6FC61AF0, void, __fastcall, (D2UnitStrc* pNPC, D2UnitStrc* pPlayer)

D2GAME_6FCCAE20, void, __fastcall, (D2GameStrc* pGame, D2UnitStrc* pPlayer, D2UnitStrc* pNPC, DWORD dwZero)
" It's not the size of the dog in the fight, it's the size of the fight in the dog. "

~Mark Twain

User avatar
Necrolis
Senior Admin
Throne
Posts: 9125
Joined: Sat Mar 25, 2006 1:22 pm
Location: The Land of the Dead
South Africa

Hand-picked

Re: [1.10] Gamble Screen Refresh

Post by Necrolis » Wed Nov 16, 2016 1:52 am

Code: Select all

gnNPCInteractState  //0x6FBB5C3B
gbDisableVendorTabNames //0x6FBB5D7C
gpActiveVendorPlayer //0x6FBB5DA0
gnNPCTrade //0x6FBB5DA4

/* 
	Date: Mon Jul 27 14:22:02 2009
	Author: Necrolis
	Function: DISPLAY_SetUIToggle
	Address: D2Client.0x6FB23260
	Comments:
*/

BOOL __fastcall DISPLAY_SetUIToggle(int nToggle, int nState, int nType)

void,__fastcall,D2SendVendorPacket,(short nType, int nSubType, DWORD dwNPCGUID, DWORD dwPlayerGUID),(D2ClientBase + 0xDA70)

/* 
	Date: Wed May 19 16:35:31 2010
	Author: Necrolis
	Function: NPCS_HandleDialogMessage
	Address: D2Game.0x6FCC9F40
	Comments: 
*/

BOOL __fastcall NPCS_HandleDialogMessage(D2GameStrc* pGame, D2UnitStrc* pPlayer, D2UnitStrc* pNPC, int nSubType, DWORD dwArg)

/* 
	Date: Sat Jun 20 07:00:52 2009
	Author: Necrolis
	Function: STORES_CreateVendorCache
	Address: D2Game.0x6FCC74F0 & D2Game.0x6FCCAE20
	Comments:
*/

void __fastcall STORES_CreateVendorCache(D2GameStrc* pGame, D2UnitStrc* pPlayer, D2UnitStrc* pNPC, BOOL bGamble)

/* 
	Date: Tue Dec 08 08:53:12 2009
	Author: Necrolis
	Function: NPCS_SetInteractTrading
	Address: D2Game.0x6FC61AF0
	Comments:
*/

void __fastcall NPCS_SetInteractTrading(D2UnitStrc* pNPC, D2UnitStrc* pPlayer)
As for the gamble and NPC record stuff:

Code: Select all

struct D2NPCGambleStrc				//sizeof 0xC
{
	D2InventoryStrc* pInventory;	//+00
	DWORD dwGUID;					//+04
	D2NPCGambleStrc* pNext;			//+08
};

struct D2NPCRecordStrc				//sizeof 0x44
{
    int nNPC;                       //+00
    D2InventoryStrc* pInventory;    //+04
    D2NPCGambleStrc* pGamble;       //+08
    BOOL bGambleInit;               //+0C
    D2MercDataStrc* pMercData;      //+10
    D2NPCEventStrc* pEvent;         //+14
	D2VendorChainStrc* pVendorChain;//+18
	BOOL bTrading;					//+1C
	union
	{
		struct
		{
			union
			{
				bool bFlags[8];             //+20
				struct
				{
					bool bVendorInit;		//+20
					bool bHireInit;			//+21
					BYTE nAct;				//+22
					bool bTrader;			//+23
					bool bLevelRefresh;		//+24
					bool bInited;			//+25
					bool bForceVendor;		//+26
					bool bRefreshInventory;	//+27
				};
			};
			
			DWORD dwTicks;                  //+28
			D2UnitProxyStrc pProxy;         //+2C
			DWORD dwUnk;					//+3C
			DWORD dwNPCGUID;				//+40
		};

		D2NPCTradeStrc pTrade;				//+20
	};
}; 
Image
Netiquette, Do you USE it?!?! | Nefarius' Fixed TXT Files | Terms Of Service
Blackened | Day of Death | D2GFEx
"What was yours is mine. Your land, your people, and now your life." - Lim-Dul, the Necromancer
Judgement is Final, Death is Eternal

User avatar
weapon-x
Forum Legend
Arch-Angel
Posts: 1047
Joined: Wed Mar 18, 2009 4:52 am
Location: Mindanao, Philippines
Philippines

Re: [1.10] Gamble Screen Refresh

Post by weapon-x » Wed Nov 16, 2016 3:03 am

Necrolis" wrote:

Code: Select all

gnNPCInteractState  //0x6FBB5C3B
gbDisableVendorTabNames //0x6FBB5D7C
gpActiveVendorPlayer //0x6FBB5DA0
gnNPCTrade //0x6FBB5DA4

/* 
	Date: Mon Jul 27 14:22:02 2009
	Author: Necrolis
	Function: DISPLAY_SetUIToggle
	Address: D2Client.0x6FB23260
	Comments:
*/

BOOL __fastcall DISPLAY_SetUIToggle(int nToggle, int nState, int nType)

void,__fastcall,D2SendVendorPacket,(short nType, int nSubType, DWORD dwNPCGUID, DWORD dwPlayerGUID),(D2ClientBase + 0xDA70)

/* 
	Date: Wed May 19 16:35:31 2010
	Author: Necrolis
	Function: NPCS_HandleDialogMessage
	Address: D2Game.0x6FCC9F40
	Comments: 
*/

BOOL __fastcall NPCS_HandleDialogMessage(D2GameStrc* pGame, D2UnitStrc* pPlayer, D2UnitStrc* pNPC, int nSubType, DWORD dwArg)

/* 
	Date: Sat Jun 20 07:00:52 2009
	Author: Necrolis
	Function: STORES_CreateVendorCache
	Address: D2Game.0x6FCC74F0 & D2Game.0x6FCCAE20
	Comments:
*/

void __fastcall STORES_CreateVendorCache(D2GameStrc* pGame, D2UnitStrc* pPlayer, D2UnitStrc* pNPC, BOOL bGamble)

/* 
	Date: Tue Dec 08 08:53:12 2009
	Author: Necrolis
	Function: NPCS_SetInteractTrading
	Address: D2Game.0x6FC61AF0
	Comments:
*/

void __fastcall NPCS_SetInteractTrading(D2UnitStrc* pNPC, D2UnitStrc* pPlayer)
As for the gamble and NPC record stuff:

Code: Select all

struct D2NPCGambleStrc				//sizeof 0xC
{
	D2InventoryStrc* pInventory;	//+00
	DWORD dwGUID;					//+04
	D2NPCGambleStrc* pNext;			//+08
};

struct D2NPCRecordStrc				//sizeof 0x44
{
    int nNPC;                       //+00
    D2InventoryStrc* pInventory;    //+04
    D2NPCGambleStrc* pGamble;       //+08
    BOOL bGambleInit;               //+0C
    D2MercDataStrc* pMercData;      //+10
    D2NPCEventStrc* pEvent;         //+14
	D2VendorChainStrc* pVendorChain;//+18
	BOOL bTrading;					//+1C
	union
	{
		struct
		{
			union
			{
				bool bFlags[8];             //+20
				struct
				{
					bool bVendorInit;		//+20
					bool bHireInit;			//+21
					BYTE nAct;				//+22
					bool bTrader;			//+23
					bool bLevelRefresh;		//+24
					bool bInited;			//+25
					bool bForceVendor;		//+26
					bool bRefreshInventory;	//+27
				};
			};
			
			DWORD dwTicks;                  //+28
			D2UnitProxyStrc pProxy;         //+2C
			DWORD dwUnk;					//+3C
			DWORD dwNPCGUID;				//+40
		};

		D2NPCTradeStrc pTrade;				//+20
	};
}; 
its time for some function crackdown :mrgreen:

8-O

thank you so much for sharing another set of code-gems to the community sir,

its amazing how you managed to map-out and define all this mind-bugling functions and data structures...

:)

a million thanks !
" It's not the size of the dog in the fight, it's the size of the fight in the dog. "

~Mark Twain

Return to “Code Editing”