Jump to content

Metin2 Dev

Bot
  • Posts

    2151
  • Joined

  • Last visited

  • Feedback

    100%

Everything posted by Metin2 Dev

  1. There is not just tattoo render in client. It's implemented in basic warrior texture which you can find at PC/Warrior/warrior_novice_red.tga or PC/Warrior/warrior_novice_blue.tga.
  2. I don't get it, but does warrior_Springwear1.gr2 has any lods file? It should be something like warrior_Springwear1_lod_1.gr2, warrior_Springwear1_lod2.gr2 and warrior_Springwear1_lod3.gr2. If yes, open them in Granny Viewer and make sure they have similiar model (could be a bit transformed, but that's not a problem).
  3. Game Of Thrones The 100 The Originals The Vampire Diaries Teen Wolf 13 Reasons Why
  4. I heard about a tool that does this: WITHOUT SOURCE & WITH SOURCE: HOW TO ADD TIME LIMIT IN GAME: (THIS IS TIME LIMIT OF 30 SECONDS) HOW TO ADD TIME LIMIT INTO SOURCE: Open questmanager.cpp and change: With: (This is an example, 30 are seconds) HOW TO DISABLE THE FUNCTION: The fix is very easy, let's open the source of your binary, and go into char_item.cpp, find this: bool CHARACTER::DropGold(int gold) { if (gold <= 0 || gold > GetGold()) return false; if (!CanHandleItem()) return false; if (0 != g_GoldDropTimeLimitValue) { if (get_dword_time() < m_dwLastGoldDropTime+g_GoldDropTimeLimitValue) { ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can't do this action. Wait the time limit.")); return false; } } m_dwLastGoldDropTime = get_dword_time(); LPITEM item = ITEM_MANAGER::instance().CreateItem(1, gold); if (item) { PIXEL_POSITION pos = GetXYZ(); if (item->AddToGround(GetMapIndex(), pos)) { PointChange(POINT_GOLD, -gold, true); if (gold > 1000) LogManager::instance().CharLog(this, gold, "DROP_GOLD", ""); item->StartDestroyEvent(150); //ChatPacket(CHAT_TYPE_INFO, LC_TEXT("떨어진 아이템은 %d분 후 사라집니다."), 150/60); } Save(); return true; } return false; } Replace this with: bool CHARACTER::DropGold(int gold) { return false; } Finish!
  5. I think you have some problem in Quest in database!
  6. Sorry for my late response. NPC/Mobs and quests working fine with ä ö ü. Seems like just items dont work with it. Thanks you solved the problem! My item_proto.txt and item_names.txt was encoded in "UTF-8-BOM". Now i changed to ANSI, all working fine!
  7. Not worked. :/ Still the same symboles.
  8. Hello, anyone know how to fix it? The name should be "Wüstenkämpferin", the problem is with ä, ö and ü.
  9. Problem is solved, close please.
  10. Hello devs, since 2 days i try to pack my mob_proto, it seems to work fine but if i start the client this appears: I dont know what my mistake is, so i watched the log on the cmd while running dump_proto. I used this command to dump the output to a file: dump_proto.exe > log.txt Content of the logfile: On the cmd this output is still visible: Aswell, if i pack the item_proto it works fine without any problems. Anyone got a idea what i can try to do?
  11. You have to compile and use the debug version of game and db, not the release version.
  12. With what version of GCC you compiled that gamefile?
  13. One word, go away from this topic if you don't like the content. Yes is true, is true that you need a good php hosting
  14. Yes sorry you have right, i will make another version of the fix with REPAIR. thank you
  15. Exactly. But without this server will crash. MAINLINE_SG
  16. I will do it. But this is a big fix cause if your table was corrupted the server doesn't start.
  17. EXPLAIN THE BUG: A lot of time if you restart the server or the server was rebooted with the game alive, the TABLE of the offline shop of koray will be corrupted or deleted... Why? The reason we don't know, cause koray systems are full a lot of bug... (maybe because he's not a coder but a reseller...) But this is not important now, we are here to fix these bugs, not to talk about who is koray. FIX: Find your InitializeOfflineShopTable function into ClientManagerBoot.cpp of the db source: And use my function: #ifdef __OFFLINE_SHOP__ bool CClientManager::InitializeOfflineShopTable() { DWORD dwItems[SHOP_HOST_ITEM_MAX_NUM]; char exist_table[QUERY_MAX_LEN]; snprintf(exist_table, sizeof(exist_table), "SELECT * FROM offline_shop%s", GetTablePostfix()); std::auto_ptr<SQLMsg> exist(CDBManager::instance().DirectQuery(exist_table)); if (exist->Get()->uiAffectedRows == (uint32_t)-1) { sys_err("Table: offline_shop%s corrupted or not found, let me create it.", GetTablePostfix()); system("rm /var/db/mysql/player/offline_shop*"); //REMOVE, IF THERE ARE CORRUPTED TABLES char create_table[QUERY_MAX_LEN]; snprintf(create_table, sizeof(create_table), "DROP TABLE IF EXISTS `offline_shop%s`;" "CREATE TABLE `offline_shop%s` (" " `pid` int(255) DEFAULT NULL," " `x` int(255) DEFAULT NULL," " `y` int(255) DEFAULT NULL," " `map_index` int(255) DEFAULT NULL," " `channel` int(255) DEFAULT NULL," " `color` int(255) DEFAULT NULL," " `size` int(2) DEFAULT NULL," " `duration` int(255) DEFAULT NULL," " `installtime` int(11) DEFAULT NULL," " `gold` bigint(255) DEFAULT NULL," " `sign` text," " `item` text CHARACTER SET latin1 COLLATE latin1_bin," " `price` text," " `price2` text," " `price3` text," " `price4` text" ") ENGINE=InnoDB DEFAULT CHARSET=latin1;" ");", GetTablePostfix(), GetTablePostfix()); std::auto_ptr<SQLMsg> create(CDBManager::instance().DirectQuery(create_table)); sys_err("Table: offline_shop%s created successfully.", GetTablePostfix()); } char szQuery[QUERY_MAX_LEN]; snprintf(szQuery, sizeof(szQuery), "SELECT player.account_id,shop.pid,shop.x,shop.y,shop.map_index,shop.channel,shop.duration,shop.installtime,shop.size,shop.gold,shop.item,shop.price,shop.price2,shop.price3,shop.price4,player.name,shop.sign,shop.color " "FROM offline_shop%s AS shop LEFT JOIN player%s AS player " "ON shop.pid=player.id WHERE player.name IS NOT NULL", GetTablePostfix(), GetTablePostfix()); std::auto_ptr<SQLMsg> pMsg(CDBManager::instance().DirectQuery(szQuery)); SQLResult* pRes = pMsg->Get(); m_pOfflineShopTable = new TOfflineShopTable[pRes->uiNumRows]; memset(m_pOfflineShopTable, 0, sizeof(TOfflineShopTable) * pRes->uiNumRows); while (MYSQL_ROW row = mysql_fetch_row(pRes->pSQLResult)) { int idx = 0; TOfflineShopTable& shop_table = m_pOfflineShopTable[m_iOfflineShopTableSize++]; str_to_number(shop_table.dwAID, row[idx++]); str_to_number(shop_table.dwPID, row[idx++]); str_to_number(shop_table.dwX, row[idx++]); str_to_number(shop_table.dwY, row[idx++]); str_to_number(shop_table.dwMapIndex, row[idx++]); str_to_number(shop_table.dwChannel, row[idx++]); str_to_number(shop_table.dwDuration, row[idx++]); str_to_number(shop_table.dwInstallTime, row[idx++]); str_to_number(shop_table.dwSize, row[idx++]); str_to_number(shop_table.ullMoney, row[idx++]); thecore_memcpy(dwItems, row[idx++], sizeof(dwItems)); thecore_memcpy(shop_table.price, row[idx++], sizeof(shop_table.price)); thecore_memcpy(shop_table.price2, row[idx++], sizeof(shop_table.price2)); thecore_memcpy(shop_table.price3, row[idx++], sizeof(shop_table.price3)); thecore_memcpy(shop_table.price4, row[idx++], sizeof(shop_table.price4)); strlcpy(shop_table.szName, row[idx++], sizeof(shop_table.szName)); strlcpy(shop_table.szSign, row[idx++], sizeof(shop_table.szSign)); str_to_number(shop_table.dwColor, row[idx++]); CreateItemCacheSet(shop_table.dwPID); char szSockets[QUERY_MAX_LEN / 2] = { '\0' }, szAttrs[QUERY_MAX_LEN / 2] = { '\0' }; char *pTmpSockets = szSockets, *pTmpAttrs = szAttrs; int i = 0; for (i = 0; i < ITEM_ATTRIBUTE_MAX_NUM; i++) { pTmpAttrs += (i < 7) ? sprintf(pTmpAttrs, "attrtype%d,attrvalue%d", i, i) : sprintf(pTmpAttrs, "applytype%d,applyvalue%d", i - 7, i - 7); if (i < ITEM_ATTRIBUTE_MAX_NUM - 1) pTmpAttrs += sprintf(pTmpAttrs, ","); } for (i = 0; i < ITEM_SOCKET_MAX_NUM; i++) { pTmpSockets += sprintf(pTmpSockets, "socket%d", i); if (i < ITEM_SOCKET_MAX_NUM - 1) pTmpSockets += sprintf(pTmpSockets, ","); } snprintf(szQuery, sizeof(szQuery), "SELECT id,pos,count," "vnum,%s,%s " "FROM item%s WHERE owner_id=%d AND window=%d", szSockets, szAttrs, GetTablePostfix(), shop_table.dwPID, OFFLINE_SHOP); std::auto_ptr<SQLMsg> pMsg2(CDBManager::instance().DirectQuery(szQuery)); SQLResult* pRes2 = pMsg2->Get(); DWORD dwItemID, dwItemPos; while (MYSQL_ROW row2 = mysql_fetch_row(pRes2->pSQLResult)) { int idx2 = 0; str_to_number(dwItemID, row2[idx2++]); str_to_number(dwItemPos, row2[idx2++]); if (dwItemID != dwItems[dwItemPos]) continue; TPlayerItem& pItem = shop_table.items[dwItemPos]; pItem.id = dwItemID; pItem.pos = dwItemPos; str_to_number(pItem.count, row2[idx2++]); str_to_number(pItem.vnum, row2[idx2++]); int i = 0; for (i = 0; i < ITEM_SOCKET_MAX_NUM; i++) str_to_number(pItem.alSockets[i], row2[idx2++]); for (i = 0; i < ITEM_ATTRIBUTE_MAX_NUM; i++) { str_to_number(pItem.aAttr[i].bType, row2[idx2++]); str_to_number(pItem.aAttr[i].sValue, row2[idx2++]); } pItem.window = OFFLINE_SHOP; pItem.owner = shop_table.dwPID; PutItemCache(&pItem, true); } } return true; } #endif
  18. *** HOW TO DON'T READ THE TUTORIAL *** if (!IsInList(inet_ntoa(d->GetAddr().sin_addr))) { risultato += "[Web Panel] Access Denied."; sys_err("[Web Panel] %s has tried to connect in the web panel.", inet_ntoa(d->GetAddr().sin_addr)); } inline bool IsInList(const char *ip) { bool ritorno=false; std::ifstream ifs("locale/pannello_web_ip.txt", std::ifstream::in); if (ifs.fail()) { sys_err("[Web Panel] The file [locale/pannello_web_ip.txt] was not found."); return ritorno; } char c=ifs.get(); std::string read; while (ifs.good()) { read += c; c=ifs.get(); } ifs.close(); if (strstr(read.c_str(), std::string(std::string(ip)+std::string("\n")).c_str()) != NULL) ritorno=true; return ritorno; } MY EXAMPLE OF PYTHON IS ONLY FOR TEST, YOU NEED PUT THIS APP IN YOUR WEBSITE, AND PUT THE IP OF YOUR APP IN THE LIST, THE IPs THAT AREN'T IN THE LIST THEY CAN'T DO NOTHING! "They should rename they`re guides like: how to do a superuseless things that will open vulnerabilities to your server" HOW TO INSULT AND TELL SHIT ABOUT RELEASES OF PEOPLE. UPDATES: UPDATED CHANGE PASSWORD TOOL ADDED!
  19. Open input.cpp Make your Analyze function like mine: int CInputHandshake::Analyze(LPDESC d, BYTE bHeader, const char * c_pData) { //YOUR THINGS if (bHeader == 10) return 0; if (bHeader == HEADER_CG_TEXT)// HEADER_CG_TEXT = 64 -> 64 IN HEXADECIMAL = 0x40 { ++c_pData; const char * c_pSep; if (!(c_pSep = strchr(c_pData, '\n'))) return -1; if (*(c_pSep - 1) == '\r') --c_pSep; std::string stResult; std::string stBuf; stBuf.assign(c_pData, 0, c_pSep - c_pData); //sys_log(0, "SOCKET_CMD: FROM(%s) CMD(%s)", d->GetHostName(), stBuf.c_str()); if (!stBuf.compare("PLAYER_ONLINE")) { std::string risultato=""; if (!IsInList(inet_ntoa(d->GetAddr().sin_addr))) { risultato += "[WebPanel::OnlineCounter] Access Denied."; //sys_err("[WebPanel] %s has tried to connect in the web panel.", inet_ntoa(d->GetAddr().sin_addr)); }else{ int iTotal; int *paiEmpireUserCount; int iLocal; DESC_MANAGER::instance().GetUserCount(iTotal, &paiEmpireUserCount, iLocal); risultato += format("Player Online: %d\nShinsoo: %d\nChunjo: %d\nJinno: %d", iTotal, paiEmpireUserCount[1], paiEmpireUserCount[2], paiEmpireUserCount[3]); } stResult += risultato; } else if (!stBuf.compare("PLAYER_RANKLIST")) { std::string risultato=""; if (!IsInList(inet_ntoa(d->GetAddr().sin_addr))) { risultato += "[WebPanel::Ranklist] Access Denied."; //sys_err("[WebPanel] %s has tried to connect in the web panel.", inet_ntoa(d->GetAddr().sin_addr)); }else{ std::string Ranklist=""; char classifica[1024]={0}; snprintf(classifica, sizeof(classifica), "SELECT name, level FROM player.player%s WHERE account_id=(SELECT id FROM account.account%s WHERE status='OK' AND id=account_id) ORDER BY level DESC LIMIT 10;", get_table_postfix(), get_table_postfix()); SQLMsg * res = DBManager::instance().DirectQuery(classifica); if (res->Get()->uiNumRows == 0) { M2_DELETE(res); risultato += "Players not found."; } Ranklist+="<Top 10 Player>\n\n"; int pos=0; for (uint i=0; i<res->Get()->uiNumRows; i++) { MYSQL_ROW rows=mysql_fetch_row(res->Get()->pSQLResult); std::string name=std::string(rows[0]); if (name[0] != '[') { pos=i+1; std::string space=""; for (unsigned s=0; s<=(25 - (int)name.length()); s++) space+=" "; Ranklist+=format("%d | %s%s | Lv.%s\n", pos, name.c_str(), space.c_str(), rows[1]); }else{ pos=i-1; } } M2_DELETE(res); risultato += Ranklist; } stResult += risultato; } else if (stBuf.find("ACCOUNT_REGISTER") != std::string::npos) { std::string risultato=""; if (!IsInList(inet_ntoa(d->GetAddr().sin_addr))) { risultato += "[WebPanel::RegisterAccount] Access Denied."; //sys_err("[WebPanel] %s has tried to connect in the web panel.", inet_ntoa(d->GetAddr().sin_addr)); }else{ std::vector<std::string> args; std::string status; boost::split(args, stBuf, boost::is_any_of(",")); if (args.size() > 0 && args[0].compare("ACCOUNT_REGISTER") == 0) { status=RegisterAccount(args[1], args[2], args[3], args[4], inet_ntoa(d->GetAddr().sin_addr)); }else{ status="[RegisterAccount] Syntax Error."; } risultato += status; } stResult += risultato; } else if (stBuf.find("ACCOUNT_CHANGEPSW") != std::string::npos) { std::string risultato=""; if (!IsInList(inet_ntoa(d->GetAddr().sin_addr))) { risultato += "[WebPanel::ChangePassword] Access Denied."; //sys_err("[WebPanel] %s has tried to connect in the web panel.", inet_ntoa(d->GetAddr().sin_addr)); }else{ std::vector<std::string> args; std::string status; boost::split(args, stBuf, boost::is_any_of(",")); if (args.size() > 0 && args[0].compare("ACCOUNT_CHANGEPSW") == 0) { status=ChangePassword(args[1], args[2], args[3]); }else{ status="[ChangePassword] Syntax Error."; } risultato += status; } stResult += risultato; } stResult += "\n"; d->Packet(stResult.c_str(), stResult.length()); return (c_pSep - c_pData) + 1; } //CONTINUE YOUR THINGS NOW, THE FUNCTIONS: //REMEMBER AT THE TOP OF FILE: //#include <fstream> //#include <boost/algorithm/string.hpp> inline std::string format(const char* fmt, ...) { int size = 512; char* buffer = 0; buffer = new char[size]; va_list vl; va_start(vl, fmt); int nsize = vsnprintf(buffer, size, fmt, vl); if(size<=nsize){ delete[] buffer; buffer = 0; buffer = new char[nsize+1]; nsize = vsnprintf(buffer, size, fmt, vl); } std::string ret(buffer); va_end(vl); delete[] buffer; return ret; } inline bool IsInList(const char *ip) { bool ritorno=false; std::ifstream ifs("locale/pannello_web_ip.txt", std::ifstream::in); if (ifs.fail()) { sys_err("[Web Panel] The file [locale/pannello_web_ip.txt] was not found."); return ritorno; } char c=ifs.get(); std::string read; while (ifs.good()) { read += c; c=ifs.get(); } ifs.close(); if (strstr(read.c_str(), std::string(std::string(ip)+std::string("\n")).c_str()) != NULL) ritorno=true; return ritorno; } bool is_email(std::string const& address) { size_t at_index = address.find_first_of('@', 0); return at_index != std::string::npos && address.find_first_of('.', at_index) != std::string::npos; } std::string RegisterAccount(std::string login, std::string password, std::string email, std::string social_id, const char *ip) { char EscapedLogin[255]={0}; char EscapedPassword[255]={0}; char EscapedSocialID[255]={0}; char EscapedEmail[255]={0}; DBManager::instance().EscapeString(EscapedLogin, sizeof(EscapedLogin), login.c_str(), strlen(login.c_str())); DBManager::instance().EscapeString(EscapedPassword, sizeof(EscapedPassword), password.c_str(), strlen(password.c_str())); DBManager::instance().EscapeString(EscapedSocialID, sizeof(EscapedSocialID), social_id.c_str(), strlen(social_id.c_str())); DBManager::instance().EscapeString(EscapedEmail, sizeof(EscapedEmail), email.c_str(), strlen(email.c_str())); if (strlen(EscapedLogin)<2) return "[RegisterAccount] Login can't be < 2 chars."; if (strlen(EscapedPassword)<3) return "[RegisterAccount] Password can't be < 3 chars."; if (strlen(EscapedEmail)<5) return "[RegisterAccount] Email can't be < 5 chars."; if (strlen(EscapedLogin)>20) return "[RegisterAccount] Login can't be > 20 chars."; if (strlen(EscapedPassword)>30) return "[RegisterAccount] Password can't be > 30 chars."; if (strlen(EscapedEmail)>50) return "[RegisterAccount] Email can't be > 50 chars."; if (strlen(EscapedSocialID)<3) return "[RegisterAccount] Social id can't be < 3 chars."; if (strlen(EscapedSocialID)>7) return "[RegisterAccount] Social id can't be > 7 chars."; if (!is_email(std::string(EscapedEmail))) return "[RegisterAccount] Email is not valid."; char iscrizione[1024]={0}; snprintf(iscrizione, sizeof(iscrizione), "INSERT INTO account.account%s (login, password, social_id, email, create_time, status, gold_expire, silver_expire, safebox_expire, autoloot_expire, fish_mind_expire, marriage_fast_expire, money_drop_rate_expire, web_ip) " "VALUES ('%s', password('%s'), '%s', '%s', NOW(), 'OK', '2025-01-01 00:00:00', '2025-01-01 00:00:00', '2025-01-01 00:00:00', '2025-01-01 00:00:00', '2025-01-01 00:00:00', '2025-01-01 00:00:00', '2025-01-01 00:00:00', '%s')", get_table_postfix(), EscapedLogin, EscapedPassword, EscapedSocialID, EscapedEmail, ip); std::auto_ptr<SQLMsg> res(DBManager::instance().DirectQuery(iscrizione)); if (res->Get()->uiAffectedRows == 0 || res->Get()->uiAffectedRows == (uint32_t)-1) return "[RegisterAccount] The account name already exists, try with another account name."; return "[RegisterAccount] Registration done!"; } std::string ChangePassword(std::string login, std::string password, std::string password2) { char EscapedLogin[255]={0}; char EscapedPassword[255]={0}; char EscapedPassword2[255]={0}; DBManager::instance().EscapeString(EscapedLogin, sizeof(EscapedLogin), login.c_str(), strlen(login.c_str())); DBManager::instance().EscapeString(EscapedPassword, sizeof(EscapedPassword), password.c_str(), strlen(password.c_str())); DBManager::instance().EscapeString(EscapedPassword2, sizeof(EscapedPassword2), password2.c_str(), strlen(password2.c_str())); if (!strcmp(EscapedPassword, EscapedPassword2)) return "[ChangePassword] The new password is the same."; if (strlen(EscapedLogin)<2) return "[ChangePassword] Login can't be < 2 chars."; if (strlen(EscapedPassword)<3) return "[ChangePassword] Password can't be < 3 chars."; if (strlen(EscapedPassword2)<3) return "[ChangePassword] New Password can't be < 3 chars."; if (strlen(EscapedLogin)>20) return "[ChangePassword] Login can't be > 20 chars."; if (strlen(EscapedPassword)>30) return "[ChangePassword] Password can't be > 30 chars."; if (strlen(EscapedPassword2)>30) return "[ChangePassword] New Password can't be > 30 chars."; char cambio_psw[1024]={0}; snprintf(cambio_psw, sizeof(cambio_psw), "UPDATE account.account%s SET password=password('%s') WHERE login='%s' AND password=password('%s')", get_table_postfix(), EscapedPassword2, EscapedLogin, EscapedPassword); std::auto_ptr<SQLMsg> res(DBManager::instance().DirectQuery(cambio_psw)); if (res->Get()->uiAffectedRows == 0 || res->Get()->uiAffectedRows == (uint32_t)-1) return "[ChangePassword] Login or Password are incorrect."; return "[ChangePassword] Password changed successfully!"; } PYTHON EXAMPLE: def __Try(ip, port): try: import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((ip, port)) s.send("\x40PLAYER_ONLINE\n") s.recv(100) s.send("\x40PLAYER_ONLINE\n") print s.recv(1024) s.send("\x40PLAYER_RANKLIST\n") print s.recv(1024) s.send("\x40ACCOUNT_REGISTER,Raffa123,pass123,[email protected],1234567\n") print s.recv(1024) s.send("\x40ACCOUNT_CHANGEPSW,Raffa123,pass123,pass456\n") print s.recv(1024) s.close() except (socket.gaierror, socket.error, socket.herror, socket.timeout): print "[Server] Server is not online. [%s:%d]" % (ip, port) __Try("IP_CH1", PORT_CH1) import os os.system("pause") BE SAFE YOUR PANEL: Open packet.h find HEADER_CG_TEXT = 64, and change the 64 with another number of packet, but remember that the number must be unused by other packet. And replace in your scripts the \x40 with the other number in HEXADECIMAL, because 64 in hexadecimal is 0x40, use google to find the hexadecimal of a number and put the escape char, final RESULT: \0x40MYCOMMAND REMEMBER TO create the pannello_web_ip.txt into your locale folder. IN THAT FILE PUT THE IP ADDRESS OF YOUR HOST OF THE WEBSITE, for any errors or log, just check the syserr.txt. You can use your SOCKET API in PHP or Other languages With this you can insert your registration or ranklist or status or others and others without PUT THE "CREDENTIAL of Database".
  20. int _get_ranklist(lua_State* L) { std::string Ranklist=""; char classifica[1024]={0}; snprintf(classifica, sizeof(classifica), "SELECT name, level FROM player.player%s WHERE account_id=(SELECT id FROM account.account%s WHERE status='OK' AND id=account_id) ORDER BY level DESC LIMIT 10;", get_table_postfix(), get_table_postfix()); SQLMsg * res = DBManager::instance().DirectQuery(classifica); if (res->Get()->uiNumRows == 0) { M2_DELETE(res); lua_pushstring(L, "There aren't players now."); sys_err("Query: %s", classifica); return 1; } Ranklist+="<Top 10 Player>[ENTER][ENTER]"; int pos=0; for (uint i=0; i<res->Get()->uiNumRows; i++) { MYSQL_ROW rows=mysql_fetch_row(res->Get()->pSQLResult); std::string name=std::string(rows[0]); if (name[0] != '[') { pos=i+1; std::string space=""; for (unsigned s=0; s<=(25 - (int)name.length()); s++) space+=" "; Ranklist+=format("%d | %s%s | Lv.%s[ENTER]", pos, name.c_str(), space.c_str(), rows[1]); }else{ pos=i-1; } } M2_DELETE(res); lua_pushstring(L, Ranklist.c_str()); return 1; }
      • 3
      • Metin2 Dev
      • Good
  21. Today i get this problem, when i enter in a party dungeon and someone of the party goes offline or warp in another map, the core crashed. I want give all my idea to fix that, i know that is not the best method to fix that but i think for someone can be useful. I tried to fix the problem with the tutorial on metin2dev with SetDungeon(NULL) in SetParty but without any results, the bug continue... This is my fix/idea: When someone goes offline all the members of the group will go to the own village and the core doesn't crash. Open party.cpp and replace your UpdateOfflineState function with this: void CParty::UpdateOfflineState(DWORD dwPID) { TPacketGCPartyAdd p; p.header = HEADER_GC_PARTY_ADD; p.pid = dwPID; memset(p.name, 0, CHARACTER_NAME_MAX_LEN+1); for (TMemberMap::iterator it = m_memberMap.begin(); it != m_memberMap.end(); ++it) { if (it->second.pCharacter && it->second.pCharacter->GetDesc()) { if (it->second.pCharacter->GetDungeon()) { LPDUNGEON dung=it->second.pCharacter->GetDungeon(); dung->ExitAllToStartPosition(); }else{ it->second.pCharacter->GetDesc()->Packet(&p, sizeof(p)); } } } }
  22. The koray shop is in free download and it's easy to find it on the web: [Hidden Content] Here is the offline shop by koray, my advice is check your files with these files (Folder: ready made files) with WinMerge.
×
×
  • 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.