- // Returns a free slot in the storage (0xffff if is full)
- UINT CPlayer::GetNewStorageItemSlot( CItem thisitem )
here is how to fix it.
in PlayerFuncions.cpp
find
Replace the entire function with
- // Returns a free slot in the storage (0xffff if is full)
- UINT CPlayer::GetNewStorageItemSlot( CItem thisitem )
- {
- //first check for a slot that already contains this item if it is stackable
- if(thisitem.itemtype == 10 || thisitem.itemtype == 11 || thisitem.itemtype == 12)
- {
- for(UINT i=0;i<160;i++)
- {
- if(storageitems[i].itemtype == thisitem.itemtype && storageitems[i].itemnum == thisitem.itemnum)
- {
- //now we make sure that the total of the new items plus the ones already there do not exceed 999
- int totalcount = storageitems[i].count + thisitem.count;
- if(totalcount < 999)
- {
- return i;
- }
- }
- }
- }
- //so we couldn't find a matching entry to stack onto
- //or the item is unstackable
- //Let's look for an empty slot instead then
- for(UINT i=0;i<160;i++)
- {
- if(storageitems[i].itemtype == 0)
- {
- return i;
- }
- }
- return 0xffff;
- }
This will now return EITHER a matching stack OR an empty space. matching stacks will always be returned first.
But this is only half of it. The code that actually puts teh items into storage is highly screwed up too
in WorldPackets.cpp
find
- // Change Storage (Deposit/Withdraw items)
- bool CWorldServer::pakChangeStorage( CPlayer* thisclient, CPacket* P)
as before, replace the entire function with this.
- // Change Storage (Deposit/Withdraw items)
- bool CWorldServer::pakChangeStorage( CPlayer* thisclient, CPacket* P)
- {
- BYTE action = GETBYTE((*P),0);
- switch(action)
- {
- case 0x00: //Deposit
- {
- int itemslot = (int)GETBYTE((*P),1);
- if(!CheckInventorySlot( thisclient, itemslot ))
- return false;
- CItem newitem = thisclient->items[itemslot];
- // find an empty or matching slot depending on new item type
- int newslot = thisclient->GetNewStorageItemSlot ( newitem );
- if(newslot==0xffff)
- return true;
- if(thisclient->storageitems[newslot].count != 0) // already something in this slot
- {
- if(newitem.itemtype == 10 || newitem.itemtype == 11 || newitem.itemtype == 12) //is it a stackable type
- {
- //stackable item
- if(newitem.itemtype != thisclient->storageitems[newslot].itemtype || newitem.itemnum != thisclient->storageitems[newslot].itemnum)
- return true; // better kick out so it doesn't overwrite something
- // by now we know that the items in this slot are the same as the ones we want to deposit so add them together
- int count = (int)GETWORD((*P),6);
- if(count > thisclient->items[itemslot].count)
- count = thisclient->items[itemslot].count; //stops players transferring more than they actually have
- thisclient->storageitems[newslot].count += count; //add the new items to the storage slot
- thisclient->items[itemslot].count -= count; //delete the items from inventory slot
- if(thisclient->items[itemslot].count <= 0)
- ClearItem(thisclient->items[itemslot]);
- }
- else // not stackable
- return true; // better kick out so it doesn't overwrite something
- }
- else // slot is empty
- {
- if(newitem.itemtype == 10 || newitem.itemtype == 11 || newitem.itemtype == 12) //is it a stackable type
- {
- //stackable item to make a new stack
- int count = (int)GETWORD((*P),6);
- if(count > thisclient->items[itemslot].count)
- count = thisclient->items[itemslot].count; //stops players transferring more than they actually have
- thisclient->storageitems[newslot] = newitem; //add the new items to the storage slot
- thisclient->storageitems[newslot].count = count; //make sure the count is right
- thisclient->items[itemslot].count -= count; //delete the items from inventory slot
- if(thisclient->items[itemslot].count <= 0)
- ClearItem(thisclient->items[itemslot]);
- }
- else
- {
- // non-stackable
- ClearItem(thisclient->items[itemslot]);
- thisclient->storageitems[newslot] = newitem;
- }
- }
- BEGINPACKET( pak, 0x7ae );
- ADDWORD ( pak, itemslot );
- ADDWORD ( pak, newslot );
- ADDDWORD ( pak, BuildItemHead( thisclient->items[itemslot] ) );
- ADDDWORD ( pak, BuildItemData( thisclient->items[itemslot] ) );
- ADDDWORD ( pak, BuildItemHead( thisclient->storageitems[newslot] ) );
- ADDDWORD ( pak, BuildItemData( thisclient->storageitems[newslot] ) );
- ADDQWORD ( pak, thisclient->CharInfo->Zulies );
- thisclient->client->SendPacket( &pak );
- //thisclient->nstorageitems++; //this is pointless and serves no purpose
- }
- break;//thanks to anon for post that this break was missing
- case 0x01: //Withdraw
- {
- BYTE storageslot = GETBYTE((*P),1);
- if(storageslot>=160)
- {
- Log( MSG_HACK, "Invalid storage slot %i from %s", storageslot, thisclient->Session->username );
- return false;
- }
- CItem newitem = newitem = thisclient->storageitems[storageslot];
- if(newitem.itemtype>9 && newitem.itemtype<14)
- {
- WORD count = GETWORD((*P),6);
- if( count>thisclient->storageitems[storageslot].count )
- count = thisclient->storageitems[storageslot].count;
- newitem.count = count;
- thisclient->storageitems[storageslot].count -= count;
- if(thisclient->storageitems[storageslot].count<=0)
- ClearItem(thisclient->storageitems[storageslot]);
- }
- else
- {
- ClearItem(thisclient->storageitems[storageslot]);
- }
- int newslot= thisclient->GetNewItemSlot ( newitem );
- if(newslot==0xffff)
- {
- thisclient->storageitems[storageslot] = newitem;
- return true;
- }
- int amount = 0;
- if(thisclient->items[newslot].count>0)
- {
- int amount = thisclient->items[newslot].count;
- newitem.count+=amount;
- }
- if( newitem.count > 999 )
- {
- amount = 999 - newitem.count;
- newitem.count = 999;
- }
- thisclient->items[newslot] = newitem;
- if( amount > 0 )
- {
- newitem.count = amount;
- unsigned int newslot2 = thisclient->GetNewItemSlot( newitem );
- if( newslot2 == 0xffff )
- {
- thisclient->storageitems[storageslot] = thisclient->items[newslot];
- thisclient->items[newslot].count = amount;
- return true;
- }
- thisclient->items[newslot2] = newitem;
- thisclient->UpdateInventory( newslot2 );
- }
- BEGINPACKET( pak, 0x7ae );
- ADDWORD ( pak, newslot );
- ADDWORD ( pak, storageslot );
- ADDDWORD ( pak, BuildItemHead( thisclient->items[newslot] ) );
- ADDDWORD ( pak, BuildItemData( thisclient->items[newslot] ) );
- ADDDWORD ( pak, BuildItemHead( thisclient->storageitems[storageslot] ) );
- ADDDWORD ( pak, BuildItemData( thisclient->storageitems[storageslot] ) );
- ADDQWORD ( pak, thisclient->CharInfo->Zulies );
- ADDBYTE ( pak, 0x00 );
- thisclient->client->SendPacket( &pak );
- //thisclient->nstorageitems--; //this is pointless and serves no purpose
- }
- break;
- default:
- Log( MSG_INFO, "Storage unknow action: %i ", action);
- }
- return true;
- }
Notice that i have removed the bit that adds or subtracts a value from thisclient->nstorageitems.
There is a very good reason for that.
It didn't work anyway.
It was incrementing or decrementing the value each time you added or removed a partial stack so it was getting pretty screwed up anyway.
However we can't lose the value completely as it is used in a packet 0x7ad in PakStorage.
So we have to add a new function to count it up for us
we will call it unsigned int CPlayer::Getnstorageitems( CPlayer* thisclient )
find
- // Returns a free slot in the storage (0xffff if is full)
- UINT CPlayer::GetNewStorageItemSlot( CItem thisitem )
BEFORE, add
- //count storage items
- unsigned int CPlayer::Getnstorageitems( CPlayer* thisclient )
- {
- UINT count = 0;
- for(UINT i=0;i<160;i++)
- {
- if(thisclient->storageitems[i].count > 0)
- count++;
- }
- return count;
- }
And we had better also add this in Player.h
find
- unsigned int AddItem( CItem item );
after add
- unsigned int Getnstorageitems( CPlayer* thisclient );
Finally we need to put in a call to this new function in the place that we actually need it.
in WorldPackets.cpp
find
- BEGINPACKET( pak, 0x7ad );
- ADDBYTE ( pak, 0x00 );
- ADDBYTE ( pak, thisclient->nstorageitems ); //numero de items
Replace with
- UINT nstorageitems = thisclient->Getnstorageitems(thisclient);
- BEGINPACKET( pak, 0x7ad );
- ADDBYTE ( pak, 0x00 );
- ADDBYTE ( pak, nstorageitems ); //numero de items
Modifications included in [rev 43]