Artix96it 2 Posted January 8, 2022 Share Posted January 8, 2022 I appreciate the tutorial but many changes are not intuitive in fact. It would be nice to take the original System and make the various modifications to make it ready for use. There might be errors during the bugfix ... Some things don't add up. Is there a way to contact you privately? Link to comment Share on other sites More sharing options...
karona200 0 Posted May 22, 2022 Share Posted May 22, 2022 Where i can find the system target info complete? this is just a fix.. Link to comment Share on other sites More sharing options...
Chookez 71 Posted May 23, 2022 Share Posted May 23, 2022 5 hours ago, karona200 said: Where i can find the system target info complete? this is just a fix.. https://letmegooglethat.com/?q=Metin2+Target+information+system 1 Link to comment Share on other sites More sharing options...
karona200 0 Posted May 24, 2022 Share Posted May 24, 2022 Quote I flwed all the stepts, but still it shows me more items at lowlevel monsters . For ex at mob 101: wild dog it show weapons lv 65+ as drop Link to comment Share on other sites More sharing options...
Forum Moderator Gurgarath 2513 Posted May 24, 2022 Forum Moderator Share Posted May 24, 2022 7 hours ago, karona200 said: That's how the game works. That's common_drop_item.txt 1 1 Gurgarath coming soon Link to comment Share on other sites More sharing options...
LordZiege 279 Posted October 20, 2022 Share Posted October 20, 2022 (edited) I found a little bug, if you have the same item as drop, both with count 1 but different pct, the target info only show the one with higher pct, but not that one with lower pct. Anyone has fixxed that problem? (When you make different counts, it works, only problem is with same count), mob_drop_item: https://metin2.download/picture/toa06GE8ClHUvcFZpA2V6HjqUCL4R7ok/.png ingame: https://metin2.download/picture/GPpRn94DBekNFWpa7r11Q3WB2UsWpPzQ/.png Edited October 20, 2022 by Metin2 Dev Core X - External 2 Internal Link to comment Share on other sites More sharing options...
Premium Intel 757 Posted December 29, 2022 Author Premium Share Posted December 29, 2022 (edited) On 10/20/2022 at 12:11 PM, LordZiege said: I found a little bug, if you have the same item as drop, both with count 1 but different pct, the target info only show the one with higher pct, but not that one with lower pct. Anyone has fixxed that problem? (When you make different counts, it works, only problem is with same count), mob_drop_item: https://metin2.download/picture/toa06GE8ClHUvcFZpA2V6HjqUCL4R7ok/.png ingame: https://metin2.download/picture/GPpRn94DBekNFWpa7r11Q3WB2UsWpPzQ/.png Mh, I see different drops. This is my python part: if app.ENABLE_SEND_TARGET_INFO: def BINARY_AddTargetMonsterDropInfo(self, raceNum, itemVnum, itemCount, rarity): if not raceNum in uiTarget.MONSTER_INFO_DATA: uiTarget.MONSTER_INFO_DATA.update({raceNum : {}}) uiTarget.MONSTER_INFO_DATA[raceNum].update({"items" : []}) curList = uiTarget.MONSTER_INFO_DATA[raceNum]["items"] isUpgradeable = False isMetin = False item.SelectItem(itemVnum) if item.GetItemType() == item.ITEM_TYPE_WEAPON or item.GetItemType() == item.ITEM_TYPE_ARMOR: isUpgradeable = True elif item.GetItemType() == item.ITEM_TYPE_METIN: isMetin = True for curItem in curList: if isUpgradeable: if curItem.has_key("vnum_list") and curItem["vnum_list"][0] / 10 * 10 == itemVnum / 10 * 10: if not (itemVnum in curItem["vnum_list"]): curItem["vnum_list"].append(itemVnum) return elif isMetin: if curItem.has_key("vnum_list"): baseVnum = curItem["vnum_list"][0] if curItem.has_key("vnum_list") and (baseVnum - baseVnum%1000) == (itemVnum - itemVnum%1000): if not (itemVnum in curItem["vnum_list"]): curItem["vnum_list"].append(itemVnum) return else: if curItem.has_key("vnum") and curItem["vnum"] == itemVnum and curItem["count"] == itemCount and curItem["rarity"] == rarity: return if isUpgradeable or isMetin: curList.append({"vnum_list":[itemVnum], "count":itemCount, "rarity":rarity}) else: curList.append({"vnum":itemVnum, "count":itemCount, "rarity":rarity}) Edited December 29, 2022 by xXIntelXx Link to comment Share on other sites More sharing options...
SanctusCZE 15 Posted January 5, 2023 Share Posted January 5, 2023 Hi i have a little problem with this system its work good but if you see the info, drop items seems not logic becose its shows more items even item that dont drop from that monster. But for First second show the right items, then it refresh And show wronk items. Someone have solution? Sorry for my bad english Link to comment Share on other sites More sharing options...
SanctusCZE 15 Posted January 5, 2023 Share Posted January 5, 2023 (edited) 1 hour ago, SanctusCZE said: Hi i have a little problem with this system its work good but if you see the info, drop items seems not logic becose its shows more items even item that dont drop from that monster. But for First second show the right items, then it refresh And show wronk items. Someone have solution? Sorry for my bad english https://metin2.download/picture/dCyh0NwMEE0V9ZUP07MYoFu8EGL12GEb/.gif Edited January 6, 2023 by Metin2 Dev Core X - External 2 Internal 1 Link to comment Share on other sites More sharing options...
Forum Moderator Gurgarath 2513 Posted January 5, 2023 Forum Moderator Share Posted January 5, 2023 (edited) 4 hours ago, SanctusCZE said: Hi i have a little problem with this system its work good but if you see the info, drop items seems not logic becose its shows more items even item that dont drop from that monster. But for First second show the right items, then it refresh And show wronk items. Someone have solution? Sorry for my bad english 3 hours ago, SanctusCZE said: https://metin2.download/picture/dCyh0NwMEE0V9ZUP07MYoFu8EGL12GEb/.gif Those are called "common_drop". This is how the game works. You can drop them on virtually any monsters, that's why they show there. Of course, it all comes to the logic of having them in this system, is it very good to have them for every monsters, or is it even worth to have them at all displayed? That's up to you. But this is not a bug Edited January 6, 2023 by Metin2 Dev Core X - External 2 Internal 1 Gurgarath coming soon Link to comment Share on other sites More sharing options...
SanctusCZE 15 Posted January 6, 2023 Share Posted January 6, 2023 (edited) 7 hours ago, Gurgarath said: Those are called "common_drop". This is how the game works. You can drop them on virtually any monsters, that's why they show there. Of course, it all comes to the logic of having them in this system, is it very good to have them for every monsters, or is it even worth to have them at all displayed? That's up to you. But this is not a bug OK but if it show in this system, mob must drop that item. Problem is, they dont drop right items, they drop only a few drops. For example: Mob 101 drops only potion, but system shows weapons from lvl 65+, i found fix but i dont know if its right fix: https://www.pastebin.cz/en/p/dGB4UQm But normally its look like that: https://www.pastebin.cz/en/p/6qdYHnr Edited January 6, 2023 by SanctusCZE Link to comment Share on other sites More sharing options...
SussyFlore96 2 Posted January 15, 2023 Share Posted January 15, 2023 Hello! Can you let me a tutorial for rarity in this system? Thank you! Link to comment Share on other sites More sharing options...
Premium Intel 757 Posted January 16, 2023 Author Premium Share Posted January 16, 2023 (edited) 20 hours ago, SussyFlore96 said: Hello! Can you let me a tutorial for rarity in this system? Thank you! Example for drop item group, replace: vec_item.push_back(std::make_pair(std::make_pair(v[i].dwVnum, v[i].iCount),v[i].rarity)); with: vec_item.emplace_back(std::make_tuple(v[i].dwVnum, v[i].iCount, rarity)); (so make_pair with make_tuple and add rarity as the third parameter) Rarities functions I've made: int CalculateDropRarityCommonDropItem(int x) { int pct = x; int rarity = 0; if(pct >= 4000000) rarity = 1; else if(pct < 40000000 && pct >= 200000 ) rarity = 2; else if(pct < 200000 && pct >= 10000 ) rarity = 3; else if(pct < 10000 && pct >= 5000 ) rarity = 4; else if(pct < 5000 && pct >= 1000 ) rarity = 5; else if(pct < 1000 && pct >= 0 ) rarity = 6; return rarity; } int CalculateDropRarityKillDrop(int x, BYTE bType) { int pct = x; int rarity = 0; if(pct == 1) rarity = 1; else if(pct > 1 && pct <= 300 ) rarity = 2; else if(pct > 300 && pct <= 500 ) rarity = 3; else if(pct > 500 && pct <= 2000 ) rarity = 4; else if(pct > 2000 && pct <= 5000 ) rarity = 5; else if(pct > 5000 ) rarity = 6; return rarity; } int CalculateDropRarityDropItemGroup(int x, BYTE bType) { int pct = x; int rarity = 0; switch(bType) { case CHAR_TYPE_BOSS: { if(pct >= 4000000) rarity = 1; else if(pct < 4000000 && pct >= 2600000 ) //100~65 rarity = 2; else if(pct < 2600000 && pct >= 1600000 ) //65~40 rarity = 3; else if(pct < 1600000 && pct >= 1000000 ) //40~25 rarity = 4; else if(pct < 1000000 && pct >= 600000 ) //25~15 rarity = 5; else if(pct < 600000 ) rarity = 6; } break; case CHAR_TYPE_MONSTER: { if(pct >= 4000000) rarity = 1; else if(pct < 4000000 && pct >= 1600000 ) //100~40 rarity = 2; else if(pct < 1600000 && pct >= 800000 ) //40~20 rarity = 3; else if(pct < 800000 && pct >= 200000 ) //20~5 rarity = 4; else if(pct < 200000 && pct >= 20000 ) //5~0.5 rarity = 5; else if(pct < 20000 ) rarity = 6; } break; case CHAR_TYPE_STONE: { if(pct >= 4000000) rarity = 1; else if(pct < 4000000 && pct >= 2000000 ) //100~50 rarity = 2; else if(pct < 2000000 && pct >= 1000000 ) //50~25 rarity = 3; else if(pct < 1000000 && pct >= 600000 ) //25~15 rarity = 4; else if(pct < 600000 && pct >= 200000 ) //15~5 rarity = 5; else if(pct < 200000 ) rarity = 6; } break; default: { if(pct >= 4000000) rarity = 1; else if(pct < 4000000 && pct >= 2000000 ) //100~50 rarity = 2; else if(pct < 2000000 && pct >= 1000000 ) //50~25 rarity = 3; else if(pct < 1000000 && pct >= 600000 ) //25~15 rarity = 4; else if(pct < 600000 && pct >= 200000 ) //15~5 rarity = 5; else if(pct < 200000 ) rarity = 6; } break; } return rarity; } int CalculateDropRarityLevelItemGroup(float x, BYTE bType) { float pct = x / 10000.0000; int rarity = 0; switch(bType) { case CHAR_TYPE_BOSS: { if(pct >= 100.0000) rarity = 1; else if(pct < 100.0000 && pct >= 65.0000 ) rarity = 2; else if(pct < 65.0000 && pct >= 40.0000 ) rarity = 3; else if(pct < 40.0000 && pct >= 25.0000 ) rarity = 4; else if(pct < 25.0000 && pct >= 15.0000 ) rarity = 5; else if(pct < 15.0000 ) rarity = 6; } break; case CHAR_TYPE_STONE: { if(pct >= 100.0000) rarity = 1; else if(pct < 100.0000 && pct >= 50.0000 ) rarity = 2; else if(pct < 50.0000 && pct >= 25.0000 ) rarity = 3; else if(pct < 25.0000 && pct >= 15.0000 ) rarity = 4; else if(pct < 15.0000 && pct >= 5.0000 ) rarity = 5; else if(pct < 5.0000 ) rarity = 6; } break; case CHAR_TYPE_MONSTER: { if(pct >= 100.0000) rarity = 1; else if(pct < 100.0000 && pct >= 30.0000 ) rarity = 2; else if(pct < 30.0000 && pct >= 15.0000 ) rarity = 3; else if(pct < 15.0000 && pct >= 1.0000 ) rarity = 4; else if(pct < 1.0000 && pct >= 0.1000 ) rarity = 5; else if(pct < 0.1000 ) rarity = 6; } break; default: { if(pct >= 100.0000) rarity = 1; else if(pct < 100.0000 && pct >= 65.0000 ) rarity = 2; else if(pct < 65.0000 && pct >= 40.0000 ) rarity = 3; else if(pct < 40.0000 && pct >= 25.0000 ) rarity = 4; else if(pct < 25.0000 && pct >= 15.0000 ) rarity = 5; else if(pct < 15.0000 ) rarity = 6; } } return rarity; } int CalculateDropRarityTimeDrop(int x, BYTE bType) { int pct = x; int rarity = 0; switch(bType) { case CHAR_TYPE_BOSS: { if(pct == 1000000) rarity = 1; else if(pct < 1000000 && pct >= 650000 ) rarity = 2; else if(pct < 650000 && pct >= 400000 ) rarity = 3; else if(pct < 400000 && pct >= 250000 ) rarity = 4; else if(pct < 250000 && pct >= 150000 ) rarity = 5; else if(pct < 150000 ) rarity = 6; } break; case CHAR_TYPE_MONSTER: { if(pct == 1000000) rarity = 1; else if(pct < 1000000 && pct >= 400000 ) rarity = 2; else if(pct < 400000 && pct >= 200000 ) rarity = 3; else if(pct < 200000 && pct >= 100000 ) rarity = 4; else if(pct < 100000 && pct >= 5000 ) rarity = 5; else if(pct < 5000 ) rarity = 6; } break; case CHAR_TYPE_STONE: { if(pct == 1000000) rarity = 1; else if(pct < 1000000 && pct >= 500000 ) rarity = 2; else if(pct < 500000 && pct >= 250000 ) rarity = 3; else if(pct < 250000 && pct >= 150000 ) rarity = 4; else if(pct < 150000 && pct >= 50000 ) rarity = 5; else if(pct < 50000 ) rarity = 6; } default: { if(pct == 1000000) rarity = 1; else if(pct < 1000000 && pct >= 500000 ) rarity = 2; else if(pct < 500000 && pct >= 250000 ) rarity = 3; else if(pct < 250000 && pct >= 150000 ) rarity = 4; else if(pct < 150000 && pct >= 50000 ) rarity = 5; else if(pct < 50000 ) rarity = 6; } break; } return rarity; } Hint: instead of the char type, since the BOSS type is not by default in the sources, you could pass the rank as well, then put the rank on the switch case and, if the rank is 5, check if it's a metin or not. Therefore in the drop item group example would be like this: // Drop Item Group { auto it = m_map_pkDropItemGroup.find(pkChr->GetRaceNum()); if(it != m_map_pkDropItemGroup.end()) { auto v = it->second->GetVector(); for (DWORD i = 0; i < v.size(); ++i) { if( iLevel >= (iMobLevel - 15) && iLevel <= (iMobLevel + 15) ) //don't show outside level limits { uint8_t rarity = CalculateDropRarityDropItemGroup(v[i].dwPct, bType); vec_item.emplace_back(std::make_tuple(v[i].dwVnum, v[i].iCount, rarity)); //vec_item.push_back(std::make_pair(std::make_pair(v[i].dwVnum, v[i].iCount),v[i].rarity)); } } } } You can sort them by rarity like this: std::sort(vec_item.begin(),vec_item.end(), sortbyrarity); //then sort by rarity sortbyrarity function: bool sortbyrarity(std::tuple<int, int, int>& a, std::tuple<int, int, int>& b) { return (std::get<2>(a) > std::get<2>(b)); } and in input_main.cpp: pInfo.dwVID = m_pkChrTarget->GetVID(); pInfo.race = m_pkChrTarget->GetRaceNum(); pInfo.dwVnum = std::get<0>(x); pInfo.count = std::get<1>(x); pInfo.rarity = std::get<2>(x); this is how you get the data from the tuple and s_vec_item declaration changes to: static std::vector<std::tuple<int,int,int>> s_vec_item; Obviously you should change the packet accordingly and in bool CPythonNetworkStream::RecvTargetInfoPacket() change: Py_BuildValue("(iii)", pInfoTargetPacket.race, pInfoTargetPacket.dwVnum, pInfoTargetPacket.count)); into: Py_BuildValue("(iiii)", pInfoTargetPacket.race, pInfoTargetPacket.dwVnum, pInfoTargetPacket.count, pInfoTargetPacket.rarity)); game.py change of BINARY_AddTargetMonsterDropInfo: if app.ENABLE_SEND_TARGET_INFO: def BINARY_AddTargetMonsterDropInfo(self, raceNum, itemVnum, itemCount, rarity): if not raceNum in uiTarget.MONSTER_INFO_DATA: uiTarget.MONSTER_INFO_DATA.update({raceNum : {}}) uiTarget.MONSTER_INFO_DATA[raceNum].update({"items" : []}) curList = uiTarget.MONSTER_INFO_DATA[raceNum]["items"] isUpgradeable = False isMetin = False item.SelectItem(itemVnum) if item.GetItemType() == item.ITEM_TYPE_WEAPON or item.GetItemType() == item.ITEM_TYPE_ARMOR: isUpgradeable = True elif item.GetItemType() == item.ITEM_TYPE_METIN: isMetin = True for curItem in curList: if isUpgradeable: if curItem.has_key("vnum_list") and curItem["vnum_list"][0] / 10 * 10 == itemVnum / 10 * 10: if not (itemVnum in curItem["vnum_list"]): curItem["vnum_list"].append(itemVnum) return elif isMetin: if curItem.has_key("vnum_list"): baseVnum = curItem["vnum_list"][0] if curItem.has_key("vnum_list") and (baseVnum - baseVnum%1000) == (itemVnum - itemVnum%1000): if not (itemVnum in curItem["vnum_list"]): curItem["vnum_list"].append(itemVnum) return else: if curItem.has_key("vnum") and curItem["vnum"] == itemVnum and curItem["count"] == itemCount and curItem["rarity"] == rarity: return if isUpgradeable or isMetin: curList.append({"vnum_list":[itemVnum], "count":itemCount, "rarity":rarity}) else: curList.append({"vnum":itemVnum, "count":itemCount, "rarity":rarity}) and in uitarget.py, the class ItemListBoxItem: class ItemListBoxItem(ui.Window): def __init__(self, width): ui.Window.__init__(self) image = ui.ExpandedImageBox() image.SetParent(self) image.Show() self.image = image nameLine = ui.TextLine() nameLine.SetParent(self) nameLine.SetPosition(32 + 5, 0) nameLine.Show() self.nameLine = nameLine rarity = ui.TextLine() rarity.SetParent(self) rarity.SetPosition(32 + 5, 13) rarity.Show() self.rarity = rarity self.SetSize(width, 32 + 5) def LoadImage(self, image, name = None): self.image.LoadImage(image) self.SetSize(self.GetWidth(), self.image.GetHeight() + 5) if name != None: self.SetText(name) def SetText(self, text): self.nameLine.SetText(text) def SetRarityText(self, text, rarity): TEXT_COLORS = [ grp.GenerateColor(1.0, 0.0, 0.0, 1.0), grp.GenerateColor(1.0, 1.0, 1.0, 1.0), grp.GenerateColor(0.33, 1.0, 0.12, 1.0), grp.GenerateColor(0.42, 0.93, 0.76, 1.0), grp.GenerateColor(0.0, 0.89, 1.0, 1.0), grp.GenerateColor(0.41, 0.0, 1.0, 1.0), grp.GenerateColor(1.0, 0.86, 0.0, 1.0) ] if rarity != 1: self.rarity.SetPackedFontColor(TEXT_COLORS[rarity]) self.rarity.SetText(text) __LoadInformation_Drops: def __LoadInformation_Drops(self, race): self.AppendSeperator() if race in MONSTER_INFO_DATA: if len(MONSTER_INFO_DATA[race]["items"]) == 0: self.AppendTextLine(localeInfo.TARGET_INFO_NO_ITEM_TEXT) else: itemListBox = ui.ListBoxExNew(32 + 5, self.MAX_ITEM_COUNT) itemListBox.SetSize(self.GetWidth() - 15 * 2 - ui.ScrollBar.SCROLLBAR_WIDTH, (32 + 5) * self.MAX_ITEM_COUNT) height = 0 for curItem in MONSTER_INFO_DATA[race]["items"]: if curItem.has_key("vnum_list"): height += self.AppendItem(itemListBox, curItem["vnum_list"], curItem["count"], curItem["rarity"], race) else: height += self.AppendItem(itemListBox, curItem["vnum"], curItem["count"], curItem["rarity"], race) if height < itemListBox.GetHeight(): itemListBox.SetSize(itemListBox.GetWidth(), height) self.AppendWindow(itemListBox, 15) itemListBox.SetBasePos(0) if len(MONSTER_INFO_DATA[race]["items"]) > itemListBox.GetViewItemCountFixed(): itemScrollBar = ui.ScrollBar() itemScrollBar.SetParent(self) itemScrollBar.SetPosition(itemListBox.GetRight(), itemListBox.GetTop()) itemScrollBar.SetScrollBarSize(32 * self.MAX_ITEM_COUNT + 5 * (self.MAX_ITEM_COUNT - 1)) itemScrollBar.SetMiddleBarSize(float(self.MAX_ITEM_COUNT) / float(height / (32 + 5))) itemScrollBar.Show() itemListBox.SetScrollBar(itemScrollBar) self.scrollBar = itemListBox.GetScrollBar() else: self.AppendTextLine(localeInfo.TARGET_INFO_NO_ITEM_TEXT) AppendItem: def AppendItem(self, listBox, vnums, count, rarity, race): if type(vnums) == int: vnum = vnums else: vnum = vnums[0] item.SelectItem(vnum) itemName = item.GetItemName() if type(vnums) != int and len(vnums) > 1: #vnums = sorted(vnums) realName = itemName[:itemName.find("+")] if item.GetItemType() == item.ITEM_TYPE_METIN: realName = localeInfo.TARGET_INFO_STONE_NAME itemName = realName + "+0 - +4" else: itemName = realName + "+" + str(vnums[0] % 10) + " - +" + str(vnums[len(vnums) - 1] % 10) vnum = vnums[len(vnums) - 1] myItem = self.ItemListBoxItem(listBox.GetWidth()) myItem.LoadImage(item.GetIconImageFileName()) if count <= 1: myItem.SetText(itemName) else: myItem.SetText("%dx %s" % (count, itemName)) RARITY_NAMES_LIST = [localeInfo.DROP_RARITY_ERROR, localeInfo.DROP_GUARANTEED, localeInfo.DROP_COMMON, localeInfo.DROP_UNCOMMON, localeInfo.DROP_RARE, localeInfo.DROP_MYTHIC, localeInfo.DROP_LEGENDARY] myItem.SetRarityText("%s" % RARITY_NAMES_LIST[rarity], rarity) myItem.SAFE_SetOverInEvent(self.OnShowItemTooltip,vnum) myItem.SAFE_SetOverOutEvent(self.OnHideItemTooltip) listBox.AppendItem(myItem) if item.GetItemType() == item.ITEM_TYPE_METIN: self.stoneImg = myItem self.stoneVnum = vnums self.lastStoneVnum = self.STONE_LAST_VNUM + vnums[len(vnums) - 1] % 1000 / 100 * 100 return myItem.GetHeight() Edited January 16, 2023 by xXIntelXx 2 Link to comment Share on other sites More sharing options...
SussyFlore96 2 Posted January 16, 2023 Share Posted January 16, 2023 (edited) 7 hours ago, xXIntelXx said: Example for drop item group, replace: vec_item.push_back(std::make_pair(std::make_pair(v[i].dwVnum, v[i].iCount),v[i].rarity)); with: vec_item.emplace_back(std::make_tuple(v[i].dwVnum, v[i].iCount, rarity)); (so make_pair with make_tuple and add rarity as the third parameter) Rarities functions I've made: int CalculateDropRarityCommonDropItem(int x) { int pct = x; int rarity = 0; if(pct >= 4000000) rarity = 1; else if(pct < 40000000 && pct >= 200000 ) rarity = 2; else if(pct < 200000 && pct >= 10000 ) rarity = 3; else if(pct < 10000 && pct >= 5000 ) rarity = 4; else if(pct < 5000 && pct >= 1000 ) rarity = 5; else if(pct < 1000 && pct >= 0 ) rarity = 6; return rarity; } int CalculateDropRarityKillDrop(int x, BYTE bType) { int pct = x; int rarity = 0; if(pct == 1) rarity = 1; else if(pct > 1 && pct <= 300 ) rarity = 2; else if(pct > 300 && pct <= 500 ) rarity = 3; else if(pct > 500 && pct <= 2000 ) rarity = 4; else if(pct > 2000 && pct <= 5000 ) rarity = 5; else if(pct > 5000 ) rarity = 6; return rarity; } int CalculateDropRarityDropItemGroup(int x, BYTE bType) { int pct = x; int rarity = 0; switch(bType) { case CHAR_TYPE_BOSS: { if(pct >= 4000000) rarity = 1; else if(pct < 4000000 && pct >= 2600000 ) //100~65 rarity = 2; else if(pct < 2600000 && pct >= 1600000 ) //65~40 rarity = 3; else if(pct < 1600000 && pct >= 1000000 ) //40~25 rarity = 4; else if(pct < 1000000 && pct >= 600000 ) //25~15 rarity = 5; else if(pct < 600000 ) rarity = 6; } break; case CHAR_TYPE_MONSTER: { if(pct >= 4000000) rarity = 1; else if(pct < 4000000 && pct >= 1600000 ) //100~40 rarity = 2; else if(pct < 1600000 && pct >= 800000 ) //40~20 rarity = 3; else if(pct < 800000 && pct >= 200000 ) //20~5 rarity = 4; else if(pct < 200000 && pct >= 20000 ) //5~0.5 rarity = 5; else if(pct < 20000 ) rarity = 6; } break; case CHAR_TYPE_STONE: { if(pct >= 4000000) rarity = 1; else if(pct < 4000000 && pct >= 2000000 ) //100~50 rarity = 2; else if(pct < 2000000 && pct >= 1000000 ) //50~25 rarity = 3; else if(pct < 1000000 && pct >= 600000 ) //25~15 rarity = 4; else if(pct < 600000 && pct >= 200000 ) //15~5 rarity = 5; else if(pct < 200000 ) rarity = 6; } break; default: { if(pct >= 4000000) rarity = 1; else if(pct < 4000000 && pct >= 2000000 ) //100~50 rarity = 2; else if(pct < 2000000 && pct >= 1000000 ) //50~25 rarity = 3; else if(pct < 1000000 && pct >= 600000 ) //25~15 rarity = 4; else if(pct < 600000 && pct >= 200000 ) //15~5 rarity = 5; else if(pct < 200000 ) rarity = 6; } break; } return rarity; } int CalculateDropRarityLevelItemGroup(float x, BYTE bType) { float pct = x / 10000.0000; int rarity = 0; switch(bType) { case CHAR_TYPE_BOSS: { if(pct >= 100.0000) rarity = 1; else if(pct < 100.0000 && pct >= 65.0000 ) rarity = 2; else if(pct < 65.0000 && pct >= 40.0000 ) rarity = 3; else if(pct < 40.0000 && pct >= 25.0000 ) rarity = 4; else if(pct < 25.0000 && pct >= 15.0000 ) rarity = 5; else if(pct < 15.0000 ) rarity = 6; } break; case CHAR_TYPE_STONE: { if(pct >= 100.0000) rarity = 1; else if(pct < 100.0000 && pct >= 50.0000 ) rarity = 2; else if(pct < 50.0000 && pct >= 25.0000 ) rarity = 3; else if(pct < 25.0000 && pct >= 15.0000 ) rarity = 4; else if(pct < 15.0000 && pct >= 5.0000 ) rarity = 5; else if(pct < 5.0000 ) rarity = 6; } break; case CHAR_TYPE_MONSTER: { if(pct >= 100.0000) rarity = 1; else if(pct < 100.0000 && pct >= 30.0000 ) rarity = 2; else if(pct < 30.0000 && pct >= 15.0000 ) rarity = 3; else if(pct < 15.0000 && pct >= 1.0000 ) rarity = 4; else if(pct < 1.0000 && pct >= 0.1000 ) rarity = 5; else if(pct < 0.1000 ) rarity = 6; } break; default: { if(pct >= 100.0000) rarity = 1; else if(pct < 100.0000 && pct >= 65.0000 ) rarity = 2; else if(pct < 65.0000 && pct >= 40.0000 ) rarity = 3; else if(pct < 40.0000 && pct >= 25.0000 ) rarity = 4; else if(pct < 25.0000 && pct >= 15.0000 ) rarity = 5; else if(pct < 15.0000 ) rarity = 6; } } return rarity; } int CalculateDropRarityTimeDrop(int x, BYTE bType) { int pct = x; int rarity = 0; switch(bType) { case CHAR_TYPE_BOSS: { if(pct == 1000000) rarity = 1; else if(pct < 1000000 && pct >= 650000 ) rarity = 2; else if(pct < 650000 && pct >= 400000 ) rarity = 3; else if(pct < 400000 && pct >= 250000 ) rarity = 4; else if(pct < 250000 && pct >= 150000 ) rarity = 5; else if(pct < 150000 ) rarity = 6; } break; case CHAR_TYPE_MONSTER: { if(pct == 1000000) rarity = 1; else if(pct < 1000000 && pct >= 400000 ) rarity = 2; else if(pct < 400000 && pct >= 200000 ) rarity = 3; else if(pct < 200000 && pct >= 100000 ) rarity = 4; else if(pct < 100000 && pct >= 5000 ) rarity = 5; else if(pct < 5000 ) rarity = 6; } break; case CHAR_TYPE_STONE: { if(pct == 1000000) rarity = 1; else if(pct < 1000000 && pct >= 500000 ) rarity = 2; else if(pct < 500000 && pct >= 250000 ) rarity = 3; else if(pct < 250000 && pct >= 150000 ) rarity = 4; else if(pct < 150000 && pct >= 50000 ) rarity = 5; else if(pct < 50000 ) rarity = 6; } default: { if(pct == 1000000) rarity = 1; else if(pct < 1000000 && pct >= 500000 ) rarity = 2; else if(pct < 500000 && pct >= 250000 ) rarity = 3; else if(pct < 250000 && pct >= 150000 ) rarity = 4; else if(pct < 150000 && pct >= 50000 ) rarity = 5; else if(pct < 50000 ) rarity = 6; } break; } return rarity; } Hint: instead of the char type, since the BOSS type is not by default in the sources, you could pass the rank as well, then put the rank on the switch case and, if the rank is 5, check if it's a metin or not. Therefore in the drop item group example would be like this: // Drop Item Group { auto it = m_map_pkDropItemGroup.find(pkChr->GetRaceNum()); if(it != m_map_pkDropItemGroup.end()) { auto v = it->second->GetVector(); for (DWORD i = 0; i < v.size(); ++i) { if( iLevel >= (iMobLevel - 15) && iLevel <= (iMobLevel + 15) ) //don't show outside level limits { uint8_t rarity = CalculateDropRarityDropItemGroup(v[i].dwPct, bType); vec_item.emplace_back(std::make_tuple(v[i].dwVnum, v[i].iCount, rarity)); //vec_item.push_back(std::make_pair(std::make_pair(v[i].dwVnum, v[i].iCount),v[i].rarity)); } } } } and in input_main.cpp: pInfo.dwVID = m_pkChrTarget->GetVID(); pInfo.race = m_pkChrTarget->GetRaceNum(); pInfo.dwVnum = std::get<0>(x); pInfo.count = std::get<1>(x); pInfo.rarity = std::get<2>(x); this is how you get the data from the tuple and s_vec_item declaration changes to: static std::vector<std::tuple<int,int,int>> s_vec_item; Obviously you should change the packet accordingly and in bool CPythonNetworkStream::RecvTargetInfoPacket() change: Py_BuildValue("(iii)", pInfoTargetPacket.race, pInfoTargetPacket.dwVnum, pInfoTargetPacket.count)); into: Py_BuildValue("(iiii)", pInfoTargetPacket.race, pInfoTargetPacket.dwVnum, pInfoTargetPacket.count, pInfoTargetPacket.rarity)); game.py change of BINARY_AddTargetMonsterDropInfo: if app.ENABLE_SEND_TARGET_INFO: def BINARY_AddTargetMonsterDropInfo(self, raceNum, itemVnum, itemCount, rarity): if not raceNum in uiTarget.MONSTER_INFO_DATA: uiTarget.MONSTER_INFO_DATA.update({raceNum : {}}) uiTarget.MONSTER_INFO_DATA[raceNum].update({"items" : []}) curList = uiTarget.MONSTER_INFO_DATA[raceNum]["items"] isUpgradeable = False isMetin = False item.SelectItem(itemVnum) if item.GetItemType() == item.ITEM_TYPE_WEAPON or item.GetItemType() == item.ITEM_TYPE_ARMOR: isUpgradeable = True elif item.GetItemType() == item.ITEM_TYPE_METIN: isMetin = True for curItem in curList: if isUpgradeable: if curItem.has_key("vnum_list") and curItem["vnum_list"][0] / 10 * 10 == itemVnum / 10 * 10: if not (itemVnum in curItem["vnum_list"]): curItem["vnum_list"].append(itemVnum) return elif isMetin: if curItem.has_key("vnum_list"): baseVnum = curItem["vnum_list"][0] if curItem.has_key("vnum_list") and (baseVnum - baseVnum%1000) == (itemVnum - itemVnum%1000): if not (itemVnum in curItem["vnum_list"]): curItem["vnum_list"].append(itemVnum) return else: if curItem.has_key("vnum") and curItem["vnum"] == itemVnum and curItem["count"] == itemCount and curItem["rarity"] == rarity: return if isUpgradeable or isMetin: curList.append({"vnum_list":[itemVnum], "count":itemCount, "rarity":rarity}) else: curList.append({"vnum":itemVnum, "count":itemCount, "rarity":rarity}) and in uitarget.py, the class ItemListBoxItem: class ItemListBoxItem(ui.Window): def __init__(self, width): ui.Window.__init__(self) image = ui.ExpandedImageBox() image.SetParent(self) image.Show() self.image = image nameLine = ui.TextLine() nameLine.SetParent(self) nameLine.SetPosition(32 + 5, 0) nameLine.Show() self.nameLine = nameLine rarity = ui.TextLine() rarity.SetParent(self) rarity.SetPosition(32 + 5, 13) rarity.Show() self.rarity = rarity self.SetSize(width, 32 + 5) def LoadImage(self, image, name = None): self.image.LoadImage(image) self.SetSize(self.GetWidth(), self.image.GetHeight() + 5) if name != None: self.SetText(name) def SetText(self, text): self.nameLine.SetText(text) def SetRarityText(self, text, rarity): TEXT_COLORS = [ grp.GenerateColor(1.0, 0.0, 0.0, 1.0), grp.GenerateColor(1.0, 1.0, 1.0, 1.0), grp.GenerateColor(0.33, 1.0, 0.12, 1.0), grp.GenerateColor(0.42, 0.93, 0.76, 1.0), grp.GenerateColor(0.0, 0.89, 1.0, 1.0), grp.GenerateColor(0.41, 0.0, 1.0, 1.0), grp.GenerateColor(1.0, 0.86, 0.0, 1.0) ] if rarity != 1: self.rarity.SetPackedFontColor(TEXT_COLORS[rarity]) self.rarity.SetText(text) __LoadInformation_Drops: def __LoadInformation_Drops(self, race): self.AppendSeperator() if race in MONSTER_INFO_DATA: if len(MONSTER_INFO_DATA[race]["items"]) == 0: self.AppendTextLine(localeInfo.TARGET_INFO_NO_ITEM_TEXT) else: itemListBox = ui.ListBoxExNew(32 + 5, self.MAX_ITEM_COUNT) itemListBox.SetSize(self.GetWidth() - 15 * 2 - ui.ScrollBar.SCROLLBAR_WIDTH, (32 + 5) * self.MAX_ITEM_COUNT) height = 0 for curItem in MONSTER_INFO_DATA[race]["items"]: if curItem.has_key("vnum_list"): height += self.AppendItem(itemListBox, curItem["vnum_list"], curItem["count"], curItem["rarity"], race) else: height += self.AppendItem(itemListBox, curItem["vnum"], curItem["count"], curItem["rarity"], race) if height < itemListBox.GetHeight(): itemListBox.SetSize(itemListBox.GetWidth(), height) self.AppendWindow(itemListBox, 15) itemListBox.SetBasePos(0) if len(MONSTER_INFO_DATA[race]["items"]) > itemListBox.GetViewItemCountFixed(): itemScrollBar = ui.ScrollBar() itemScrollBar.SetParent(self) itemScrollBar.SetPosition(itemListBox.GetRight(), itemListBox.GetTop()) itemScrollBar.SetScrollBarSize(32 * self.MAX_ITEM_COUNT + 5 * (self.MAX_ITEM_COUNT - 1)) itemScrollBar.SetMiddleBarSize(float(self.MAX_ITEM_COUNT) / float(height / (32 + 5))) itemScrollBar.Show() itemListBox.SetScrollBar(itemScrollBar) self.scrollBar = itemListBox.GetScrollBar() else: self.AppendTextLine(localeInfo.TARGET_INFO_NO_ITEM_TEXT) AppendItem: def AppendItem(self, listBox, vnums, count, rarity, race): if type(vnums) == int: vnum = vnums else: vnum = vnums[0] item.SelectItem(vnum) itemName = item.GetItemName() if type(vnums) != int and len(vnums) > 1: #vnums = sorted(vnums) realName = itemName[:itemName.find("+")] if item.GetItemType() == item.ITEM_TYPE_METIN: realName = localeInfo.TARGET_INFO_STONE_NAME itemName = realName + "+0 - +4" else: itemName = realName + "+" + str(vnums[0] % 10) + " - +" + str(vnums[len(vnums) - 1] % 10) vnum = vnums[len(vnums) - 1] myItem = self.ItemListBoxItem(listBox.GetWidth()) myItem.LoadImage(item.GetIconImageFileName()) if count <= 1: myItem.SetText(itemName) else: myItem.SetText("%dx %s" % (count, itemName)) RARITY_NAMES_LIST = [localeInfo.DROP_RARITY_ERROR, localeInfo.DROP_GUARANTEED, localeInfo.DROP_COMMON, localeInfo.DROP_UNCOMMON, localeInfo.DROP_RARE, localeInfo.DROP_MYTHIC, localeInfo.DROP_LEGENDARY] myItem.SetRarityText("%s" % RARITY_NAMES_LIST[rarity], rarity) myItem.SAFE_SetOverInEvent(self.OnShowItemTooltip,vnum) myItem.SAFE_SetOverOutEvent(self.OnHideItemTooltip) listBox.AppendItem(myItem) if item.GetItemType() == item.ITEM_TYPE_METIN: self.stoneImg = myItem self.stoneVnum = vnums self.lastStoneVnum = self.STONE_LAST_VNUM + vnums[len(vnums) - 1] % 1000 / 100 * 100 return myItem.GetHeight() Thank you! Now I get this: Spoiler Edited January 17, 2023 by Metin2 Dev Core X - External 2 Internal Link to comment Share on other sites More sharing options...
Premium Intel 757 Posted January 16, 2023 Author Premium Share Posted January 16, 2023 (edited) 52 minutes ago, SussyFlore96 said: Thank you! Now I get this: You need c++11 (-std=c++11 on your makefile in the CXXFLAGS) I think.. I say I think because generally I'd understand this if you were trying to put some objects of a class with no default constructor (but they are integers...) Spoiler Edited January 17, 2023 by Metin2 Dev Core X - External 2 Internal Link to comment Share on other sites More sharing options...
SussyFlore96 2 Posted January 16, 2023 Share Posted January 16, 2023 3 minutes ago, xXIntelXx said: You need c++11 (-std=c++11 on your makefile in the CXXFLAGS) I have c++2a, can't be adapted for this? Link to comment Share on other sites More sharing options...
Premium Intel 757 Posted January 16, 2023 Author Premium Share Posted January 16, 2023 Just now, SussyFlore96 said: I have c++2a, can't be adapted for this? Oh hell no, I also use c++2a. That's odd. AH NO WAIT hold up lmao. You need to add: #include <tuple> in input_main.cpp and item_manager.cpp Link to comment Share on other sites More sharing options...
SussyFlore96 2 Posted January 16, 2023 Share Posted January 16, 2023 23 minutes ago, xXIntelXx said: Oh hell no, I also use c++2a. That's odd. AH NO WAIT hold up lmao. You need to add: #include <tuple> in input_main.cpp and item_manager.cpp Thanks for your answer, but stil doesn't work, same error. In item_manager.h no need to add something? I don't know how to fix this... Link to comment Share on other sites More sharing options...
Honorable Member Mali 41864 Posted January 16, 2023 Honorable Member Share Posted January 16, 2023 just use struct, that tuple looks ugly AF 1 Link to comment Share on other sites More sharing options...
Premium Intel 757 Posted January 16, 2023 Author Premium Share Posted January 16, 2023 (edited) 30 minutes ago, Mali said: just use struct, that tuple looks ugly AF or that, yeah lol so: //somewhere maybe a header in common/target_info.h struct drop_info { uint32_t vnum; uint16_t count; uint8_t rarity; } //and in input_main include the new header and the vector becomes: static std::vector<drop_info> s_vec_item; //and to read its info: for(const auto& x : s_vec_item) { pInfo.dwVID = m_pkChrTarget->GetVID(); pInfo.race = m_pkChrTarget->GetRaceNum(); pInfo.dwVnum = x.vnum; pInfo.count = x.count; pInfo.rarity = x.rarity; //.... //and to fill the vector (include the header again): // Drop Item Group { auto it = m_map_pkDropItemGroup.find(pkChr->GetRaceNum()); if(it != m_map_pkDropItemGroup.end()) { auto v = it->second->GetVector(); for (DWORD i = 0; i < v.size(); ++i) { if( iLevel >= (iMobLevel - 15) && iLevel <= (iMobLevel + 15) ) { drop_info info{}; info.vnum = v[i].dwVnum; info.count = v[i].iCount; info.rarity = CalculateDropRarityDropItemGroup(v[i].dwPct, bType); vec_item.emplace_back(info); } } } } Edited January 16, 2023 by xXIntelXx 1 Link to comment Share on other sites More sharing options...
anton96 2 Posted May 15, 2023 Share Posted May 15, 2023 On 1/5/2023 at 6:25 PM, SanctusCZE said: https://metin2.download/picture/dCyh0NwMEE0V9ZUP07MYoFu8EGL12GEb/.gif I'm having exactly the same issue, can anyone help us fix this? should we remove everything in common_drop_item? Link to comment Share on other sites More sharing options...
Premium Intel 757 Posted May 15, 2023 Author Premium Share Posted May 15, 2023 17 minutes ago, anton96 said: I'm having exactly the same issue, can anyone help us fix this? should we remove everything in common_drop_item? I don't think your players would enjoy to be inundated by low level/useless items anyway.. but you can choose not to show the common_drop_item stuff Link to comment Share on other sites More sharing options...
anton96 2 Posted May 20, 2023 Share Posted May 20, 2023 (edited) On 5/15/2023 at 2:25 PM, Intel said: I don't think your players would enjoy to be inundated by low level/useless items anyway.. but you can choose not to show the common_drop_item stuff do those items from common drop item actually drop? I've never seen a lvl 61 weapon drop from a dog or wolf. How do I choose not to show the common_drop_item stuff? does it make any sense to show the drops from common_drop_item in the target information system? Edited May 20, 2023 by anton96 Link to comment Share on other sites More sharing options...
Premium Intel 757 Posted May 20, 2023 Author Premium Share Posted May 20, 2023 8 hours ago, anton96 said: do those items from common drop item actually drop? I've never seen a lvl 61 weapon drop from a dog or wolf. How do I choose not to show the common_drop_item stuff? does it make any sense to show the drops from common_drop_item in the target information system? Of course it makes sense, if you edit it (otherwise just clean it). Also, technically, they can drop from a dog. std::vector<CItemDropInfo>::iterator it = g_vec_pkCommonDropItem[bRank].begin(); while (it != g_vec_pkCommonDropItem[bRank].end()) { const CItemDropInfo & c_rInfo = *(it++); if(iLevel < c_rInfo.m_iLevelStart || iLevel > c_rInfo.m_iLevelEnd) continue; TItemTable * table = GetTable(c_rInfo.m_dwVnum); if(!table) continue; int rarity = CalculateDropRarityCommonDropItem((c_rInfo.m_iPercent * iDeltaPercent) / 100, iRandRange); if(rarity){ vec_item.emplace_back(std::make_tuple(c_rInfo.m_dwVnum, 1, rarity)); } } uint8_t CalculateDropRarityCommonDropItem(const uint32_t pct, const uint32_t randRange) { uint8_t rarity = 0; if(pct <= 0){ return rarity; } const float realPct = static_cast<float>(pct)/randRange; const float minimumPct = 1.0f/randRange; if(realPct >= 1.0f) rarity = 1; else if(realPct < 1.0f && realPct >= 0.05f) rarity = 2; else if(realPct < 0.05f && realPct >= 0.0025f) rarity = 3; else if(realPct < 0.0025f && realPct >= 0.00125f) rarity = 4; else if(realPct < 0.00125 && realPct >= 0.00025f) rarity = 5; else if(realPct < 0.00025f && realPct > minimumPct) rarity = 6; return rarity; } I can assure you, rarity will not be 0 and a player lv60 would see the drop if the range is that high (although it would be very very very very low) 1 Link to comment Share on other sites More sharing options...
anton96 2 Posted June 13, 2023 Share Posted June 13, 2023 On 5/20/2023 at 7:15 PM, Intel said: Of course it makes sense, if you edit it (otherwise just clean it). Also, technically, they can drop from a dog. std::vector<CItemDropInfo>::iterator it = g_vec_pkCommonDropItem[bRank].begin(); while (it != g_vec_pkCommonDropItem[bRank].end()) { const CItemDropInfo & c_rInfo = *(it++); if(iLevel < c_rInfo.m_iLevelStart || iLevel > c_rInfo.m_iLevelEnd) continue; TItemTable * table = GetTable(c_rInfo.m_dwVnum); if(!table) continue; int rarity = CalculateDropRarityCommonDropItem((c_rInfo.m_iPercent * iDeltaPercent) / 100, iRandRange); if(rarity){ vec_item.emplace_back(std::make_tuple(c_rInfo.m_dwVnum, 1, rarity)); } } uint8_t CalculateDropRarityCommonDropItem(const uint32_t pct, const uint32_t randRange) { uint8_t rarity = 0; if(pct <= 0){ return rarity; } const float realPct = static_cast<float>(pct)/randRange; const float minimumPct = 1.0f/randRange; if(realPct >= 1.0f) rarity = 1; else if(realPct < 1.0f && realPct >= 0.05f) rarity = 2; else if(realPct < 0.05f && realPct >= 0.0025f) rarity = 3; else if(realPct < 0.0025f && realPct >= 0.00125f) rarity = 4; else if(realPct < 0.00125 && realPct >= 0.00025f) rarity = 5; else if(realPct < 0.00025f && realPct > minimumPct) rarity = 6; return rarity; } I can assure you, rarity will not be 0 and a player lv60 would see the drop if the range is that high (although it would be very very very very low) Should this be placed under :? #ifdef __SEND_TARGET_INFO__ bool ITEM_MANAGER::CreateDropItemVector(LPCHARACTER pkChr, LPCHARACTER pkKiller, std::vector<LPITEM> & vec_item) { if (pkChr->IsPolymorphed() || pkChr->IsPC()) { return false; } int iLevel = pkKiller->GetLevel(); BYTE bRank = pkChr->GetMobRank(); LPITEM item = NULL; std::vector<CItemDropInfo>::iterator it = g_vec_pkCommonDropItem[bRank].begin(); Or does it go under :? bool ITEM_MANAGER::CreateDropItem(LPCHARACTER pkChr, LPCHARACTER pkKiller, std::vector<LPITEM> & vec_item) { int iLevel = pkKiller->GetLevel(); int iDeltaPercent, iRandRange; if (!GetDropPct(pkChr, pkKiller, iDeltaPercent, iRandRange)) return false; BYTE bRank = pkChr->GetMobRank(); LPITEM item = NULL; // Common Drop Items std::vector<CItemDropInfo>::iterator it = g_vec_pkCommonDropItem[bRank].begin(); I've gotten a bit confused as to what should calculate drop rate should replace... Link to comment Share on other sites More sharing options...
Recommended Posts