Jump to content
metin2dev
Sign in to follow this  
Johnny69

c++ New Item Type = ITEM_GACHA

Recommended Posts

This item type is the new type from official servers used for battle boxes and recently for boss chest and fish event boxes. You can open boxes few times (set in item_proto).

1. You can use macro ENABLE_BATTLE_FIELD because was added with battle zone.

2. Number of openings is in item_proto -> LimitValue1 (Like official)

Let's start:

Server Source Part:

#db\src\ProtoReader.cpp (same steps in ItemCSVReader.cpp)
//Search:
		"ITEM_BELT",
//Add after:
		"ITEM_GACHA"
          
//Search: in array string* arSubType
		0,			//34
//Add after:
		0,			//37

//Search: in array int arNumberOfSubtype
		0,			//34
//Add after:
		0,			//37


#common\item_length.h
//Search:
	ITEM_BELT,	
//Add after:
	ITEM_GACHA,


#game\src\item_manager.cpp
//Search:
	if (id == 0)
//Add before: (be careful , before)
	if(item->GetType() == ITEM_GACHA)
		item->SetSocket(0, item->GetLimitValue(1));


#game\src\char_item.cpp
//Search: (CHARACTER::UseItemEx)
		case ITEM_EXTRACT:
			...
			break;
//Add after:
		case ITEM_GACHA:
			{
				DWORD dwBoxVnum = item->GetVnum();
				std::vector <DWORD> dwVnums;
				std::vector <DWORD> dwCounts;
				std::vector <LPITEM> item_gets(0);
				int count = 0;

				if (GiveItemFromSpecialItemGroup(dwBoxVnum, dwVnums, dwCounts, item_gets, count))
				{
					if(item->GetSocket(0) > 1)
						item->SetSocket(0, item->GetSocket(0) - 1);
					else
						ITEM_MANAGER::instance().RemoveItem(item, "REMOVE (ITEM_GACHA)");
				}
			}
			break;

 

Client Source Part:

#GameLib\ItemData.h
//Search:
			ITEM_TYPE_BELT,
//Add after:
			ITEM_TYPE_GACHA,

#UserInterface\PythonItemModule.cpp
//Search:
	PyModule_AddIntConstant(poModule, "ITEM_TYPE_BELT",				CItemData::ITEM_TYPE_BELT);
//Add after:
	PyModule_AddIntConstant(poModule, "ITEM_TYPE_GACHA",			CItemData::ITEM_TYPE_GACHA);

 

Client root part:

#root\uitooltip.py
#Search:
		elif item.ITEM_TYPE_FISH == itemType:
			if 0 != metinSlot:
				self.__AppendFishInfo(metinSlot[0])
#Add after:
		### Gacha = Battle Shop Chest ###
		elif item.ITEM_TYPE_GACHA == itemType:
			if 0 != metinSlot:
				if self.isShopItem:
					restUsableCount = int(item.GetLimit(1)[1])
				else:
					restUsableCount = int(metinSlot[0])

				self.AppendSpace(5)
				self.AppendTextLine(localeInfo.TOOLTIP_REST_USABLE_COUNT % (restUsableCount), grp.GenerateColor(0.5, 1.0, 0.3, 1.0))

 

Client locale part:

#locale_game.txt
#Add:
TOOLTIP_REST_USABLE_COUNT	Left: %d

 

Server Item_proto example:

25111	fish 보상상자	ITEM_GACHA	0	1	NONE	NONE	NONE	NONE	0	0	0	0	0	LIMIT_NONE	0	LIMIT_NONE	1	APPLY_NONE	0	APPLY_NONE	0	APPLY_NONE	0	0	0	0	0	0	0	0	0	0	12
25112	fish 보상상자	ITEM_GACHA	0	1	NONE	NONE	NONE	NONE	0	0	0	0	0	LIMIT_NONE	0	LIMIT_NONE	2	APPLY_NONE	0	APPLY_NONE	0	APPLY_NONE	0	0	0	0	0	0	0	0	0	0	12
25113	fish 보상상자	ITEM_GACHA	0	1	NONE	NONE	NONE	NONE	0	0	0	0	0	LIMIT_NONE	0	LIMIT_NONE	3	APPLY_NONE	0	APPLY_NONE	0	APPLY_NONE	0	0	0	0	0	0	0	0	0	0	12

 

  • Like 2
  • Thanks 4

Share this post


Link to post
Share on other sites

I made something like 

 

 

		case ITEM_CHEST:
			{
				DWORD dwBoxVnum = item->GetVnum();
				std::vector <DWORD> dwVnums;
				std::vector <DWORD> dwCounts;
				std::vector <LPITEM> item_gets(NULL);
				int count = 0;



				if (GiveItemFromSpecialItemGroup(dwBoxVnum, dwVnums, dwCounts, item_gets, count))
					{
						for (int i = 0; i < count; i++)
						{
							char buf[50 + 1];
							snprintf(buf, sizeof(buf), "%u %u", dwVnums[i], dwCounts[i]);
	//						LogManager::instance().ItemLog(this, item, "MOONLIGHT_GET", buf);
	
							item->SetSocket(0, item->GetSocket(0) + 1);			
							if (item->GetSocket(0) >= Maxim_ClarLuna)
							{
							ITEM_MANAGER::instance().RemoveItem(item);
							}	
							ChatPacket(CHAT_TYPE_INFO, "[DEBUG]Test Chest");	
	
							switch (dwVnums[i])
							{
							case CSpecialItemGroup::GOLD:
								ChatPacket(CHAT_TYPE_INFO, LC_TEXT("돈 %d 냥을 획득했습니다."), dwCounts[i]);
								break;
	
							case CSpecialItemGroup::EXP:
								ChatPacket(CHAT_TYPE_INFO, LC_TEXT("상자에서 부터 신비한 빛이 나옵니다."));
								ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%d의 경험치를 획득했습니다."), dwCounts[i]);
								break;
	
							case CSpecialItemGroup::MOB:
								ChatPacket(CHAT_TYPE_INFO, LC_TEXT("상자에서 몬스터가 나타났습니다!"));
								break;
	
							case CSpecialItemGroup::SLOW:
								ChatPacket(CHAT_TYPE_INFO, LC_TEXT("상자에서 나온 빨간 연기를 들이마시자 움직이는 속도가 느려졌습니다!"));
								break;
	
							case CSpecialItemGroup::DRAIN_HP:
								ChatPacket(CHAT_TYPE_INFO, LC_TEXT("상자가 갑자기 폭발하였습니다! 생명력이 감소했습니다."));
								break;
	
							case CSpecialItemGroup::POISON:
								ChatPacket(CHAT_TYPE_INFO, LC_TEXT("상자에서 나온 녹색 연기를 들이마시자 독이 온몸으로 퍼집니다!"));
								break;
	
							case CSpecialItemGroup::MOB_GROUP:
								ChatPacket(CHAT_TYPE_INFO, LC_TEXT("상자에서 몬스터가 나타났습니다!"));
								break;
	
							default:
								if (item_gets[i])
								{
									if (dwCounts[i] > 1)
										ChatPacket(CHAT_TYPE_INFO, LC_TEXT("상자에서 %s 가 %d 개 나왔습니다."), item_gets[i]->GetName(), dwCounts[i]);
									else
										ChatPacket(CHAT_TYPE_INFO, LC_TEXT("상자에서 %s 가 나왔습니다."), item_gets[i]->GetName());
								}
								break;
							}
						}
					}
					else
					{
						ChatPacket(CHAT_TYPE_TALKING, LC_TEXT("아무것도 얻을 수 없었습니다."));
						return false;
					}
				}
				break;

 

and lenght.h

 

Maxim_ClarLuna 			= 3,

 

Share this post


Link to post
Share on other sites
Acum 17 ore, Johnny69 a spus:

This item type is the new type from official servers used for battle boxes and recently for boss chest and fish event boxes. You can open boxes few times (set in item_proto).

1. You can use macro ENABLE_BATTLE_FIELD because was added with battle zone.

2. Number of openings is in item_proto -> LimitValue1 (Like official)

Let's start:

Server Source Part:


#db\src\ProtoReader.cpp
//Search:
		"ITEM_BELT",
//Add after:
		"ITEM_GACHA"

#common\item_length.h
//Search:
	ITEM_BELT,	
//Add after:
	ITEM_GACHA,


#game\src\item_manager.cpp
//Search:
	if (id == 0)
//Add before: (be careful , before)
	if(item->GetType() == ITEM_GACHA)
		item->SetSocket(0, item->GetLimitValue(1));


#game\src\char_item.cpp
//Search: (CHARACTER::UseItemEx)
		case ITEM_EXTRACT:
			...
			break;
//Add after:
		case ITEM_GACHA:
			{
				DWORD dwBoxVnum = item->GetVnum();
				std::vector <DWORD> dwVnums;
				std::vector <DWORD> dwCounts;
				std::vector <LPITEM> item_gets(0);
				int count = 0;

				if (GiveItemFromSpecialItemGroup(dwBoxVnum, dwVnums, dwCounts, item_gets, count))
				{
					if(item->GetSocket(0) > 1)
						item->SetSocket(0, item->GetSocket(0) - 1);
					else
						ITEM_MANAGER::instance().RemoveItem(item, "REMOVE (ITEM_GACHA)");
				}
			}
			break;

 

Client Source Part:


#GameLib\ItemData.h
//Search:
			ITEM_TYPE_BELT,
//Add after:
			ITEM_TYPE_GACHA,

#UserInterface\PythonItemModule.cpp
//Search:
	PyModule_AddIntConstant(poModule, "ITEM_TYPE_BELT",				CItemData::ITEM_TYPE_BELT);
//Add after:
	PyModule_AddIntConstant(poModule, "ITEM_TYPE_GACHA",			CItemData::ITEM_TYPE_GACHA);

 

Client root part:


#root\uitooltip.py
#Search:
		elif item.ITEM_TYPE_FISH == itemType:
			if 0 != metinSlot:
				self.__AppendFishInfo(metinSlot[0])
#Add after:
		### Gacha = Battle Shop Chest ###
		if item.ITEM_TYPE_GACHA == itemType:
			if 0 != metinSlot:
				if self.isShopItem:
					restUsableCount = int(item.GetLimit(1)[1])
				else:
					restUsableCount = int(metinSlot[0])

				self.AppendSpace(5)
				self.AppendTextLine(localeInfo.TOOLTIP_REST_USABLE_COUNT % (restUsableCount), grp.GenerateColor(0.5, 1.0, 0.3, 1.0))

 

Client locale part:


#locale_game.txt
#Add:
TOOLTIP_REST_USABLE_COUNT	Left: %d

 

Server Item_proto example:


25111	fish 보상상자	ITEM_GACHA	0	1	NONE	NONE	NONE	NONE	0	0	0	0	0	LIMIT_NONE	0	LIMIT_NONE	1	APPLY_NONE	0	APPLY_NONE	0	APPLY_NONE	0	0	0	0	0	0	0	0	0	0	12
25112	fish 보상상자	ITEM_GACHA	0	1	NONE	NONE	NONE	NONE	0	0	0	0	0	LIMIT_NONE	0	LIMIT_NONE	2	APPLY_NONE	0	APPLY_NONE	0	APPLY_NONE	0	0	0	0	0	0	0	0	0	0	12
25113	fish 보상상자	ITEM_GACHA	0	1	NONE	NONE	NONE	NONE	0	0	0	0	0	LIMIT_NONE	0	LIMIT_NONE	3	APPLY_NONE	0	APPLY_NONE	0	APPLY_NONE	0	0	0	0	0	0	0	0	0	0	12

 

can you help me ? because for me , not work.

Share this post


Link to post
Share on other sites

Yeah, because he forgot the other parts of the protoreader(arrays for subtype).

  • Thanks 1

Share this post


Link to post
Share on other sites
Acum 35 minute, xP3NG3Rx a spus:

Yeah, because he forgot the other parts of the protoreader(arrays for subtype).

and...can you help me with there part ?

Share this post


Link to post
Share on other sites

Sorry , I hurried and forgot. I have other types between BELT and this type and I don't use define in ProtoReader.cpp / ItemCSVReader.cpp. I edited.

Share this post


Link to post
Share on other sites

Please revise the client/root/ part. After adding all tooltips are gone like autopotion remaining count, wear timer..

There's no error in any syserr.

Share this post


Link to post
Share on other sites
17 hours ago, ragem0re said:

Please revise the client/root/ part. After adding all tooltips are gone like autopotion remaining count, wear timer..

There's no error in any syserr.

the truth is that YOU should revise your client root part, maybe it`s so bad coded that when you add something it automatically breaks for some reason
 

Share this post


Link to post
Share on other sites

Anyone who has problems make a topic here and give me link in PM or just send me PM with problem and I help you. Don't make spam with problems here.

Share this post


Link to post
Share on other sites
58 minutes ago, Fleon said:

the truth is that YOU should revise your client root part, maybe it`s so bad coded that when you add something it automatically breaks for some reason
 

I don't know what the definition of revision is for you, but this post was not meant to be ungrateful in any way.

 

3 minutes ago, Johnny69 said:

Anyone who has problems make a topic here and give me link in PM or just send me PM with problem and I help you. Don't make spam with problems here.

I will

Share this post


Link to post
Share on other sites

Hi there!

Here you can see my all modifications about this codes, what I showed in my video, when you split or stack the same items the opening count will be correct always.
<!> Carefully, it could be different name of variables, and different types what you have to fix by yourself <!>

Spoiler

//char_item.cpp -> bool CHARACTER::UseItemEx
			case ITEM_GACHA:
			{
#ifdef ENABLE_NEWSTUFF
				if (0 != g_BoxUseTimeLimitValue)
				{
					if (get_dword_time() < m_dwLastBoxUseTime + g_BoxUseTimeLimitValue)
					{
						ChatPacket(CHAT_TYPE_INFO, LC_TEXT("ľĆÁ÷ °ńµĺ¸¦ ąö¸± Ľö ľř˝Ŕ´Ď´Ů."));
						return false;
					}
				}

				m_dwLastBoxUseTime = get_dword_time();
#endif

				DWORD dwBoxVnum = item->GetVnum();
				std::vector <DWORD> dwVnums;
				std::vector <DWORD> dwCounts;
				std::vector <LPITEM> item_gets(0);
				int count = 0;

				if (GiveItemFromSpecialItemGroup(dwBoxVnum, dwVnums, dwCounts, item_gets, count))
				{
					long lOpenCount = item->GetSocket(0);
					WORD wCount = lOpenCount / item->GetLimitValue(1), wRest = (lOpenCount % item->GetLimitValue(1));
					item->SetSocket(0, item->GetSocket(0) - 1);
					if (wRest == 1)
						if (IS_SET(item->GetFlag(), ITEM_FLAG_STACKABLE) && !IS_SET(item->GetAntiFlag(), ITEM_ANTIFLAG_STACK) && item->GetCount() > 1)
							item->SetCount(item->GetCount() - 1);
						else
							ITEM_MANAGER::instance().RemoveItem(item);

					for (int i = 0; i < count; i++)
					{
						switch (dwVnums[i])
						{
						case CSpecialItemGroup::GOLD:
							ChatPacket(CHAT_TYPE_INFO, LC_TEXT("µ· %lld łÉŔ» ČąµćÇß˝Ŕ´Ď´Ů."), static_cast<long long>(dwCounts[i]));
							break;
						case CSpecialItemGroup::EXP:
#ifdef ENABLE_ANTIEXP
							if (!IsBlockedExpGaining())
							{
								ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»óŔÚżˇĽ­ şÎĹÍ ˝ĹşńÇŃ şűŔĚ łŞżÉ´Ď´Ů."));
								if (dwCounts[i] > 0)
									ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%dŔÇ °ćÇčġ¸¦ ČąµćÇß˝Ŕ´Ď´Ů."), dwCounts[i]);
							}
							else
								ChatPacket(CHAT_TYPE_INFO, LC_TEXT("ľĆą«°Íµµ ľňŔ» Ľö ľřľú˝Ŕ´Ď´Ů."));
#else
							ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»óŔÚżˇĽ­ şÎĹÍ ˝ĹşńÇŃ şűŔĚ łŞżÉ´Ď´Ů."));
							ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%dŔÇ °ćÇčġ¸¦ ČąµćÇß˝Ŕ´Ď´Ů."), dwCounts[i]);
#endif
							break;
						case CSpecialItemGroup::MOB:
							ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»óŔÚżˇĽ­ ¸ó˝şĹÍ°ˇ łŞĹ¸łµ˝Ŕ´Ď´Ů!"));
							break;
						case CSpecialItemGroup::SLOW:
							ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»óŔÚżˇĽ­ łŞżÂ »ˇ°Ł ż¬±â¸¦ µéŔ̸¶˝ĂŔÚ żňÁ÷ŔĚ´Â ĽÓµµ°ˇ ´Ŕ·ÁÁł˝Ŕ´Ď´Ů!"));
							break;
						case CSpecialItemGroup::DRAIN_HP:
							ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»óŔÚ°ˇ °©ŔÚ±â ĆřąßÇĎż´˝Ŕ´Ď´Ů! »ý¸í·ÂŔĚ °¨ĽŇÇß˝Ŕ´Ď´Ů."));
							break;
						case CSpecialItemGroup::POISON:
							ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»óŔÚżˇĽ­ łŞżÂ łě»ö ż¬±â¸¦ µéŔ̸¶˝ĂŔÚ µ¶ŔĚ żÂ¸öŔ¸·Î ĆŰÁý´Ď´Ů!"));
							break;
#ifdef ENABLE_WOLFMAN_CHARACTER
						case CSpecialItemGroup::BLEEDING:
							ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»óŔÚżˇĽ­ łŞżÂ łě»ö ż¬±â¸¦ µéŔ̸¶˝ĂŔÚ µ¶ŔĚ żÂ¸öŔ¸·Î ĆŰÁý´Ď´Ů!"));
							break;
#endif
						case CSpecialItemGroup::MOB_GROUP:
							ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»óŔÚżˇĽ­ ¸ó˝şĹÍ°ˇ łŞĹ¸łµ˝Ŕ´Ď´Ů!"));
							break;
						default:
							if (item_gets[i])
							{
								if (dwCounts[i] > 1)
									ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»óŔÚżˇĽ­ %s °ˇ %d °ł łŞżÔ˝Ŕ´Ď´Ů."), item_gets[i]->GetName(), dwCounts[i]);
								else
									ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»óŔÚżˇĽ­ %s °ˇ łŞżÔ˝Ŕ´Ď´Ů."), item_gets[i]->GetName());
							}
						}
					}
				}
				else
				{
					ChatPacket(CHAT_TYPE_TALKING, LC_TEXT("ľĆą«°Íµµ ľňŔ» Ľö ľřľú˝Ŕ´Ď´Ů."));
					return false;
				}
			}
			break;

 


//char_item.cpp -> bool CHARACTER::MoveItem
		LPITEM item2;
		if ((item2 = GetItem(DestCell)) && item != item2 && item2->IsStackable() &&
				!IS_SET(item2->GetAntiFlag(), ITEM_ANTIFLAG_STACK) &&
				item2->GetVnum() == item->GetVnum()) // ÇŐÄĄ Ľö ŔÖ´Â ľĆŔĚĹŰŔÇ °ćżě
		{
			for (int i = 0; i < ITEM_SOCKET_MAX_NUM; ++i)
				if (i == 0 && item->GetType() == ITEM_GACHA)
					item2->SetSocket(0, item->GetSocket(0) + item2->GetSocket(0));
				else
					if (item2->GetSocket(i) != item->GetSocket(i))
						return false;

			if (wCount == 0)
				wCount = (WORD)item->GetCount();

			sys_log(0, "%s: ITEM_STACK %s (window: %d, cell : %d) -> (window:%d, cell %d) count %d", GetName(), item->GetName(), Cell.window_type, Cell.cell, DestCell.window_type, DestCell.cell, wCount);

 


//char_item.cpp -> bool CHARACTER::MoveItem
		else if (wCount < item->GetCount())
		{

			sys_log(0, "%s: ITEM_SPLIT %s (window: %d, cell : %d) -> (window:%d, cell %d) count %d", GetName(), item->GetName(), Cell.window_type, Cell.cell, DestCell.window_type, DestCell.cell, wCount);

			item->SetCount(item->GetCount() - wCount);
			LPITEM item2 = ITEM_MANAGER::instance().CreateItem(item->GetVnum(), wCount);
			// copy socket -- by mhh
			FN_copy_item_socket(item2, item);
			if (item->GetType() == ITEM_GACHA)
			{
				item->SetSocket(0, item->GetSocket(0) - wCount * item->GetLimitValue(1));
				item2->SetSocket(0, wCount * item->GetLimitValue(1));
			}

			item2->AddToCharacter(this, DestCell);

 


// item_manager.cpp -> LPITEM ITEM_MANAGER::CreateItem
	else if (item->GetType() == ITEM_UNIQUE)
	{
		for (itertype (m_map_pkSpecialItemGroup) it = m_map_pkSpecialItemGroup.begin(); it != m_map_pkSpecialItemGroup.end(); it++)
			if (it->second->m_bType == CSpecialItemGroup::SPECIAL && it->second->Contains(vnum))
				item->SetSIGVnum(it->first);
	}
	else if (item->GetType() == ITEM_GACHA)
		item->SetSocket(0, item->GetLimitValue(1) * count);


	// »ő·Î »ýĽşµÇ´Â żëČĄĽ® Ăł¸®.
	if (item->IsDragonSoul() && 0 == id)
		DSManager::instance().DragonSoulItemInitialize(item);

 

 

  • Like 2
  • Thanks 2

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×