plugy/PlugY/InfinityStash.cpp
2017-06-19 15:01:03 +02:00

1032 lines
28 KiB
C++

/*=================================================================
File created by Yohann NICOLAS.
Add support 1.13d by L'Autour.
Gestion of the infinity and shared Stash.
=================================================================*/
#include "infinityStash.h"
#include "updateClient.h"
#include "interface_Stash.h"
#include "common.h"
#define STASH_TAG 0x5453 //"ST"
#define JM_TAG 0x4D4A //"JM"
DWORD maxSelfPages = -1;
DWORD maxSharedPages = -1;
DWORD nbPagesPerIndex = 10;
DWORD nbPagesPerIndex2 = 100;
bool active_multiPageStash = false;
bool active_sharedStash = false;
bool separateHardSoftStash = false;
bool active_sharedGold=false;
char* sharedStashFilename = NULL;
typedef int (*TchangeToSelectedStash)(Unit* ptChar, Stash* newStash, DWORD bOnlyItems, DWORD bIsClient);
Unit* firstClassicStashItem(Unit* ptChar)
{
Unit* ptItem = D2InventoryGetFirstItem(PCInventory);
while (ptItem)
{
if (D2ItemGetPage(D2GetRealItem(ptItem)) == 4)
return ptItem;
ptItem = D2UnitGetNextItem(ptItem);
}
return NULL;
}
DWORD endStashList(Unit* ptChar, Stash* ptStash)//WORKS
{
Stash* stash = ptStash;
while (stash)
{
if (stash->ptListItem || ((stash == PCPY->currentStash) && firstClassicStashItem(ptChar))) return 0;
if (stash->isIndex || (stash->name != NULL && stash->name[0])) return 0;
stash = stash->nextStash;
}
return 1;
}
//bool isInList(Stash* list, Stash* pStash)
//{
// Stash* ptStash = list;
// while(ptStash)
// {
// if (ptStash->id == pStash->id) return true;
// ptStash = ptStash->nextStash;
// }
// return false;
//}
Stash* getLastStash(Stash* ptStash)//WORKS
{
Stash* stash = ptStash;
if (!stash) return NULL;
while (stash->nextStash)
stash = stash->nextStash;
return stash;
}
Stash* newStash(DWORD id)
{
d2_assert( id == 0xFFFFFFFF , "Too much stash", __FILE__, __LINE__);
Stash* stash = (Stash*)malloc(sizeof(Stash));//D2AllocMem(memPool, sizeof(Stash),__FILE__,__LINE__,0);
d2_assert(!stash , "Error on stash allocation.", __FILE__, __LINE__);
ZeroMemory(stash, sizeof(Stash));
stash->id = id;
return stash;
}
Stash* addStash(Unit* ptChar, bool isShared)
{
Stash* previous;
Stash* stash;
// DWORD memPool = PCGame ? PCGame->memoryPool :0;
if (isShared)
{
previous = getLastStash(PCPY->sharedStash);
stash = newStash(PCPY->nbSharedPages++);
} else {
previous = getLastStash(PCPY->selfStash);
stash = newStash(PCPY->nbSelfPages++);
}
stash->isShared = isShared;
stash->previousStash = previous;
if (previous)
previous->nextStash = stash;
else if (isShared)
PCPY->sharedStash = stash;
else
PCPY->selfStash = stash;
log_msg("AddStash: stash->id=%d\tstash->isShared=%d\tstash->previous=%08X\tnbSelf=%d\tnbShared=%d\n",
stash->id,stash->isShared,stash->previousStash,PCPY->nbSelfPages,PCPY->nbSharedPages);
return stash;
}
Stash* getStash(Unit* ptChar, DWORD isShared, DWORD id)//WORKS
{
Stash* ptStash = isShared ? PCPY->sharedStash : PCPY->selfStash;
while(ptStash)
{
if (ptStash->id == id) return ptStash;
ptStash = ptStash->nextStash;
}
return NULL;
}
int changeToSelectedStash_9(Unit* ptChar, Stash* newStash, DWORD bOnlyItems, DWORD bIsClient)
{
if (!newStash) return 0;
log_msg("changeToSelectedStash ID:%d\tshared:%d\tonlyItems:%d\tclient:%d\n", newStash->id, newStash->isShared, bOnlyItems, bIsClient);
Stash* currentStash = PCPY->currentStash;
if (currentStash == newStash) return 0;
d2_assert( currentStash && currentStash->ptListItem, "ERROR : currentStash isn't empty (ptListItem != NULL)",__FILE__,__LINE__);
// collect items to remove
Inventory* ptInventory = PCInventory;
Unit* ptNextItem;
Unit* ptPrevItem = NULL;
Unit* ptItem = D2InventoryGetFirstItem(ptInventory);
while (ptItem)
{
ptNextItem = D2UnitGetNextItem(ptItem);
if (D2ItemGetPage(D2GetRealItem(ptItem)) == 4)
{
D2SetAnim(D2GetRealItem(ptItem),-1);
if (ptPrevItem) {
ptPrevItem->CurrentAnim = (DWORD)ptNextItem;//is ptPrevItem->nextNode = ptNextItem;
} else {
ptInventory->currentUsedSocket = (DWORD)ptNextItem;//is ptInventory->ptListItem = ptNextItem;
}
if (!ptNextItem)
ptInventory->Inventory2C = (DWORD)ptPrevItem;
ptInventory->Inventory30 = ptInventory->Inventory30 - 1;
D2Common10250(__FILE__,__LINE__,ptInventory, D2GetPosX(D2GetRealItem(ptItem)), D2GetPosY(D2GetRealItem(ptItem)), 0xC, bIsClient, 4);
// ptItem = D2InvRemoveItem(PCInventory, D2GetRealItem(ptItem));
// D2Common10250(__FILE__,__LINE__,PCInventory, D2GetPosX(ptItem), D2GetPosY(ptItem), 0xC, bIsClient, 4);
if (currentStash)
{
// ptItem = setNextItem(ptItem, PCPY->currentStash->ptListItem);
ptItem->CurrentAnim = (DWORD)currentStash->ptListItem;//is ptItem->nextNode = ptListItem
currentStash->ptListItem = ptItem;
};
} else ptPrevItem = ptItem;
ptItem = ptNextItem;
}
// add items of new stash
ptItem = newStash->ptListItem;
while (ptItem)
{
D2InvAddItem(PCInventory, D2GetRealItem(ptItem), D2GetPosX(D2GetRealItem(ptItem)), D2GetPosY(D2GetRealItem(ptItem)), 0xC, bIsClient, 4);
D2Common10242(PCInventory, D2GetRealItem(ptItem), 1);
ptItem = D2UnitGetNextItem(ptItem);
}
if (bOnlyItems)
newStash->ptListItem = PCPY->currentStash->ptListItem;
else
PCPY->currentStash = newStash;
PCPY->currentStash->ptListItem = NULL;
return 1;
}
int changeToSelectedStash_10(Unit* ptChar, Stash* newStash, DWORD bOnlyItems, DWORD bIsClient)
{
if (!newStash) return 0;
log_msg("changeToSelectedStash ID:%d\tshared:%d\tonlyItems:%d\tclient:%d\n",newStash->id,newStash->isShared, bOnlyItems,bIsClient);
Stash* currentStash = PCPY->currentStash;
if (currentStash == newStash) return 0;
d2_assert( currentStash && currentStash->ptListItem, "ERROR : currentStash isn't empty (ptListItem != NULL)",__FILE__,__LINE__);
// Remove items from current page
Unit* ptNextItem;
Unit* ptItem = D2InventoryGetFirstItem(PCInventory);
while (ptItem)
{
ptNextItem = D2UnitGetNextItem(ptItem);
if (D2ItemGetPage(ptItem) == 4)
{
BYTE tmp = ptItem->ptItemData->ItemData2;
ptItem = D2InvRemoveItem(PCInventory, ptItem);
ptItem->ptItemData->ItemData2 = tmp;
if (currentStash)
{
ptItem->ptItemData->ptNextItem = currentStash->ptListItem;
currentStash->ptListItem = ptItem;
}
}
ptItem = ptNextItem;
}
// add items of new stash
ptItem = newStash->ptListItem;
while (ptItem)
{
D2InvAddItem(PCInventory, ptItem, ptItem->path->x, ptItem->path->y, 0xC, bIsClient, 4);
ptItem = D2UnitGetNextItem(ptItem);
}
if (bOnlyItems)
newStash->ptListItem = PCPY->currentStash->ptListItem;
else
PCPY->currentStash = newStash;
PCPY->currentStash->ptListItem = NULL;
return 1;
}
TchangeToSelectedStash changeToSelectedStash;
DWORD loadStash(Unit* ptChar, Stash* ptStash, BYTE data[], DWORD startSize, DWORD maxSize, DWORD* retSize)
{
DWORD curSize = startSize;
DWORD nbBytesRead;
log_msg("loadStash\n");
*retSize = curSize;
if( *(WORD *)&data[curSize] != STASH_TAG )//"ST"
{
log_msg("loadStash -> Bad tag of stash of character %s : %04X\n",PCPlayerData->name,*(WORD *)&data[curSize]);
return 0x7;//Unable to enter game. Bad inventory data
}
curSize += 2;
// Read flags.
int len = strlen((char*)&data[curSize]);
if (*(WORD*)&data[curSize + len + 1] != JM_TAG)
{
ptStash->flags = *(DWORD *)&data[curSize];
curSize += 4;
}
// Read Name
// if (strlen((char *)&data[curSize]) > 0xF)
// *(char *)&data[curSize+0xF] = NULL;
if (strlen((char *)&data[curSize]))
ptStash->name = (char*)malloc(strlen((char *)&data[curSize]));//D2AllocMem(PCGame->memoryPool, strlen((char *)&data[curSize]),__FILE__,__LINE__,0);
if (ptStash->name)
strcpy(ptStash->name, (char *)&data[curSize]);
curSize += strlen((char *)&data[curSize]) + 1;
// Read inventory.
DWORD ret = D2LoadInventory(PCGame, ptChar, (saveBitField*)&data[curSize], 0x60, maxSize-curSize, 0, &nbBytesRead);
if (ret) log_msg("loadStash -> D2LoadInventory failed\n");
log_msg("Stash loaded (%d : %s)\n", ptStash->id ,ptStash->name);
*retSize=curSize + nbBytesRead;
return ret;
}
DWORD loadStashList(Unit* ptChar, BYTE* data, DWORD maxSize, DWORD* curSize, bool isShared)//WORKS
{
DWORD curStash = 0;
Stash* newStash;
DWORD nbStash = *(DWORD*)&data[*curSize];
*curSize += 4;
while (curStash < nbStash)
{
newStash = addStash(ptChar, isShared);
changeToSelectedStash(ptChar, newStash, 0, false);
DWORD ret = loadStash(ptChar, newStash, data, *curSize, 10000000, curSize);
if (ret) return ret;
curStash++;
}
if (!isShared && !PCPY->selfStash)
{
newStash = addStash(ptChar, isShared);
PCPY->currentStash = newStash;
}
if (isShared && !PCPY->sharedStash)
{
newStash = addStash(ptChar, isShared);
if (!PCPY->currentStash)
PCPY->currentStash = newStash;
}
return 0;
}
//ADDDATA(DWORD, curSize, 0);
#define DATA (*data + *curSize)
#define ADDDATA(T) (T*)DATA; *curSize += sizeof(T)
#define SETDATA(T,V) *(T*)DATA = V; *curSize += sizeof(T)
void saveStash(Unit* ptChar, Stash* ptStash, BYTE** data, DWORD* maxSize, DWORD* curSize)
{
//write "ST"
SETDATA(WORD, STASH_TAG);
//Write flags.
SETDATA(DWORD, ptStash->flags);
//save name
if (ptStash->name)
{
int size = strlen(ptStash->name);
if (size > 15) size = 15;
strncpy((char*)DATA, ptStash->name, size);
*curSize += size;
}
SETDATA(char, NULL);
//Write "JM" of inventory
SETDATA(WORD, JM_TAG);
//Get position of counter of items in inventory
WORD* ptNBItem = ADDDATA(WORD);
*ptNBItem = 0;
//Get first item
Unit* ptItem;
if ((ptStash->id == PCPY->currentStash->id) && (ptStash->isShared == PCPY->currentStash->isShared))
ptItem = D2InventoryGetFirstItem(PCInventory);
else
ptItem = ptStash->ptListItem;
//Write all items
while (ptItem)
{
if (D2ItemGetPage(D2GetRealItem(ptItem)) == 4)
{
int nbBytes = D2SaveItem(D2GetRealItem(ptItem), (saveBitField*)DATA, *maxSize - *curSize, 1, 1, 0);
d2_assert(!nbBytes, "!\"Character has too many items\"", __FILE__, __LINE__ );
*curSize += nbBytes;
(*ptNBItem)++;
}
ptItem = D2UnitGetNextItem(ptItem);
}
}
void saveStashList(Unit* ptChar, Stash* ptStash, BYTE** data, DWORD* maxSize, DWORD* curSize)
{
DWORD curSizeNbStash = *curSize;
*curSize += sizeof(DWORD);
DWORD nbStash=0;
while(ptStash)
{
if (*curSize + 0x2000 > *maxSize)
{
BYTE* oldData = *data;
*maxSize *= 2;
*data = (BYTE *)D2AllocMem(PCGame->memoryPool, *maxSize,__FILE__,__LINE__,0);
d2_assert(!*data, "Error : Memory allocation", __FILE__, __LINE__);
CopyMemory(*data, oldData, *curSize);
D2FreeMem(PCGame->memoryPool, oldData,__FILE__,__LINE__,0);
}
saveStash(ptChar, ptStash, data, maxSize, curSize);
nbStash++;
ptStash = endStashList(ptChar, ptStash->nextStash) ? NULL : ptStash->nextStash;
}
*(DWORD*)(*data + curSizeNbStash) = nbStash;
}
/////// client
void updateSelectedStashClient(Unit* ptChar)//WORKS
{
Stash* newStash = PCPY->currentStash;
if (!newStash)
return;
updateClient(ptChar, UC_SELECT_STASH, newStash->id, newStash->flags, PCPY->flags);
updateClient(ptChar, UC_PAGE_NAME, newStash->name);
}
void setSelectedStashClient(DWORD stashId, DWORD stashFlags, DWORD flags, bool bOnlyItems)//WORKS
{
log_msg("setSelectedStashClient ID:%d, stashFlags:%d, flags:%08X\n", stashId, stashFlags, flags);
Unit* ptChar = D2GetClientPlayer();
Stash* newStash = getStash(ptChar, (stashFlags & 1) == 1, stashId);
if (!newStash) do
newStash = addStash(ptChar, (stashFlags & 1) == 1);
while (newStash->id < stashId);
newStash->flags = stashFlags;
changeToSelectedStash(ptChar, newStash, bOnlyItems, 1);
PCPY->flags = flags;
}
void selectStash(Unit* ptChar, Stash* newStash)
{
if (!newStash)
return;
changeToSelectedStash(ptChar, newStash, 0, 0);
updateSelectedStashClient(ptChar);
}
///// public functions
void toggleToSelfStash(Unit* ptChar)
{
Stash* selStash = PCPY->selfStash;
if (selStash && (selStash != PCPY->currentStash))
{
PCPY->showSharedStash = false;
selectStash(ptChar, selStash);
}
}
void toggleToSharedStash(Unit* ptChar)
{
Stash* selStash = PCPY->sharedStash;
if (selStash && (selStash != PCPY->currentStash))
{
PCPY->showSharedStash = true;
selectStash(ptChar, selStash);
}
}
void swapStash(Unit* ptChar, Stash* curStash, Stash* swpStash)
{
if (!ptChar || !curStash || !swpStash || curStash == swpStash)
return;
changeToSelectedStash(ptChar, swpStash, 1, 0);
updateClient(ptChar, UC_SELECT_STASH, swpStash->id, swpStash->flags | 8, PCPY->flags);
}
void toggleStash(Unit* ptChar, DWORD page)
{
log_msg("toggle stash page = %u\n", page);
Stash* curStash = PCPY->currentStash;
Stash* swpStash = curStash->isShared ? PCPY->selfStash : PCPY->sharedStash;
swapStash(ptChar, curStash, swpStash);
}
void swapStash(Unit* ptChar, DWORD page, bool toggle)
{
log_msg("swap stash page = %u\n", page);
Stash* curStash = PCPY->currentStash;
Stash* swpStash = curStash->isShared == toggle ? PCPY->selfStash : PCPY->sharedStash;
for (DWORD i = 0; i < page; i++)
{
if (curStash->nextStash == NULL)
addStash(ptChar, swpStash->isShared);
swpStash = swpStash->nextStash;
}
swapStash(ptChar, curStash, swpStash);
}
void insertStash(Unit* ptChar)
{
Stash* curStash = PCPY->currentStash;
Stash* stash = addStash(ptChar, curStash->isShared);
while (stash->previousStash != curStash)
{
stash->flags = stash->previousStash->flags;
stash->name = stash->previousStash->name;
stash->ptListItem = stash->previousStash->ptListItem;
stash = stash->previousStash;
}
stash->isIndex = 0;
stash->isMainIndex = 0;
stash->name = NULL;
stash->ptListItem = NULL;
}
bool deleteStash(Unit* ptChar, bool isClient)
{
if (firstClassicStashItem(ptChar) != NULL)
return false;
//if (D2InventoryGetFirstItem())
Stash* stash = PCPY->currentStash;
if (stash->nextStash == NULL)
{
stash->isIndex = 0;
stash->isMainIndex = 0;
stash->name = NULL;
return true;
}
stash->flags = stash->nextStash->flags;
stash->name = stash->nextStash->name;
if (stash->nextStash->ptListItem != NULL)
changeToSelectedStash(ptChar, stash->nextStash, 1, isClient);
stash = stash->nextStash;
while (stash->nextStash)
{
stash->flags = stash->nextStash->flags;
stash->name = stash->nextStash->name;
stash->ptListItem = stash->nextStash->ptListItem;
stash = stash->nextStash;
}
stash->isIndex = 0;
stash->isMainIndex = 0;
stash->name = NULL;
stash->ptListItem = NULL;
return true;
}
void renameCurrentStash(Unit* ptChar, char* name)
{
log_msg("renameCurrentStash : %08X, %s\n", ptChar, name);
Stash* stash = PCPY->currentStash;
int len = 0;
if (name != NULL)
len = strlen(name);
log_msg("renameCurrentStash : %d\n", len);
if (stash->name)
D2FogMemDeAlloc(stash->name, __FILE__, __LINE__, 0);
log_msg("renameCurrentStash 3\n");
if (len > 0)
{
stash->name = (char *)malloc(len);//D2FogMemAlloc(len,__FILE__,__LINE__,0);
strcpy(stash->name, name);
}
else
stash->name = NULL;
log_msg("renameCurrentStash 4\n");
}
void setCurrentStashIndex(Unit* ptChar, int index)
{
if (!PCPY->currentStash)
return;
PCPY->currentStash->isIndex = index >= 1;
PCPY->currentStash->isMainIndex = index == 2;
updateSelectedStashClient(ptChar);
}
void selectPreviousStash(Unit* ptChar)
{
Stash* selStash = PCPY->currentStash->previousStash;
if (selStash && (selStash != PCPY->currentStash))
selectStash(ptChar, selStash);
}
void selectPrevious2Stash(Unit* ptChar)// Select first stash
{
Stash* selStash = PCPY->showSharedStash ? PCPY->sharedStash : PCPY->selfStash;
if (selStash && (selStash != PCPY->currentStash))
selectStash(ptChar, selStash);
}
void selectNextStash(Unit* ptChar)
{
Stash* selStash = PCPY->currentStash;
if (!selStash->isShared && (selStash->id >= maxSelfPages)) return;
if (selStash->isShared && (selStash->id >= maxSharedPages)) return;
selStash = selStash->nextStash ? selStash->nextStash : addStash(ptChar, PCPY->showSharedStash);
if (selStash && (selStash != PCPY->currentStash))
selectStash(ptChar, selStash);
}
void selectNext2Stash(Unit* ptChar)//select last stash
{
Stash* selStash = PCPY->showSharedStash ? PCPY->sharedStash : PCPY->selfStash;//PCPY->currentStash;
Stash* lastStash = NULL;
Unit* currentStashItem = firstClassicStashItem(ptChar);
while (selStash)
{
if (selStash->ptListItem || (selStash == PCPY->currentStash) && currentStashItem) lastStash=selStash;
selStash = selStash->nextStash;
}
if (!lastStash)
lastStash = PCPY->showSharedStash ? PCPY->sharedStash : PCPY->selfStash;
if (lastStash != PCPY->currentStash)
selectStash(ptChar, lastStash);
}
void selectPreviousIndexStash(Unit* ptChar)
{
selectPreviousStash(ptChar);
Stash* selStash = PCPY->currentStash;
while (selStash && !selStash->isIndex)
selStash = selStash->previousStash;
if (selStash == NULL)
{
selStash = PCPY->currentStash;
while (selStash->previousStash && ((selStash->id + 1) % nbPagesPerIndex != 0))
selStash = selStash->previousStash;
}
if (selStash && (selStash != PCPY->currentStash))
selectStash(ptChar, selStash);
}
void selectPreviousIndex2Stash(Unit* ptChar)
{
selectPreviousStash(ptChar);
Stash* selStash = PCPY->currentStash;
while (selStash && !selStash->isMainIndex)
selStash = selStash->previousStash;
if (selStash == NULL)
{
selStash = PCPY->currentStash;
while (selStash->previousStash && ((selStash->id+1) % nbPagesPerIndex2 != 0))
selStash = selStash->previousStash;
}
if (selStash && (selStash != PCPY->currentStash))
selectStash(ptChar, selStash);
}
void selectNextIndexStash(Unit* ptChar)
{
selectNextStash(ptChar);
Stash* selStash = PCPY->currentStash;
while (selStash && !selStash->isIndex)
selStash = selStash->nextStash;
if (selStash == NULL)
{
selStash = PCPY->currentStash;
while ((selStash->id + 1) % nbPagesPerIndex != 0)
{
if (!selStash->isShared && (selStash->id >= maxSelfPages)) break;
if (selStash->isShared && (selStash->id >= maxSharedPages)) break;
selStash = selStash->nextStash ? selStash->nextStash : addStash(ptChar, PCPY->showSharedStash);;
}
}
if (selStash && (selStash != PCPY->currentStash))
selectStash(ptChar, selStash);
}
void selectNextIndex2Stash(Unit* ptChar)
{
selectNextStash(ptChar);
Stash* selStash = PCPY->currentStash;
while (selStash && !selStash->isMainIndex)
selStash = selStash->nextStash;
if (selStash == NULL)
{
selStash = PCPY->currentStash;
while ((selStash->id+1) % nbPagesPerIndex2 != 0)
{
if (!selStash->isShared && (selStash->id >= maxSelfPages)) break;
if (selStash->isShared && (selStash->id >= maxSharedPages)) break;
selStash = selStash->nextStash ? selStash->nextStash : addStash(ptChar, PCPY->showSharedStash);;
}
}
if (selStash && (selStash != PCPY->currentStash))
selectStash(ptChar, selStash);
}
//////////////////////////////////////////////////////////////////////
Stash* curStash2;
DWORD currentSawStash2;
Unit* STDCALL getNextItem(Unit* ptChar, Unit* ptItem)
{
Unit* item = D2UnitGetNextItem(ptItem);
if (item) return item;
if (!curStash2)
{
switch (currentSawStash2)
{
case 0: curStash2 = PCPY->selfStash;
currentSawStash2 = 1;
break;
case 1: curStash2 = PCPY->sharedStash;
currentSawStash2 = 2;
break;
default: return NULL;//case 2:
}
} else {
curStash2 = curStash2->nextStash;
}
if (curStash2)
{
item = curStash2->ptListItem;
if (item) return item;
}
return getNextItem(ptChar,item);
}
Unit* STDCALL initGetNextItem(Unit* ptChar, Unit* ptItem)
{
if (ptChar->nUnitType != UNIT_PLAYER) return NULL;
if (!PCPY) return NULL;
curStash2 = NULL;
currentSawStash2 = 0;
if (ptItem) return ptItem;
return getNextItem(ptChar,ptItem);
}
FCT_ASM ( caller_initGetNextItem )
PUSH DWORD PTR SS:[ESP+0x20]
PUSH DWORD PTR SS:[ESP+0xC]
CALL initGetNextItem
MOV EDI,EAX
TEST EDI,EDI
RETN
}}
FCT_ASM ( caller_getNextItem )
PUSH DWORD PTR SS:[ESP+4]
PUSH DWORD PTR SS:[ESP+0x10]
CALL getNextItem
RETN 4
}}
DWORD STDCALL carry1Limit(Unit* ptChar, Unit* ptItemParam, DWORD itemNum, BYTE page)
{
if (!ptChar) return 0;
Unit* ptItem = ptItemParam ? ptItemParam : D2GameGetObject(PCGame, UNIT_ITEM, itemNum);
if ((page != 4) && (D2GetItemQuality(ptItem) == 7) && ptChar)
{
int uniqueID = D2GetUniqueID(ptItem);
if ((uniqueID>=0) && (uniqueID < (int)SgptDataTables->nbUniqueItems))
{
UniqueItemsBIN* uniqueItems = SgptDataTables->uniqueItems + uniqueID;
if (uniqueItems && (uniqueItems->carry1==1))
{
ItemsBIN* ptItemsBin = D2GetItemsBIN(ptItem->nTxtFileNo);
Unit* ptFirstItem = D2InventoryGetFirstItem(PCInventory);
if (ptItemsBin && ptFirstItem)
return D2VerifIfNotCarry1(ptItem, ptItemsBin, ptFirstItem);
}
}
}
return 0;
}
FCT_ASM ( caller_carry1Limit_111 )
PUSH DWORD PTR SS:[ESP+0x08]//page
PUSH 0//EDI
PUSH DWORD PTR SS:[ESP+0x0C]
PUSH ESI//ptChar
CALL carry1Limit
TEST EAX,EAX
JNZ end_carry1Limit
JMP D2ItemSetPage
end_carry1Limit:
ADD ESP,0xC
XOR EAX,EAX
POP EDI
POP EBX
POP ESI
POP EBP
RETN 8
}}
FCT_ASM ( caller_carry1Limit )
PUSH DWORD PTR SS:[ESP+0x08]//page
PUSH 0//EBP
PUSH DWORD PTR SS:[ESP+0x0C]
PUSH DWORD PTR SS:[ESP+0x28]//ptChar
CALL carry1Limit
TEST EAX,EAX
JNZ end_carry1Limit
JMP D2ItemSetPage
end_carry1Limit:
ADD ESP,0xC
POP EDI
POP ESI
POP EBP
XOR EAX,EAX
POP EBX
ADD ESP,0x24
RETN 8
}}
FCT_ASM ( caller_carry1LimitSwap_112 )
PUSH EAX
PUSH DWORD PTR SS:[ESP+0x1C]
PUSH 0
PUSH ESI//ptChar
CALL carry1Limit
TEST EAX,EAX
JNZ end_carry1Limit
JMP D2ItemGetPage
end_carry1Limit:
ADD ESP,8
XOR EAX,EAX
POP EDI
POP EBP
POP ESI
POP EBX
POP ECX
RETN 8
}}
FCT_ASM ( caller_carry1LimitSwap_111 )
PUSH EAX
PUSH EBP
PUSH 0
PUSH DWORD PTR SS:[ESP+0x24]//ptChar
CALL carry1Limit
TEST EAX,EAX
JNZ end_carry1Limit
JMP D2ItemGetPage
end_carry1Limit:
ADD ESP,8
XOR EAX,EAX
POP EDI
POP EBP
POP ESI
POP EBX
POP ECX
RETN 8
}}
FCT_ASM ( caller_carry1LimitSwap )
PUSH EAX
PUSH DWORD PTR SS:[ESP+0x20]
PUSH 0
PUSH EBP//ptChar
CALL carry1Limit
TEST EAX,EAX
JNZ end_carry1Limit
JMP D2ItemGetPage
end_carry1Limit:
ADD ESP,8
POP EDI
POP ESI
POP EBP
XOR EAX,EAX
POP EBX
ADD ESP,0x4C
RETN 8
}}
/*
FCT_ASM ( caller_carry1LimitWhenDrop )
PUSH EAX
PUSH 0
PUSH ESI//ptItem
PUSH EDI//ptChar
CALL carry1Limit
TEST EAX,EAX
POP EAX
JE END_carry1LimitWhenDrop
MOV EDX,0x806
RETN
END_carry1LimitWhenDrop:
ADD DWORD PTR SS:[ESP],0x1F
RETN
}}*/
FCT_ASM ( caller_carry1LimitWhenDrop_111 )
PUSH 0
PUSH 0
PUSH DWORD PTR SS:[ESP+0x10] //ptItem
PUSH ESI //ptChar
CALL carry1Limit
TEST EAX,EAX
JNZ end_carry1Limit
JMP D2CanPutItemInInv
end_carry1Limit:
XOR EAX,EAX
RETN 0x1C
}}
/*
FCT_ASM ( caller_carry1LimitWhenDrop )
PUSH 0
PUSH 0
PUSH DWORD PTR SS:[ESP+0x10] //ptItem
PUSH EDI //ptChar
CALL carry1Limit
JNZ end_carry1Limit
JMP D2CanPutItemInInv
end_carry1Limit:
XOR EAX,EAX
RETN 0x1C
}}*/
FCT_ASM ( caller_carry1LimitWhenDrop )
PUSH EAX
PUSH 0
PUSH 0
PUSH ESI//ptItem
PUSH EDI//ptChar
CALL carry1Limit
TEST EAX,EAX
POP EAX
JNZ END_carry1LimitWhenDrop
MOV EDX,0x806
RETN
END_carry1LimitWhenDrop:
ADD DWORD PTR SS:[ESP],0x1F
RETN
}}
FCT_ASM ( caller_carry1OutOfStash_111 )
PUSH EDI
CALL D2ItemGetPage
CMP AL,4
JNZ continue_carry1OutOfStash
ADD DWORD PTR SS:[ESP],0x17C
RETN
continue_carry1OutOfStash:
MOV ESI,DWORD PTR SS:[ESP+0x10]
TEST ESI,ESI
RETN
}}
FCT_ASM ( caller_carry1OutOfStash )
PUSH ESI
CALL D2ItemGetPage
CMP AL,4
JNZ continue_carry1OutOfStash
ADD DWORD PTR SS:[ESP],0x1AF
RETN
continue_carry1OutOfStash:
MOV EAX,DWORD PTR SS:[ESP+0x14]
TEST EAX,EAX
RETN
}}
void Install_MultiPageStash()
{
static int isInstalled = false;
if (isInstalled) return;
Install_PlayerCustomData();
Install_InterfaceStash();
changeToSelectedStash = version_D2Common >= V110 ? changeToSelectedStash_10 : changeToSelectedStash_9;
if ( version_D2Game >= V110 )
{
log_msg("Patch D2Game for carry1 unique item. (MultiPageStash)\n");
// Cannot put 2 items carry1 in inventory
mem_seek R7(D2Game, 0000, 0000, 55050, 57CA3, 2FE63, 99B03, CF1E3, 6B013);
MEMJ_REF4( D2ItemSetPage , version_D2Game >= V111 ? caller_carry1Limit_111 : caller_carry1Limit);
//6FC8504F . E8 94670900 CALL <JMP.&D2Common.#10720>
//01FD7CA2 . E8 6329FBFF CALL <JMP.&D2Common.#10485>
//01F9FE62 . E8 47A8FDFF CALL <JMP.&D2Common.#10608>
//6FCB9B02 . E8 9709F7FF CALL <JMP.&D2Common.#10223>
//6FCEF1E2 . E8 47B7F3FF CALL <JMP.&D2Common.#10012>
//6FC8B012 . E8 13F7F9FF CALL <JMP.&D2Common.#11026>
// Cannot put 2 items carry1 in inventory by swapping
mem_seek R7(D2Game, 0000, 0000, 558D9, 58968, 310E8, 9B6E8, D10C8, 6BC78);
MEMJ_REF4( D2ItemGetPage , version_D2Game >= V112 ? caller_carry1LimitSwap_112 : version_D2Game >= V111 ? caller_carry1LimitSwap_111 : caller_carry1LimitSwap);
//6FC858D8 . E8 175F0900 CALL <JMP.&D2Common.#10719>
//01FD8967 . E8 8E1DFBFF CALL <JMP.&D2Common.#10820>
//01FA10E7 . E8 9A96FDFF CALL <JMP.&D2Common.#10505>
//6FCBB6E7 . E8 CAEDF6FF CALL <JMP.&D2Common.#10370>
//6FCF10C7 . E8 F895F3FF CALL <JMP.&D2Common.#10020>
//6FC8BC77 . E8 22E9F9FF CALL <JMP.&D2Common.#10810>
if ( version_D2Game >= V111 )
{
// Cannot put 2 items carry1 in inventory when drop cube
mem_seek R7(D2Game, 0000, 0000, 0000, 3D935, 49FD5, 17AD5, D7B75, B7B15);
MEMJ_REF4( D2CanPutItemInInv , caller_carry1LimitWhenDrop_111);
//01FBD934 |. E8 5BD3FCFF |CALL <JMP.&D2Common.#10855>
//01FB9FD4 |. E8 3912FCFF |CALL <JMP.&D2Common.#10813>
//6FC37AD4 |. E8 0535FFFF |CALL <JMP.&D2Common.#10289>
//6FCF7B74 |. E8 232FF3FF |CALL <JMP.&D2Common.#10133>
//6FCD7B14 |. E8 7D32F5FF |CALL <JMP.&D2Common.#10402>
} else {
// Cannot put 2 items carry1 in inventory when drop cube
mem_seek R7(D2Game, 0000, 0000, 14341, 0000, 0000, 0000, 0000, 0000);
memt_byte( 0xBA ,0xE8);
MEMT_REF4( 0x00000806 , caller_carry1LimitWhenDrop);
//6FC44341 |. BA 06080000 |MOV EDX,806
}
// Verif only carry1 out of stash page when pick up an item
mem_seek R7(D2Game, 0000, 0000, 1299E, 38E3B, 43F0B, 1209B, D211B, B301B);
memt_byte( 0x8B ,0xE8);
MEMT_REF4( version_D2Game >= V111 ? 0x850C2474 : 0x85102444 , version_D2Game >= V111 ? caller_carry1OutOfStash_111 : caller_carry1OutOfStash);
memt_byte( version_D2Game >= V111 ? 0xF6 : 0xC0 ,0x90);
//6FC4299E |. 8B4424 10 |MOV EAX,DWORD PTR SS:[ESP+10]
//6FC429A2 |. 85C0 |TEST EAX,EAX
//01FB8E3B |. 8B7424 0C |MOV ESI,DWORD PTR SS:[ESP+C]
//01FB8E3F |. 85F6 |TEST ESI,ESI
//01FB3F0B |. 8B7424 0C |MOV ESI,DWORD PTR SS:[ESP+C]
//01FB3F0F |. 85F6 |TEST ESI,ESI
//6FC3209B |. 8B7424 0C |MOV ESI,DWORD PTR SS:[ESP+C]
//6FC3209F |. 85F6 |TEST ESI,ESI
//6FCF211B |. 8B7424 0C |MOV ESI,DWORD PTR SS:[ESP+C]
//6FCF211F |. 85F6 |TEST ESI,ESI
//6FCD301B |. 8B7424 0C |MOV ESI,DWORD PTR SS:[ESP+C]
//6FCD301F |. 85F6 |TEST ESI,ESI
log_msg("\n");
}
isInstalled = true;
}
/*================================= END OF FILE =================================*/