Cripplez 40 Posted January 16, 2020 Share Posted January 16, 2020 Hello, I have a problem with stackable Stones, when I try to attach a stack of 200 Stones to an armor/weapon it correctly attach only one and i have 199 stones in inventory, but when I try to upgrade a stones from a stack of 200 they are all removed instead of one, do you know how can I fix this? Thank you Link to comment Share on other sites More sharing options...
Vanilla 1454 Posted January 17, 2020 Share Posted January 17, 2020 With upgrade you mean refining them? If that's the case than look at the way metin2 handles refining. If I'm not mistaken the item gets removed and then a new, refined one, is given to the player with same attributes/etc.. But it's just from my memory. That'd explain why your stone stack is missing because the refinement shouldn't check for a higher quantity, usually it was just meant for single equipment to be used with. We are the tortured. We're not your friends. As long as we're not visible. We are unfixable. Link to comment Share on other sites More sharing options...
Cripplez 40 Posted January 17, 2020 Author Share Posted January 17, 2020 I made some changes and now when the refine fails it correcly remove only one stone instead of all the stack. But when I succesfully refine the stone it remove all the stack of stones and give me the new stone. The problem should be here, because I think the new stone replace the position of the old item instead of going in another free space of my inventory, understand what I mean? this is the code from char_item.cpp if (prob <= prt->prob) { LPITEM pkNewItem = ITEM_MANAGER::instance().CreateItem(result_vnum, 1, 0, false); if (pkNewItem) { ITEM_MANAGER::CopyAllAttrTo(item, pkNewItem); LogManager::instance().ItemLog(this, pkNewItem, "REFINE SUCCESS", pkNewItem->GetName()); BYTE bCell = item->GetCell(); // DETAIL_REFINE_LOG NotifyRefineSuccess(this, item, IsRefineThroughGuild() ? "GUILD" : "POWER"); DBManager::instance().SendMoneyLog(MONEY_LOG_REFINE, item->GetVnum(), -cost); item->SetCount(item->GetCount() - 1); //ITEM_MANAGER::instance().RemoveItem(item, "REMOVE (REFINE SUCCESS)"); // END_OF_DETAIL_REFINE_LOG // ***** I THINK THE PROBLEM COULD BE HERE ***** pkNewItem->AddToCharacter(this, TItemPos(INVENTORY, bCell)); ITEM_MANAGER::instance().FlushDelayedSave(pkNewItem); sys_log(0, "Refine Success %d", cost); pkNewItem->AttrLog(); //PointChange(POINT_GOLD, -cost); sys_log(0, "PayPee %d", cost); PayRefineFee(cost); sys_log(0, "PayPee End %d", cost); } else { // DETAIL_REFINE_LOG sys_err("cannot create item %u", result_vnum); NotifyRefineFail(this, item, IsRefineThroughGuild() ? "GUILD" : "POWER"); // END_OF_DETAIL_REFINE_LOG } } else { DBManager::instance().SendMoneyLog(MONEY_LOG_REFINE, item->GetVnum(), -cost); NotifyRefineFail(this, item, IsRefineThroughGuild() ? "GUILD" : "POWER"); item->AttrLog(); // ***** THIS CORRECLY REMOVE ONLY ONE STONE WHEN REFINE FAIL ***** item->SetCount(item->GetCount() - 1); //ITEM_MANAGER::instance().RemoveItem(item, "REMOVE (REFINE FAIL)"); //PointChange(POINT_GOLD, -cost); PayRefineFee(cost); } I think I should change this part so instead of going the the same inventory space of the refined item it should go to a new inventory free space Do you know how this part should be coded? Thank you pkNewItem->AddToCharacter(this, TItemPos(INVENTORY, bCell)); 46 minutes ago, Vanilla said: With upgrade you mean refining them? If that's the case than look at the way metin2 handles refining. If I'm not mistaken the item gets removed and then a new, refined one, is given to the player with same attributes/etc.. But it's just from my memory. That'd explain why your stone stack is missing because the refinement shouldn't check for a higher quantity, usually it was just meant for single equipment to be used with. Link to comment Share on other sites More sharing options...
Vanilla 1454 Posted January 17, 2020 Share Posted January 17, 2020 Yes, that's absolutely true. You're literally overwriting the current item being hold at this position. This is actually the standard procedure and should be handled like this in every normal case. Like if you wanna upgrade equipment and stuff... But if you're going to do that to stones etc. you might as well just make it a bit different. What you need to do is check for free space in the players inventory and use this instead of the current position. If there is no free space, you may also be able to just drop the item with ownership and let him pick it up one he made some room. You have plenty examples of this procedure, especially in char_item.cpp. Here is one I adapted. Note it's just an example, you may wanna use pkNewItem you have in your code instead for the new item: if(item->GetCount() > 1) { int pos = GetEmptyInventory(item->GetSize()); if (-1 == pos) { ChatPacket(CHAT_TYPE_INFO, LC_TEXT("소지품에 빈 공간이 없습니다.")); break; } LPITEM newitem = ITEM_MANAGER::instance().CreateItem( item->GetVnum(), 1 ); newitem->AddToCharacter(this, TItemPos(INVENTORY, pos)); } You can even adapt this code to the function you already mentioned, just use the pkNewItem you created instead Last but not least here is the code snippet if you wanna issue a drop item with ownership. You can replace the case if the player has no empty cell in inventory left. PIXEL_POSITION pos = GetXYZ(); LPITEM newitem = ITEM_MANAGER::instance().CreateItem( item->GetVnum(), 1 ); newitem->AddToGround(GetMapIndex(), pos); newitem->SetOwnership(this); newitem->StartDestroyEvent(); pos.x += number(-7, 7) * 20; pos.y += number(-7, 7) * 20; This example does issue a drop with ownership, obviously only if you place it within a function inside CHARACTER class (otherwise add LPCHARACTER pointer to it so you can get coordinates and stuff). In the code example you gave me above you're fulfilling that, so you might as well just place in the new code. Just remember: You may wanna use your pkNewItem instead. Note that you may also make a type an subtype check to make sure you're not refining equipment with this. But yeah, as long as you cannot refine a stack of swords it'd just work pretty fine, I just wanted to mention it in case something happens that I did not think of. Just to make sure no one can exploit something. We are the tortured. We're not your friends. As long as we're not visible. We are unfixable. Link to comment Share on other sites More sharing options...
Cripplez 40 Posted January 18, 2020 Author Share Posted January 18, 2020 1 hour ago, Vanilla said: Thank you very much!!! I did like this and it seems it is works perfectly, with full inventory i receive the item with drop owership, otherwise it goes to a new slot if (prob <= prt->prob) { LPITEM pkNewItem = ITEM_MANAGER::instance().CreateItem(result_vnum, 1, 0, false); int pos = GetEmptyInventory(item->GetSize()); if (pkNewItem) { ITEM_MANAGER::CopyAllAttrTo(item, pkNewItem); LogManager::instance().ItemLog(this, pkNewItem, "REFINE SUCCESS", pkNewItem->GetName()); //BYTE bCell = item->GetCell(); // DETAIL_REFINE_LOG NotifyRefineSuccess(this, item, IsRefineThroughGuild() ? "GUILD" : "POWER"); DBManager::instance().SendMoneyLog(MONEY_LOG_REFINE, item->GetVnum(), -cost); item->SetCount(item->GetCount() - 1); //ITEM_MANAGER::instance().RemoveItem(item, "REMOVE (REFINE SUCCESS)"); // END_OF_DETAIL_REFINE_LOG //pkNewItem->AddToCharacter(this, TItemPos(INVENTORY, bCell)); if ((pos = GetEmptyInventory(item->GetSize())) != -1) { pkNewItem->AddToCharacter(this, TItemPos(INVENTORY, pos)); ITEM_MANAGER::instance().FlushDelayedSave(pkNewItem); } else { PIXEL_POSITION pos = GetXYZ(); LPITEM pkNewItem = ITEM_MANAGER::instance().CreateItem(result_vnum, 1, 0, false); ITEM_MANAGER::instance().FlushDelayedSave(pkNewItem); pkNewItem->AddToGround(GetMapIndex(), pos); pkNewItem->SetOwnership(this); pkNewItem->StartDestroyEvent(); pos.x += number(-7, 7) * 20; pos.y += number(-7, 7) * 20; } sys_log(0, "Refine Success %d", cost); pkNewItem->AttrLog(); //PointChange(POINT_GOLD, -cost); sys_log(0, "PayPee %d", cost); PayRefineFee(cost); sys_log(0, "PayPee End %d", cost); } } 2 Link to comment Share on other sites More sharing options...
asdasd1234 0 Posted March 27 Share Posted March 27 Hi. I tried to use your code but the stack refining works as before.. what did i do wrong? Link to comment Share on other sites More sharing options...
Recommended Posts
Please sign in to comment
You will be able to leave a comment after signing in
Sign In Now