Jump to content

Search the Community

Showing results for tags 'python' in content posted in Programming & Scripts / Systems.



More search options

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Forums

  • Community
    • M2Dev
    • Offtopic
    • Games Talk
    • Music / Videos / Art
    • Member Representations
    • Services & Sales
  • Metin2
    • General
    • Questions and Answers
    • Frequently Asked Questions
    • Private Servers
    • Videos
  • Suggest a Tutorial / Release
    • Suggest a Tutorial / Release
    • Temporary forum
  • Releases
    • General
    • Guides & HowTo
    • Tools
    • Programming & Scripts / Systems
    • Maps
    • Quests
    • Binaries & Clients / ServerFiles
    • 3D Models
    • 2D Graphics
    • Operating Systems

Categories

There are no results to display.

There are no results to display.


Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


Nationality


Skype


Discord


Website


Steam ID


Mapping


3D


2D


C++


LUA


Python


PHP


SQL


HTML


CSS


JavaScript


Empire

Found 65 results

  1. Hey everyone, it's a nice day to share something I just wrote Grid class in python language. You can use it as fast moving into the window with this or something else. Usage: from grid import Grid import item import chat grid = Grid(width=5, height=9) item.SelectItem(11299) (width, height) = item.GetItemSize() available_position = grid.find_blank(width, height) if available_position == -1: chat.AppendChat(chat.CHAT_TYPE_INFO, "There is no available position.") return chat.AppendChat(chat.CHAT_TYPE_INFO, "Available position is %d" % (available_position)) Best Regards Ken
  2. Hellow, I want to share my work, I've created 2 year ago, for my old server (Resthea). So, what is it exacly? It's python libraries and code that allow us to have many environment (clouds, light settings, flare and so on) on one map. By default, you can have only one environment for each map. How does it work? Well, once every 30 seconds (you can configure that time) checks our coordinates and compare it to jpg file, which size is the same as map size. Diffrent colors mean diffrent msenv file. What this pack contains? possibility to add up to 16777215 areas with diffrent environment on every map. possibility to add diffrent music on these areas possibility to add random snow on these areas 28 ready skyboxes possibility to choose skyboxes quality possibility to configure the time script refreshes possibility to add special xmas configuration easy configuration via text file code is easy to modify bugfix for night and snow systems Disadvantages: not so optimal solution .jpg format has indirect coloring between two colors, which sometimes could lead to problems xmas song probably doesn't work (I haven't got time to fix it) lots of redundant libraries, because i've uploaded whole Lib folder descriptions how to add this are in polish, you can use google translate , if you wish i can translate it too. Screens: Code sample: def __SpecialEnvironmentEnable(self, Env, Resthea, SnowEnable, NightEnable, ConfigTime, ConfigSkybox, XmasEvent): ### START OF ENVIRONMENT MODULE Resthea.eu, qentinios self.Env = Env self.Resthea = Resthea self.SnowEnable = SnowEnable self.NightEnable = NightEnable self.ConfigTime = ConfigTime self.ConfigSkybox = ConfigSkybox self.XmasEvent = XmasEvent czass = str(time.ctime()) sekundy = czass[17:19] bg = background.GetCurrentMapName() if ConfigTime == 0: try: ConfigTime = int(linecache.getline("config.cfg", 2)) except: chat.AppendChat(chat.CHAT_TYPE_INFO, "Error while changing environment") chat.AppendChat(chat.CHAT_TYPE_INFO, "Cannot open file: config.cfg") if ConfigTime == -1: return map = ( "metin2_map_4_wiatry", "metin2_map_krance_swiata", "metin2_map_srodziemie", "metin2_map_resthea", ) if bg in map and sekundy != Env: if ConfigTime == 5 and int(sekundy) in (5,10,15,20,25,30,35,40,45,50,55,00): self.Env = sekundy pass elif ConfigTime == 15 and int(sekundy) in (15,30,45,00): self.Env = sekundy pass elif ConfigTime == 30 and int(sekundy) in (30,00): self.Env = sekundy pass elif ConfigTime == 60 and int(sekundy) == 30: pass else: if ConfigTime not in (-1,5,15,30,60) and int(sekundy) == 30: chat.AppendChat(chat.CHAT_TYPE_INFO, "Error while changing environment") chat.AppendChat(chat.CHAT_TYPE_INFO, "Wrong data: " + ConfigTime + ", config.cfg, line 2") self.Env = sekundy return else: return minuty = czass[14:16] godziny = czass[11:13] czas = int(godziny + minuty) try: im = Image.open("msenv/" + bg + ".jpg") except: chat.AppendChat(chat.CHAT_TYPE_INFO, "Error while changing environment") chat.AppendChat(chat.CHAT_TYPE_INFO, "Cannot open file: " + "msenv/" + bg + ".jpg") return (x, y, z) = player.GetMainCharacterPosition() x = int(x/100) y = int(y/100) try: color = str(im.getpixel((int(x),int(y)))) except: chat.AppendChat(chat.CHAT_TYPE_INFO, "Error while changing environment") chat.AppendChat(chat.CHAT_TYPE_INFO, "Not exist pixel: " + str(x) + ", " + str(y) + "; " + "msenv/" + bg + ".jpg") return #Skybox config if ConfigSkybox == "0": try: ConfigSkybox = linecache.getline("config.cfg", 5) except: ConfigSkybox = "_1k" if ConfigSkybox in ("_512n","_1kn","_1.5kn"): ConfigSkybox = ConfigSkybox[:-1] if ConfigSkybox not in ("_512","_1k","_1.5k"): ConfigSkybox = "_1k" #End of skybox config #Xmas event if XmasEvent == -1: try: XmasEvent = int(linecache.getline("config.cfg", 8)) except: XmasEvent = 0 if XmasEvent == 1: ColorList={ #Color (RGB) 1 : ("(255, 255, 255)", "(241, 255, 158)", "(254, 0, 0)", "(0, 255, 127)", "(158, 255, 248)", "(253, 254, 62)", "(255, 176, 63)", "(222, 255, 0)", "(95, 255, 0)", "(50, 121, 19)", "(95, 192, 35)", "(214, 214, 214)", "(148, 0, 0)", "(142, 142, 142)", "(251, 165, 0)"), #Msenv 2 : ("snowm02", "map_n_desert_01", "fire_low", "white_sky", "default", "rainy", "sand_mountain", "vanilia_white", "trent", "trent02", "vanilia", "snowm02", "fire_low", "default", "desert_cloud"), #Mp3 3 : ("christmas/4w/xmas", "christmas/4w/xmas", "christmas/4w/xmas", "christmas/4w/xmas", "christmas/4w/xmas", "christmas/krance/xmas", "christmas/krance/xmas", "christmas/krance/xmas", "christmas/krance/xmas", "christmas/krance/xmas", "christmas/srodziemie/xmas", "christmas/srodziemie/xmas", "christmas/srodziemie/xmas", "christmas/resthea/xmas", "christmas/resthea/xmas_wyspa"), #Snow 4 : (1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1) } #End of Xmas event else: ColorList={ #Color (RGB) 1 : ("(255, 255, 255)", "(241, 255, 158)", "(254, 0, 0)", "(0, 255, 127)", "(158, 255, 248)", "(253, 254, 62)", "(255, 176, 63)", "(222, 255, 0)", "(95, 255, 0)", "(50, 121, 19)", "(95, 192, 35)", "(214, 214, 214)", "(148, 0, 0)", "(142, 142, 142)", "(251, 165, 0)"), #Msenv 2 : ("snowm02", "map_n_desert_01", "fire_low", "white_sky", "default", "rainy", "sand_mountain", "vanilia_white", "trent", "trent02", "vanilia", "snowm02", "fire_low", "default", "desert_cloud"), #Mp3 3 : ("4w/lodowa", "4w/pustynia", "4w/ognista", "4w/orki", "4w/srodek", "krance/przeklete", "krance/pustynia", "krance/swiatynia", "krance/las", "krance/las2", "srodziemie/trawa", "srodziemie/lodowa", "srodziemie/ognista", "resthea/trawa", "resthea/wyspa"), #Snow 4 : (1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0) } i = 0 Colors = ColorList[1] length = len(Colors) for ColorItem in xrange(length): if color == Colors[ColorItem]: #START OF SNOW EFFECT Snow = ColorList[4] if SnowEnable != 1: if Snow[ColorItem] == 1 and int(minuty) in (2,7,12,17,22,27,32,37,42,47,52,57) and int(sekundy) in (00,01,30,31): random = app.GetRandom(1,3) if random == 1: background.EnableSnow(1) else: background.EnableSnow(0) if Snow[ColorItem] == 0: background.EnableSnow(0) #END OF SNOW EFFECT if Resthea == color: break #START OF MUSIC MODULE Music = ColorList[3] if app.IsExistFile("BGM/" + Music[ColorItem] + ".mp3")==1: if musicInfo.fieldMusic != "": snd.FadeOutMusic("BGM/" + musicInfo.fieldMusic) musicInfo.fieldMusic = (Music[ColorItem] + ".mp3") snd.FadeInMusic("BGM/" + musicInfo.fieldMusic) else: if musicInfo.fieldMusic != "": snd.FadeOutMusic("BGM/" + musicInfo.fieldMusic) musicInfo.fieldMusic=musicInfo.METIN2THEMA snd.FadeInMusic("BGM/" + musicInfo.fieldMusic) #END OF MUSIC MODULE Msenv = ColorList[2] if NightEnable == 1 and self.__IsXMasMap(): background.RegisterEnvironmentData(1, constInfo.ENVIRONMENT_NIGHT) background.SetEnvironmentData(1) else: background.RegisterEnvironmentData(1, "d:/ymir work/environment/" + Msenv[ColorItem] + ConfigSkybox + ".msenv") background.SetEnvironmentData(1) self.Resthea = color break else: i = i+1 if i == length: background.SetEnvironmentData(0) snd.FadeOutMusic("BGM/" + musicInfo.fieldMusic) musicInfo.fieldMusic=musicInfo.METIN2THEMA snd.FadeInMusic("BGM/" + musicInfo.fieldMusic) self.Resthea = color ### END OF ENVIRONMENT MODULE Resthea.eu, qentinios Old video with system: https://www.youtube.com/watch?v=sz1njy6sBqQ Download: Without skyboxes: https://www.mediafire.com/?edtdz50gc4tzmqj With skyboxes: https://www.mediafire.com/?y14v0yir24tqbvv
  3. Builtin Debug Formatter A simple debug class which is used for output the messages for debugging. The class doesn't need to be called, we've added the functions into built-in functions. The purpose was to ease the work of developers. What's the difference between them? Using the new method: TraceError("str", 1, 4.0, (31, 22), [100, 200], True) Tracef("str", 1, 4.0, (31, 22), [100, 200], True) LogBox("str", 1, 4.0, (31, 22), [100, 200], True) sys_err("str", 1, 4.0, (31, 22), [100, 200], True) # No import needed, is a built-in function, you can call it everywhere. # The function sys_err or TraceError doing the same thing. # Allow to pass unlimited argument-lines, no data types check, can be everything you want: <int, float, string, tuple, list, boolean>. Using the old method: import dbg dbg.TraceError("just_one_string_allowed") dbg.Tracef("just_one_string_allowed") dbg.LogBox("just_one_string_allowed") # Need to import the module dbg every time in every file where you want to use it. # Allow to pass just one argument-line which need to be string, otherwise nothing happen. Built-In-Functions: Built in or inbuilt function are that type of functions which are already defined or created in a program or in programming framework. User don’t need to create these type of functions. User or developer can directly use built in function by only call it. This function is built into an application and can it can be accessed by end-users with simply call it. How-It-Works: TraceError(args) - function prints the given arguments to the text stream file syserr.txt Tracef(args) - function prints the given arguments to the console window (screen) while executable is compiled in a debug mode. LogBox(args) - function prints the given arguments to the dialog box that contains a system icon, a set of buttons, and a brief application-specific message, such as status or error information. sys_err(args) - same as TraceError. How-To-Call-Ex : sys_err('warning', 'error', 'unknown') << 415 17:8:1130 :: warning << 415 17:8:1130 :: error << 415 17:8:1130 :: unknown sys_err(100/2==50, 'set value to {}'.format(25)) << 415 17:6:1083 :: True << 415 17:6:1083 :: set value to 25 sys_err([45, 100], (200, 1500, 32), 42.8, 500, "donald-trump", False) << 415 17:8:1094 :: [45, 100] << 415 17:8:1094 :: (200, 1500, 32) << 415 17:8:1094 :: 42.8 << 415 17:8:1094 :: 500 << 415 17:8:1094 :: donald-trump << 415 17:8:1094 :: False sys_err("what-you-want") << 415 17:8:1072 :: what-you-want GitHub repository: [hide] https://github.com/Vegas007/Metin2-Builtin-Debug-Formatter [/hide]
  4. Hello, today I will give you this login interface, which is very similar to WoM2. It's coded by me, good luck Original interface(WoM2): My interface: Photo1: Photo2: Download: 1. https://1drv.ms/u/s!AhOzstvwiFbCa_hZFTG57aD_mTU 2. https://www111.zippyshare.com/v/rIWjrge8/file.html btw: configuration in root/intrologin.py: SERVER_IP = "192.168.1.5" CH1_PORT = 21000 CH2_PORT = 22000 CH3_PORT = 23000 CH4_PORT = 24000 PORT_AUTH = 31009 NUME_SERVER = "Andy"
  5. Get bonus name from tooltip affect dictionary as string, ignore the %value% and function SA, SNA etc. Ignore the dump.txt & dump_test.py, is just to test how function works. Just follow tutorial from localeInfo.py. How-To-use import localeInfo import item # FormatBonusNameString print localeInfo.FormatBonusNameString(item.APPLY_RESIST_SWORD) # FormatBonusNameDict for bonusIndex, bonusName in localeInfo.FormatBonusNameDict().iteritems(): print '{:d}: {:s}'.format(bonusIndex, bonusName) GitHub repository: [hide] https://github.com/Vegas007/Metin2-Dump-Bonus-Name [/hide]
  6. There's just a smart python module which i did for fun, for a friend, no support for implementation. Enjoy. Github repository: [hide] https://github.com/Vegas007/Metin2-Events-Calendar-Test [/hide]
  7. Someone wondered if I could do this script for him, i don't know the reason (maybe 4 find and extract some things), enjoy. Full repository: [hide] https://github.com/Vegas007/Metin2-Unknown-Tool #! /usr/bin/env python ''' MIT License Copyright (c) 2018 VegaS LINK PREVIEW : http://i.epvpimg.com/2gvyeab.png http://i.epvpimg.com/i0XIdab.png http://i.epvpimg.com/hKK8cab.png Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ''' __author__ = "VegaS" __date__ = "2018-11-30" __consignee__ = '#Mithras' __version__ = "0.1.6" import os import sys import re import time import shutil import operator import string import functools from datetime import datetime as dt ''' How-To-use: cd ../main.py location_file_name.msm ''' class ReadMSM_SourceSkin: BACKUP_FOLDER_NAME = 'backup' OUTPUT_FILE_NAME = 'result.txt' PATTERN_STRING_WHITESPACE = string.whitespace[1] GROUP_MEMBER_MAX_NUM = 5 PATH_STRING_NAME = 'PathName' SOURCE_SKIN_STRING_NAME = 'SourceSkin' SPECIAL_PATH_STRING_NAME = 'SpecialPath' def __init__(self): self.outputList = [] # Contains the command-line arguments passed to the script. self.srcReadFileName = sys.argv[1] def __GetDateTime(self): return dt.now().strftime('%d-%m-%Y %H-%M-%S_{file_name}').format(file_name = self.srcReadFileName) # Return a string representing the date, controlled by an explicit format string. def __GetDirectoryName(self): return os.path.dirname('{:s}/{:s}/{:s}'.format(os.getcwd(), self.BACKUP_FOLDER_NAME, self.OUTPUT_FILE_NAME)) # Return the directory name of pathname path. def __FindStringByPattern(self, string, pattern='''(?<=")\s*[^']+?\s*(?=")'''): # A regular expression (or RE) specifies a set of strings that matches it; the functions in this module let you check if a particular string # matches a given regular expression (or if a given regular expression matches a particular string, which comes down to the same thing). strResult = re.search(pattern, string) if strResult: return strResult.group().strip().lower() return str() def __FindStringByLine(self, lines, string, pattern=r'(^|[^\w]){}([^\w]|$)', msmGroupDict={}): tokens = [] for index, value in enumerate(lines): value = functools.reduce(lambda k, v: k.replace(v, '\0'), self.PATTERN_STRING_WHITESPACE, value) # Recompile the lines and search by unique strings. if bool(re.search(re.compile(pattern.format(string), re.IGNORECASE), value)): if string is self.PATH_STRING_NAME: return value elif string is self.SOURCE_SKIN_STRING_NAME: strExceptLine = lines.__getitem__(operator.isub(index, self.GROUP_MEMBER_MAX_NUM - 2)).strip(self.PATTERN_STRING_WHITESPACE) tokens.append((value, strExceptLine if self.SPECIAL_PATH_STRING_NAME in strExceptLine else None)) return tuple(tokens) def __OnResult(self): textLineTuple = ( '[*] Filename: {:s}\n'.format(self.srcReadFileName), '[*] {:s} count: [{:d}]'.format(self.SOURCE_SKIN_STRING_NAME, len(self.outputList)) ) if self.outputList: if os.path.exists(self.OUTPUT_FILE_NAME): # Recursive directory creation function. Like mkdir(), but makes all intermediate-level directories needed to contain the leaf directory. if not os.path.exists(self.BACKUP_FOLDER_NAME): os.makedirs(self.BACKUP_FOLDER_NAME) # Recursively move a file or directory (src) to another location (dst). destFileName = '{:s}/{:s}'.format(self.__GetDirectoryName(), self.__GetDateTime()) shutil.move('{:s}/{:s}'.format(os.getcwd(), self.OUTPUT_FILE_NAME), destFileName) textLineTuple += tuple('\n[*] Generated a backup for old {:s} in {:s}.'.format(self.OUTPUT_FILE_NAME, destFileName)) with open(self.OUTPUT_FILE_NAME, 'a+') as fp: fp.write(self.PATTERN_STRING_WHITESPACE.join(self.outputList)) # Returns a string in which the string elements of sequence have been joined by str separator. print functools.reduce(lambda k, v: operator.iadd(k, v), textLineTuple) # Same as join method. def Initialize(self): try: lines = open(self.srcReadFileName, "r").readlines() except IOError: print ("Can't load file: {:s}".format(self.srcReadFileName)) return for sourceSkin, specialPath in self.__FindStringByLine(lines, self.SOURCE_SKIN_STRING_NAME): strPathName = self.__FindStringByPattern(self.__FindStringByLine(lines, self.PATH_STRING_NAME)) strSourceSkin = self.__FindStringByPattern(sourceSkin) if specialPath: strPathName = self.__FindStringByPattern(specialPath) self.outputList.append(operator.iadd(strPathName, strSourceSkin)) self.__OnResult() Instance = ReadMSM_SourceSkin() Instance.Initialize() [/hide]
  8. Hello, i maked a simple script for get initial lang... the proposite is automate the choice of the languaje (for servers internationals). Unknown if there will be something similar Source: import requests class CurrentPositionForLang: # Code langs __LANGS_AVAILABLES = ("ES", "EN", "FR", "TR",) # County with lang __COUNTRY_CODES_WITH_LANG = ( ("MX", __LANGS_AVAILABLES[0]), ("US", __LANGS_AVAILABLES[1]), ("FR", __LANGS_AVAILABLES[2]), ("ES", __LANGS_AVAILABLES[0]), ("TR", __LANGS_AVAILABLES[3]) ) @staticmethod def get_lang(): lang = "US" # Default lang for errors try: r = requests.get("http://ip-api.com/json/") if r.status_code != 200: return lang countryCode = r.json()["countryCode"] for country, langCountry in CurrentPositionForLang.__COUNTRY_CODES_WITH_LANG: if countryCode == country: return langCountry # If not finded return default return lang except requests.exceptions.ConnectionError: return lang For utilicy this class only call this method: CurrentPositionForLang.get_lang() this return only String "US, ES..." If you need add more langs, in this fields add the country and the code. __LANGS_AVAILABLES = ("ES", "EN", "FR", "TR",) # County with lang __COUNTRY_CODES_WITH_LANG = ( ("MX", __LANGS_AVAILABLES[0]), ("US", __LANGS_AVAILABLES[1]), ("FR", __LANGS_AVAILABLES[2]), ("ES", __LANGS_AVAILABLES[0]), ("TR", __LANGS_AVAILABLES[3]) ) This is the standar for code countrys: https://www.ncbi.nlm.nih.gov/books/NBK7249/ current_position.py
  9. Metin2 Web Page (Mt2Web.py) + Admin Panel + deploy with Docker. Today I bring this post the page that I have been working on, and use in my servers for production. This page is made in python and the code is available in github, this to be able to track and have a centralized way to get the update of it. In addition to this this page has a Dockerfile to deploy it and so people who have no knowledge in installing servers can make use of it easily. Features: paymentwall for donations. account activation email google captcha to give security to the forms password recovery by mail administration panel ORM to analyze the different types of databases. Top of players by crontab. -> Available from the dockerfile multi language, currently only has English and Spanish implemented Advantage: Easy installation, you just have to configure a file. Easy administration Page with security implemented Open Source, has an MIT license and because of this anyone can send improvements to the page through pull request on github It can be deployed in any unix operating system including FreeBSD thanks to the Dockerized page. Disadvantages If it is going to be mounted separately it requires a VPS of minimum 512 Megabytes of ram to be able to deploy it. At the moment it only has one appearance, the new skin for this website is in development. Download links only available from github. Deploy Links https://hub.docker.com/r/luisito666/mt2web https://github.com/luisito666/Mt2Web.py-docker Web Page https://github.com/luisito666/Mt2Web.py How To deploy. You can run the Mt2Web.py project after cloning it and being inside the directory where all the source code is. docker run -d -p 80:80 --name mt2web -v $PWD:/var/www/html/Mt2Web.py/ luisito666/mt2web With this we finalize the process of deployment of the application. Execute migrations To execute the migrations we first enter the container and execute this command. python3 manage.py migrate Execute commands inside of Docker docker exec -it mt2web bash Some screnshots
  10. Hi there everyone, I'd like to share a small function which will give you a random name whilst creating a new character. This will only include the function and a list of names, so you will have to set the event on your own. Preview: The function which will most likely be put in introCreate.py import os import app #import the above lines if you don't have them already def __randomizeName(self): dir = os.path.dirname(os.path.abspath("introCreate.py")) list = open("%s\\names.list" % dir, "r").read().split("\n") rng = app.GetRandom(0, len(list)-1) randomName = list[rng] self.heroName.SetText("%s" % randomName) ## change variable 'heroName' with your editline's name Also place the attached file to this thread in the main directory of the client. (i.e: where the launcher is) names.list contains 150 names, if you ever need more names let me know so I can up the number or you can add more yourself, but do note you need to put each name as a new line so you won't mess up the function. That's all for now, hope you all have a great day! Cheers. names.list
  11. Hi, I want to release shop with the new currency. Client: inventorywindow.py (locale/uiscript): You must replace this: "y" : SCREEN_HEIGHT - 37 - 565, "y" : SCREEN_HEIGHT - 37 - 589, 2x replace this: "height" : 565, "height" : 589, And replace this: ## Print { "name":"Money_Slot", "type":"button", "x":8, "y":28, "horizontal_align":"center", "vertical_align":"bottom", "default_image" : "d:/ymir work/ui/public/parameter_slot_05.sub", "over_image" : "d:/ymir work/ui/public/parameter_slot_05.sub", "down_image" : "d:/ymir work/ui/public/parameter_slot_05.sub", "children" : ( { "name":"Money_Icon", "type":"image", "x":-18, "y":2, "image":"d:/ymir work/ui/game/windows/money_icon.sub", }, { "name" : "Money", "type" : "text", "x" : 3, "y" : 3, "horizontal_align" : "right", "text_horizontal_align" : "right", "text" : "123456789", }, ), }, ## Print { "name":"Money_Slot", "type":"button", "x":8, "y":28+24, "horizontal_align":"center", "vertical_align":"bottom", "default_image" : "d:/ymir work/ui/public/parameter_slot_05.sub", "over_image" : "d:/ymir work/ui/public/parameter_slot_05.sub", "down_image" : "d:/ymir work/ui/public/parameter_slot_05.sub", "children" : ( { "name":"Money_Icon", "type":"image", "x":-18, "y":2, "image":"d:/ymir work/ui/game/windows/money_icon.sub", }, { "name" : "Money", "type" : "text", "x" : 3, "y" : 3, "horizontal_align" : "right", "text_horizontal_align" : "right", "text" : "123456789", }, ), }, ## Print { "name":"Premium_Slot", "type":"button", "x":8, "y":28, "horizontal_align":"center", "vertical_align":"bottom", "default_image" : "d:/ymir work/ui/public/parameter_slot_05.sub", "over_image" : "d:/ymir work/ui/public/parameter_slot_05.sub", "down_image" : "d:/ymir work/ui/public/parameter_slot_05.sub", "children" : ( { "name":"Premium_Icon", "type":"image", "x":-18, "y":2, "image":"d:/ymir work/ui/game/windows/money_icon.sub", }, { "name" : "Premium", "type" : "text", "x" : 3, "y" : 3, "horizontal_align" : "right", "text_horizontal_align" : "right", "text" : "123456789", }, ), }, game.py (root): In table "servercommandlist" you must add this lines: "GetInputStart" : self.GetInputStart, "GetInputStop" : self.GetInputStop, "GetInput" : self.GetInput, "SetQuestIndex" : self.QuestIndexShop, "SetIsNpc" : self.SetIsNpc, "SetPrice" : self.SetIsPrice, "NieMamPP" : self.NieMamPP, "setPP" : self.__setAchievementPoints, And add this lines under "servercommandlist" table: def NieMamPP(self): import uiShop self.wndShop = uiShop.ShopDialog() self.wndShop.NieMamPP() def __setAchievementPoints(self, points): constInfo.ACHIEVEMENT_POINTS = int(points) self.interface.wndInventory.UpdatePremiumInSlot() def SetIsPrice(self, value): self.interface.dlgShop.SetShopPrice(value) def SetIsNpc(self): constInfo.IsItemShop = 1 def QuestIndexShop(self, value): constInfo.IS_QUEST = int(value) def GetInputStart(self): constInfo.INPUT_IGNORE = 1 def GetInputStop(self): constInfo.INPUT_IGNORE = 0 def GetInput(self): net.SendQuestInputStringPacket(str(constInfo.INPUT_DATA)) constinfo.py (root): You must add this lines in the middle of the file: ACHIEVEMENT_POINTS = 0 IS_QUEST = 0 IsItemShop = 0 INPUT_IGNORE = 0 INPUT_DATA = "" uitooltip.py (root): You must replace this function: def SetShopItem(self, slotIndex): itemVnum = shop.GetItemID(slotIndex) if 0 == itemVnum: return price = shop.GetItemPrice(slotIndex) self.ClearToolTip() self.isShopItem = TRUE item.SelectItem(itemVnum) metinSlot = [] for i in xrange(player.METIN_SOCKET_MAX_NUM): metinSlot.append(shop.GetItemMetinSocket(slotIndex, i)) attrSlot = [] for i in xrange(player.ATTRIBUTE_SLOT_MAX_NUM): attrSlot.append(shop.GetItemAttribute(slotIndex, i)) self.AddItemData(itemVnum, metinSlot, attrSlot) self.AppendPrice(price) def SetShopItem(self, slotIndex, addprice = 0, waltype = 0): itemVnum = shop.GetItemID(slotIndex) if 0 == itemVnum: return price = shop.GetItemPrice(slotIndex) self.ClearToolTip() self.isShopItem = TRUE item.SelectItem(itemVnum) metinSlot = [] for i in xrange(player.METIN_SOCKET_MAX_NUM): metinSlot.append(shop.GetItemMetinSocket(slotIndex, i)) attrSlot = [] for i in xrange(player.ATTRIBUTE_SLOT_MAX_NUM): attrSlot.append(shop.GetItemAttribute(slotIndex, i)) self.AddItemData(itemVnum, metinSlot, attrSlot) if waltype == 0: self.AppendPrice(price) else: self.AppendSpace(5) self.AppendTextLine("Cena: %s TR" % (locale.NumberToMoneyString(addprice)[:-5]), self.SPECIAL_TITLE_COLOR) uiinventory.py (root): Under: def RefreshStatus(self): money = player.GetElk() self.wndMoney.SetText(locale.NumberToMoneyString(money)) Add: def UpdatePremiumInSlot(self): import constInfo value = str(constInfo.ACHIEVEMENT_POINTS) self.wndPremium.SetText(locale.NumberToMoneyString(value)[:-5] + " TR") Under: self.wndMoneySlot = 0 Add: self.wndPremium = 0 self.wndPremiumSlot = 0 Under: self.wndMoneySlot = self.GetChild("Money_Slot") Add: self.wndPremium = self.GetChild("Premium") self.wndPremiumSlot = self.GetChild("Premium_Slot") And replace this function: def SelectEmptySlot(self, selectedSlotPos): if constInfo.GET_ITEM_DROP_QUESTION_DIALOG_STATUS() == 1: return selectedSlotPos = self.__InventoryLocalSlotPosToGlobalSlotPos(selectedSlotPos) if mouseModule.mouseController.isAttached(): attachedSlotType = mouseModule.mouseController.GetAttachedType() attachedSlotPos = mouseModule.mouseController.GetAttachedSlotNumber() attachedItemCount = mouseModule.mouseController.GetAttachedItemCount() attachedItemIndex = mouseModule.mouseController.GetAttachedItemIndex() if player.SLOT_TYPE_INVENTORY == attachedSlotType: itemCount = player.GetItemCount(attachedSlotPos) attachedCount = mouseModule.mouseController.GetAttachedItemCount() self.__SendMoveItemPacket(attachedSlotPos, selectedSlotPos, attachedCount) if item.IsRefineScroll(attachedItemIndex): self.wndItem.SetUseMode(FALSE) elif player.SLOT_TYPE_PRIVATE_SHOP == attachedSlotType: mouseModule.mouseController.RunCallBack("INVENTORY") elif player.SLOT_TYPE_SHOP == attachedSlotType: if constInfo.IsItemShop == 0: net.SendShopBuyPacket(attachedSlotPos) else: import uiShop self.wndShop = uiShop.ShopDialog() self.wndShop.BuyFromIS(attachedSlotPos) elif player.SLOT_TYPE_SAFEBOX == attachedSlotType: if player.ITEM_MONEY == attachedItemIndex: net.SendSafeboxWithdrawMoneyPacket(mouseModule.mouseController.GetAttachedItemCount()) snd.PlaySound("sound/ui/money.wav") else: net.SendSafeboxCheckoutPacket(attachedSlotPos, selectedSlotPos) elif player.SLOT_TYPE_MALL == attachedSlotType: net.SendMallCheckoutPacket(attachedSlotPos, selectedSlotPos) mouseModule.mouseController.DeattachObject() uishop.py (root): This file is too much editing, I give you the finished file. http://wklej.to/YR452 Server: Add shop, and then add items in this shop. In my system, a standard shop has id 15. Remember not to give the shop directly at NPC! Quest: http://wklej.to/T5Ild The price we give here: cmdchat("SetPrice 200|50|100|200|150|250|100|100|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0") Slots are separated by "|". The items we give here: local items = { [1]={71124, 1, 200}, [2]={71125, 1, 200}, [3]={71126, 1, 200}, [4]={71127, 1, 200}, [5]={71128, 1, 200}, } [slot_id]={item_id, item_count, item_price}, This guide and information contained in it things are by Teodor. Sorry for my english, I come from Polish. Greetings! Screen:
  12. As we work with maps we accumulate a large number of unused textures which end up making the client / pack downloads for our server bigger. For this reason I made this little python 2.7 script. It will read all the textureset files and the texture paths on it and copy to textureset_release/ only the textures that are actually being used by your maps, as listed in Settings.txt The folder where the script looks for Settings.txt files recursively is "maps/", change it at the start of the code if yours is different. Likewise, it will look for "textureset/" and "terrainmaps/", and create "textureset_release/". No files will be deleted. Disclaimer: The code is very ugly, I actually have no idea of python, I made this script looking at docs and based on my knowledge of other languages. If you actually know python I suggest you don't look at it to avoid hurting your eyes. import os import re import string import shutil import sys ct = 0 usedimg = [] usedsets = [] list = [] mapfolder = 'maps/' class cd: """Context manager for changing the current working directory""" def __init__(self, newPath): self.newPath = os.path.expanduser(newPath) def __enter__(self): self.savedPath = os.getcwd() os.chdir(self.newPath) def __exit__(self, etype, value, traceback): os.chdir(self.savedPath) def cleanValue(val): val = val.replace('\\', '/') val = val.strip(' \t\n"') val = val.lower() return val def copyFile(src, dest): try: shutil.copy(src, dest) # eg. src and dest are the same file except shutil.Error as e: print('Error: %s' % e) # eg. source or destination doesn't exist except IOError as e: print('Error: %s' % e.strerror) # Read the tab-separated value of a parameter "param" in all files named "fname" (can be an extension) in folder "folder" def SaveParams(param,fname,folder,list): for path, subdirs, files in os.walk(folder): for filename in files: if filename.lower() == fname.lower() or (fname.startswith('.') and filename.endswith (fname)): f = os.path.join(path, filename) with open(f, "rt") as current: for line in current: lcline = line.lower() lcparam = param.lower() if lcparam in lcline: # strip tabs and split values value = line.rstrip('\t\n') # get parameter value list.append(value) # Read a value with the order number "order" within a parameter block "block" in all files named "fname" (can be an extension) in folder "folder" which are also in list "compare" def SaveParamsFromBlock(block,order,fname,folder,list,compare): for path, subdirs, files in os.walk(folder): for filename in files: if filename in compare and (filename.lower() == fname.lower() or (fname.startswith('.') and filename.endswith (fname))): countblock = -1 f = os.path.join(path, filename) with open(f, "rt") as current: for line in current: lcline = line.lower() lcblock = block.lower() if countblock == order: list.append(line) countblock = -1 elif lcline.startswith(lcblock): countblock = 0 elif countblock >= 0: countblock = countblock + 1 # move to the client data folder with cd('..\client\data'): try: os.makedirs('terrainmaps_release') except: shutil.rmtree('terrainmaps_release') os.makedirs('terrainmaps_release') print "This script copies to terrainmaps_release only the textures which are actually listed in textureset files." print "The folder is emptied on each run. make_archive.py uses this folder as source for making the terrainmaps pack." print "This script is written to be run from the tools repo copy and assumes the client repo copy to be in the same base directory as tools" print "" select = raw_input("Press any key to start, e to exit") if str(select) == "e": sys.exit() # Get all the texturesets used in our maps SaveParams('TextureSet','Setting.txt','maps',usedsets) # Extract the filename part of the used TextureSet paths and write it back to the list for idx,val in enumerate(usedsets): val = cleanValue(val) parts = re.split('/', val.lower()) # check its actually a terrainmaps path usedsets[idx] = parts[-1] # Fetch a list of the textures used in the sets used SaveParamsFromBlock('Start Texture',0,'.txt','textureset',usedimg,usedsets) # Copy the textures used in textureset_release for idx,val in enumerate(usedimg): # check its actually a terrainmaps path if "terrainmaps" in val: val = cleanValue(val) val = val[len('d:/ymir work/terrainmaps/'):] usedimg[idx] = val.lower() srcPath = 'terrainmaps/' + usedimg[idx] destPath = 'terrainmaps_release/' + usedimg[idx] print "Copy " + srcPath + " to " + destPath if not os.path.isdir(os.path.dirname(destPath)): os.makedirs(os.path.dirname(destPath)) copyFile(srcPath, destPath) ct = ct + 1 print "Total " + str(ct) + " textures copied in terrainmaps_release" raw_input("Press any key to exit") As a bonus another python 2.7 script used to create the property/list file with all your prb, pre. Assumes a property/ folder at the location where you run it. import os import math count = 0 extensions = ('prb','prt','prd','pre','pra') with open("property/list", "w") as a: for path, subdirs, files in os.walk(r'property'): for filename in files: f = os.path.join(path, filename) if filename != "list" and filename !="reserve": extension = filename.split ('.')[-1] if (extension in extensions): a.write(str(f) + '\n') else: Print ("Strange file: " + f) count = count + 1 print 'Total: ' + str(count) + ' files listed on property/list!' raw_input("Press any key to exit") And finally another script to copy all your msa and motlist.txt files to a server/data folder that you can upload later to your server. It will only copy when files are different or not existing at the destination. It assumes a ../client/data/npc (and so on) and ../server/data/monster etc. structure, feel free to edit the paths in the scripts to your needs. import os import shutil from itertools import chain import filecmp pathList = [] count = 0 def copyFile(src, dest): try: shutil.copy(src, dest) return True # eg. src and dest are the same file except shutil.Error as e: print('Error: %s' % e) # eg. source or destination doesn't exist except IOError as e: print('Error: %s' % e.strerror) print "This script moves all the .msa and motlist.txt files from pc monster and npc client folders to the appropiate server folders, creating them if necessary." paths = ('../client/data/monster/', '../client/data/monster2/', '../client/data/npc/', '../client/data/npc2/', '../client/data/pc/', '../client/data/pc2/') for path, dirs, files in chain.from_iterable(os.walk(path) for path in paths): for filename in files: if filename.endswith('.msa') or filename.endswith('.txt'): realpath = path.replace('\\', '/') cfolder = os.path.split(realpath)[1] gfolder = 'monster' if ('/pc/' in realpath): gfolder = 'pc/' + realpath.split('/')[4] elif ('/pc2/' in realpath): gfolder = 'pc2/' + realpath.split('/')[4] else: # Check for duplicated non-pc folders existingpath = next((s for s in pathList if ('/' + cfolder) in s), None) if existingpath and existingpath.endswith(cfolder): if realpath != existingpath: print("Warning: duplicate folders " + realpath + " and " + existingpath + "!") pathList.remove(existingpath) break elif path not in pathList: pathList.append(realpath) else: pathList.append(realpath) spath = realpath + '/' + filename dpath = '../server/data/' + gfolder + '/' + cfolder # Create destination folder if not existing if not os.path.isdir(dpath): os.makedirs(dpath) dpath = dpath + '/' + filename # Copy file if destination is not existing or different if not os.path.exists(dpath) or not filecmp.cmp(spath,dpath): if copyFile(spath, dpath): print "Copied " + spath + " to " + dpath count = count + 1 print "Finished copying " + str(count) + " files!" raw_input("Press any key to exit") How to use: install python 2.7 anywhere on your hd (C:\Python27 for example), add this path to the system path, and save this code in a file named something.py, then run it by doubleclick Remember to change directory to wherever you have your client files.
  13. Hello, To extend NPC Shop to 80 Items follow these steps. ServerSide Open "common/length.h" and search: SHOP_HOST_ITEM_MAX_NUM = 40 Replace with: SHOP_HOST_ITEM_MAX_NUM = 80 In the same file search: SHOP_PRICELIST_MAX_NUM = 40 Replace with: SHOP_PRICELIST_MAX_NUM = 80 Now open "game/shop.cpp" and search: m_pGrid = M2_NEW CGrid(5, 9) Replace with: m_pGrid = M2_NEW CGrid(10, 9) Now open "game/shop_manager.cpp" and search: CGrid grid = CGrid(5, 9) Replace with: CGrid grid = CGrid(10, 9) Now compile Db File & Game File and ServerSide's steps complete. ClientSide NOTE: If you want Only NPC Shop's with 80 Items follow this guide, else if you want NPC Shop & Private Shop follow the Update Istruction. Extract "pack/uiscript" from your Client and open "shopdialog.py". Now reaplace all content with: Shopdialog.py ~ 80 Items Now create "shopdialog2.py" and insert this content: ShopDialog2 ~ 80 Items for Shop Ok, at this point you can compress your UiScript with the new file "shopdialog2.py". Extract "pack/root" from your Client and open "interfacemodule.py" Search this: self.dlgShop = uiShop.ShopDialog() self.dlgShop.LoadDialog() self.dlgShop.Hide() After add: self.dlgShop2 = uiShop.ShopDialog2() self.dlgShop2.LoadDialog() self.dlgShop2.Hide() Same file, search this: def OpenShopDialog(self, vid): self.wndInventory.Show() self.wndInventory.SetTop() self.dlgShop.Open(vid) self.dlgShop.SetTop() After add: def OpenShopDialog2(self, vid): self.wndInventory.Show() self.wndInventory.SetTop() self.dlgShop2.Open(vid) self.dlgShop2.SetTop() Now open "game.py" and Search: def StartShop(self, vid): self.interface.OpenShopDialog(vid) Replace with: def StartShop(self, vid): if chr.IsNPC(vid): self.interface.OpenShopDialog(vid) else: self.interface.OpenShopDialog2(vid) Now open "uishop.py" and Search: def Close(self): self.OnCloseQuestionDialog() shop.Close() net.SendShopEndPacket() self.CancelShopping() self.tooltipItem.HideToolTip() self.Hide() Replace with: def Close(self): self.OnCloseQuestionDialog() shop.Close() net.SendShopEndPacket() self.CancelShopping() self.Hide() Same file, search: def OnUpdate(self): USE_SHOP_LIMIT_RANGE = 1000 (x, y, z) = player.GetMainCharacterPosition() if abs(x - self.xShopStart) > USE_SHOP_LIMIT_RANGE or abs(y - self.yShopStart) > USE_SHOP_LIMIT_RANGE: self.Close() After add: UiShop.py ~ ShopDialog2 Now you can compress "root" file. #Update [24-02-15] Fixed Client Bug. Changes in "shop_manager.cpp" added. #Update [26-02-15] Added PrivateShop with 80 Items. NPC & PrivateShop with 80 Items ClientSide: Open "UserInterface/Packet.h" in you Binary Client Source and Search: SHOP_HOST_ITEM_MAX_NUM = 40 Replace with: SHOP_HOST_ITEM_MAX_NUM = 80 Now you can compile your Binary Source. Open your Client File and extract "pack/uiscript". Open "shopdialog.py" and replace all contentwith: Shopdialog.py ~ 80 Items Now open "privateshopbuilder.py" and replace all content with: PrivateShopBuilder ~ 80 Items Now you can compress your UiScript. Screen Private Shop: Et Voilà, we ended. Good work, Bye.
  14. Perhaps it will be useful for some people for various systems. Have fun. # onPressKeyDict[app.DIK_F5] = lambda : self.Print() # For test function @root/game.py def Print(self): import app, chat list = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" # Set list maxStr = 10 # Set the maximum number of characters k = "" for v in xrange(maxStr): k = k + list[app.GetRandom(0, len(list) - 1)] chat.AppendChat(chat.CHAT_TYPE_INFO, "Result word: %s" % str(k))
  15. Hello Dev Community! Today I will share You my litlle project what I made, because i saw many things of this problem - it means bonus page, bonus window or as You call it. This is my first thread on metin2dev forum. I do this 2 years ago nad post on known polish forum - mpcforum.pl. This can be a long topic, sorry in advance but I think it's worth. Original thread on mpcforum: http://www.mpcforum.pl/topic/1038647-okno-bonus-by-sanki/ I will share it there, because I think it's good idea for servers. So let's go! Screen: I know... it is in polish language, but You can translate it very fast and simply... Google translator can help You Notice the tabs, spaces, etc. THIS IS THE FIRST BAD thing what You can do wrong. 1. For first... unpack root and uiscript, go to root folder and open game.py, in imports add this: import uiBonus under: import uiCharacter 2. Next search in this file: onPressKeyDict[app.DIK_Z] and add under(this function is for opening and closing this bonus window): onPressKeyDict[app.DIK_X] = lambda: self.interface.ToggleBonusWindow() in this file it's end. You can close this file. 3. Now go to interfacemodule.py also in root files (in this file will be add very much so You have to be carefoul and check to add all good) and add import like in game.py: import uiBonus 4. Now in this file search: def __init__(self): and under this: self.wndInventory = None add this: self.wndBonus = None 5. Now search this function: def __MakeWindows(self): and under: wndInventory = uiInventory.InventoryWindow() add this: wndBonus = uiBonus.BonusWindow() 6. In this same function but a few lines below after this: self.wndCharacter = wndCharacter add this: self.wndBonus = wndBonus 7. Ok. Good. Now search this function: def Close(self): and after this: if self.wndInventory: self.wndInventory.Destroy() add this: if self.wndBonus: self.wndBonus.Destroy() 7.1 Now again in the same function, a few lines below, we are looking for: del self.wndInventory add this: del self.wndBonus 8. Now search another function: def ShowAllWindows(self): and under this: self.wndInventory.Show() add this: self.wndBonus.Show() 9. Now next function or search this: def HideAllWindows(self): under: if self.wndInventory: self.wndInventory.Hide() add: if self.wndBonus: self.wndBonus.Hide() 10. Uff... not far...but now be carefoul! Search function : def ToggleInventoryWindow(self): and UNDER this function, NOT IN THIS function add new: def ToggleBonusWindow(self): if FALSE == player.IsObserverMode(): if FALSE == self.wndBonus.IsShow(): self.wndBonus.Show() self.wndBonus.SetTop() else: self.wndBonus.Hide() 11. Ok. Next search: def __HideWindows(self): and in this after line: self.wndInventory, add: self.wndBonus, OK. In this way, we end add window to python files. Now only remain for us to add and pack to root files: uibonus.py and add and pack to uiscript files: bonus.py link for this files: http://speedy.sh/Yn8Jb/zakladka-bonus.rar scan: http://img23.imageshack.us/img23/1237/l6n5.png IF AFTER ADD, SOMETHING DON'T WONT WORKING( turn off client etc.) check client SYSERR! PS. If problem is in this window bonus, errors will be in the middle of the polish. A reference to the file where to look. Only one problem for older clients(2010) and oldest, is checking locals "IsARABIC", but the solution is easy... There You must only comment three lines(add # in beginning of the line) 38, 39 and 40 in uiBonus.py file. It must be like this: If I somewhere write something wrong, misspell, translate, spoilers etc or incorrect description(everything write what i learned alone) I ask for precise, explanation, etc. I don't translate this files because I don't have time for it... :< If anybody translate files to english(show text in window ingame and errors) will be that good and send me this files or give link in thread I will add it to topic. PS.2. There is a little small bug( resis sura and ninja are reversed), only numbers in uibonus.py( now it is like this: odpninja... bonusid = 61 ... odpsura... bonusid = 60... ) reverse bonusid and it will be good( odpninja... bonusid = 60 ... odpsura.... bonusid = 61 ... ). I think, everyone know what i mean Prohibition of copying on other forums, etc. For personal use only. Kind Regards, Sanki
  16. Hello. I was looking inside the official python files and I found a little fix for this: Let me explain a bit the problem. If you leave open the inventory/dragon soul inventory/expanded taskbar or the affected objects and then you are using quest for teleportation, the windows what you left open will be closed because of the quest and when the quest executed those windows what you left open before would be opened again, but the warp is killing this procedure and that happens what you can see in the video, the windows are there but you cannot see them. Btw you can close them with escape key. The fix is coming from webzen: Simple, just execute a .Hide() function before the Destroy function has been called on that object what is stuck on the main window after teleport and that's it. For example: interfaceModule.py -> Interface class -> Close function: if self.wndInventory: self.wndInventory.Hide()#fix self.wndInventory.Destroy() if self.wndDragonSoul: self.wndDragonSoul.Hide()#fix self.wndDragonSoul.Destroy()
  17. I made a sequence generator script. You can find it in here: https://github.com/martysama0134/how-to-mt2-general/tree/master/sequence-generator This python script automatically generates the sequence table for `EterLib\NetStream.cpp` (in `s_bSequenceTable`) and `game\src\sequence.cpp` (in `gc_abSequence`). (the keys get changed every time you run the script) A sequence table is just a simple random generated array with 16x2048 bytes between 0x0 and 0xfe. Replacing the sequence table makes older/unwanted launchers unable to access the server.
  18. Some years ago I created a (python2) script to generate xtea keys randomly, here it is: xtea-keys-generator.rar You can also find it in here: https://github.com/martysama0134/how-to-mt2-general/tree/master/xtea-keys-generator It generates the code for EterNexus, for EterPack.cpp, and also the hex string you see inside the compiled launcher.
  19. Yo guys, here you have a script that i made to fix the annoying fact that epack32 craps out when you use for some reason uppercase extensions, this can happen with gr2's for example. Here you have a video showing how to use it properly, this is for an earlier version but you should get how it works. I'm also writing a py library that acts as manager for the query/msm/protos etc, the quality of the code is been improving since this script, stay tuned for the future. ## Author North - Fleon # Usage: python scriptname.py import os,fnmatch,shutil,re lenght = 3 # Set here the size of the extension, default 3 extension = None; class FileManager(): @staticmethod def Main(): print("\n\n#### Extension to lowercase V.01 ####\n\n") print("Renames recursively from a caps extension to lower.") print("USAGE: Place your content and script into C:\workdir") print("The script will recursively change the extension to lower.") input(">>>> Press ENTER to continue...") # In case you are using a python version that is equal or lower than 2.7 please use raw_input instead of input above. FileManager.GetExtension() FileManager.GetLogFile() FileManager.RenameFile() def GetExtension(): global extension global lenght while not extension or len(extension) > lenght: print("Tell me wich extension would you like to lower") print("/!\ The extension must not be left empty.") extension = str(input(">>>> Now type an extension: (Example: txt) \n")) return(extension) def GetLogFile(): path = os.getcwd() global extension Extension = "*." + str(extension) with open("rename_log", "w") as File_txt: for root, dirnames, filenames in os.walk(path): for gr2 in fnmatch.filter(filenames, Extension): write_txt = (os.path.join(root, gr2) +"\n") File_txt.write(write_txt) def RenameFile(): global extension with open("rename_log", "r") as file_directory: for element in file_directory: element = element[:-1] ren_element = element.replace(str.upper(extension), str.lower(extension)) os.rename(element, ren_element) print(">>>> This file has been renamed: " + element) total_elements = sum(1 for line in open('rename_log')) print("Total renamed files: {0}".format(str(total_elements))) FileManager.Main()
  20. Hello Metin2dev users, I want to relase this because it can be useful for someone who's starting to understand what kind of logic there is behind the ui managment This is a really simple thing, but it can be optimized to get you the idea of what you can do with small parts of code. As exercise do the followings: + Add the metin2 official effect for the brave cape + Add a keyboard shortcut to the button + Set a time of 4s in the c++ function for anti command spam + Enhance the overall looking? + What ever you'd like to add Video of the button: Link DL: https://mega.nz/#!MRg1zDra!h0eEHRpbxU5M_IycdhvRbYlaNs5i993JqcCgFTI5Q1M If i missed something in the file just tell me, ill adjust the file. I don't know and i don't care if this is already relased, it's so simple that no one is gonna be offended. Let me know your feedback for this kind of exercise-typeof-relases
  21. https://i.imgur.com/TBOcLui.gifv uiCommon.py class ItemQuestionDialog(ui.ScriptWindow): def __init__(self): ui.ScriptWindow.__init__(self) self.__CreateDialog() self.tooltipItem = uiToolTip.ItemToolTip() self.toolTip = uiToolTip.ToolTip() self.window_type = 0 self.count = 0 self.dropType = 0 self.dropCount = 0 self.dropNumber = 0 def __del__(self): ui.ScriptWindow.__del__(self) def __CreateDialog(self): pyScrLoader = ui.PythonScriptLoader() pyScrLoader.LoadScriptFile(self, "QuestionDialog.py") self.board = self.GetChild("board") self.textLine = self.GetChild("message") self.acceptButton = self.GetChild("accept") self.cancelButton = self.GetChild("cancel") self.titleBar = ui.TitleBar() self.titleBar.SetParent(self.board) self.titleBar.MakeTitleBar(244, "yellow") self.titleBar.SetPosition(8, 7) self.titleBar.Show() self.titleName = ui.TextLine() self.titleName.SetParent(self.titleBar) self.titleName.SetPosition(0, 4) self.titleName.SetWindowHorizontalAlignCenter() self.titleName.SetHorizontalAlignCenter() self.titleName.Show() self.slotList = [] for i in xrange(3): slot = ui.ImageBox() slot.LoadImage("d:/ymir work/ui/public/slot_base.sub") slot.SetParent(self) slot.SetWindowHorizontalAlignCenter() self.slotList.append(slot) def Open(self, vnum, slot = None, price = None): item.SelectItem(vnum) xSlotCount, ySlotCount = item.GetItemSize() try: if self.window_type == "inv": metinSlot = [player.GetItemMetinSocket(player.INVENTORY, slot, i) for i in xrange(player.METIN_SOCKET_MAX_NUM)] elif self.window_type == "shop": metinSlot = [shop.GetItemMetinSocket(slot, i) for i in xrange(player.METIN_SOCKET_MAX_NUM)] except: pass if vnum in (50300, 70037): self.titleName.SetText("%s %s" % (skill.GetSkillName(metinSlot[0]), item.GetItemName())) elif vnum == 70104: self.titleName.SetText("%s %s" % (nonplayer.GetMonsterName(metinSlot[0]), item.GetItemName())) else: self.titleName.SetText(item.GetItemName()) newHeight = 0 if price: newHeight = 20 itemPrice = ui.TextLine() itemPrice.SetPosition(0, 77 + 32*ySlotCount) itemPrice.SetWindowHorizontalAlignCenter() itemPrice.SetHorizontalAlignCenter() itemPrice.SetVerticalAlignCenter() itemPrice.SetParent(self.board) if str(price).isdigit(): itemPrice.SetText(localeInfo.NumberToMoneyString(price)) else: itemPrice.SetText(price) itemPrice.Show() self.itemPrice = itemPrice slotGrid = ui.SlotWindow() slotGrid.SetParent(self) slotGrid.SetPosition(-16, 62) slotGrid.SetWindowHorizontalAlignCenter() slotGrid.AppendSlot(0, 0, 0, 32*xSlotCount, 32*ySlotCount) slotGrid.AddFlag("not_pick") slotGrid.Show() self.slotGrid = slotGrid if self.count > 1 and vnum != 1: self.slotGrid.SetItemSlot(0, vnum, self.count) else: self.slotGrid.SetItemSlot(0, vnum) self.SetSize(260, 110 + 32*ySlotCount + newHeight) self.board.SetSize(260, 110 + 32*ySlotCount + newHeight) self.textLine.SetPosition(0, 44) for i in xrange(min(3, ySlotCount)): self.slotList[i].SetPosition(0, 30 + ySlotCount*32 - i*32) if vnum != 1: self.slotList[i].OnMouseOverIn = lambda arg = slot: self.OverInItem(arg) self.slotList[i].OnMouseOverOut = lambda arg = self.tooltipItem: self.OverOutItem(arg) else: self.slotList[i].OnMouseOverIn = lambda arg = localeInfo.MONETARY_UNIT0: self.OverInToolTip(arg) self.slotList[i].OnMouseOverOut = lambda: self.OverOutToolTip() self.slotList[i].Show() self.GetChild("accept").SetPosition(-40, 74 + 32*ySlotCount + newHeight) self.GetChild("cancel").SetPosition(40, 74 + 32*ySlotCount + newHeight) self.titleBar.SetCloseEvent(ui.__mem_func__(self.Close)) self.SetCenterPosition() self.SetTop() self.Show() def SetCloseEvent(self, event): self.titleBar.SetCloseEvent(event) def SetMessage(self, text): self.textLine.SetText(text) def OverInToolTip(self, arg): self.toolTip.ClearToolTip() self.toolTip.AppendTextLine(arg, 0xffffff00) self.toolTip.Show() def OverOutToolTip(self): self.toolTip.Hide() def OverInItem(self, slot): if self.window_type == "shop": self.tooltipItem.SetShopItem(slot) elif self.window_type == "inv": self.tooltipItem.SetInventoryItem(slot) def OverOutItem(self, tooltipItem): if None != tooltipItem: self.tooltipItem.HideToolTip() self.tooltipItem.ClearToolTip() def Close(self): self.ClearDictionary() self.slotList = [] self.titleBar = None self.titleName = None self.itemPrice = None self.slotGrid = None self.toolTip = None self.tooltipItem = None self.Hide() constInfo.SET_ITEM_QUESTION_DIALOG_STATUS(0) def SetWidth(self, width): height = self.GetHeight() self.SetSize(width, height) self.board.SetSize(width, height) self.SetCenterPosition() self.UpdateRect() def SAFE_SetAcceptEvent(self, event): self.acceptButton.SAFE_SetEvent(event) def SAFE_SetCancelEvent(self, event): self.cancelButton.SAFE_SetEvent(event) def SetAcceptEvent(self, event): self.acceptButton.SetEvent(event) def SetCancelEvent(self, event): self.cancelButton.SetEvent(event) def SetText(self, text): self.textLine.SetText(text) def SetAcceptText(self, text): self.acceptButton.SetText(text) def SetCancelText(self, text): self.cancelButton.SetText(text) def OnPressEscapeKey(self): self.Close() return True add imports import constInfo import skill import nonplayer This is just a class, now you just have to call it itemQuestionDialog = uiCommon.ItemQuestionDialog() itemQuestionDialog.window_type = "inv" #for inventory itemQuestionDialog.window_type = "shop" #for shops itemQuestionDialog.count = ... drop MONEY itemQuestionDialog.Open(1, "", attachedMoney) drop ITEM itemQuestionDialog.Open(itemVNum, slotNumber) buy&sell ITEM itemQuestionDialog.Open(itemVNum, slotNumber, price)
  22. #FIRST YEAH Hi Guys, Just a Simple "python Security script". Just include the file in your root for example and import in prototype.py. Its really not a big deal. Somebody asked for it. And you have to have Python 2.7 Code: import subprocess import app import threading import os import time Evil_ProcessList = ["notepad++.exe"] Evil_FileNameList = [".sdsd",".asd",".asds"] class SuperUnsecureAndNotEnoughProtectionOfferingScript(object): def __init__(self): self.LoadSuperUnsecureSystem() def __del__(self): pass def LoadSuperUnsecureSystem(self): while 1: self.CheckForEvilFiles() self.CheckForEvilProcesses() def KillProcess(self, processname): try: os.system("taskkill /f /im %s" % processname) except: app.Exit() def DeleteFile(self, filename): try: os.remove(filename) except IOError: app.Exit() def CheckForEvilFiles(self): for file in os.listdir(os.getcwd()): for filename in Evil_FileNameList: if file.endswith(filename): self.DeleteFile(file) def CheckForEvilProcesses(self): for evil in Evil_ProcessList: if evil in subprocess.Popen("tasklist", stdout=subprocess.PIPE, shell=False).communicate()[0]: self.KillProcess(evil) if __name__ == '__main__': threading.Thread(target=SuperUnsecureAndNotEnoughProtectionOfferingScript, args=()).start()
  23. Open: root.eix & epk && uichat.py Find: Kod: if net.IsChatInsultIn(text): Change: Kod: if net.IsInsultIn(text): It extracts all known banwords from the file "insult.txt" in the "Locale_en" folder.
×
×
  • 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.