Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 08/01/20 in all areas

  1. Hello, this is a random and unwanted tutorial for building the Metin2 source code with vcpkg. It was intended for new comers for sure, but it might get more complicated than it should be. If you remember the wiki pages about building the source and creating the Extern from scratch, this is the cleaned and updated 2020 method™ . This tutorial focuses doing changes on both some revisions that I have on the internet and the original leaked one. We will use vcpkg, but this tutorial also contains several fixes that are required to get a general source file to be built. Introduction vcpkg is a C++ package manager for Windows, Linux, Mac (and FreeBSD). It allows us to build any third party program required by any of our applications, and keep them updated. It also allows us to easily install anything new it might be required to our sources. In Metin2, this program fully replaces the old Extern directory. The tutorial is compatible for both Windows and FreeBSD, both client and server. This method also supports adding custom inclusions or libraries inside the vcpkg installation root, I'll explain more later on the topic. Why shoud you use this method? You want a quick and slimmer way of distributing your sources, the idea would be not distributing the Extern at all, and let people perform the installation of vcpkg in their PC. Keep all the third party components of Metin2 always up to date. You might get better performance and security enchanges. (Most commonly the Python update) You want to achieve static linking (removing extra DLL in your client or SO in the game). My client source only contain SpeedTreeRT and Granny2 dll files (which could be removed if you use static Granny 2.9 and build SpeedTreeRT from sources) Changes applied: Modify inclusions & libraries to use vcpkg. (No more Extern, for ever) Updated various files to use the last version from vcpkg. Changes old NANOBEGIN/NANOEND to the last SDK and fix some bugs that were generated by using Nanomites with debug builds. Cleaned up Makefile and enable static library usage (no more .so) Fixes some bugs or issues that you can get if you use the server under Windows. Compatibility and incompatibility I was not able to get libmariadb working with FreeBSD, it might have been due to the fact that I was compiling with a FreeBSD 64-bit application, in case something bad happens, I suggest you mitigate by dropping [Hidden Content]:(YOUR FREEBSD VERSION):amd64/latest/All/mariadb-connector-c-3.1.9.txz include and lib files inside (vcpkg directory)\installed\x86-freebsd. (FreeBSD recently updated their pkg to 3.1.9, it might work now) You can not build in 32-bit vcpkg under 64-bit (I was using a cross-toolchain and I never got it to work), get a 32-bit build machine. It might be possible to get multilib to build on FreeBSD, but I am not aware of any method that could be achieved under vcpkg. You need internet on your FreeBSD virtual machine or VPS, it also needs to be updated to a relavant version, any supported FreeBSD version is fine, check them at [Hidden Content] You need to use, at least, Windows 7 SP1 to build the Client (or Server). I do not reccomend using clang for building your source, I get some issues with Crypto++. Please report if cryptopp is working fine Windows prerequisites Get the last version of Visual Studio here: [Hidden Content] Choose the workload "C++ desktop application development" (or something similar) in Visual Studio installer. MAKE SURE TO INSTALL THE VISUAL STUDIO ENGLISH LANGUAGE PACK AS WELL, OR VCPKG WILL NOT WORK. YOU CAN INSTALL LANGUAGE PACK BY CLICKING THE "LANGUAGE PACK" OPTION IN VISUALSTUDIO INSTALLER. We can download Git from here [Hidden Content] and CMake from here [Hidden Content] FreeBSD Setup (Server only) This process must be executed only in the BUILD MACHINE, not in the place where the Server will be started. Type the following command: pkg install gcc makedepend gmake cmake git openssl ninja Then, type the following commands: cd (folder where we want to store vcpkg) git clone --depth=1 [Hidden Content] cd vcpkg ./bootstrap-vcpkg.sh -disableMetrics -useSystemBinaries ./vcpkg install devil cryptopp boost-system boost-container boost-unordered boost-algorithm boost-pool boost-math boost-lexical-cast Windows setup (Client and, optionally, Server) Under Windows, type the following commands: (Please note that you need to launch all this commands in an elevated/administrator command prompt) cd (folder where we want to store vcpkg) git clone --depth=1 [Hidden Content] cd vcpkg bootstrap-vcpkg -disableMetrics vcpkg integrate install vcpkg install devil:x86-windows-static cryptopp:x86-windows-static boost-system:x86-windows-static boost-container:x86-windows-static boost-unordered:x86-windows-static boost-algorithm:x86-windows-static lzo:x86-windows-static python2:x86-windows-static If you use the Type6 Snappy compression, also type the following command: vpckg install snappy:x86-windows-static If you want to build a Server under Windows, also type the following command: vcpkg install libmariadb:x86-windows-static openssl:x86-windows-static boost-pool:x86-windows-static boost-math:x86-windows-static boost-lexical-cast:x86-windows-static Inside your client source directory (where there's Metin2Client.sln) create a new folder called Extern (unfortunally some components cannot be distributed via vcpkg) and extract this pack inside that folder. Server: Common changes You need to follow the OpenSSL update to build the sources. You might also need to follow the char_skill compilation fix if you get some issue. This changes must be done inside game/src. Open cipher.h and modify the following line: encoder_->ProcessData((byte*)buffer, (const byte*)buffer, length); to: encoder_->ProcessData((CryptoPP::byte*)buffer, (const CryptoPP::byte*)buffer, length); and from: decoder_->ProcessData((byte*)buffer, (const byte*)buffer, length); to: decoder_->ProcessData((CryptoPP::byte*)buffer, (const CryptoPP::byte*)buffer, length); Open cipher.cpp and delete the following line: #include <cryptopp/cryptoppLibLink.h> Open utils.cpp and delete this lines if you have them: #ifdef WIN32 extern "C" void my_make_scrambled_password(char *to, const char *password, size_t pass_len); #endif and if you have this lines, change them: #ifdef WIN32 my_make_scrambled_password(hash_buf, tmp_pwd, strlen(tmp_pwd)); #else make_scrambled_password(hash_buf, tmp_pwd); #endif to: make_scrambled_password(hash_buf, tmp_pwd); Then, search if you have this lines: #ifndef SHA1_HASH_SIZE #define SHA1_HASH_SIZE 20 #endif if you have them, add this after those 3 lines: extern "C" { #include "sha1.h" } char *hexify(char * const result, const unsigned char *digest, const size_t size_result, size_t size_digest) { static const char * const hexchars = "0123456789ABCDEF"; char *result_pnt = result; if (size_digest <= (size_t) 0 || size_result <= (size_digest * (size_t) 2U)) { return NULL; } do { *result_pnt++ = hexchars[(*digest >> 4) & 0xf]; *result_pnt++ = hexchars[*digest & 0xf]; digest++; size_digest--; } while (size_digest > (size_t) 0U); *result_pnt = 0; return result; } // Implementation from commit 2db6b50c7b7c638104bd9639994f0574e8f4813c in Pure-ftp source. void make_scrambled_password(char scrambled_password[42], const char password[255]) { SHA1_CTX ctx; unsigned char h0[20], h1[20]; SHA1Init(&ctx); SHA1Update(&ctx, (unsigned char*)password, strlen(password)); SHA1Final(h0, &ctx); SHA1Init(&ctx); SHA1Update(&ctx, h0, sizeof h0); #ifdef HAVE_EXPLICIT_BZERO explicit_bzero(h0, strlen(password)); #else volatile unsigned char *pnt_ = (volatile unsigned char *) h0; size_t i = (size_t) 0U; while (i < strlen(password)) { pnt_[i++] = 0U; } #endif SHA1Final(h1, &ctx); *scrambled_password = '*'; hexify(scrambled_password + 1U, h1, 42, sizeof h1); } Download the following two files (sha1.c and sha1.h) and put them inside game/src folder. [Hidden Content] [Hidden Content] Open input_auth.cpp and if you have this lines, change them from: #ifdef __WIN32__ DBManager::instance().ReturnQuery(QID_AUTH_LOGIN, dwKey, p, "SELECT PASSWORD('%s'),password,securitycode,social_id,id,status,availDt - NOW() > 0," "UNIX_TIMESTAMP(silver_expire)," "UNIX_TIMESTAMP(gold_expire)," "UNIX_TIMESTAMP(safebox_expire)," "UNIX_TIMESTAMP(autoloot_expire)," "UNIX_TIMESTAMP(fish_mind_expire)," "UNIX_TIMESTAMP(marriage_fast_expire)," "UNIX_TIMESTAMP(money_drop_rate_expire)," "UNIX_TIMESTAMP(create_time)" " FROM account WHERE login='%s'", szLogin); #else // @fixme138 1. PASSWORD('%s') -> %s 2. szPasswd wrapped inside mysql_hash_password(%s).c_str() DBManager::instance().ReturnQuery(QID_AUTH_LOGIN, dwKey, p, "SELECT '%s',password,securitycode,social_id,id,status,availDt - NOW() > 0," "UNIX_TIMESTAMP(silver_expire)," "UNIX_TIMESTAMP(gold_expire)," "UNIX_TIMESTAMP(safebox_expire)," "UNIX_TIMESTAMP(autoloot_expire)," "UNIX_TIMESTAMP(fish_mind_expire)," "UNIX_TIMESTAMP(marriage_fast_expire)," "UNIX_TIMESTAMP(money_drop_rate_expire)," "UNIX_TIMESTAMP(create_time)" " FROM account WHERE login='%s'", mysql_hash_password(szPasswd).c_str(), szLogin); #endif to: DBManager::instance().ReturnQuery(QID_AUTH_LOGIN, dwKey, p, "SELECT '%s',password,securitycode,social_id,id,status,availDt - NOW() > 0," "UNIX_TIMESTAMP(silver_expire)," "UNIX_TIMESTAMP(gold_expire)," "UNIX_TIMESTAMP(safebox_expire)," "UNIX_TIMESTAMP(autoloot_expire)," "UNIX_TIMESTAMP(fish_mind_expire)," "UNIX_TIMESTAMP(marriage_fast_expire)," "UNIX_TIMESTAMP(money_drop_rate_expire)," "UNIX_TIMESTAMP(create_time)" " FROM account WHERE login='%s'", mysql_hash_password(szPasswd).c_str(), szLogin); Inside this file, change this lines if you have them: #ifdef __WIN32__ DBManager::instance().ReturnQuery(QID_AUTH_LOGIN, dwKey, p, "SELECT PASSWORD('%s'),password,securitycode,social_id,id,status,availDt - NOW() > 0," "UNIX_TIMESTAMP(silver_expire)," "UNIX_TIMESTAMP(gold_expire)," "UNIX_TIMESTAMP(safebox_expire)," "UNIX_TIMESTAMP(autoloot_expire)," "UNIX_TIMESTAMP(fish_mind_expire)," "UNIX_TIMESTAMP(marriage_fast_expire)," "UNIX_TIMESTAMP(money_drop_rate_expire)," "UNIX_TIMESTAMP(create_time)" " FROM account WHERE login='%s'", szLogin); #else // @fixme138 1. PASSWORD('%s') -> %s 2. szPasswd wrapped inside mysql_hash_password(%s).c_str() DBManager::instance().ReturnQuery(QID_AUTH_LOGIN, dwKey, p, "SELECT '%s',password,securitycode,social_id,id,status,availDt - NOW() > 0," "UNIX_TIMESTAMP(silver_expire)," "UNIX_TIMESTAMP(gold_expire)," "UNIX_TIMESTAMP(safebox_expire)," "UNIX_TIMESTAMP(autoloot_expire)," "UNIX_TIMESTAMP(fish_mind_expire)," "UNIX_TIMESTAMP(marriage_fast_expire)," "UNIX_TIMESTAMP(money_drop_rate_expire)," "UNIX_TIMESTAMP(create_time)" " FROM account WHERE login='%s'", mysql_hash_password(szPasswd).c_str(), szLogin); #endif to: DBManager::instance().ReturnQuery(QID_AUTH_LOGIN, dwKey, p, "SELECT '%s',password,securitycode,social_id,id,status,availDt - NOW() > 0," "UNIX_TIMESTAMP(silver_expire)," "UNIX_TIMESTAMP(gold_expire)," "UNIX_TIMESTAMP(safebox_expire)," "UNIX_TIMESTAMP(autoloot_expire)," "UNIX_TIMESTAMP(fish_mind_expire)," "UNIX_TIMESTAMP(marriage_fast_expire)," "UNIX_TIMESTAMP(money_drop_rate_expire)," "UNIX_TIMESTAMP(create_time)" " FROM account WHERE login='%s'", mysql_hash_password(szPasswd).c_str(), szLogin); Open the file libsql/AsyncSQL.cpp and change: fprintf(stdout, "AsyncSQL: connected to %s (reconnect %d)\n", m_stHost.c_str(), m_hDB.reconnect);[ in fprintf(stdout, "AsyncSQL: connected to %s\n", m_stHost.c_str()); Open the file libthecore/src/log.c and change: #ifndef __WIN32__ // log_level이 1 이상일 경우에는 테스트일 경우가 많으니 stdout에도 출력한다. if (log_level_bits > 1) { #endif in: // log_level이 1 이상일 경우에는 테스트일 경우가 많으니 stdout에도 출력한다. if (log_level_bits > 1) { also change this line, you will find it some lines after the last change: #ifndef __WIN32__ } #endif in: } Open the file libthecore/include/stdafx.h and delete //struct timespec { time_t tv_sec; /* seconds */ long tv_nsec; /* and nanoseconds */ }; also delete this line: #define strtof(str, endptr) (float)strtod(str, endptr) If you have libserverkey, open libserverkey/RSACrypto.cpp and delete this lines: #ifdef _WIN32 #include <atlenc.h> #endif also ope nthe file libserverkey/RSACrypto.h and delete this lines: #ifdef _WIN32 // needed only for using openssl #pragma comment(lib, "libeay32") #endif Open libserverkey/CheckServerKey.h and change #ifdef _WIN32 #include <atlenc.h> #else #include "base64_ssl.h" #endif to: #include "base64_ssl.h" Also inside this file, modifiy this: #ifdef _WIN32 if (FALSE == Base64Decode(key.c_str(), key.size(), buf, &buflen)) { errorString = "base64 decode failed"; return false; } #else if (false == unbase64_ssl((unsigned char *)key.c_str(), key.size(), buf, buflen)) { errorString = "base64 decode failed"; return false; } buflen = strlen((const char *)buf); #endif to: if (false == unbase64_ssl((unsigned char *)key.c_str(), key.size(), buf, buflen)) { errorString = "base64 decode failed"; return false; } buflen = strlen((const char *)buf); Open db/src/CsvReader.h and change: #if _MSC_VER #include <hash_map> #else #include <map> #endif to: #include <boost/unordered_map.hpp> also change this: #if _MSC_VER typedef stdext::hash_map<std::string, size_t> NAME2INDEX_MAP; typedef stdext::hash_map<size_t, std::string> INDEX2NAME_MAP; #else typedef std::map<std::string, size_t> NAME2INDEX_MAP; typedef std::map<size_t, std::string> INDEX2NAME_MAP; #endif to this: typedef boost::unordered_map<std::string, size_t> NAME2INDEX_MAP; typedef boost::unordered_map<size_t, std::string> INDEX2NAME_MAP; Open the file db/src/Main.cpp and delete this lines: #ifdef __FreeBSD__ _malloc_options = "A"; #endif #ifdef __FreeBSD__ extern const char * _malloc_options; #endif Open game/src/MarkImage.h and before this: #include <IL/il.h> add this: #define IL_STATIC_LIB 1 Server: FreeBSD only changes We have to modify "CC = (something)" in "CC = g++" open those files with a text editor and modify it, here's the list of files: - libthecore/src/Makefile - libsql/Makefile - libpoly/Makefile - libgame/src/Makefile - libserverkey/Makefile - db/src/Makefile - game/src/Makefile - game/src/quest/Makefile (Here it's called CPP not CC) We also have to modify "CC= gccX" (where X is a number) in "CC = gcc" inside "liblua/config" (or liblua/5.0/config) Open libsql/Makefile and delete the following lines: IFLAGS = -I/usr/local/include/ #sometimes necessary included IFLAGS = -I/usr/local/include/mysql or the following lines if you have them: oppure potreste avere le seguenti righe che sono da rimuovere: IFLAGS = -I../libmysql/5.x-5.1.35 IFLAGS = -I../libmysql/7.x-5.1.35 Before "LIBS =" add this: VCPKG_DIR=(Your vcpkg directory) IFLAGS = -I$(VCPKG_DIR)/installed/x86-freebsd/include Check if you have "-m32" inside this files, otherwise add this before "LIBS = " CFLAGS += -m32 This check and add process must be done for the following files: - libthecore/src/Makefile - libsql/Makefile - libpoly/Makefile - libserverkey/Makefile - libgame/src/Makefile Open the file game/src/quest/Makefile and if you don't have "-m32" add this before "all: qc cc" CFLAGS += -m32 If you don't have "ENABLE_STATIC = 0" add this before "all: qc cc" CPP += -static If you have "ENABLE_STATIC = 0" change the 0 in 1. If you are under FreeBSD x64, you have to add this before "all: qc cc". LIBDIR += -L/usr/local/lib32/gccX While for x86 Freebsd, this LIBDIR += -L/usr/local/lib/gccX Replace X with the gcc major version, you can verify that by typing "gcc --version" in the console. You can get something like this: gcc (FreeBSD Ports Collection) 9.3.0 In my case, the number is 9. Open "db/src/Makefile", and delete this lines if you have them ifeq ($(BSD_VERSION), 7) INCDIR += -I../../libmysql/7.x-5.1.35 LIBDIR += -L../../libmysql/7.x-5.1.35 else INCDIR += -I../../libmysql/5.x-5.1.35 LIBDIR += -L../../libmysql/5.x-5.1.35 endif also delete this lines if you have them: # boost INCDIR += -I../../boost and also delete this lines: # Boost INCDIR += -I../../../Extern/include/boost # MySQL INCDIR += -I/usr/local/include/mysql LIBS += /usr/local/lib/mysql/libmysqlclient.a /usr/lib/libz.a and also this line: INCDIR += -I/usr/local/include and this ones: # Project Libraries INCDIR += -I../../../Extern/include LIBDIR += -I../../../Extern/lib also delete this word: -lmysqlclient and this one as well: -Wl,-rpath=/usr/local/lib/gccX (there could be any number where there is X) If you don't have "-m32" add before "SRCS = (some text)" or "CPPFILE = (some text)" this: CFLAGS += -m32 Add this before "SRCS = (some text)" or "CPPFILE = (some text)" this: VCPKG_ROOT (your vcpkg directory) LIBS += -lmariadbclient -lssl -lcrypto -lz INCDIR += -I$(VCPKG_ROOT)/installed/x86-freebsd/include LIBDIR += -L$(VCPKG_ROOT)/installed/x86-freebsd/lib Under FreeBSD x64, you have to add this after the LIBDIR += code you have added before: LIBDIR += -L/usr/local/lib32/gccX Under FreeBSD x86 this: LIBDIR += -L/usr/local/lib/gccX Replace X with your gcc major version code, you can grab that from "gcc --version". If you don't have "ENABLE_STATIC = 0" add this before the code we added before (LIBDIR += and INCDR +=) CFLAGS += -static If you have "ENABLE_STATIC = 0" change the 0 to 1. Open game/src/Makefile and delete the following lines (it doesn't matter if you don't have all of them) # boost INCDIR += -I../../../Extern/include/boost # DevIL INCDIR += -I../../libdevil LIBDIR += -L../../libdevil LIBS += -lIL -lpng -ltiff -lmng -llcms -ljpeg # MySQL ifeq ($(BSD_VERSION), 7) INCDIR += -I../../libmysql/7.x-5.1.35 LIBDIR += -L../../libmysql/7.x-5.1.35 else INCDIR += -I../../libmysql/5.x-5.1.35 LIBDIR += -L../../libmysql/5.x-5.1.35 endif LIBS += -lmysqlclient -lz # Miscellaneous external libraries INCDIR += -I../../../Extern/include LIBDIR += -L../../../Extern/lib LIBS += -lcryptopp -lgtest # HackShield INCDIR += -I../../libhackshield/include LIBDIR += -L../../libhackshield/lib LIBS += -lanticpxsvr # XTrap INCDIR += -I../../libxtrap/include and # Boost INCDIR += -I../../../Extern/include/boost # DevIL INCDIR += -I../../../Extern/include/IL LIBS += ../../../Extern/lib/libIL.a\ ../../../Extern/lib/libjasper.a\ ../../../Extern/lib/libpng.a\ ../../../Extern/lib/libtiff.a\ ../../../Extern/lib/libjbig.a\ ../../../Extern/lib/libmng.a\ /usr/lib/liblzma.a\ ../../../Extern/lib/liblcms.a\ ../../../Extern/lib/libjpeg.a # MySQL INCDIR += -I/usr/local/include/mysql LIBS += /usr/local/lib/mysql/libmysqlclient.a /usr/lib/libz.a # CryptoPP LIBS += ../../../Extern/lib/libcryptopp.a and # OpenSSL INCDIR += -I/usr/include LIBS += -lssl -lcrypto # LIBS += /usr/lib/libssl.a and # Project Libraries INCDIR += -I../../../Extern/include INCDIR += -I/usr/local/include LIBDIR += -L/usr/local/lib Before "CFILE = minilzo.c" add this: VCPKG_ROOT= (your vcpkg directory) INCDIR += -I$(VCPKG_ROOT)/installed/x86-freebsd/include LIBDIR += -L$(VCPKG_ROOT)/m2pkg/installed/x86-freebsd/lib LIBS += -lmariadbclient -lcryptopp -lIL -lpng -ljpeg -lssl -lcrypto Under FreeBSD x64, you have to add this after the LIBDIR += code you have added before: LIBDIR += -L/usr/local/lib32/gccX Under FreeBSD x86 this: LIBDIR += -L/usr/local/lib/gccX Replace X with your gcc major version code, you can grab that from "gcc --version". If you don't have "ENABLE_STATIC = 0" add this before the code we added before (LIBDIR += and INCDR +=) CFLAGS += -static If you have "ENABLE_STATIC = 0" change the 0 to 1. Replace: CFILE = minilzo.c with: CFILE = minilzo.c sha1.c Some sources might not have CFILE, in case you don't have it add "sha1.c" after "item_manager_read_tables.cpp" like this: item_manager_read_tables.cpp sha1.c Server: Changes for Windows Open m2server.sln or Metin2Server.sln and update the toolchain if you ask it, ignore any "ServerkeyGenerator" error. Open game.2008.vcxproj with a text editor and add after this: <ClCompile Include="war_map.cpp" /> this: <ClCompile Include="sha1.c" /> <ClCompile Include="sha1.h" /> If you used an old version of the tutorial, please remove this line: <VcpkgUserTriplet>x86-windows-static</VcpkgUserTriplet> You have to remove this line in all the vcxproj files. Open the solution with VisualStudio, select ALL projects, then right click the selection and click Properties. Inside the properties, click on the left "vcpkg" and make sure to select: "Static libraries: Yes" "Auto link: Yes" Client changes Open EterBase/cipher.h and change the following lines: Open cipher.h and modify the following line: encoder_->ProcessData((byte*)buffer, (const byte*)buffer, length); to: encoder_->ProcessData((CryptoPP::byte*)buffer, (const CryptoPP::byte*)buffer, length); and from: decoder_->ProcessData((byte*)buffer, (const byte*)buffer, length); to: decoder_->ProcessData((CryptoPP::byte*)buffer, (const CryptoPP::byte*)buffer, length); Open Eterbase/lzo.cpp and delete this line: #include <lzo-2.03/lzoLibLink.h> "lzo-2.03" may vary, it's important to delete the lzoLibLink inclusion. Open EterBase/lzo.h and check that the #include with lzo1x.h is like this: #include <lzo/lzo1x.h> Open UserInterface/MarkImage.h and before this: #include <IL/il.h> add this: #define IL_STATIC_LIB 1 Open UserInterface.cpp and delete the following line: #include <cryptopp/cryptoppLibLink.h> Inside UserInterface.cpp modifiy this: static const char * sc_apszPythonLibraryFilenames[] = { "UserDict.pyc", "future.pyc", "copy_reg.pyc", "linecache.pyc", "ntpath.pyc", "os.pyc", "site.pyc", "stat.pyc", "string.pyc", "traceback.pyc", "types.pyc", "\n", }; to: static const char * sc_apszPythonLibraryFilenames[] = { #if PY_MINOR_VERSION == 7 "abc.pyc", "bisect.pyc", "codecs.pyc", "collections.pyc", "copy.pyc", "copy_reg.pyc", "fnmatch.pyc", "functools.pyc", "genericpath.pyc", "heapq.pyc", "hashlib.pyc", // new "keyword.pyc", "linecache.pyc", "locale.pyc", "ntpath.pyc", "os.pyc", // removed pyexpat "random.pyc", "re.pyc", "shutil.pyc", "site.pyc", "sre_compile.pyc", "sre_constants.pyc", "sre_parse.pyc", "stat.pyc", "string.pyc", "sysconfig.pyc", "traceback.pyc", "types.pyc", "UserDict.pyc", "warnings.pyc", "weakref.pyc", "_abcoll.pyc", "_weakrefset.pyc", "__future__.pyc", "encodings\\aliases.pyc", "encodings\\ascii.pyc", "encodings\\cp1250.pyc", "encodings\\cp1251.pyc", "encodings\\cp1252.pyc", "encodings\\cp949.pyc", "encodings\\utf_8.pyc", "encodings\\cp850.pyc", //new "encodings\\__init__.pyc", // removed xml #else "UserDict.pyc", "__future__.pyc", "copy_reg.pyc", "linecache.pyc", "ntpath.pyc", "os.pyc", "site.pyc", "stat.pyc", "string.pyc", "traceback.pyc", "types.pyc", #endif "\n", }; Delete the following lines: #if GrannyProductMinorVersion==4 #pragma comment( lib, "granny2.4.0.10.lib" ) #elif GrannyProductMinorVersion==7 #pragma comment( lib, "granny2.7.0.30.lib" ) #elif GrannyProductMinorVersion==8 #pragma comment( lib, "granny2.8.49.0.lib" ) #elif GrannyProductMinorVersion==9 #pragma comment( lib, "granny2.9.12.0.lib" ) #else #error "unknown granny version" #endif or this line: #pragma comment( lib, "granny2.lib" ) Also delete this lines: //ifdef _DEBUG //#pragma comment( lib, "python2_d.lib" ) //#else #pragma comment( lib, "python2.lib" ) //#endif #pragma comment( lib, "devil.lib" ) #ifdef _DEBUG #pragma comment( lib, "jpegd.lib" ) #else #pragma comment( lib, "jpeg.lib" ) #endif #pragma comment( lib, "cryptopp-static.lib" ) #pragma comment( lib, "snappy.lib" ) #pragma comment( lib, "lzo2.lib" ) Delete snappy inclusion if you don't use Type6. If you have ENABLE_PY_CHECK, add before #elif PY_VERSION_HEX==0x020712F0 this one: #elif PY_VERSION_HEX==0x020712F0 { PYFOLD"/abc.pyc", 6594, 0xb23cfe1aL}, { PYFOLD"/bisect.pyc", 3276, 0x306b93d2L}, { PYFOLD"/codecs.pyc", 40678, 0xe2dc76f0L}, { PYFOLD"/collections.pyc", 28295, 0xaffface7L}, { PYFOLD"/copy.pyc", 13236, 0xaf4763dcL}, { PYFOLD"/copy_reg.pyc", 5618, 0x8612d494L}, { PYFOLD"/fnmatch.pyc", 3860, 0xdad2ad3aL}, { PYFOLD"/functools.pyc", 7859, 0x110b58e2L}, { PYFOLD"/genericpath.pyc", 3968, 0x3005313bL}, { PYFOLD"/hashlib.pyc", 7278, 0x709b3325L}, { PYFOLD"/heapq.pyc", 15302, 0x763f87a6L}, { PYFOLD"/keyword.pyc", 2187, 0x6e8bf638L}, { PYFOLD"/linecache.pyc", 3518, 0xe414a862L}, { PYFOLD"/locale.pyc", 57922, 0xe5bae851L}, { PYFOLD"/ntpath.pyc", 14031, 0x2170738fL}, { PYFOLD"/os.pyc", 27862, 0xd1b87519L}, { PYFOLD"/random.pyc", 27469, 0x626a1305L}, { PYFOLD"/re.pyc", 14274, 0xf6615b33L}, { PYFOLD"/shutil.pyc", 20489, 0x5f86796aL}, { PYFOLD"/site.pyc", 20470, 0x1e5d86efL}, { PYFOLD"/sre_compile.pyc", 13175, 0xdb74e1f3L}, { PYFOLD"/sre_constants.pyc", 6400, 0x62725f60L}, { PYFOLD"/sre_parse.pyc", 22632, 0x73a3417bL}, { PYFOLD"/stat.pyc", 3161, 0x505339d3L}, { PYFOLD"/string.pyc", 22550, 0xa831251fL}, { PYFOLD"/struct.pyc", 280, 0x692620a3L}, { PYFOLD"/sysconfig.pyc", 18751, 0x1609c777L}, { PYFOLD"/traceback.pyc", 12499, 0xc55a9ea6L}, { PYFOLD"/types.pyc", 3012, 0xab7ff24eL}, { PYFOLD"/UserDict.pyc", 11556, 0xec08a651L}, { PYFOLD"/warnings.pyc", 14453, 0x191fb51bL}, { PYFOLD"/weakref.pyc", 18614, 0xc850b7d7L}, { PYFOLD"/_abcoll.pyc", 29948, 0x2e08dd19L}, { PYFOLD"/_generate.py", 368, 0xa1759794L}, { PYFOLD"/_weakrefset.pyc", 11646, 0x37eda60dL}, { PYFOLD"/__future__.pyc", 4469, 0xfc87d05aL}, { PYFOLD"/encodings/aliases.pyc", 8811, 0x1cc93e8dL}, { PYFOLD"/encodings/ascii.pyc", 2691, 0x675a99b1L}, { PYFOLD"/encodings/cp1250.pyc", 3347, 0xdbb8207eL}, { PYFOLD"/encodings/cp1251.pyc", 3344, 0x8ef98d98L}, { PYFOLD"/encodings/cp1252.pyc", 3347, 0x7b5e1208L}, { PYFOLD"/encodings/cp850.pyc", 8292, 0xa0865dd5L}, { PYFOLD"/encodings/cp949.pyc", 2065, 0x5f2c4c06L}, { PYFOLD"/encodings/utf_8.pyc", 2294, 0xbc12dc7fL}, { PYFOLD"/encodings/__init__.pyc", 4542, 0x861f2a28L}, Open EterPack/EterPack.cpp and delete this line: #include <cryptopp/cryptoppLibLink.h> Open UserInterface/GuildMarkUploader.cpp and delete: (ILvoid*) Open EterLib/JpegFile.cpp and make sure that jpeglib.h inclusion is like this: #include <jpeglib.h> then remove this line: #include <libjpeg-6b/jpegLibLink.h> "libjpeg-6b" may vary. Inside GrpDetector.h add this after #include <d3dx8.h> #include <string> Inside ScriptLib\StdAfx.h replace: #ifdef _DEBUG #undef _DEBUG #include "../../Extern/Python2/Python.h" #define _DEBUG #else #include "../../Extern/Python2/Python.h" #endif #include "../../Extern/Python2/node.h" #include "../../Extern/Python2/grammar.h" #include "../../Extern/Python2/token.h" #include "../../Extern/Python2/parsetok.h" #include "../../Extern/Python2/errcode.h" #include "../../Extern/Python2/compile.h" #include "../../Extern/Python2/symtable.h" #include "../../Extern/Python2/eval.h" #include "../../Extern/Python2/marshal.h" the Python inclusion may vary to #include <python2.7/Python.h> #include <python2.7/node.h> #include <python2.7/grammar.h> #include <python2.7/token.h> #include <python2.7/parsetok.h> #include <python2.7/errcode.h> #include <python2.7/compile.h> #include <python2.7/eval.h> #include <python2.7/marshal.h> #undef BYTE // Fixed python bitset.h build issue Inside scriptLib/PythonLauncher.h modify #include "../../Extern/Python2/frameobject.h" to: #include <python2.7/frameobject.h> Open scriptLib/PythonLauncher.cpp and modify: #include "../../Extern/Python2/frameobject.h" to: #include <python2.7/frameobject.h> Open scriptLib/PythonMarshal.cpp and modify: #include "../../Extern/Python2/longintrepr.h" to: #include <python2.7/longintrepr.h> Open ScriptLib/PythonUtils.cpp and if we don't have this #define PyLong_AsLong PyLong_AsLongLong #define PyLong_AsUnsignedLong PyLong_AsUnsignedLongLong add it after this: #include "PythonUtils.h" Open EterBase\StdAfx.h and modify: // Armadillo nanomite protection #ifndef NANOBEGIN #ifdef __BORLANDC__ #define NANOBEGIN __emit__ (0xEB,0x03,0xD6,0xD7,0x01) #define NANOEND __emit__ (0xEB,0x03,0xD6,0xD7,0x00) #else #define NANOBEGIN __asm _emit 0xEB __asm _emit 0x03 __asm _emit 0xD6 __asm _emit 0xD7 __asm _emit 0x01 #define NANOEND __asm _emit 0xEB __asm _emit 0x03 __asm _emit 0xD6 __asm _emit 0xD7 __asm _emit 0x00 #endif #endif in: // Armadillo nanomite protection #if !defined(NANOBEGIN) && !defined(NANOEND) #ifdef _DEBUG #define NANOBEGIN #define NANOEND #else #include <armadillo/SecuredSections.h> #endif #endif This change also needs to be applied to the following files: - EterGrnLib/StdAfx.h - MilesLib/StdAfx.h - SpeedTreeLib/StdAfx.h Open MilesLib/StdAfx.h and delete this line: #include <mss.h> Open the client sln file (like Metin2Client.sln or Metin2Client_VC90.sln) if it asks for any linked update press yes. Then go to UserInterface properties, select at the top of the window "Configuration: ", it might be Debug, Release, Distribute, and set it "All configurations": Modify /SAFESEH to /SAFESEH:NO. Select ALL projects, then right click the selection and click Properties. Inside the properties, click on the left "vcpkg" and make sure to select: "Static libraries: Yes" "Auto link: Yes" Go to C/C++, General, you will find "Extra inclusion directories" for something similar. Press the little arrow in the text, then modify. Add the following: $(SolutionDir)Extern\include. Then, select the UserInterface project. Go to Linker, General and find "Extra library directory". Press the little arrow in the text, then Modify. Add the following: $(SolutionDir)Extern\lib. If you used an old version of the tutorial, please remove this line: <VcpkgUserTriplet>x86-windows-static</VcpkgUserTriplet> You have to remove this line in all .vcxproj files. Client: Cleanup and update of binary files Open our clinet directory and delete all DLL with the exception of this (MAKE SURE TO NOT RMEOVE ANY EXTRA DLL YOU HAVE INSERTED) - SpeedTreeRT.dll - granny2.dll - MSS32.dll Delete the "lib" directory and replace with this directory This directory works for Python 2.7. Final notes and infos If you use Granny 2.9 open EterBase/ServiceDefs.h and add this: #define __GRANNY_VERSION__ 9 after #define _IMPROVED_PACKET_ENCRYPTION_ The vcpkg folder already contains MSL (required for marty sources), check in share/moduleinfo.txt and if there is a new commit, you can replace the inclusions, you can also upload the new updated package and I can update the tutorial. The Python libraries I have distributed works for 2.7.18, it includes some encoding modules, this is the last ever version of python 2.7.18 Expat and xml were removed as they don't work with static python (GIL stuff) Fell free to comment with the check code updated and I'll update the post. The Visual Studio and Makefile updates do not apply with CMake or Premake (pff anyone uses them unironically?) The tutorial might not be 100% accurate for all the sources, I have tested it with mainline_released, a marty internet released and some friends sources (Client side) FreeBSD currently does not work on vcpkg, I will look at fixing the issues when I have time. The log.c changes removed 1058340518920543890 logging messages on Windows. The armadillo change not only update the nanomites to the last version (while Armadillo is deprecated) but also fixes some debugging issues, sometimes, calling those asm routimes might corrupt the debugger, so it's better to disable them if they are not required (Debug builds) If you need newer version of granny2, modify granny2.h accordingly, you can also share the update if you wish to. Changes: - Updated to python 2.7.18 (v3) - Removed all x86-windows-static specification as the new vcpkg integration is easier to use. - Ability to customize the vcpkg root directory - Removed all infos about compiling the sources and so on as they were not required in this forum (I do really expect that people knows how to build in this forum) - Removed all the old manual linking as vcpkg supports automatic linking now I apologize for any grammar error or formatting error, I have not checked the post twice, you can freely report any error in the comments. Good luck in your experiments.
    2 points
  2. M2 Download Center Download Here ( Internal ) Download Here ( Latest Version ) This WE is a version compiled directly by me which includes infinite fixes and features. It's certain that you won't longer use the worldeditor_en! To make it simple, I wrote all the details about this feature and the common WE inside the relative config file: (called WorldEditorRemix.ini) ; Info: ; -) 100% translated ; -) granny2.11 ; -) F6 as Insert alternative ; -) many default features not present inside the worldeditor_en (probably, that binary was taken out from an SVN long time ago and resource hacked) such as Ins for all regions and skyboxes ; -) WASD UPLEFTDOWNRIGHT to move around (+asynchronous diagonally movements) ; -) UP-LEFT-DOWN-RIGHT to move around*10 (+asynchronous diagonally movements) ; -) config file for few things ; Output options by default ; few others such as default WASD movement ; whether or not Insert should let you go where you were before the press ; no MAI dump when saving atlas ; whether or not DevIL should compress and remove alpha from minimap.dds ; whether or not loading .mdatr building heights ; default textureset when creating maps ; overlapped tabs ; other stuff ; -) several bugfixes ; default title app name ; attempting to write to an empty textureset name when creating new maps ; ViewRadius doubled every load&save ; shadowmap.dds creation ; assert when saving atlas ; crash when adjusting height ; many buffer under/overflows ; *.mdc collision data saving (for game_test) ; not checking output options when loading maps ; water brush waterid bug (the id was increased until 256 each time the function was called; now it's based on the water height just like it should be) ; init texture map reload map crash and last 2px always blank ; square shape even for up/down height brushes ; add textureset texture button (+multiselection) ; remove textureset texture feature (just selecting a texture from the list and pressing DELETE) ; creation of empty textureset with index -1 (changed to 0) ; change baseposition button ; misspelled stuff ; skybox bottom image (nb: you also need a fixed launcher for this) ; removed boring CTRL requirement (to move the camera) when editing daylight/attr ; fixed refresh texture imagebox onKey pressing the down/up keys (like when onClicking them) ; fixed TextureSet file creation if not existing ; fixed new wolfman motion event handling ; fixed crash when editing animation attack bones and 00010.gr2 was missing ; fixed locale/ymir/mob_proto load (it autodetects the most common structures) and <map>/regen.txt load/save ; fixed ./group.txt load ; fixed load/save/edit <map>/regen.txt (very nice for "m" regens, untested for "g") ; load from PACK is available if pack/property is present! Be sure pack/Index exists! ; fixed multi-object selection crash ; fixed crash when previewing a missing texture ; fixed not clearing of old environment (e.g. skybox) when switching maps ; fixed not creating property folders in root tree (object tab) ; fixed object attachment in Model Tab ; fixed newly particles names in Effect Tab ; fixed crash when saving a .mse script with no mesh model ; fixed crash when inserting a lower gradient ; -) created new TextureSet field when creating new maps ; -) created new Change/Delete Texture buttons when double-clicking a texture ; -) created Background Music playback and Shadow Recalculate buttons ; -) created water height "set 0z", "+1z", "-1z" buttons ; -) server_attr generator ; -) every crash will generate a logs/WorldEditorRemix_{target}_{date}.dmp file useful for debugging ; -) implemented a "water path" mapsettings option (the launcher requires additional code) ; -) implemented a "wind strength" msenv option (the launcher requires additional code) ; -) the "encrypt data" feature does nothing (unimplemented) ; Note: ; 0) there are no regressions in this version! a bug here means it'd also be present in older WE versions too! ; 1) the shadow output option is tricky: when UpdateUI is called, shadows are hidden although the check is pressed (i implemented the shadow recalculate function for that) #fixed since v11 ; 2) the bgm player requires /miles and the fadein/out doesn't work until you load the map ; 3) the adjusting height button works only if mdatr height is detected ; 4) the Debug version is laggy when working on maps such as n_flame_dungeon and n_ice_dungeon (by default, because SphereRadius are intensively checked in SphereLib\spherepack.h) ; 5) if you load a map, the script panels (where you load .msa et similia) will have the camera perspective a little fucked up (0z instead of -32767z or 0x 0y -163,94z) ; 6) few tree objects are not movable and/or highlightable after placed on the ground and their selection is invisible (you can still delete 'em) ; trick: draw a square selecting a normal building and 'em, then move the building and you'll see all of 'em will be moved! ; 7) the server_attr generator will clean all the unused flags! attr[idx]&=~0xFFFFFFF8; ; 8) you can read files from pack/Index 'n stuff but be aware that Property will not be considered! #fixed since v15 ; 9) the MonsterAreaInfo features are laggy and buggy as fuck ; 10) even though you can select many textures at once (using ctrl+click on textureset list; for brushing or initializing a base texture), you can't delete more than one at the same time ; 11) the .mdatr height is tricky; if you move a building, the height will not be refreshed until you put a new building or whatever you want to trigger the update event ; 12) by default, the worldeditor tries to render only the first 8 terrain textures of a 32x32px region (nb: a 1x1 map is a 256x256 px region) ; 13) the minimap rendering cannot catch the buildings/trees inside the first 2x2 regions due a ymir cache fault and you need to set the camera to "see" them ; 14) when the textureset, environment, etc load fails, the old filename still remains loaded ; 15) the attr flag "3" (three) has no implementation, so don't use it! ; 16) load from PACK doesn't load texturesets from files for first (if they are already in pack/), and the object placer's object list will remain empty because it takes the list from property/ (and not from pack/property) ; 17) to save the regen.txt you press CTRL+S ; 18) if you enable the wireframe (f4) when on Attr Tab, you see the terrain all white ; 19) the water brush disappears when the camera renders the waterwheel small/big effect ; 20) the monster area info goes under ground if you're outside the relative sectree ; 21) the full skybox may be displayed only after the top picture has been added (if the other textures have already been inserted) ; 22) the slider in the Attr Tab is something like "16 photoshop layers" in which you can split your attrs; not so helpful and quite confusing sometimes ; 23) the fixed model - object attachment attaches static objects (hairs'skeleton will not mirror the playing animation) ; 24) in environment tab, if you insert lower gradients, you may end up with an out of range crash #fixed since v30 ; 25) brushes working out-of-screen/map-range may affect random terrain places ; TODO: ; A) look at more than 8 textures for region -> DONE ; B) create a shortcut to fix the #5 note -> DONE ; C) disable the radius <= GetRadius()+0.0001f check to fix the #4 note -> REJECTED ; the worldeditor_en calls this assert and, if ignored, the lag ceases to exist (this will not occur in source version) ; at least, if the release version is not a problem for you, use that in those few cases when .mse are abused and try to kill the debug one ; D) translation in more languages other than english -> REJECTED ; english should be enough! ; E) alternative path for d: -> REJECTED ; you can mount d as a subpath of c like this: ; subst d: "c:\mt2stuff" ; F) need to fix note #19 #25 -> TODO [shortcuts] ; ### SHORTCUTS ; # ESC(ape) Clean cursor ; # Canc(el|Delete) Delete stuff such as selected buildings ; # Ctrl+S Save map ; # Ins(ert) or F6 Save shadowmap|minimap.dds ; # F3 BoundGrid Show/Hide ; # F4 Render UI Show/Hide ; # F11 WireFrame Show/Hide ; # R Reload Texture ; # Z and X Decrease/Increase Texture Splat by 0.1 ; # CapsLock Show GaussianCubic effect if shadows are displayed ; # L-Shift+1-6 Show TextureCountThreshold flags (&2-7) as colors on the ground ; # L-Shift+8 Set Max Showable texture to 8 (de-fix note 12) ; # L-Shift+0 Set Max Showable texture to 255 (fix note 12) ; # H Refresh MDATR Heights (useful when you move an object) (fix note 11) ; # Y Set Perspective as default (fix note 5) ; # T Set the Camera to catch all the object on the screen (w/a note 13) then you'll be ready to press Insert/F6 ; # DO NOT HAVE AN OBJECT SELECTED WHEN USING THOSE SHORTCUTS (MW1-7) ; # MouseWheel+1 move cursor x rotation ; # MouseWheel+2 move cursor y rotation ; # MouseWheel+3 move cursor z rotation ; # MouseWheel+4 move cursor height base (1x) ; # MouseWheel+5 move cursor height base (0.5x) ; # MouseWheel+6 move cursor height base (0.05x) ; # MouseWheel+7 move cursor ambience scale (1x) ; # MouseWheel+Q move selected object height base (1x) ; # MouseWheel+9 move selected object x position (1x) (+asyncronous) ; # MouseWheel+0 move selected object y position (1x) (+asyncronous) ; # MW+RSHIFT+9|0 as above but *10x (+asyncronous) ; # MW+RCONTROL+9|0 as above but *100x (+asyncronous) ; # MouseLeft Insert Objects ; # MouseRight Move camera (it could require CTRL too) ; # SPACE Start move/selected animation in Object/Effect/Fly CB ; # ESC Stop animation in Effect/Fly CB [config] ; ### CONFIG OPTIONS VIEW_CHAR_OUTPUT_BY_DEFAULT = 1 VIEW_SHADOW_OUTPUT_BY_DEFAULT = 1 VIEW_WATER_OUTPUT_BY_DEFAULT = 1 ; WINDOW_HEIGHT_SIZE = 1080 ; WINDOW_WIDTH_SIZE = 1920 WINDOW_FOV_SIZE = 45 ; #100 = 1px (minimal px movement when pressing WASD) WASD_MINIMAL_MOVE = 100 ; came back from where you were before pressing Insert/F6 NO_GOTO_AFTER_INSERT = 1 ; disable MAI dumps when saving atlas and/or pressing Insert/F6 NOMAI_ATLAS_DUMP = 1 ; disable minimap.dds alpha saving and enable compression NOMINIMAP_RAWALPHA = 1 ; enable .mdatr height collision loading when moving on buildings or adjusting terrain DETECT_MDATR_HEIGHT = 1 ; disable fog when loading maps NOFOG_ONMAPLOAD = 1 ; refresh all checkbox configurations when loading maps 'n stuff REFRESHALL_ONUPDATEUI = 0 ; set a default mapname prefix when creating new maps ("" to disable) NEW_MAP_MAPNAME_PREFIX = "metin2_map_" ; display a default textureset when creating new maps ("" to disable) ; note: it loads the filepath if exists, otherwise it will create an empty textureset file NEWMAP_TEXTURESETLOADPATH = "textureset\metin2_a1.txt" ; create a default textureset as "textureset/{mapname}.txt" ; note: this option is not considered if NEWMAP_TEXTURESETLOADPATH is not empty. [before v24] ; note: this option is not considered if the TextureSet path input is not empty when creating a new map [since v24] NEWMAP_TEXTURESETSAVEASMAPNAME = 1 ; remove the weird attr flags from the generated server_attr SERVERATTR_REMOVE_WEIRD_FLAGS = 1 ; show diffuse lighting to object VIEW_OBJECT_LIGHTING = 1 ; path of mob_proto used for regen MOB_PROTO_PATH = "locale/ymir/mob_proto" ; select monster area info checkbox at startup VIEW_MONSTER_AREA_INFO = 0 ; brush cursor / object selection color RGB float between 0.0 to 1.0 (default: green -> 0 1 0) RENDER_CURSOR_COLOR_R = 0.0 RENDER_CURSOR_COLOR_G = 1.0 RENDER_CURSOR_COLOR_B = 0.0 Download: [Hidden Content] How To Map: This release will not cover this part. Look at CryPrime`s tutorials to understand how to do it. About the ServerAttr Generator: (since v14) This is a beta function but it should work fine. I tested it on gm_guild_build (1x1), metin2_map_a1 (4x5), metin2_map_trent (2x2), metin2_n_snowm_01 (6x6) and the result was the same as the blackyuko map editor. (I use a different lzo version and I clean deprecated and useless flags, so the size is different from this last one but the "final image" will be the same; using game_test to fix his server_attr will let mine and his perfectly equal byte per byte) I also give you the source code of my server_attr generator function. CLICK A server_attr file is based on all the attr.atr files merged into a one raw RGBA image and each one scaled from 256x256 to 512x512. After that, the image will be splitted into sectors of 128x128 px and each one compressed using lzo compression. The server_attr header is composed by the size of the map*4. (e.g. a 4x4 will have a 16x16 size with 256 sectors inside) (gj ymir CLICK) An uncompressed server_attr sector is just like this: CLICK (the sub 4 byte header is the size returned by the LzoCompress which indicates how much the compressed sector data are large) Each attr.atr is just like this: CLICK (the header is composed of 6 byte in total: 3 WORDs respectively for version, width and height; they are always 2634, 1, 1 so don't bother about it) A single attr.atr scaled from 256x256 to 512x512 will be just like this: CLICK You can use the game_test (from source) to perform few tasks like: Create a server_attr from a .mcd file (I won't suggest it) a <collision data filename> <map directory> Regenerate an old server_attr to server_attr.new using the current lzo compression and cleaning useless flag CLICK c <filename> Other stuff such as b to create a character instance or q to quit About the SkyBox Bottom pic fix: (since v21) Both metin2launch.exe and worldeditor.exe should be edited to see the bottom pic of the skybox. Ymir messed up the code wrongly flipping the bottom image. Open ./Srcs/Client/EterLib/SkyBox.cpp and replace: ////// Face 5: BOTTOM v3QuadPoints[0] = D3DXVECTOR3(1.0f, -1.0f, -1.0f); v3QuadPoints[1] = D3DXVECTOR3(1.0f, 1.0f, -1.0f); v3QuadPoints[2] = D3DXVECTOR3(-1.0f, -1.0f, -1.0f); v3QuadPoints[3] = D3DXVECTOR3(-1.0f, 1.0f, -1.0f); with: ////// Face 5: BOTTOM v3QuadPoints[0] = D3DXVECTOR3(1.0f, 1.0f, -1.0f); v3QuadPoints[1] = D3DXVECTOR3(1.0f, -1.0f, -1.0f); v3QuadPoints[2] = D3DXVECTOR3(-1.0f, 1.0f, -1.0f); v3QuadPoints[3] = D3DXVECTOR3(-1.0f, -1.0f, -1.0f); then recompile. Credits:
    1 point
  3. M2 Download Center Download Here ( Internal ) Here ( Required ) Hi everyone. The time has come, and sorry for this late. What is this? Check the base version on this video: Necessary functions: It doesn't hurt to know: Need a bit of knowledge of programming, especially for implementing the python parts. You need to see the whole python core of metin2 how it works to understand what, why and how. Regarding to 1. and 2. this release is not for beginners. It has been tested on test and a live server too, small problems what appeared has been fixed. MouseWheel is not included, but public on the internet. Special thank to @masodikbela for testing and @Tatsumaru for the gui elements(wider tab buttons). Download PS.: If I missed something out from the guide feel free to let me know.
    1 point
  4. M2 Download Center Download Here ( Internal ) Hey there, I have an Halloween gift for you all. i have been working for a few hours on official like element image on target window(See screenshots below). When you click on a mob if it is defined as elemental, it will open an element image in addition to the target window. Don't forget to hit the like button! (C) Metin2 guild wars - coded by [GA]Ruin - 27/10/2017 (I create custom metin2 systems in c++/python. if you want a custom system send me a pm and we can talk over skype). Let's begin! Server Side: Open service.h, add in the end: #define ELEMENT_TARGET Open char.cpp, search for else { p.dwVID = 0; p.bHPPercent = 0; } add below: #ifdef ELEMENT_TARGET const int ELEMENT_BASE = 11; DWORD curElementBase = ELEMENT_BASE; DWORD raceFlag; if (m_pkChrTarget && m_pkChrTarget->IsMonster() && (raceFlag = m_pkChrTarget->GetMobTable().dwRaceFlag) >= RACE_FLAG_ATT_ELEC) { for (int i = RACE_FLAG_ATT_ELEC; i <= RACE_FLAG_ATT_DARK; i *= 2) { curElementBase++; int diff = raceFlag - i; if (abs(diff) <= 1024) break; } p.bElement = curElementBase - ELEMENT_BASE; } else { p.bElement = 0; } #endif open packet.h, search for: } TPacketGCTarget; add above: #ifdef ELEMENT_TARGET BYTE bElement; #endif Client side: open locale_inc.h, add in the end: #define ELEMENT_TARGET open packet.h, search for } TPacketGCTarget; add above: #ifdef ELEMENT_TARGET BYTE bElement; #endif open PythonNetworkPhaseGame.cpp, look for: else if (pInstPlayer->CanViewTargetHP(*pInstTarget)) replace below with the following: #ifdef ELEMENT_TARGET PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "SetHPTargetBoard", Py_BuildValue("(iii)", TargetPacket.dwVID, TargetPacket.bHPPercent, TargetPacket.bElement)); #else PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "SetHPTargetBoard", Py_BuildValue("(ii)", TargetPacket.dwVID, TargetPacket.bHPPercent)); #endif open PythonApplicationModule.cpp, look for #ifdef ENABLE_ENERGY_SYSTEM add above: #ifdef ELEMENT_TARGET PyModule_AddIntConstant(poModule, "ENABLE_VIEW_ELEMENT", 1); #else PyModule_AddIntConstant(poModule, "ENABLE_VIEW_ELEMENT", 0); #endif open game.py, look for def SetHPTargetBoard(self, vid, hpPercentage): if vid != self.targetBoard.GetTargetVID(): self.targetBoard.ResetTargetBoard() self.targetBoard.SetEnemyVID(vid) self.targetBoard.SetHP(hpPercentage) self.targetBoard.Show() replace with: if app.ENABLE_VIEW_ELEMENT: def SetHPTargetBoard(self, vid, hpPercentage,bElement): if vid != self.targetBoard.GetTargetVID(): self.targetBoard.ResetTargetBoard() self.targetBoard.SetEnemyVID(vid) self.targetBoard.SetHP(hpPercentage) self.targetBoard.SetElementImage(bElement) self.targetBoard.Show() else: def SetHPTargetBoard(self, vid, hpPercentage): if vid != self.targetBoard.GetTargetVID(): self.targetBoard.ResetTargetBoard() self.targetBoard.SetEnemyVID(vid) self.targetBoard.SetHP(hpPercentage) self.targetBoard.Show() open uitarget.py, look for import background add below: if app.ENABLE_VIEW_ELEMENT: ELEMENT_IMAGE_DIC = {1: "elect", 2: "fire", 3: "ice", 4: "wind", 5: "earth", 6 : "dark"} look for: self.isShowButton = False add below: if app.ENABLE_VIEW_ELEMENT: self.elementImage = None inside Destroy method, look for: self.__Initialize() add below: if app.ENABLE_VIEW_ELEMENT: self.elementImage = None inside ResetTargetBoard method, look for: self.hpGauge.Hide() add below: if app.ENABLE_VIEW_ELEMENT and self.elementImage: self.elementImage = None look for : def SetElementImage(self,elementId): add above: if app.ENABLE_VIEW_ELEMENT: def SetElementImage(self,elementId): try: if elementId > 0 and elementId in ELEMENT_IMAGE_DIC.keys(): self.elementImage = ui.ImageBox() self.elementImage.SetParent(self.name) self.elementImage.SetPosition(-60,-12) self.elementImage.LoadImage("d:/ymir work/ui/game/12zi/element/%s.sub" % (ELEMENT_IMAGE_DIC[elementId])) self.elementImage.Show() except: pass Compile server, client source and root pack and that's it! Enjoy! Happy halloween!
    1 point
  5. I like the titlebar we have when compiling with vs2019, but makes the client to have a bigger height. In PythonSystem.cpp search for if (m_Config.height >= screen_height) And update with if (m_Config.height >= screen_height) { int config_height = m_Config.height; int difference = (config_height-screen_height)+7; m_Config.height = config_height - difference; } Without fix: With fix:
    1 point
  6. M2 Download Center Download Here ( Internal ) Hi there. While cleaning out "my closet", I found this thing I developed between 2014-2015 - maybe(?) - for my, at that moment, server. Since it's now closed, and I won't use it, I'm sharing it with you guys. Note: Didn't do the scrollbar, wasn't needed for me, so yeah. Now, let's start with opening your locale_game.txt and adding these lines: QUESTCATEGORY_0 Main Quests QUESTCATEGORY_1 Sub Quests QUESTCATEGORY_2 Collect Quests QUESTCATEGORY_3 Levelup Quests QUESTCATEGORY_4 Scroll Quests QUESTCATEGORY_5 System Quests Alright, now find your characterwindow.py (uiscript?) and you can either comment Quest_Page children or simply remove them all. Moving on to your interfaceModule.py find this line self.BINARY_RecvQuest(index, name, "file", localeInfo.GetLetterImageName()) and replace it with self.wndCharacter.questCategory.RecvQuest(self.BINARY_RecvQuest, index, name) Ok, then we are at the most, let's say, difficult part of this. Open your uiCharacter.py and just as you did in your characterwindow.py, remove or simply comment any single line related to quests. You can just search for these vars: self.questShowingStartIndex self.questScrollBar self.questSlot self.questNameList self.questLastTimeList self.questLastCountList Once you did that, you just: # Find these lines self.soloEmotionSlot = self.GetChild("SoloEmotionSlot") self.dualEmotionSlot = self.GetChild("DualEmotionSlot") self.__SetEmotionSlot() # And add the following import uiQuestCategory self.questCategory = uiQuestCategory.QuestCategoryWindow(self.pageDict["QUEST"]) # Find this def OnUpdate(self): self.__UpdateQuestClock() # Replace it with def OnUpdate(self): self.questCategory.OnUpdate() And we're done with the client-side. I attached some extra elements needed (such as the main python file (uiQuestCategory.py) and some image resources). Remember to edit the path linked to these images in that file. For the server-side... Well, screw it, uploaded it too. Too lazy to write. It has only a new quest function (q.getcurrentquestname()) and a few things to add in your questlib.lua. Btw, not sure if you have it, but if not, just add this extra function in ui.Button() (ui.py - class Button). def SetTextAlignLeft(self, text, height = 4): if not self.ButtonText: textLine = TextLine() textLine.SetParent(self) textLine.SetPosition(27, self.GetHeight()/2) textLine.SetVerticalAlignCenter() textLine.SetHorizontalAlignLeft() textLine.Show() self.ButtonText = textLine #Äù½ºÆ® ¸®½ºÆ® UI¿¡ ¸ÂÃç À§Ä¡ ÀâÀ½ self.ButtonText.SetText(text) self.ButtonText.SetPosition(27, self.GetHeight()/2) self.ButtonText.SetVerticalAlignCenter() self.ButtonText.SetHorizontalAlignLeft() Forgot the source part, fml, here it is. Add it to your questlua_quest.cpp. int quest_get_current_quest_name(lua_State* L) { CQuestManager& q = CQuestManager::instance(); PC* pPC = q.GetCurrentPC(); lua_pushstring(L, pPC->GetCurrentQuestName().c_str()); return 1; } void RegisterQuestFunctionTable() { luaL_reg quest_functions[] = { { "getcurrentquestname", quest_get_current_quest_name}, { NULL, NULL } }; CQuestManager::instance().AddLuaFunctionTable("q", quest_functions); } Now, finally, have fun and bye!
    1 point
  7. M2 Download Center Download Here ( Internal )
    1 point
  8. They actually do since they just copy paste from tutorial. I saw several P server what came to this glitch. The quest what contains this is official and from gayF, when they introduced cheque they had this bug too for a couple days
    1 point
  9. I think nowadays nobody does things like that in lua.
    1 point
  10. same error, can someone help us?
    1 point
  11. No, I saved it as "get_skill_group.lua". I also already saved as ".quest". Nothing changed. Update: When I recompiled using the quest "ANSI", my problem is solved. But I can not use Turkish characters.
    0 points
×
×
  • 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.