-
Posts
72 -
Joined
-
Last visited
-
Feedback
0%
About LethalArms

Informations
-
Gender
Male
-
Country
Portugal
-
Nationality
Portuguese
Development
Recent Profile Visitors
1658 profile views
LethalArms's Achievements
-
Hi, i'm not as expert as those we have wrote on the topic such as @ Gurgarath@ Distraught@ Takuma but i would like to share my experience, by far the cleanest way i have found to have a better work flow is actually using Linux, more specifically using KDE, the distro itself i've tested ubuntu based, fedora and arch based and its pretty much the same for this example. Dolphin (kde file explorer) can access directly the VM folders using ssh (like winscp), so its like any other folder on your system without extra tools About putty, in windows you can also do this, use the terminal instead, it has ssh by default and you can create a shortcut on the desktop to just run the command line. As for executing the client, wine for me has been actually very simple, i just open cmd and type wine metin2client.exe and works, and you can even create a shortcut for it. And etermanager also works under wine (but UI is a bit messy) and packmakerlite works too and i believe with some configuration it can even be put on the context menu (right click) like on windows The only problem when running on Linux is that you need a Windows VM to compile src, but you can also share folders between VM and host and trigger building via CMD with ssh without needing to even opening windows GUI (you can even consider using windows server no gui but its harder to install things) I only still have windows on my 2 pc's cuz some games dont work on linux and my laptop is very slow to have a windows vm active and already have it all setup and optimized Oh and you can also test other editors such as Zed, i find VSCode/VSCodium to be very slow, specially on my laptop, while notepad++ (windows) or zed (linux) are way smoother And on Linux you can use KVM which is a faster virtualization option (faster than vmware and virtualbox) like Hyper-V on Windows
-
So, one of the most common problems i've seen in metin2 development, is people using text editors without configuring them for the euc-kr encoding which causes translation issues when editing server side files and also when programming its easier to check for a english text than some korean string, so i created a simple python script that takes the translated strings from server side locale_string and changes every korean string to their english translation while also changing the file encoding from euc-kr to utf-8, it will also create a new locale string file. This is a small script and i think there's no need for a tutorial, but always take backups as safety measure import re import sys import os mainPath = 'path\\to\\server\\source' textFound = [] rawStrings = [] rawStringsPT = [] translations = [] translationsPT = [] blacklistFiles = [ 'empire_text_convert.cpp' ] def openFile(file_path): pattern = r'LC_TEXT.*?"(.*?)"' print("Opening file: %s" % file_path) with open(file_path, 'r', encoding="latin-1") as file: for line in file: match = re.search(pattern, line) if match: if not match.group(1) in textFound: textFound.append(match.group(1)) def saveFoundedTexts(): with open('textFound.txt', 'w', encoding="latin-1") as f: for i in textFound: f.write(i) f.write("\n") def loadLocaleStringEN(): pattern = r'"(.*?)"' with open('locale_string_en.txt', 'r', encoding='latin-1') as file: lines = file.readlines() raw_line = None for line_number, line in enumerate(lines): line = line.strip() if not line: continue match = re.search(pattern, line) if match: extracted_text = match.group(1) if raw_line is None: raw_line = extracted_text else: rawStrings.append(raw_line) translations.append(extracted_text) raw_line = None def updateLocale(file): raw_to_translations_map = dict(zip(rawStrings, translations)) updated_lines = [] new_file = "new_" + str(file) with open(file, 'r', encoding='latin-1') as file: lines = file.readlines() for line in lines: line = line.strip() if not line: updated_lines.append(line) continue match = re.search(r'"(.*?)"', line) if match: raw_string = match.group(1) if raw_string in raw_to_translations_map: updated_line = line.replace(f'"{raw_string}"', f'"{raw_to_translations_map[raw_string]}"') updated_lines.append(updated_line) else: updated_lines.append(line) else: updated_lines.append(line) with open(new_file, 'w', encoding='latin-1') as file: file.write('\n'.join(updated_lines)) def replaceTexts(file_path): pattern = r'LC_TEXT.*?"(.*?)"' print("Replacing text in file: %s" % file_path) with open(file_path, 'r', encoding="latin-1") as file: content = file.read() for raw, translated in zip(rawStrings, translations): content = re.sub( f'LC_TEXT.*?"{re.escape(raw)}"', f'LC_TEXT("{translated}"', content ) with open(file_path, 'w', encoding="utf-8") as file: file.write(content) def scan(path, replace=False): for root, dirs, files in os.walk(path): for file in files: if file.endswith('.cpp'): path = os.path.join(root, file) if not file in blacklistFiles: if replace: replaceTexts(path) else: openFile(path) def main(): loadLocaleStringEN() updateLocale('locale_string_en.txt') # updateLocale('locale_string_pt.txt') scan(mainPath) scan(mainPath, True) saveFoundedTexts() if __name__ == '__main__': main()
-
Multiple Login Saver System With Account Slots
LethalArms replied to LethalArms's topic in Features & Metin2 Systems
By bad, the introwindow file is for the interface i had at the time, the correct file is LoginWindow which normally is located on locale/yourlanguage/ui Take in mind that my code of introwindow was set up for my interface, you will need to change the images path and positions to work with your interface but its not hard to do -
This is basically a system to complement my other system. With this you one can have a custom tag name behind the name/karma of the character As you can see on this picture Behind the character name and karma there's a red tag, this is achieved using this system. I didn't make it show the level by my personal choice but you can easily add it. I remember seeing another post on this forum about this, but i cant find it anymore not sure why, so i'm posting my own version. InstanceBaseEffect.cpp Search for CInstanceBase::UpdateTextTailLevel Below sprintf(szText, "Lv %d", level); And before CPythonTextTail::Instance().AttachLevel(GetVirtualID(), szText, s_kLevelColor); Add this if (IsGameMaster()) { const char* name = GetNameString(); size_t len = strcspn(name, "]"); char *result = (char *)malloc((len + 1) * sizeof(char)); // Not sure why on client side needs to be like this strncpy(result, name, len +1); result[len + 1] = '\0'; const char *tagDictionary[] = { "[GM]", "[SA]", "[GA]", "[DEV]" }; //Here you can also change the color of the tag const char *nameDictionary[] = { "|cffff0000[STAFF]", "|cffff0000[EQUIPA]", "|cffff0000[STAFF2]", "|cffff0000[DEVELOPER]" }; int tagIndex = -1; for (int i = 0; i < sizeof(tagDictionary) / sizeof(tagDictionary[0]); ++i) { if (strcmp(result, tagDictionary[i]) == 0) { tagIndex = i; break; } } if (tagIndex != -1){ sprintf(szText, nameDictionary[tagIndex]); } else{ // This is just for if the code cant find any tag, it will default to this one. // You can also just delete this whole else statement and it will default to the level text sprintf(szText, "|cffff0000[TEST]"); } free(result); CPythonTextTail::Instance().AttachLevel(GetVirtualID(), szText, s_kLevelColor); } And thats all xD
-
- 6
-
-
-
-
Different InGame GM Effects Based on GM Name
LethalArms replied to LethalArms's topic in Features & Metin2 Systems
EDIT: I found a better way to search for the tag On char.cpp Instead of #ifdef ENABLE_CUSTOM_TAG_EFFECTS const char* name = GetName(); char result[5]; strncpy(result, name, 4); result[4] = '\0'; Make it like this #ifdef ENABLE_CUSTOM_TAG_EFFECTS const char* name = GetName(); size_t len = strcspn(name, "]"); char result[len+1]; strncpy(result, name, len +1); result[len + 1] = '\0'; This way you can have any tag size without having to do any modification on the code, and for what i saw on my tests, if i increased from 4 chars to 5 it will have problems, this way there is no problem at all!!! -
So ashika posted this a few days ago And since i couldnt find a way to show all of them ingame depending on the GM "class" i decided to make my own, its not that hard tbh, and i think it doesnt fck anything but if u find problems let me know. Here's the result First of all, the way the system works is by the GM name, so if it has [SA] or [GM] in name it will apply the effect for it. Server Side service.h #define ENABLE_CUSTOM_TAG_EFFECTS affect.h in enum EAffectBits search for the last enum (in my case is AFF_BITS_MAX) and before it add #ifdef ENABLE_CUSTOM_TAG_EFFECTS AFF_GA, AFF_GM, AFF_SA, #endif on char.cpp Search for m_afAffectFlag.Set(AFF_YMIR); And replace it with this #ifdef ENABLE_CUSTOM_TAG_EFFECTS const char* name = GetName(); // This will only search for the first 4 characters if u want more for tags such as [DEV] you will need to increase this values char result[5]; strncpy(result, name, 4); result[4] = '\0'; // This is where you change the tag const char *tagDictionary[] = { "[GM]", "[SA]", "[GA]" }; // This is where you change the effect name to what you put on affect.h const EAffectBits nameDictionary[] = { AFF_GM, AFF_SA, AFF_GA }; int tagIndex = -1; for (int i = 0; i < sizeof(tagDictionary) / sizeof(tagDictionary[0]); ++i) { if (strcmp(result, tagDictionary[i]) == 0) { tagIndex = i; break; } } if (tagIndex != -1) { m_afAffectFlag.Set(nameDictionary[tagIndex]); } else{ m_afAffectFlag.Set(AFF_YMIR); } #endif On client side locale_inc.h #define ENABLE_CUSTOM_TAG_EFFECTS InstanceBaseEffect.cpp On CInstanceBase::__SetAffect( Search case AFFECT_YMIR: Add below #ifdef ENABLE_CUSTOM_TAG_EFFECTS case AFFECT_GA: case AFFECT_GM: case AFFECT_SA: #endif InstanceBase.h Search for AFFECT_NUM Add before #ifdef ENABLE_CUSTOM_TAG_EFFECTS AFFECT_GA, // 50 AFFECT_GM, // 51 AFFECT_SA, // 52 #endif InstanceBase.cpp On CInstanceBase::IsGameMaster() Add before return false #ifdef ENABLE_CUSTOM_TAG_EFFECTS if (m_kAffectFlagContainer.IsSet(AFFECT_GA)) return true; if (m_kAffectFlagContainer.IsSet(AFFECT_GM)) return true; if (m_kAffectFlagContainer.IsSet(AFFECT_SA)) return true; #endif PythonCharacterModule.cpp Add next to the others #ifdef ENABLE_CUSTOM_TAG_EFFECTS PyModule_AddIntConstant(poModule, "AFFECT_GA", CInstanceBase::AFFECT_GA); PyModule_AddIntConstant(poModule, "AFFECT_GM", CInstanceBase::AFFECT_GM); PyModule_AddIntConstant(poModule, "AFFECT_SA", CInstanceBase::AFFECT_SA); #endif This file is for the Faster Loading System found here on the forum, if u dont have it, you will need to add the effect on client/root/playersettingsmodule.py, i wont provide a code for cuz i dont really have a way to test it, but shouldn't be that hard PythonPlayerSettingsModule.cpp Find {pkBase.EFFECT_REFINED + 1 Before add #ifdef ENABLE_CUSTOM_TAG_EFFECTS {pkBase.EFFECT_AFFECT + CInstanceBase::AFFECT_GA, "Bip01", "d:/ymir work/effect/team_ranks/ga.mse"}, {pkBase.EFFECT_AFFECT + CInstanceBase::AFFECT_GM, "Bip01", "d:/ymir work/effect/team_ranks/gm.mse"}, {pkBase.EFFECT_AFFECT + CInstanceBase::AFFECT_SA, "Bip01", "d:/ymir work/effect/team_ranks/sa.mse"}, #endif Lastly, on client you will need to add ashika files where you want (in my case i added to etc/ymir work/effect/team_ranks/ and duplicate the gm.mse file (in this case 2 times), change the name to ga.mse and sa.mse, then will open them and at the end of the file there is going to be this line List TextureFiles { "gamemaster.tga" } change them acording to the effect you want, on this case, for GA is gameadmin.tga, for GM is gamemaster.tga and for SA is serveradmin.tga. And thats all, hope you all like it!
-
Download If anyone wants to have this system with Lykan here are the files, i've changed them to work with lykan, it took me a lot of time but it works! Just replace, compile, and it should all work normally.
- 63 replies
-
- 30
-
-
-
-
Metin2 Server with RadminVPN
LethalArms replied to LethalArms's topic in Community Support - Questions & Answers
On tmp4 files go to each core config and change BIND_IP and PROXY_IP to the RadminVPN IP , i think its but i'm not sure, do that, start the server and it should work -
Multiple Login Saver System With Account Slots
LethalArms replied to LethalArms's topic in Features & Metin2 Systems
Fixed, glad to know it works, gonna add it on the original post thanks! Also, you can easily make it show F1 - accountid, F2-accountid on the button like some servers have on def LoadAccounts(): Find self.loginAcc0.SetText(ind[1]) Replace with self.loginAcc0.SetText('F1 - ' + ind[1]) Find self.loginAcc1.SetText(ind[1]) Replace with self.loginAcc1.SetText('F2 - ' + ind[1]) -
Multiple Login Saver System With Account Slots
LethalArms replied to LethalArms's topic in Features & Metin2 Systems
Yes and i think it can be done in a easier way than that, making use of the functions loginAccount, i'm currently trying to implement the Sash System on my server but as soon as i'm done with it, i will do that But this code might work, i didnt test it, but give it a try and let me know! -
Hi, i made some changes on this system so that it now can show multiple accounts slots and add/delete accounts easily I'm not an experienced programmer by any means, so bugs might happen and the code isn't the most efficient and clean, so if anyone has a suggestion let me know! [Hidden Content] First i recommend installing his system first because i will only be listing the changes i made and this wont work without his system installed first Also, i will only show the steps to have 2 slots account, but they can easily be replicated to have multiple accounts. Implemented and Tested on TMP4 Server Files but most likely will work on any other server files. Be extremely careful with tabulations, i would recommend using Visual Studio Code or something similar to avoid problems with it Small video: Icons used for save and delete account button (it doesn't have on hover and on click icons so you will have to add them yourself) Download -> Mediafire or M2DL So lets start First delete the root/uiSelectCredentials.py and uiscript/accountlistwindow files that wont be needed anymore root/introwindow.py (This is configured for my own interface so you will have to change positions according to yours) root/intrologin.py (Remember you need to have the system from North implemented or you wont be able to find the correct lines) I think i'm not missing anything but if you find any error let me know and i will update the post. Probably gonna try to do some changes on the code to make it easier to add more accounts, currently it's not that hard but can be better. Feel free to leave suggestions and help improve this!
-
The weapons models and textures are missing, do u have the download for them?
-
If it gives this error to someone: While compiling the server source go to src/common/item_lenght.h Search for enum EMaterialSubTypes and add at the end of the function this "MATERIAL_DS_CHANGE_ATTR,"
-
Not sure if it's a error or not (since i've found the same problem with other similar tools) but while exporting sura model, the bones of 2 of the fingers in the left hand always export bigger than the other fingers The only way i found to kinda fix this was using grnreader or noesis and exporting to smd (if it was exported to fbx the problem also occurs)
-
New Exchange Window Yang BUG
LethalArms replied to LethalArms's topic in Community Support - Questions & Answers
PROBLEM FIXED the OnPickMoney function on uiExchange.py was wrong instead of: def OnPickMoney(self, money): net.SendExchangeElkAddPacket(str(money)) it needs to be like this def OnPickMoney(self, money): net.SendExchangeElkAddPacket(money) and it works perfectly :v
