|
You last visited: Today at 18:27
Advertisement
question about selling items to npc
Discussion on question about selling items to npc within the SRO Coding Corner forum part of the Silkroad Online category.
04/21/2021, 16:26
|
#1
|
elite*gold: 47
Join Date: Oct 2017
Posts: 574
Received Thanks: 967
|
question about selling items to npc
since we blocking the confirmation(0xb034) and sends fake pick at buy case
simultaneously, at sell case i blocked the confirmation packet from reaching the client now iam missing the second part
|
|
|
04/21/2021, 17:52
|
#2
|
elite*gold: 0
Join Date: Jan 2009
Posts: 314
Received Thanks: 685
|
If you send a fake pick up when buying then send a fake drop when
selling.
But imho you should use ADD_ITEM_BY_SERVER and DEL_ITEM_BY_SERVER instead. You can find them for example in Alchemy.
|
|
|
04/21/2021, 18:07
|
#3
|
elite*gold: 47
Join Date: Oct 2017
Posts: 574
Received Thanks: 967
|
Quote:
Originally Posted by DaxterSoul
If you send a fake pick up when buying then send a fake drop when
selling.
But imho you should use ADD_ITEM_BY_SERVER and DEL_ITEM_BY_SERVER instead. You can find them for example in Alchemy.
|
i forgot to mention that it's a transport pet
|
|
|
04/21/2021, 18:28
|
#4
|
elite*gold: 0
Join Date: Jan 2009
Posts: 314
Received Thanks: 685
|
The same applies for COS.
You can use PICK_ITEM_COS and DROP_ITEM_COS or my preferred operations
ADD_COSITEM_BY_SERVER and DEL_COSITEM_BY_SERVER which you can probably only find by reverse engineering.
Edit: Forget about what I said.
DROP_ITEM_COS and DEL_COSITEM_BY_SERVER are being parsed by the client but have no effect.
DEL_COSITEM_BY_SERVER doesn't even contain a GID of the COS it's targeting. Must be old code dating back to when there where no ability pets or you where able to only spawn a single COS.
Alright, after a some debugging I found the cause of DROP_ITEM_COS not working.
This is part of the code that reads the COSID from the message.
Code:
case INV_OP_DROP_ITEM: // SP_DROP_ITEM
case INV_OP_DROP_ITEM_COS: // SP_DROP_ITEM_COS
case INV_OP_23: // SP_UNKNOWN_23
if ( nOperation == INV_OP_DROP_ITEM_COS ) // SP_DROP_ITEM_COS
MsgStreamBuffer::ReadDWORD(pMsg, &this->dwCOSID);// COS.UniqueID
Those operations types will be simplified into 2 bytes that specify the source and target storage.
When the sourceStorage is a COS and the targetStorage is the WORLD or SERVER which means either DROP or DELETE_BY_SERVER then this section will be executed.
Code:
switch(sourceStorage)
{
case STORAGE_COS:
switch(targetStorage)
{
case STORAGE_TARGET_WORLD:
case STORAGE_TARGET_SERVER:
dwCOSID = pOperation->dwGIDorParam0;
pCOSManager = GetCOSManagerOrSomethingFromPlayer((int)g_pMyPlayerObj);
pCOS = (char *)COSManager::GetByID((char *)pCOSManager, dwCOSID);
v267 = pCOS;
if ( !pCOS )
goto label_exit;
// Remove item visually...
}
}
}
You might have noticed that the dwCOSID is read from a different location than where it was stored into.
dwGIDorParam0 is normally used for NPCs and only used with COS when moving items between the player and the COS. So this looks like a real bug to me.
In order to fix this you'd need to patch the offset that is accessed. Although I haven't checked if it breaks anything yet.
Code:
0087DD96 mov eax, [esi+0Ch]
to
0087DD96 mov eax, [esi+30h]
|
|
|
04/25/2021, 19:04
|
#5
|
elite*gold: 0
Join Date: May 2006
Posts: 667
Received Thanks: 348
|
Quote:
Originally Posted by bimbum*
since we blocking the confirmation(0xb034) and sends fake pick at buy case
simultaneously, at sell case i blocked the confirmation packet from reaching the client now iam missing the second part
|
You can't "trick" the GS into expecting a different movement operation without any memory hooks.
I'm not sure what are you trying to achieve here. But i assume you are interested in Transport / NPC operations.
Operation flags:
Code:
public enum ItemMovement : byte
{
InventoryToInventory = byte.MinValue,
StorageToStorage = 0x01,
InventoryToStorage = 0x02,
StorageToInventory = 0x03,
InventoryToExchange = 0x04,
ExchangeToInventory = 0x05,
GroundToInventory = 0x06,
InventoryToGround = 0x07,
ShopToInventory = 0x08,
InventoryToShop = 0x09,
InventoryGoldToGround = 0x0A,
StorageGoldToInventory = 0x0B,
InventoryGoldToStorage = 0x0C,
InventoryGoldToExchange = 0x0D,
GameServerToInventory = 0x0E,
InventoryToGameServer = 0x0F,
PetToPet = 0x10,
GroundToPet = 0x11,
ShopToTransport = 0x13,
TransportToShop = 0x14,
ItemMallToInventory = 0x18,
PetToInventory = 0x1A,
InventoryToPet = 0x1B,
GroundToPetToInventory = 0x1C,
GuildToGuild = 0x1D,
InventoryToGuild = 0x1E,
GuildToInventory = 0x1F,
InventoryGoldToGuild = 0x20,
GuildGoldToInventory = 0x21,
ShopBuyBack = 0x22,
AvatarToInventory = 0x23,
InventoryToAvatar = 0x24,
OpenMagicCube = 0x2A,
ShopToInventoryCoin = 0x2B,
InventoryToCube = 0x27,
MagicCubeConsumed = 0x29
}
The grouped interpretation of the movement operations:
Code:
if (packet.ReadUInt8() == 0x01) // Success flag
{
ItemMovement itemMovement = (ItemMovement)packet.ReadUInt8();
switch (itemMovement)
{
#region Gold (source to different source and gold to ground)
case ItemMovement.InventoryGoldToStorage: // Tested, OK
Parser.MoveGoldSrcToSrc(packet, ref storageGold, false);
break;
case ItemMovement.StorageGoldToInventory: // Tested, OK
Parser.MoveGoldSrcToSrc(packet, ref storageGold, true);
break;
case ItemMovement.InventoryGoldToGuild: // Tested, OK
Parser.MoveGoldSrcToSrc(packet, ref guildStorageGold, false);
break;
case ItemMovement.GuildGoldToInventory: // Tested, OK
Parser.MoveGoldSrcToSrc(packet, ref guildStorageGold, true);
break;
case ItemMovement.InventoryGoldToGround: // Tested, OK
Parser.MoveGoldToGround(packet);
break;
#endregion
#region Items from source to the same source
case ItemMovement.InventoryToInventory: // Tested, OK
Parser.MoveSrcToSameSrc(packet, Inventory);
break;
case ItemMovement.GuildToGuild: // Tested, OK
Parser.MoveSrcToSameSrc(packet, GuildStorage);
break;
case ItemMovement.StorageToStorage: // Tested, OK
Parser.MoveSrcToSameSrc(packet, Storage, false);
break;
case ItemMovement.PetToPet: // Tested, OK
uint InvPetUniqueID = packet.ReadUInt32();
List<Item> petInventory = (InvPetUniqueID == GrabPet ? GrabpetInventory : TransportInventory);
Parser.MoveSrcToSameSrc(packet, petInventory);
break;
#endregion
#region Items from source to different source
case ItemMovement.InventoryToAvatar: // Tested, OK
Parser.MoveSrcToDiffSrc(packet, Inventory, AvatarInventory);
break;
case ItemMovement.AvatarToInventory: // Tested, OK
Parser.MoveSrcToDiffSrc(packet, AvatarInventory, Inventory);
break;
case ItemMovement.InventoryToStorage: // Tested, OK
Parser.MoveSrcToDiffSrc(packet, Inventory, Storage);
break;
case ItemMovement.StorageToInventory: // Tested, OK
Parser.MoveSrcToDiffSrc(packet, Storage, Inventory);
break;
case ItemMovement.InventoryToGuild: // Tested, OK
Parser.MoveSrcToDiffSrc(packet, Inventory, GuildStorage);
break;
case ItemMovement.GuildToInventory: // Tested, OK
Parser.MoveSrcToDiffSrc(packet, GuildStorage, Inventory);
break;
case ItemMovement.InventoryToPet: // Tested, OK
packet.ReadUInt32(); // UniqueID
Parser.MoveSrcToDiffSrc(packet, Inventory, GrabpetInventory);
break;
case ItemMovement.PetToInventory: // Tested, OK
packet.ReadUInt32(); // UniqueID
Parser.MoveSrcToDiffSrc(packet, GrabpetInventory, Inventory);
break;
#endregion
#region Exchange
case ItemMovement.InventoryToExchange: // Tested, OK
Parser.MoveInventoryToExchange(packet, Inventory, ExchangeInput);
break;
case ItemMovement.ExchangeToInventory: // Tested, OK
Parser.MoveExchangeToInventory(packet, ExchangeInput);
break;
case ItemMovement.InventoryGoldToExchange: // Tested, OK
Parser.MoveGoldToExchange(packet, ExchangeInput);
break;
#endregion
#region Shops, Item Mall and ShopBuyBack
case ItemMovement.InventoryToShop: // Tested, OK
Parser.MoveInventoryToShopBuyBack(packet, Inventory, ShopBuyBack);
break;
case ItemMovement.ShopToInventory: // Tested, OK
case ItemMovement.ShopToInventoryCoin: // Tested, OK
Parser.MoveShopToSrc(packet, Inventory, SelectedEntity);
break;
case ItemMovement.TransportToShop: // Tested, OK
packet.ReadUInt32(); // Transport UniqueID
Parser.MoveTransportToShop(packet, TransportInventory);
break;
case ItemMovement.ShopToTransport: // Tested, OK
packet.ReadUInt32(); // Transport UniqueID
Parser.MoveShopToSrc(packet, TransportInventory, SelectedEntity);
break;
case ItemMovement.ItemMallToInventory: // Tested, OK
Parser.MoveItemMallToSrc(packet, Inventory);
break;
case ItemMovement.ShopBuyBack: // Tested, OK
Parser.MoveShopBuyBackToInventory(packet, ShopBuyBack, Inventory);
packet.ReadUInt16(); // Amount Sold
break;
#endregion
#region Pick or Drop
case ItemMovement.InventoryToGround:// Tested, OK
Parser.MoveSrcToGround(packet, Inventory);
break;
case ItemMovement.GroundToInventory: // Tested, OK
Parser.MoveGroundToSrc(packet, Inventory);
break;
case ItemMovement.GroundToPetToInventory: // Tested, OK
packet.ReadUInt32(); // UniqueID
Parser.MoveGroundToSrc(packet, Inventory);
break;
case ItemMovement.GroundToPet: // Tested, OK
uint gpetUniqueID = packet.ReadUInt32();
List<Item> gpetInventory = (gpetUniqueID == GrabPet ? GrabpetInventory : TransportInventory);
Parser.MoveGroundToSrc(packet, gpetInventory);
break;
#endregion
#region GameServer (Quests, Mob traps, CTF, BA, etc)
case ItemMovement.GameServerToInventory: // Tested, OK
Parser.MoveGameServerToInventory(packet, Inventory);
break;
case ItemMovement.InventoryToGameServer: // Tested, OK
Parser.MoveInventoryToGameServer(packet, Inventory);
break;
#endregion
#region Magic Cubes
// Magic Cubes are not fully working in vSRO 1.88
// So the implementation is a bit quirky but matches
// exactly what happens in game
case ItemMovement.OpenMagicCube: // Tested, OK
Parser.OpenMagicCubeInventory(packet);
break;
case ItemMovement.InventoryToCube: // Tested, OK
Parser.MoveInventoryToCube(packet, Inventory);
break;
case ItemMovement.MagicCubeConsumed: // Tested, OK
Parser.MagicCubeConsumed(packet);
break;
#endregion
}
}
Note that many of the operations incorporate the same logic hence they are grouped together.
"Src" is just the referenced container
For an accurate tracking of Shop items, you will have to interpolate the shops either from the client like bots or from the DB directly.
I should also mention that the Shops are identifiable by UniqueID, and you will have to perfectly parse any Entity spawn to correlate the data between the Shop UniqueID and commonID.
Despite of that, those UniqueIDs are somewhat "constant" for the NPCs even though UniqueID in its nature is not constant, that is because the GS loads and assigns the UniqueIDs for the NPCs when it initializes the WorldServer.
That's how the old bots have done it, back when there was no db available. But then any custom NPCs you added to your server are out of the question.
Anyway, not my forte.
Regards, Iso.
|
|
|
04/25/2021, 20:23
|
#6
|
elite*gold: 0
Join Date: Jan 2009
Posts: 314
Received Thanks: 685
|
Quote:
Originally Posted by Isoline*
You can't "trick" the GS into expecting a different movement operation without any memory hooks.
I'm not sure what are you trying to achieve here. But i assume you are interested in Transport / NPC operations.
|
From what I understood the problem he's referring to is closely related to  .
But instead of the buy response crashing the client, the sell response is crashing the client. Thus it has to be translated into an inventory operation that is not shop depended in the client.
|
|
|
04/26/2021, 02:07
|
#7
|
elite*gold: 47
Join Date: Oct 2017
Posts: 574
Received Thanks: 967
|
Quote:
Originally Posted by DaxterSoul
From what I understood the problem he's referring to is closely related to  .
But instead of the buy response crashing the client, the sell response is crashing the client. Thus it has to be translated into an inventory operation that is not shop depended in the client.
|
exactly
|
|
|
Similar Threads
|
[Question] how to change CTF So Ok NPC to another NPC ?
04/26/2018 - SRO Private Server - 11 Replies
hi there
i wonder if someone knows how to add CTF Event to another NPC rather than SO Ok NPC ?
is it a gameserver coded ?
or there is a quest table to change the NPC code ?
please share with me and ill really appreciate your help
thanks.
|
question about selling items to NPC
11/17/2009 - Dekaron Private Server - 5 Replies
what file can i find the sell back price of items to NPC's?
yeah, ive searched
and i have tried appraisal in the item index
looked thru some other files, but for some reason i cant seem to find this anywhere, could someone point me in the right direction please b4 i throw my PC off the baloney.
and Zombe, if u read this, could you look at the post i made in ur antigm release thread, thx ;)
|
All times are GMT +1. The time now is 18:28.
|
|