Jump to content

Search the Community

Showing results for tags 'fix'.



More search options

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Forums

  • Forum board
    • M2Zone.tech
  • Create private server
    • Problems and Questions
    • Looking for...
    • Cooperation
    • Tutorials / Video
    • C++ / Python / Server
    • Sources / Serverfiles / Clients
    • Quests
    • Graphics
    • Programs
  • Marketplace
    • Sell
    • Buy
  • Hydepark
    • About all
    • Introduce yourself
    • Media
    • My Creativity
  • Others
    • Archives
    • Trash

Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


Sex


Country


Facebook


Discord


Telegram


Gadu-Gadu

Found 24 results

  1. Cześć, dzisiaj przedstawię, w jaki sposób naprawić skill u Sury pt. Czarowane Ostrze. Edytujemy plik Char_Battle.cpp, który znajdziemy w Source Game'a. Następnie szukamy tej linijki: pAttacker->PointChange(POINT_HP, i); Edytując ją w następujący sposób: pAttacker->PointChange(POINT_HP, abs(i));
  2. UPDATE item_proto SET specular = '30' WHERE locale_name LIKE '%+4' ; UPDATE item_proto SET specular = '40' WHERE locale_name LIKE '%+5' ; UPDATE item_proto SET specular = '50' WHERE locale_name LIKE '%+6' ; UPDATE item_proto SET specular = '65' WHERE locale_name LIKE '%+7' ; UPDATE item_proto SET specular = '80' WHERE locale_name LIKE '%+8' ; UPDATE item_proto SET specular = '100' WHERE locale_name LIKE '%+9' ; UPDATE item_proto SET addon_type=-1 WHERE vnum>=180 AND vnum<=189; UPDATE item_proto SET addon_type=-1 WHERE vnum>=190 AND vnum<=199; UPDATE item_proto SET addon_type=-1 WHERE vnum>=290 AND vnum<=299; UPDATE item_proto SET addon_type=-1 WHERE vnum>=1130 AND vnum<=1139; UPDATE item_proto SET addon_type=-1 WHERE vnum>=1170 AND vnum<=1179; UPDATE item_proto SET addon_type=-1 WHERE vnum>=2150 AND vnum<=2159; UPDATE item_proto SET addon_type=-1 WHERE vnum>=2170 AND vnum<=2179; UPDATE item_proto SET addon_type=-1 WHERE vnum>=3160 AND vnum<=3169; UPDATE item_proto SET addon_type=-1 WHERE vnum>=3210 AND vnum<=3219; UPDATE item_proto SET addon_type=-1 WHERE vnum>=5110 AND vnum<=5119; UPDATE item_proto SET addon_type=-1 WHERE vnum>=5120 AND vnum<=5129; UPDATE item_proto SET addon_type=-1 WHERE vnum>=7160 AND vnum<=7169; UPDATE item_proto SET socket_pct=0; UPDATE item_proto SET socket_pct=1 WHERE (type=1 or (type=2 and subtype=0)) and limittype0=1 and limitvalue0>= 0 and limitvalue0<= 24; UPDATE item_proto SET socket_pct=2 WHERE (type=1 or (type=2 and subtype=0)) and limittype0=1 and limitvalue0>=25 and limitvalue0<= 44; UPDATE item_proto SET socket_pct=3 WHERE (type=1 or (type=2 and subtype=0)) and limittype0=1 and limitvalue0>=45 and limitvalue0<=255;
  3. Kiedyś na forum kokosza react wrzucał sporą paczke fixów, wam pewnie też się przydadzą [FIX] Dwie osoby kupują ten sam przedmiot w tym samym czasie (wywala klienta) [FIX] Wywalenie serwera za pomocą obiektów (dodanie do gildii) [FIX] Wywalanie yangów (obciążenie do tego stopnia aż kanał siada) [FIX] Expienie drugiej postaci na odległość (otrzymanie doświadczenia pomimo dwóch różnych lokacji) [FIX] Czarowane Ostrze (raczej każdy wie na czym on polega) [FIX] Prawdopodobny fix skoków hp/sp (podczas np. użycia sarży lub krycia się) [FIX] Naprawa slotów w Smoczej Alchemii [FIX] Niewidzialność postaci po zalogowaniu/teleporcie (pakiet) [FIX] Odbugowanie wojen gildii (komenda /war) [FIX] Brak możliwości stworzenia sklepu na wierzchowcu [FIX] -32k HP postaci po teleporcie bądź logowaniu [FIX] Drop przedmiotów (z potworów/metinów raz na milion killów leci przedmiot, który nie jest przypisany do dropu) [FIX] Teleportacja członka grupy do lidera (np. jesteśmy w m1, a poprzez kamer moda wzywamy gracza do siebie) [FIX] SQL Injection (Przyjaciele i Gildia) [FIX] Odbugowanie Zwoju Boga Smoków (+10% szans na ulepszenie)
  4. Witam Pokaże Wam jak zablokować zakładanie kostiumu na przedmioty ślubne oraz analogicznie na odwrót. Zapobiega to dużej ilości defa gdy ktoś kupi sobie ItemShop. char_item.cpp Szukaj: if (item->GetWearFlag() & WEARABLE_UNIQUE) { if ((GetWear(WEAR_UNIQUE1) && GetWear(WEAR_UNIQUE1)->IsSameSpecialGroup(item)) || (GetWear(WEAR_UNIQUE2) && GetWear(WEAR_UNIQUE2)->IsSameSpecialGroup(item))) { ChatPacket(CHAT_TYPE_INFO, LC_TEXT("°°Ŕş Áľ·ůŔÇ ŔŻ´ĎĹ© ľĆŔĚĹŰ µÎ °ł¸¦ µż˝Ăżˇ ŔĺÂřÇŇ Ľö ľř˝Ŕ´Ď´Ů.")); return false; } if (marriage::CManager::instance().IsMarriageUniqueItem(item->GetVnum()) && !marriage::CManager::instance().IsMarried(GetPlayerID())) { ChatPacket(CHAT_TYPE_INFO, LC_TEXT("°áČĄÇĎÁö ľĘŔş »óĹÂżˇĽ­ żąą°Ŕ» ÂřżëÇŇ Ľö ľř˝Ŕ´Ď´Ů.")); return false; } } Dodaj pod: LPITEM CheckSuit = GetWear(WEAR_BODY); if (CheckSuit) { if (CheckSuit->GetVnum() >= 11901 && CheckSuit->GetVnum() <= 11914) { if (item->GetType() == ITEM_COSTUME) { ChatPacket(CHAT_TYPE_INFO, LC_TEXT("FIX_CHANGE_COSTUME_WEDDING1")); return false; } } } LPITEM CostumeCheck = GetWear(WEAR_COSTUME_BODY); if (CostumeCheck) { if (item->GetVnum() >= 11901 && item->GetVnum() <= 11914) { ChatPacket(CHAT_TYPE_INFO, LC_TEXT("FIX_CHANGE_COSTUME_WEDDING2")); return false; } } locale_string.txt "FIX_CHANGE_COSTUME_WEDDING1"; "Nie możesz założyć kotiumu na przedmiot ślubny"; "FIX_CHANGE_COSTUME_WEDDING2"; "Nie możesz założyć przedmiotu ślubnego na kostium";
  5. Pewnie wielu z was słyszało o możliwości lagowania, wyrzucania graczy z danej mapy w odległości postaci która używa autoclick itp. Daje wam tutaj małego fixa który temu zapobiegnie. commonDefines.h lub service.h #define __BLOCK_PACKETS__ enum tBlocks { timeWaitItem = 10, }; #ifdef __BLOCK_PACKETS__ #define __BLOCK_USE_ITEM__ #endif char.cpp Znajdź: void CHARACTER::Initialize() { //KOD dodaj przed } #ifdef __BLOCK_USE_ITEM__ m_UseItemPulse = 0; m_UseItemCount = 0; #endif char.h PRZED !!!!! }; ESex GET_SEX(LPCHARACTER ch); DODAJ: #ifdef __BLOCK_USE_ITEM__ public: void SetNextItemUsePulse(int pulse) { m_UseItemPulse = pulse; } int GetItemUsePulse() { return m_UseItemPulse; } protected: int m_UseItemPulse; int m_UseItemCount; #endif char_item.cpp POD: bool CHARACTER::UseItem(TItemPos Cell, TItemPos DestCell) { WORD wCell = Cell.cell; BYTE window_type = Cell.window_type; //WORD wDestCell = DestCell.cell; //BYTE bDestInven = DestCell.window_type; LPITEM item; if (!CanHandleItem()) return false; if (!IsValidItemPosition(Cell) || !(item = GetItem(Cell))) return false; DODAJ: #ifdef __BLOCK_USE_ITEM__ static const DWORD m_tableItems[] = { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 }; bool passed = true; for (auto it : m_tableItems) if (it == item->GetVnum()) passed = false; if (passed) { int lastUseItemBlock = GetItemUsePulse(); int currentPulse = thecore_pulse(); if (currentPulse > lastUseItemBlock + 25) m_UseItemCount = 0; if (currentPulse < lastUseItemBlock + 25 && m_UseItemCount >= 50) { int deltaInSeconds = ((lastUseItemBlock / PASSES_PER_SEC(1)) - (currentPulse / PASSES_PER_SEC(1))); int minutes = deltaInSeconds / 60; int seconds = (deltaInSeconds - (minutes * 60)); ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can use item after %d seconds."), seconds); return false; } SetNextItemUsePulse(thecore_pulse() + PASSES_PER_SEC(timeWaitItem)); m_UseItemCount++; } #endif #UPDATE1 To samo można wywołać innymi sposobami takimi jak handel commonDefines.h lub service.h enum tBlocks { timeWaitItem = 10, timeWaitExchange = 10, }; #define __BLOCK_SEND_EXCHANGE__ #define __BLOCK_SEND_EXCHANGE_FLAG__ "exchange.last_use" char.cpp POD: #ifdef __BLOCK_USE_ITEM__ m_UseItemPulse = 0; m_UseItemCount = 0; #endif Dodaj: #ifdef __BLOCK_SEND_EXCHANGE__ m_UseEchangeCount = 0; m_SendExchangePulse = 0; #endif char.h PRZED: }; ESex GET_SEX(LPCHARACTER ch); Dodaj: #ifdef __BLOCK_SEND_EXCHANGE__ public: int m_UseEchangeCount; int m_SendExchangePulse; #endif input_main.cpp W funkcji: void CInputMain::Exchange(LPCHARACTER ch, const char * data) { Wyszukaj: switch (pinfo->sub_header) NAD DODAJ : #ifdef __BLOCK_SEND_EXCHANGE__ if (thecore_pulse() > ch->m_SendExchangePulse + 25) ch->m_UseEchangeCount = 0; if (thecore_pulse() < ch->m_SendExchangePulse + 25 && ch->m_UseEchangeCount >= 50) { ch->m_UseEchangeCount = 0; ch->SetQuestFlag(__BLOCK_SEND_EXCHANGE_FLAG__, get_global_time()); return; } int pUseGetTime[] = { timeWaitExchange }; int pUseItem = ch->GetQuestFlag(__BLOCK_SEND_EXCHANGE_FLAG__); const char* pGetUseItemMessage[] = { "|cFFd0ffcc|H|h Nie możesz tego wykonać|cFFd0ffcc|H|h odczekaj |cFFec03e2|H|h[%u] |cFFd0ffcc|H|h sekund!" }; if (pUseItem) { if (get_global_time() < pUseItem + pUseGetTime[0]) { ch->ChatPacket(CHAT_TYPE_INFO, pGetUseItemMessage[0], pUseGetTime[0]); return; } } #endif POD: if (ch->GetMyShop() || ch->IsOpenSafebox() || ch->GetShopOwner() || ch->IsCubeOpen()) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("´Ů¸Ą °Ĺ·ˇÁßŔĎ°ćżě °łŔλóÁˇŔ» ż­Ľö°ˇ ľř˝Ŕ´Ď´Ů.")); return; } ch->ExchangeStart(to_ch); DODAJ: #ifdef __BLOCK_SEND_EXCHANGE__ ch->m_SendExchangePulse = thecore_pulse(); ch->m_UseEchangeCount++; #endif Chciałbym tylko dodać, że możecie w taki sposób blokować większość funkcji, zawsze jest to bezpieczniejsze. Jeśli chodzi o funkcje które mogą działać jako drophack, jest ich bardzo wiele
  6. Cześć. Zapisuje na tym forum, fxa na najnowszy exploit, który polega na wywalaniu logowania. Autorem jest Sherer ( aby nie było, że coś tam, coś tam.) Hello, Didn't know whether to place this subject either here or on guides but since I'm gonna not only share the mitigation but also express my conclusion about this issue and further after-effects. Only part of codes are attached below. For methods definitions + headers jump here: [Hidden Content] 1. Vulnerability overview. Any kind of tcp application is required to have a server (anda client). Once a server is launched it's binded to appropriate socket and set on listening for further connections (in a cutoff, navigate here for more precise info) On the other side client is the one which is suppose to connect to server. It does it by connecting to server's socket and start to process a handshake. This is how it works in a big shortcut - or I should rather say, it does work if we deal with normal peer. In case of more-like modern apps the traffic is held by efficient algorithms that can carry even heavy traffic or eventual feeble attack. But since Metin2's core is not a state-of-art app and simply runs on old C style code (libthecore) without a real concurrency support that might dive us into some tricky issues. So let's imagine what happens if someone tries to pull off an attack and flood the server with enormous amount of packets. Since each of connection needs to be validated first, it goes through the handshake. Server catches it through the fdwatch function (jump to io_loop, main.cpp), then if no desc is presented moves it to AcceptDesc where the connection is validated. It is usually allowed unless the peer's ip is not in a banlist. Then desc is created and connection is saved for further handshake response. Sounds reasonable, right? Now imagine when thousands connection are accepted, validated, and expected to send handshake response. Does it still sound so optimistic? Additionally, when a desc is created it does allocated buffer for I/O traffic. Each connection. Each time. Each desc. Now do the math and try to conceive how much of memory is simply wasted. So that's the point we've been heading. That's our vulnerability. And btw, if so many agents are in the queue, do you think anybody will be able to connect your server? 2. Four major problems. Let's start from handshake itself. Imagine that someone approaches you and gives you his hand to shake it. And than second. And then third. Doesn't make sense, does it? Same applies to handshake process. Simply, only one handshake shall be ongoing for the host unless it completes it. So, let's jump to AcceptDesc in desc_manager.cpp and add this little code above: newd = M2_NEW DESC; // Let's check if a handshake from this host is already ongoing if (GetHostHandshake(peer)) { sys_log(0, "Handshake from %s is not permitted!", host); socket_close(desc); return NULL; } So let's consider this as solved for now. Then the second issue. Let's imagine yet another event. Someone shakes your hand but this time completes the handshake. But he does it again. And again. And again. Sounds exhausting? Let's add this 2 conditions below our recent code from above: static const int HOST_CONNECTION_LIMIT = 3; // In case if host completed handshake process let's check if it doesn't reach the limit if (GetHostConnectionCount(peer) >= HOST_CONNECTION_LIMIT) { sys_log(0, "Host %s connection limit has been reached!", host); socket_close(desc); return NULL; } // And block intrusive connections as well if (IsIntrusiveConnection(host)) { sys_log(0, "Host %s is intrusive!", host); socket_close(desc); return NULL; } First if checks if host doesn't reach the handshake limit and if it does - the host is dropped. Second if seeks for intrusive peers. That simply means if one tries to connect again, and again, and again in defined time lapse it probably turns out to be an attacking IP. Let's jump for a moment to desc.cpp, Initialize and add this variable initialization there: tt_creation_time = get_global_time(); Yet another problem solved. Still tho, all this code is considered to work more for authentication than for game's core. Why is so? Imagine a person how is not suppose to have any attention at all - a movie star for example. Usually when one walks on red carpet there are bunch of body guards sealing him/her out from the crowd around. Same should happen to game cores because why one would try to perform a handshake with game if hadn't even logged in? So that's we are going to do, simply whitelist players who were succeeded to perform through the login process and obtained login key. Firstly let's jump back to the desc_manager.cpp and add this little code above our previous alterations: // If it's not an auth server - check for validation first if (!g_bAuthServer) { if (!IsOnHandshakeWhitelist(peer)) { // sys_log(0, "Host %s has not validated through login!", host); socket_close(desc); return NULL; } } Now open input_db.cpp, move to AuthLogin function and add at the end: // Validating handshake TPacketGGHandshakeValidate pack; pack.header = HEADER_GG_HANDSHAKE_VALIDATION; strlcpy(pack.sUserIP, d->GetHostName(), sizeof(pack.sUserIP)); P2P_MANAGER::instance().Send(&pack, sizeof(pack)); And so on repeat it for AuthLoginOpenID if you use it. Now let's jump to input_p2p.cpp, move to Analyze function and after the initial syslog: // Auth server is not allowed for p2p if (g_bAuthServer) { // Clearing buffers for dynamic packets switch (bHeader) { case HEADER_GG_RELAY: { TPacketGGRelay * p = (TPacketGGRelay *) c_pData; if (m_iBufferLeft < sizeof(TPacketGGRelay) + p->lSize) iExtraLen = -1; else iExtraLen = p->lSize; } break; case HEADER_GG_NOTICE: { TPacketGGNotice * p = (TPacketGGNotice *) c_pData; if (m_iBufferLeft < sizeof(TPacketGGNotice) + p->lSize) iExtraLen = -1; else iExtraLen = p->lSize; } break; case HEADER_GG_GUILD: { iExtraLen = m_iBufferLeft - sizeof(TPacketGGGuild); } break; case HEADER_GG_MONARCH_NOTICE: { TPacketGGMonarchNotice * p = (TPacketGGMonarchNotice *) c_pData; if (m_iBufferLeft < p->lSize + sizeof(TPacketGGMonarchNotice)) iExtraLen = -1; else iExtraLen = p->lSize; } break; } return iExtraLen; } Since some of the packets might be dynamic, we need to ensure that data they hold is cleared properly. If you have more dynamic packets binded - add them as above. Move to db.cpp, find function SendLoginPing and replace with following: void DBManager::SendLoginPing(const char * c_pszLogin) { /* TPacketGGLoginPing ptog; ptog.bHeader = HEADER_GG_LOGIN_PING; strlcpy(ptog.szLogin, c_pszLogin, sizeof(ptog.szLogin)); if (!g_pkAuthMasterDesc) // If I am master, broadcast to others { P2P_MANAGER::instance().Send(&ptog, sizeof(TPacketGGLoginPing)); } else // If I am slave send login ping to master { g_pkAuthMasterDesc->Packet(&ptog, sizeof(TPacketGGLoginPing)); } */ } Avoiding clearing billing like that (wtf is that btw, shouldn't be executed at all). Now move to packet_info.cpp and add this code in constructor: Set(HEADER_GG_HANDSHAKE_VALIDATION, sizeof(TPacketGGHandshakeValidate), "HandShakeValidation", false); Finally jump to ClientManager.cpp in DB. Find function QUERY_SETUP and if condition with bAuthServer and add there following code: peer->SetChannel(1); Sine P2P communication is allowed only for peers possessing any channel number greater than zero, we set it. Usually this practice should be forbidden but since we restrain the traffic for auth server (with code above) it should be safe. Beware that this might cause first login failed because of packet propagation that can reach the cores after player connects. Voilà, were mostly done with coding! Last but no least, we need to take a brief introduction into kqueue and tedious tour between sockets and kernel vars. Starting with kqueue. I would try to explain this but you better jump to this link. Freebsd documentation always appreciated. Since Metin2 implementation of kqueue wrapper has its size limit you may try to increase it a bit and seek for a feedback. If'd like to do so jump to main.cpp, start function and edit this variable: main_fdw = fdwatch_new(VALUE); Yet keep in mind! Do not try to over-optimize it! Try to experiment, put the different values. If you somehow screw it up it might drag you into the checkpoint issues and eventually crash the whole app. So now a few words about sockets and how the listening process works. When each connection aiming to appropriate port is detected it is dropped into the queue where it's waiting for application to pick it up. So simply we can consider this as a waiting queue like in a grocery store. The point is that this queue has it's limit and once the limit is reached, any new connection is declined at sight. The listening limit for Metin2 core is wrapped into variable called SOMAXCONN. If you dive into C socket documentation you can find something like this: /* *Maximum queue length specifiable by listen /* #define SOMAXCONN 10 As for me it was 128. Since it's a define the value is simply embedded into the app and you cannot manipulate it once a binary is built. So let's change it to let more connection be scheduled. You may ask, why? If player tries to log in it does connect the channel port. If the channel is unavailable you see fadeout and connection is terminated. It happens because there is no place in the queue thus connection is scheduled at all. But be careful! Do not set this value into some high-peak numbers! Be aware that our io_loop function need to iterate through these all events and manage to handle this during the heartbeat session. If you try to over optimize this value you can end up causing lags on the server, internal packets delays and more. In case you'd ask me, value around 1024 is acceptable but still it's better if you take some lecture and experiment a bit. And one more thing, don't forget to set this kernel option on the machine where your server runs: sysctl kern.ipc.soacceptqueue=1024 sysctl kern.ipc.somaxconn=1024 So we are done! Don't forget to add the code from my github repo! Epilogue Metin2's quite an old app and we should not forget about that. The netcode is old, rubbish and cumbersome thus this issue might be only one of many we haven't found just yet. Keep in mind tho that even that mitigation won't protect your server. Actually I doubt that even rewriting the code into more modern shape would do that if you don't get yourselves a good protection. Protection, filters, external firewalls are actually the key especially now when stressers and all this stuff are back and harmful again. Hope that this little thread will help you in your future development. Extra I manage to write a little collector for getting rid of handshakes that never completed this process (outdated). If you'd like to switch it on jump to desc_manager.cpp constructor and add there: CEventFunctionHandler::instance().AddEvent([this](SArgumentSupportImpl *) { desc_manager_garbage_collector_info* info = AllocEventInfo<desc_manager_garbage_collector_info>(); m_pkDescManagerGarbageCollector = event_create(desc_manager_garbage_collector_event, info, PASSES_PER_SEC(1)); }, "DESC_MANAGER_COLLECTOR", 1);
  7. Tak wiem są lepsze rozwiązania lecz czasem prostota jest najlepsza. FIX: 1) Działa na zasadzie, że jeśli w przeciągu X sekund otworzysz X razy shop zostaniesz wyrzucony. 2) Loga postać by m2bob nie mógł zapisać przedmiotów oraz cen. 3) Jeśli jesteś GM nie wyloguję Cię tylko pojawi się informacja, że powinieneś zostać wylogowany (do testów). Komenda to słabe zabezpieczenie ? bo można ją zmienić ? No problem zawsze można przerobić na pakiet. Czekam na hejty ^^ Zasada działania. [Hidden Content] char.cpp Szukaj: if ((GetExchange() || IsOpenSafebox() || IsCubeOpen())) { pkChrCauser->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»ó´ëąćŔĚ ´Ů¸Ą °Ĺ·ˇ¸¦ ÇĎ°í ŔÖ´Â ÁßŔÔ´Ď´Ů.")); return; } Dodaj pod: #ifdef ANTY_SEARCH_M2BOB int limit_time = 50; //ms int limit_open = 3; int iPulse = thecore_pulse(); if (pkChrCauser->GetShopOpenTime() < iPulse) { pkChrCauser->ClearShopOpenCount(); pkChrCauser->SetShopOpenTime(limit_time); } pkChrCauser->AddShopOpenCount(); if(pkChrCauser->GetShopOpenCount() > limit_open && pkChrCauser->GetShopOpenTime() > iPulse) { if (!pkChrCauser->IsGM()){ GetDesc()->SetPhase(PHASE_CLOSE); return; } else pkChrCauser->ChatPacket(CHAT_TYPE_INFO, "[TEST] Anty M2Bob SearchShop - logout!"); } #endif Na końcu pliku dodaj: #ifdef ANTY_SEARCH_M2BOB void CHARACTER::SetShopOpenTime(int time) { ShopOpenTime = thecore_pulse() + time; } #endif char.h Dodaj gdzieś: #ifdef ANTY_SEARCH_M2BOB public: int GetShopOpenTime(void) { return ShopOpenTime; } void SetShopOpenTime(int time); int GetShopOpenCount(void) { return ShopOpenCount; } void AddShopOpenCount(void) { ShopOpenCount++; } void ClearShopOpenCount(void) { ShopOpenCount = 0; } protected: int ShopOpenTime; int ShopOpenCount; #endif service.h #define ANTY_SEARCH_M2BOB // Zapobiega przeszukiwaniu shopów.
  8. Siema jak wiecie domyślnie rekawice złodzieja, pdki itd nie stackują się a jeżeli damy im flag 20 do stackowania się to zakłada się tyle ile jest ich w stacku macie tutaj najprostszy sposób, jak rozwiązać ten problem. service.h #define ENABLE_STACKABLE_UNIQUE_ITEMS char_item.cpp //szukasz: bool CHARACTER::EquipItem(LPITEM item, int iCandidateCell) { //pod dodajesz: #ifdef ENABLE_STACKABLE_UNIQUE_ITEMS if ((item->GetCount() > 1) && (item->GetType() != WEAPON_ARROW)) { ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Rodziel przedmioty, aby to zalozyc.")); return false; } #endif locale_string.txt //dodajesz: "Rodziel przedmioty, aby to zalozyc."; "Aby założyć ten przedmiot, najpierw go rozdziel."; Macie dodatkowo poprawke na strzały, żebyście nie beczeli że nie założycie strzał. Poradnik tak prosty, że 13 latek grający w fortnajta doda, więc nie pomagam przy dodawaniu. Przykład jak to działa: @szybki edit: zamiencie to: if ((item->GetCount() > 1) && (item->GetType() != WEAPON_ARROW)) na: if ((item->GetCount() > 1) && (item->GetSubType() != WEAPON_ARROW)) Bo arrow to przecież podtyp WEAPON'a. zamuliłem dupe dzięki @pakon Nie wiem kto, ale ktoś mi nawet ładnie troche schludniej ostatni poradnik sformatował. Pssst, jak Ci sie chce to możesz to zrobić jeszcze raz. Tanio skóry nie sprzedam.
  9. Domyślnie funkcja jest zepsuta i jeśli używamy jej w queście, to możemy spodziewać się dwukrotnego naliczania zabitego jednego potwora, czy postaci. Rozwiązanie: Otwieramy Plik Quest_Manager.cpp, który znajdziemy w Source Game'a. No i szukamy poniższej linijki: m_mapNPC[npc].OnKill(*pPC); Zamieniając ją na ten warunek: if (npc > 0) { m_mapNPC[npc].OnKill(*pPC); }
  10. Siemka Wchodzimy do input_main.cpp Szukamy funkcji: void CInputMain::QuickslotAdd(LPCHARACTER ch, const char * data) Zamieniamy na: void CInputMain::QuickslotAdd(LPCHARACTER ch, const char * data) { struct command_quickslot_add * pinfo = (struct command_quickslot_add *) data; if(pinfo->slot.type == QUICKSLOT_TYPE_ITEM) { LPITEM item = NULL; TItemPos srcCell(INVENTORY, pinfo->slot.pos); if (!(item = ch->GetItem(srcCell))) return; if (item->GetType() != ITEM_USE && item->GetType() != ITEM_QUEST) return; if ((item->GetVnum() == 50513) || // Kamień Duchowy (item->GetVnum() >= 50801 && item->GetVnum() <= 50826) || // Rosy i Wody (item->GetVnum() >= 39017 && item->GetVnum() <= 39022) || // Atak, Inteligencja (item->GetVnum() >= 39024 && item->GetVnum() <= 39025)) // Krytyk Szycie { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("FIX_WKLADANIE_PRZEDMIOTOW")); return; } } ch->SetQuickslot(pinfo->pos, pinfo->slot); } Blokuję to włożenie do paska szybkiego dostępu Kamyków Duchowych i reszty rzeczy które widać.. Zapobiega to bugowaniu kamyka, że jednym można na P wbić.
  11. No elo, nie wiem czy wiecie ale Atak Boga Smoków nie pokazuje się w lewym górnym rogu (przynajmniej na bince od Paszki napewno). Także macie tutaj poprawke. Efekt dodania: root->uiaffectshower.py szukacie: MALL_DESC_IDX_START+player.POINT_MALL_ATTBONUS : (localeInfo.TOOLTIP_MALL_ATTBONUS_STATIC, "d:/ymir work/ui/skill/common/affect/att_bonus.sub",), pod dodajecie: MALL_DESC_IDX_START+player.POINT_ATT_BONUS : (localeInfo.TOOLTIP_MALL_ATTBONUS_STATIC, "d:/ymir work/ui/skill/common/affect/att_bonus.sub",), UserInterace->PythonPlayerModule.cpp szukacie: PyModule_AddIntConstant(poModule, "POINT_ATT_BONUS", POINT_ATT_BONUS); Jeżeli znajdziecie to nie dodajecie nic, jeżeli nie znaleźliście to dodajcie sobie np. po: PyModule_AddIntConstant(poModule, "POINT_MALL_ATTBONUS", POINT_MALL_ATTBONUS); No i tak że ten tego to by było tyle. ~MasnoMT2
  12. Ten slot na 2 pierścienie jest troszkę "zepsuty", i nie do końca dobrze działa. To znaczy wszystko jest okej, ale po prostu jeśli ustawisz sobie czas na tym przedmiocie (czyli np. pierścieniu), to tego czasu nie będzie widać w tym slocie. Z tego co wiem, to bonusy również były tam popsute, ale chyba mi się wydaje, pewnie to po prostu moje przypuszczenia. Problem rozwiązałem całkiem sam, kopiując linijki z działających funkcji, czyli tych, gdzie dobrze pokazuje czas, no i efekt się udał. Dodam, że wszystkich zmian dokonujemy w uitooltip.py Rozwiązanie błędu jest banalne, a tutaj treść poprawionej, i działającej już funkcji, dla chociażby ludzi, którzy nie potrafią zrobić tego, co opisałem wyżej. [Hidden Content]
  13. [video=youtube] Symulacja efektu flary w metinie została zaimplementowana bardzo dawno temu jeszcze za czasów, gdy część z was prawdopodobnie chodziła z majtkami na głowie. Jednak z jakiegoś powodu finalnie efektu nie wykorzystali i od tamtego momentu też nie był rozwijany. Głównym problemem, przez którego nikt nie wykorzystywał tego efektu na swoich mapach po dziś dzień, była jego niska rozdzielczość. Efekt przy grze w trybie wysokiej rozdzielczości widziany był tylko na połowie ekranu. Wiec słaby był sens jego wykorzystania. Z tego poradnika dowiemy się jak dźwignąć rozdzielczość efektu do dzisiejszych ultramegatronHDmezopotamia ekranów. [hide] 01: Otwieramy LensFlare.cpp (source bin client/EterLib) i szukamy tego: RenderBar2d(0.0f, 0.0f, 1024.0f, 1024.0f); Następnie zmieniamy liczby na takie, jakie odpowiadają konkretnej rozdzielczości np. full HD RenderBar2d(0.0f, 0.0f, 1920.0f, 1080.0f); Kompilujemy i gotowe! Gdyby ktoś chciał się pobawić kolorami flary, może to zrobić tutaj: static float g_afColors[ ][4] = { { 1.0f, 1.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 0.8f }, { 0.3f, 0.5f, 1.0f, 0.9f }, { 0.3f, 0.5f, 1.0f, 0.6f }, { 1.0f, 0.6f, 0.9f, 0.4f }, { 1.0f, 0.0f, 0.0f, 0.5f }, { 1.0f, 0.6f, 0.3f, 0.4f } }; [/hide]
  14. Standardowo podczas tworzenia postaci, limit nazewnictwa wynosi 12 znaków. Są jednak sposoby, aby stworzyć postać o nazwie przekraczającej dozwoloną ilość znaków. Do tego celu został nawet strzeżony program, lecz przez małą popularność i upływ czasu zaginął w odmętach internetu. Niemniej nadal można to zrobić ręcznie, a więc może warto to zmienić. [hide] 01: Otwieramy input_login.cpp (source game /Srcs/Server/game/src). Szukamy tego: if (true == g_BlockCharCreation) { d->Packet(&packFailure, sizeof(packFailure)); return; } I zmieniamy na to: if (true == g_BlockCharCreation) { d->Packet(&packFailure, sizeof(packFailure)); return; } if (strlen(pinfo->name) > 12) { d->Packet(&packFailure, sizeof(packFailure)); return; } I to tyle [/hide]
  15. Problem polega na tym, że gdy będziemy chcieli kupić przedmiot na straganie gracza, a ktoś go wykupi przed nami, zanim zdążymy potwierdzić zakup, to gra nam się zamknie, jeśli potwierdzimy takowy zakup. 01: Otwieramy shop.cpp (source game /usr/src/mainline_released/mainline_sg/Srcs/Server/game/src). Szukamy tego: LPITEM pkSelectedItem = ITEM_MANAGER::instance().Find(r_item.itemid); if (IsPCShop()) { if (!pkSelectedItem) { sys_log(0, "Shop::Buy : Critical: This user seems to be a hacker : invalid pcshop item : BuyerPID:%d SellerPID:%d", ch->GetPlayerID(), m_pkPC->GetPlayerID()); return false; } if ((pkSelectedItem->GetOwner() != m_pkPC)) { sys_log(0, "Shop::Buy : Critical: This user seems to be a hacker : invalid pcshop item : BuyerPID:%d SellerPID:%d", ch->GetPlayerID(), m_pkPC->GetPlayerID()); return false; } } I zmieniamy na to: LPITEM pkSelectedItem = ITEM_MANAGER::instance().Find(r_item.itemid); if (IsPCShop()) { if (!pkSelectedItem) { sys_log(0, "Shop::Buy : Critical: This user seems to be a hacker : invalid pcshop item : BuyerPID:%d SellerPID:%d", ch->GetPlayerID(), m_pkPC->GetPlayerID()); return SHOP_SUBHEADER_GC_SOLD_OUT; } if ((pkSelectedItem->GetOwner() != m_pkPC)) { sys_log(0, "Shop::Buy : Critical: This user seems to be a hacker : invalid pcshop item : BuyerPID:%d SellerPID:%d", ch->GetPlayerID(), m_pkPC->GetPlayerID()); return SHOP_SUBHEADER_GC_SOLD_OUT; } }
  16. Syserr: ResourceManager::GetResourcePointer: NOT SUPPORT FILE g:\(ÁÖ)Ŕ̸̹Ł\3d\õŔDZşąý»ç\õŔ Fix: [Hidden Content] Info: Błąd dotyczy brakującej textury o niewspieranym formacie w Metin2 (.psd) przy mobie o id: 2403 Zmieniłem texture na dobrą wystarczy podmienić na mój plik.
  17. Siema, stary błąd jak świat ale zgadując połowa z was nie ma go naprawionego, bądź o nim zapomniała ewentualnie nie uważa go za błąd, ale jest to irytujące. Opis błędu: - Gdy jesteśmy w party i jakiś byczek z party odpali sobie wolny i zacznie kasować ludzi to -2000 punktów rangi jest rozkładane na wszystkie osoby w party zamiast tylko na osobę która zabiła na wolnym. Naprawa: [hide] common->service.h dodajecie: #define ENABLE_PARTY_ALGIN_FIX game->char_battle.cpp szukacie: if (number(1, 100) < iNoPenaltyProb) pkKiller->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("żë˝ĹŔÇ ş¸ČŁ·Î ľĆŔĚĹŰŔĚ ¶łľîÁöÁö ľĘľŇ˝Ŕ´Ď´Ů.")); else { if (g_iUseLocale && pkKiller->GetParty()) { FPartyAlignmentCompute f(-20000, pkKiller->GetX(), pkKiller->GetY()); pkKiller->GetParty()->ForEachOnlineMember(f); if (f.m_iCount == 0) pkKiller->UpdateAlignment(-20000); else { sys_log(0, "ALIGNMENT PARTY count %d amount %d", f.m_iCount, f.m_iAmount); f.m_iStep = 1; pkKiller->GetParty()->ForEachOnlineMember(f); } } else pkKiller->UpdateAlignment(-20000); } zamieniacie na: #ifdef ENABLE_PARTY_ALGIN_FIX if (number(1, 100) < iNoPenaltyProb) pkKiller->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("żë˝ĹŔÇ ş¸ČŁ·Î ľĆŔĚĹŰŔĚ ¶łľîÁöÁö ľĘľŇ˝Ŕ´Ď´Ů.")); else pkKiller->UpdateAlignment(-20000); #else if (number(1, 100) < iNoPenaltyProb) pkKiller->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("żë˝ĹŔÇ ş¸ČŁ·Î ľĆŔĚĹŰŔĚ ¶łľîÁöÁö ľĘľŇ˝Ŕ´Ď´Ů.")); else { if (g_iUseLocale && pkKiller->GetParty()) { FPartyAlignmentCompute f(-20000, pkKiller->GetX(), pkKiller->GetY()); pkKiller->GetParty()->ForEachOnlineMember(f); if (f.m_iCount == 0) pkKiller->UpdateAlignment(-20000); else { sys_log(0, "ALIGNMENT PARTY count %d amount %d", f.m_iCount, f.m_iAmount); f.m_iStep = 1; pkKiller->GetParty()->ForEachOnlineMember(f); } } else pkKiller->UpdateAlignment(-20000); } #endif [/hide]
  18. Krótko i na temat: 1. Otwieramy plik gm.mse 2. Szukamy: List TimeEventSizeX { 0.000000 64.000000 } List TimeEventSizeY { 0.000000 64.000000 } } 3. Edytujemy jak chcemy 4. Gotowe
  19. Dobra witam ozięble. Jeden podobny poradnik został już tutaj przezemnie napisany, ale widze że to wciążnie pomogło to niech wam będzie macie jeszcze jeden. Teraz zablokujecie sobie ulepszanie przedmiotów, które są w stacku. Przyda się szczególnie, gdy dodawaliście stackowalne KD. service.h #define ENABLE_BLOCK_STACK_REFINE char_item.cpp szukacie: [hide] [/hide] [hide] bool CHARACTER::DoRefine(LPITEM item, bool bMoneyOnly) bool CHARACTER::DoRefineWithScroll(LPITEM item) [/hide] W tych funkcjach na początku dodajecie: #ifdef ENABLE_BLOCK_STACK_REFINE if(item->GetCount() > 1) { ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Takie trudne bylo.")); return false; } #endif locale_string.txt "Takie trudne bylo."; "[serwer] Nie ulepszaj w stacku menelu."; @Edit: Poprawka związana z ulepszaniem przedmiotów zwojami, dla ludzi nieużywających żadnej części mózgu.
  20. Sysser: 0131 22:56:11004 :: CEffectManager::RegisterEffect - LoadScript(d:/ymir work/effect/background/tent_s_lamp.mse) Error 0131 22:56:11004 :: CArea::SetEffect effect register error d:/ymir work/effect/background/tent_s_lamp.mse Fix: [Hidden Content] Info: Błąd występuje w Katakumbach, brakuje pliku tutaj go dorobiłem aby nie wywalało błędu.
  21. GMowie posiadają specjalną umiejętność ukrywania się przed graczem, mogą być po prostu dla innych niewidoczni. Aktywuje się ją komendą /in, która nie do końca poprawnie funkcjonuje. Gdy odwrócimy efekt niewidzialności (zechcemy z powrotem być widzialni), nasz znaczek GMa nad głową oraz iskry w pancerzu już się nie pojawią. Zatem to, w tym poradniku sobie naprawimy. 01: Otwieramy char.h (source game /usr/src/mainline_released/mainline_sg/Srcs/Server/game/src). Szukamy tego: bool ChangeSex(); I zmieniamy na to: bool ChangeSex(); bool do_invisibility(); 02: Otwieramy char.cpp (source game /usr/src/mainline_released/mainline_sg/Srcs/Server/game/src). Szukamy tego: WORD CHARACTER::GetRaceNum() const { if (m_dwPolymorphRace) return m_dwPolymorphRace; if (m_pkMobData) return m_pkMobData->m_table.dwVnum; return m_points.job; } I zmieniamy na to: WORD CHARACTER::GetRaceNum() const { if (m_dwPolymorphRace) return m_dwPolymorphRace; if (m_pkMobData) return m_pkMobData->m_table.dwVnum; return m_points.job; } bool CHARACTER::do_invisibility() { UpdatePacket(); SET_BIT(m_bAddChrState, ADD_CHARACTER_STATE_SPAWN); m_afAffectFlag.Set(AFF_SPAWN); ViewReencode(); REMOVE_BIT(m_bAddChrState, ADD_CHARACTER_STATE_SPAWN); m_afAffectFlag.Reset(AFF_SPAWN); } 03: Otwieramy cmd_gm.cpp (source game /usr/src/mainline_released/mainline_sg/Srcs/Server/game/src). Szukamy tego: ACMD(do_invisibility) { if (ch->IsAffectFlag(AFF_INVISIBILITY)) { ch->RemoveAffect(AFFECT_INVISIBILITY); } else { ch->AddAffect(AFFECT_INVISIBILITY, POINT_NONE, 0, AFF_INVISIBILITY, INFINITE_AFFECT_DURATION, 0, true); } } I zmieniamy na to: ACMD(do_invisibility) { if (ch->IsAffectFlag(AFF_INVISIBILITY)) { ch->RemoveAffect(AFFECT_INVISIBILITY); } else { ch->AddAffect(AFFECT_INVISIBILITY, POINT_NONE, 0, AFF_INVISIBILITY, INFINITE_AFFECT_DURATION, 0, true); } ch->do_invisibility(); } I to wszystko
  22. Ta poprawka blokuje włączanie Aury Miecza, czy też Czarowanego Ostrza bez założonej broni. game->src->char_skill.cpp // 1.) Szukamy: bool CHARACTER::UseSkill(DWORD dwVnum, LPCHARACTER pkVictim, bool bUseGrandMaster) { if (false == CanUseSkill(dwVnum)) return false; // 2.) Następnie pod tym warunkiem dopisujemy nastepny: if ((dwVnum == SKILL_GEOMKYUNG || dwVnum == SKILL_GWIGEOM) && !GetWear(WEAR_WEAPON)) return false;
  23. Problem polega na tym, że nie możemy wejść do małpich lochów na pustyni, bo zaraz zostajemy przeniesieni z powrotem przed wejście. Podobnie jest z wyjściem z atlantydy, ale wbrew pozorom są to dwa różne problemy. Zatem pokażę wam, jak je naprawić. 01: Zaczniemy sobie od naprawienia wyjścia z atlantydy. W tym celu będziemy musieli zmienić współrzędne odniesienia teleportów w mob_proto (navicat/player). - szukamy ID 10077 i zmieniamy name i locale_name na to: Atlantyda 100 12085 - szukamy ID 10078 i zmieniamy name i locale_name na to: Seungryong 2844 8105 I problem z wyjściem naprawiony. Podobnie możecie sobie poprawić inne odniesienia teleportów jak coś znajdziecie. Dla ciekawskich, na dnie tego poradnika wyjaśnienie jak zdobyć te cyfry (współrzędne). 02: Teraz zajmiemy się tymi małpimi lochami na pustyni. - wchodzimy do WinScp /usr/home/mt2/share/locale/poland/map i otwieramy index, a w nim zmieniamy: 107 metin2_map_monkey_dungeon 108 metin2_map_monkey_dungeon2 109 metin2_map_monkey_dungeon3 Na to: 87 metin2_map_monkey_dungeon 88 metin2_map_monkey_dungeon2 89 metin2_map_monkey_dungeon3 - wchodzimy do /usr/home/mt2/chs i w każdym kanale (ch11, ch21, ch31, ch41), w pliku CONFIG zmieniamy numery (MAP_ALLOW): 108 na 88 109 na 89 Zapisujemy pliki i mamy poprawione małpie lochy na pustyni. DLA CIEKAWSKICH: Jeśli się w czymś mylę lub o czymś w tym poradniki zapomniałem to piszcie.
  24. Chodzi o to, że po dodaniu tej poprawki bodajże nie możemy przenieść przedmiotów z tzw. "Belt Inventory" do dozorcy, i vice versa. Edytujemy plik "Input_Main.cpp", który znajdziemy w Source Game'a, a następnie dopisujemy nowego Include'a. #include "belt_inventory_helper.h" Szukamy poniższego warunku: if (!ch->IsEmptyItemGrid(p->ItemPos, pkItem->GetSize())) return; Dopisując pod nim następny. if (p->ItemPos.IsBeltInventoryPosition() && false == CBeltInventoryHelper::CanMoveIntoBeltInventory(pkItem)) return;
×
×
  • Create New...