Posts by VegaS

    You could check the method that I did for item award.


    2018-04-02 14:02:11 Monday Please login to see this link.

    • Added a check for attr types and values min - max.
    • You can't insert wrong bonuses into a specific item.
    • Eg. Add 2000 MAX_HP on your Sword+9, was possible, now not.
    • Eg. Add +500 INT to your shield, now there's a check for min-max value of player.item_attr Lv.1 - Lv.5 and your 500 INT value will be replaced with max value from lvl5 of bonus, like 12 (lv5), that happen with all the bonuses, same thing with the values lower than lvl1, like 5 HP_REGEN on your neck, when the minimum (lv1) is 10, the value will be replaced with 10.
    • If the bonus type can't be added into a specific item, the bonus will be ignored > deleted. (example: critical pct to armor)
    • Refactorized all the code and moved all features into Please login to see this link..
    • C++11 or higher is required for checking attributes.

    I just wanted to kindly ask why you don't use the name conventions given by ymir or just any convention for yourself. Is there any reason to call the variable m_EnterToken instead of m_bEnterToken for example? Or naming the vector multi_line instead of m_vecMultiLine?

    They're called hungarian notation (1972–1981), here you can find everything about it.

    Please login to see this link.

    Please login to see this link.

    No I don't recommend 'Hungarian'. I regard 'Hungarian' (embedding an abbreviated version of a type in a variable name) as a technique that can be useful in untyped languages, but is completely unsuitable for a language that supports generic programming and object-oriented programming — both of which emphasize selection of operations based on the type and arguments (known to the language or to the run-time support). In this case, 'building the type of an object into names' simply complicates and minimizes abstraction.

    Please login to see this link.

    Encoding the type of a function into the name (so-called Hungarian notation) is brain damaged—the compiler knows the types anyway and can check those, and it only confuses the programmer.

    Please login to see this link.

    ... nowadays HN and other forms of type encoding are simply impediments. They make it harder to change the name or type of a variable, function, member or class. They make it harder to read the code. And they create the possibility that the encoding system will mislead the reader.

    Please login to see this link.

    Design Guidelines[14] discourage developers from using Systems Hungarian notation when they choose names for the elements in .NET class libraries, although it was common on prior Microsoft development platforms like Visual Basic 6 and earlier. These Design Guidelines are silent on the naming conventions for local variables inside functions.

    Thanks for the remark, but I never used this command in game as a player, this should be active just for debug as GM's, no sense for players.

    About the fix, could be done directly from here too:

    • cmd_general.cpp

    Search for: (do_hair too)

    1. snprintf(buf, bufferSize, FN_point_string(attr.bType), attr.sValue);

    Replace it with:

    1. const char * cPointString = FN_point_string(attr.bType);
    2. if (!*cPointString)
    3. continue;
    4. snprintf(buf, bufferSize, cPointString, attr.sValue);

    There's no sense for showing to a player 'UNK... 23%' since he don't know what it's..

    I think it's better just to ignore the type if doesn't exist and don't show it in the chat.

    If you really want to do something like this, you can add a sys_log as an error to see the bonus missing and add it into the function.

    Thanks for thread, here's a trick that you don't have specify the index, already can get it automatically.

    Instead of:

    1. self.categories = (["Ente 1", 0],["Ente 2", 1],["Ente 3", 2],["Ente 4", 3],["Ente 5", 4],["Ente 6", 5],["Ente 7", 6])
    2. for category in self.categories:
    3. comboBox.InsertItem(category[1], category[0])
    4. def OnSelectItem(self, id):
    5. category = self.categories[id]
    6.     # You know that you could use "id" instead of list[1]
    7. self.textLine.SetText('["%s",%d]' %(category[0], category[1]))

    You can do it as:

    1. self.categories = ("Ente 1", "Ente 2", "Ente 3", "Ente 4", "Ente 5", "Ente 6", "Ente 7")
    2. for categoryIndex, categoryName in enumerate(self.categories):
    3. comboBox.InsertItem(categoryIndex, categoryName)
    4. def OnSelectItem(self, categoryIndex):
    5. categoryName = self.categories[categoryIndex]
    6. self.textLine.SetText('["%s",%d]' % (categoryName, categoryIndex))
    Python3.0 because of the print statements.

    getopt exists since over 15 years ago, if i'm not mistake.

    If you code in Python, you should know that in each version of python you can use print (something). In Python3 you're forced to use it, but in the previous versions you're not, print is just a normal function, which calling the sys.stdout.write(string).


    You should read Please login to see this link.:

    The print statement has been replaced with a print() function, with keyword arguments to replace most of the special syntax of the old print statement (Please login to see this link.).

    Please login to see this link.:

    The changes proposed in this PEP will render most of today's print statements invalid. Only those which incidentally feature parentheses around all of their arguments will continue to be valid Python syntax in version 3.0, and of those, only the ones printing a single parenthesized value will continue to do the same thing.

    Also in all of these years I didn't heard about this error, but instead of doing a tool to rename all of your file names into lower case, you could check your client source or the EterManager source (is public), and just convert the file name to lower name, in one line, no tools, no anything.

    But you guys always prefer the hardest method, it's fine.


    Python >= 3.0

    That's wrong, you don't have any features from Python 3.


    When packing, the EterManager makes the file name small and then packs, the client cannot find the file, because upper and lower case was probably not found in Japan in 2004. (Strangely, it works if you write it down yourself before packing. And that's where my tool comes in.)

    I don't have this problem and I don't think that somebody have it, because metin2 reading file from pack or whatever, doesn't have case sensitivity for file names Please login to see this link. Please login to see this link., already they're readed in lower case. So, you don't need this "Pythonskript", everything works fine.

    Please login to see this picture.

    Hello cowboys, since i was at job and i was bored while coding in other languages, i thought would be funny if i code something in Python, so an idea came in mind, doing a general text file loader for parsing different data, with different structs, normal variables, groups and lists, like ymir idea for parsing the files (.mse, .msa, .msm, .txt like mob_drop_item.txt, group.txt, etc)

    This tool can be used everywhere, for metin2 or else, i wrote this from scratch using ymir idea, also you can run it in any version of Python.

    If you use this for metin2, change USING_METIN2_CLIENT to True.

    • Please login to see this link.
    • Please login to see this link.

    Source repository:

    If someone want to use it in client too:

    Please login to see this link.

    • root/

    How-To-Use: < import localeInfo

    • Please login to see this picture.
    1. self.timeTextLine.SetText(localeInfo.GetCurrentServerTime12H())
    2. # 06:00:08 PM
    • Please login to see this picture.
    1. self.timeTextLine.SetText(localeInfo.GetCurrentServerTime12H())
    2. # 04:30:56 AM
    • Please login to see this picture.
    1. self.timeTextLine.SetText(localeInfo.GetCurrentServerTime24H())
    2. # 21:05:03

    Please login to see this link.


    Please login to see this picture.


    • Fixed non-returning time for processing, if the specific event function has no value from returning, it runs continuously.
    • Fixed the check if an event exist, now will be replaced with the new one.
    • Removed Please login to see this link.library (i heard that some people don't have it) and using builtin functions, instead of Please login to see this link. now we're using Please login to see this link.(object), which check if the event function can be called, now you can insert classes and others callable methods, not just simple functions.
    • Added a reset time event function.

    Next update: (when i'll have some free time again)

    • Insert a new type of event, which you can run an event by specific counter like:
    1. t.AppendEvent(eventName='RUN', eventStartTime=5, eventRunCount=10, eventFunc=self.Run, eventFuncArgs=player.GetLevel())

    The following things will happen:

    • The function Run(args), will start to run in 5 seconds for 10 times.

    Can you maybe tell how to do the Video with escape key, like official ?
    I mean being able to cancel the Video with escape key.

    As the title says, here's the simple method how you can skip the video without waiting until is finished, like official did long time ago.

    Please login to see this link., right now these are by default:

    • VK_LBUTTON 0x01 - Left mouse button
    • VK_ESCAPE 0x1B - ESC key
    • VK_SPACE 0x20 - SPACEBAR



    How to do it when i press any key/mouse etc to skip it? Not only by specific keys, people don't know those keys maybe

    Thanks for release, the idea isn't bad, but there're some bad things.

    I'll show you the problems part and how can be improved, there're just advices, i hope you'll get them.

    • Python
      1. def __del__(self):
      2. if len(self.eventList) > 0:
      3. self.eventList.clear()

      If you're using Python 2+ or Python 3.2 and below, you can't use the clear() method (allowed on 3.3+), also as i said in the second message you don't need to check the length of the list, already the clear() method doing that inside and there's no reason to put it to __del__ method, it will be called when the object is garbage collected. if you really want to use in future, something outside of this and want just to check the list if isn't empty, is enough to do it just with if some_list, like a normal boolean, there no need to check the length of the list if you don't use it in your code.

    • Python
      1. if len(self.eventList) > 0:
      2. for j in xrange(len(self.eventList)):
      3. [...]

      You don't have to check the list if you already did a numeric range loop or iterator based loop.

    • Python
      1. app.GetTime() + time

      I would say to use app.GetGlobalTimeStamp() instead of app.GetTime(), if you teleport while the event is running, the event function will run after 10 seconds like. While app.GetGlobalTimeStamp() will run after the specific time, because is the server timestamp and is updated on each enter in game.

    • Python
      1. if i == 0:
      2. self.eventList[j].clear()

      I would put here an big exclamation, with this you creating 999999999 lines in syserr, what you do here is like: While Process() function is called in OnUpdate, so, your condition trying to get the returned value from an specific function, what means the next update time or 0 to destroy the event/clear it. Everything's fine until you return 0 and event should be stopped yes? But there is a problem, you clear the specific dictionary of event and still remained in the list [{}], and the Process() function will take your self.eventList with the items included, the empty dictionaries from your events, and of course even if you've [{}, {}, {}], that doesn't mean your list is empty, have 3 items, so, the loop will trying to read an empty dictionary and you'll get key errors in each milisecond. The method which you need is to delete the dictionary itself from the list after the result value from the function is 0, like this:


    I wrote fast some self extensions, if somebody is interested i'll do another updates in the next days.

    • You can use unlimited arguments on functions, now is using the apply method which returns the result of a function or class object called with supplied arguments, with the old structure you could use just one argument.
    • You can lock/unlock an event for being processed, it's like a prevent in some actions, if the event is created and you want to do something, you should lock the event, do some actions then you can unlock it again and the process function will run where remained.
    • Delete an event instantly and force it to stop the process.
    • Adding return t.EXIT inside of the running function, will delete the event too.
    • Functions to check if an event exists or is locked or not.
    • Check if the function is a Please login to see this link..
    • Delete the events with a properly method.
    • Using app.GetGlobalTimeStamp() now will give you the chance to run the event after teleport where timer remained instantly.


    The code:

    PS: Don't quote this reply, will be updated.


    • if len(antiFlagNames) <= 0

    In programming, in all languages, a list/vector/map/array... never can have size lower than 0, just >= 0.

    If you want just to check the list if isn't empty, is enough to do it just with if antiFlagName, like a normal boolean, there no need check length of it if you don't use it.

    About your method of antiFlagNameLines isn't related with this structure what's here, and also is hard-core for non-sense in this case.

    This is just an advice, i hope you got it.

    @Please login to see this link.

    You guys.. make things so complicated for a little thing, here we don't need two lists for non-sense, three for-loop and bla bla.

    I would do it like this:

    Please login to see this link.