Jump to content

[Help] Refine problem with stackable Stone


Recommended Posts

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

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

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

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);
			
		}
	}

 

 

  • Love 2
Link to comment
Share on other sites

  • 4 years later...

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

Announcements



×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.