Johnny69 365 Posted August 26, 2017 Share Posted August 26, 2017 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 1 9 Link to comment Share on other sites More sharing options...
ManiacRobert 427 Posted August 26, 2017 Share Posted August 26, 2017 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, Link to comment Share on other sites More sharing options...
Sebypunct 24 Posted August 27, 2017 Share Posted August 27, 2017 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. Link to comment Share on other sites More sharing options...
Honorable Member xP3NG3Rx 19658 Posted August 27, 2017 Honorable Member Share Posted August 27, 2017 Yeah, because he forgot the other parts of the protoreader(arrays for subtype). 1 Link to comment Share on other sites More sharing options...
Sebypunct 24 Posted August 27, 2017 Share Posted August 27, 2017 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 ? Link to comment Share on other sites More sharing options...
Johnny69 365 Posted August 27, 2017 Author Share Posted August 27, 2017 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. Link to comment Share on other sites More sharing options...
Sebypunct 24 Posted August 27, 2017 Share Posted August 27, 2017 same steps in ItemCSVReader.cpp what same steps ? Link to comment Share on other sites More sharing options...
Honorable Member xP3NG3Rx 19658 Posted August 27, 2017 Honorable Member Share Posted August 27, 2017 dump_proto Btw, works fine. Spoiler Link to comment Share on other sites More sharing options...
Premium North 1172 Posted August 28, 2017 Premium Share Posted August 28, 2017 cool, thanks for sharing boys Link to comment Share on other sites More sharing options...
TRBizeps 49 Posted August 28, 2017 Share Posted August 28, 2017 Thanks for sharing Link to comment Share on other sites More sharing options...
Premium ragem0re 155 Posted August 30, 2017 Premium Share Posted August 30, 2017 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. Link to comment Share on other sites More sharing options...
Premium North 1172 Posted August 31, 2017 Premium Share Posted August 31, 2017 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 Link to comment Share on other sites More sharing options...
Johnny69 365 Posted August 31, 2017 Author Share Posted August 31, 2017 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. Link to comment Share on other sites More sharing options...
Premium ragem0re 155 Posted August 31, 2017 Premium Share Posted August 31, 2017 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 Link to comment Share on other sites More sharing options...
Honorable Member xP3NG3Rx 19658 Posted September 15, 2017 Honorable Member Share Posted September 15, 2017 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); 5 Link to comment Share on other sites More sharing options...
Johnny69 365 Posted September 15, 2017 Author Share Posted September 15, 2017 Thanks @xP3NG3Rx. I did not make those changes because in official server GACHA box is not stackable. Link to comment Share on other sites More sharing options...
Kreciok 73 Posted November 7, 2017 Share Posted November 7, 2017 Thanks! Link to comment Share on other sites More sharing options...
Jokerino 3 Posted November 7, 2017 Share Posted November 7, 2017 Thanks for the release Link to comment Share on other sites More sharing options...
M3ragon 11 Posted November 7, 2017 Share Posted November 7, 2017 # removed to many error Link to comment Share on other sites More sharing options...
RcDragon 1 Posted February 20, 2018 Share Posted February 20, 2018 Your system didn't work on my server, so I took some parts and I created a chest subtype, and changed the "open count" to "value1" (less risk of conflict) and now is working perfectly... Thank you m8. +1 Link to comment Share on other sites More sharing options...
Jamie 12 Posted March 20, 2018 Share Posted March 20, 2018 when dropping items gacha does not stack @xP3NG3Rx i pay for the fix Link to comment Share on other sites More sharing options...
Premium North 1172 Posted March 20, 2018 Premium Share Posted March 20, 2018 (edited) 3 hours ago, Jamie said: when dropping items gacha does not stack @xP3NG3Rx i pay for the fix https://metin2.download/picture/6ZJVdNWYNmE6e2zs07DVL2DyK9Opxcvy/.gif ITEM_STACKABLE? this is not a gacha problem. Edited September 3, 2022 by Metin2 Dev Core X - External 2 Internal Link to comment Share on other sites More sharing options...
Jamie 12 Posted March 20, 2018 Share Posted March 20, 2018 1 hour ago, Fleon said: ITEM_STACKABLE? this is not a gacha problem. yes, those chets do not stack when they fall out of the boxes Link to comment Share on other sites More sharing options...
Aerrow 41 Posted March 31, 2018 Share Posted March 31, 2018 On 2017. 09. 15. at 11:33 AM, xP3NG3Rx said: 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 <!> Reveal hidden contents //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); Thanks for the useful modifications @xP3NG3Rx! But there are some bug. Let's get 2 same kind of box which has for ex. 5 usage. Then use the two box until they has 2-2 max usage. Stack them. Take it apart. Now one box has 5 usage, the other has -1. I think the system needs to if you stack them remove one of the stack, because 2+2 < 5. Btw, as I see the wCount variable is defined, but not used in the case ITEM_GACHA function. wCount = lOpenCount / item->GetLimitValue(1) Link to comment Share on other sites More sharing options...
Honorable Member xP3NG3Rx 19658 Posted April 4, 2018 Honorable Member Share Posted April 4, 2018 (edited) Thanks for it. Spoiler CHARACTER::MoveItem Edited August 20, 2022 by Metin2 Dev Core X - External 2 Internal 3 Link to comment Share on other sites More sharing options...
Recommended Posts