Forum Moderator VegaS™ 10274 Posted April 1, 2019 Forum Moderator Share Posted April 1, 2019 There are a lot of people which had problem with localeInfo because korean-characters and bad encoding, there's a clean file with refactored code. Removed all the code which isn't used like korean characters < bad encoding [runmain error / crash](editors problem) and more checks. Removed over 500 lines unused. Removed function mapping(**kwargs) and use constructor of dict > dict(**kwarg) which is same (**kwarg let you take arbitrary number of keyword arguments). Removed function CutMoneyString because is used just when locale is HongKong, CIBN. Removed check IsYMIR from function LoadLocaleData which load locale as locale/ymir or locale/we_korea. Removed GUILD_MARK_NOT_ENOUGH_LEVEL, GUILD_HEADQUARTER, GUILD_FACILITY, GUILD_OBJECT, MAP_TRENT02, MAP_WL, MAP_NUSLUCK, MAP_TREE2, LOGIN_FAILURE_WEB_BLOCK, LOGIN_FAILURE_BLOCK_LOGIN, CHANNEL_NOTIFY_FULL, now they're readed directly from locale_game.txt. Removed declared global variables. Removed checks for declaring LOCALE_FILE_NAME, FN_GM_MARK and use current path. Removed korean functions/lists/dictionaries/characters GetAuxiliaryWordType, JOBINFO_DATA_LIST, dictSingleWord, dictDoubleWord, etc. Removed unused things: locale mapping, 'all' list etc. Removed IN_GAME_SHOP_ENABLE declaration, should be declared inside of constInfo directly. Removed checks (locale path) - 949, 932 == app.GetDefaultCodePage(), IsHONGKONG, IsNEWCIBN() or IsCIBN10() from declaration of functions like (NumberToMoneyString, NumberToSecondaryCoinString, ...),now they're declared directly from old style (IsEUROPE() and not IsWE_KOREA() and not IsYMIR()). Added custom string format(format_string, *args, **kwargs) instead of %. (old-style). Added new checks inside of LoadLocaleFile for security: Check if token3 (token1=original_string, token2=return-string, token3=function) function name exist in our types (SA, SNA, SAA, SAN) then try to call it. Check if string line have no tabs. Diff-checker: (856 Removals + 301 Additions) https://www.diffchecker.com/v1Nwk2r0 Spoiler """ File: localeInfo.py Refactored code date: 12.05.2016 Changes: Removed all the code which isn't used like korean characters < bad encoding(editors problem) and more checks. Removed over 500 lines unused. Removed function mapping(**kwargs) and use constructor of dict > dict(**kwarg) which is same (**kwarg let you take arbitrary number of keyword arguments). Removed function CutMoneyString because is used just when locale is HongKong, CIBN. Removed check IsYMIR from function LoadLocaleData which load locale as locale/ymir or locale/we_korea. Removed GUILD_MARK_NOT_ENOUGH_LEVEL, GUILD_HEADQUARTER, GUILD_FACILITY, GUILD_OBJECT, MAP_TRENT02, MAP_WL, MAP_NUSLUCK, MAP_TREE2, LOGIN_FAILURE_WEB_BLOCK, LOGIN_FAILURE_BLOCK_LOGIN, CHANNEL_NOTIFY_FULL, now they're readed directly from locale_game.txt. Removed declared global variables. Removed checks for declaring LOCALE_FILE_NAME, FN_GM_MARK and use current path. Removed korean functions/lists/dictionaries/characters GetAuxiliaryWordType, JOBINFO_DATA_LIST, dictSingleWord, dictDoubleWord, etc. Removed unused things: locale mapping, 'all' list etc. Removed IN_GAME_SHOP_ENABLE declaration, should be declared inside of constInfo directly. Removed checks (locale path) - 949, 932 == app.GetDefaultCodePage(), IsHONGKONG, IsNEWCIBN() or IsCIBN10() from declaration of functions like (NumberToMoneyString, NumberToSecondaryCoinString, ...), now they're declared directly from old style (IsEUROPE() and not IsWE_KOREA() and not IsYMIR()). Added custom string format(format_string, *args, **kwargs) instead of %. (old-style). Added new checks inside of LoadLocaleFile for security: * Check if token3 (token1=original_string, token2=return-string, token3=function) function name exist in our types (SA, SNA, SAA, SAN) then try to call it. * Check if string line have no tabs. """ import app import constInfo import dbg APP_GET_LOCALE_PATH = app.GetLocalePath() APP_GET_LOCALE_SERVICE_NAME = app.GetLocaleServiceName() APP_TITLE = 'METIN2' BLEND_POTION_NO_TIME = 'BLEND_POTION_NO_TIME' BLEND_POTION_NO_INFO = 'BLEND_POTION_NO_INFO' LOGIN_FAILURE_WRONG_SOCIALID = 'LOGIN_FAILURE_WRONG_SOCIALID' LOGIN_FAILURE_SHUTDOWN_TIME = 'LOGIN_FAILURE_SHUTDOWN_TIME' GUILD_MEMBER_COUNT_INFINITY = 'INFINITY' GUILD_MARK_MIN_LEVEL = '3' GUILD_BUILDING_LIST_TXT = '{:s}/GuildBuildingList.txt'.format(APP_GET_LOCALE_PATH) FN_GM_MARK = '{:s}/effect/gm.mse'.format(APP_GET_LOCALE_PATH) MAP_TREE2 = 'MAP_TREE2' ERROR_MARK_UPLOAD_NEED_RECONNECT = 'UploadMark: Reconnect to game' ERROR_MARK_CHECK_NEED_RECONNECT = 'CheckMark: Reconnect to game' VIRTUAL_KEY_ALPHABET_LOWERS = r"[1234567890]/qwertyuiop\=asdfghjkl;`'zxcvbnm.," VIRTUAL_KEY_ALPHABET_UPPERS = r"{1234567890}?QWERTYUIOP|+ASDFGHJKL:~'ZXCVBNM<>" VIRTUAL_KEY_SYMBOLS = "!@#$%^&*()_+|{}:'<>?~" VIRTUAL_KEY_NUMBERS = "1234567890-=\[];',./`" VIRTUAL_KEY_SYMBOLS_BR = "!@#$%^&*()_+|{}:'<>?~áàãâéèêíìóòôõúùç" __IS_ENGLISH = 'ENGLISH' == APP_GET_LOCALE_SERVICE_NAME __IS_HONGKONG = 'HONGKONG' == APP_GET_LOCALE_SERVICE_NAME __IS_EUROPE = 'EUROPE' == APP_GET_LOCALE_SERVICE_NAME __IS_NEWCIBN = 'locale/newcibn' == APP_GET_LOCALE_PATH __IS_CANADA = 'locale/ca' == APP_GET_LOCALE_PATH __IS_BRAZIL = 'locale/br' == APP_GET_LOCALE_PATH __IS_SINGAPORE = 'locale/sg' == APP_GET_LOCALE_PATH __IS_VIETNAM = 'locale/vn' == APP_GET_LOCALE_PATH __IS_ARABIC = 'locale/ae' == APP_GET_LOCALE_PATH __IS_CIBN10 = 'locale/cibn10' == APP_GET_LOCALE_PATH __IS_WE_KOREA = 'locale/we_korea' == APP_GET_LOCALE_PATH __IS_YMIR = 'locale/ymir' == APP_GET_LOCALE_PATH __IS_TAIWAN = 'locale/taiwan' == APP_GET_LOCALE_PATH __IS_JAPAN = 'locale/japan' == APP_GET_LOCALE_PATH if __IS_CANADA: __IS_EUROPE = TRUE def IsYMIR(): return __IS_YMIR def IsJAPAN(): return __IS_JAPAN def IsENGLISH(): return __IS_ENGLISH def IsHONGKONG(): return __IS_HONGKONG def IsTAIWAN(): return __IS_TAIWAN def IsNEWCIBN(): return __IS_NEWCIBN def IsCIBN10(): return __IS_CIBN10 def IsEUROPE(): return __IS_EUROPE def IsCANADA(): return __IS_CANADA def IsBRAZIL(): return __IS_BRAZIL def IsVIETNAM(): return __IS_VIETNAM def IsSINGAPORE(): return __IS_SINGAPORE def IsARABIC(): return __IS_ARABIC def IsWE_KOREA(): return __IS_WE_KOREA def IsCHEONMA(): return __IS_YMIR # Load locale data by specific path def LoadLocaleData(): app.LoadLocaleData(app.GetLocalePath()) # Load locale_game.txt def LoadLocaleFile(srcFileName, localeDict): def SNA(text): def f(x): return text return f def SA(text): def f(x): return text % x return f def SAN(text): def f(x): return text % x return f def SAA(text): def f(x): return text % x return f funcDict = {"SA": SA, "SNA": SNA, "SAA": SAA, "SAN": SAN} lineIndex = 1 try: lines = open(srcFileName, "r").readlines() except IOError: dbg.LogBox("LoadLocaleError(%(srcFileName)s)" % locals()) app.Abort() for line in lines: if line.count("\t") == 0: continue try: tokens = line[:-1].split("\t") if len(tokens) == 2: localeDict[tokens[0]] = tokens[1] elif len(tokens) >= 3: type = tokens[2].strip() if type: if type in funcDict: localeDict[tokens[0]] = funcDict[type](tokens[1]) else: localeDict[tokens[0]] = tokens[1] else: localeDict[tokens[0]] = tokens[1] else: raise RuntimeError, "Unknown TokenSize" lineIndex += 1 except: dbg.LogBox("%s: line(%d): %s" % (srcFileName, lineIndex, line), "Error") raise LoadLocaleFile("{:s}/locale_game.txt".format(APP_GET_LOCALE_PATH), locals()) # Option pvp messages OPTION_PVPMODE_MESSAGE_DICT = { 0: PVP_MODE_NORMAL, 1: PVP_MODE_REVENGE, 2: PVP_MODE_KILL, 3: PVP_MODE_PROTECT, 4: PVP_MODE_GUILD, } # Whisper messages WHISPER_ERROR = { 1: CANNOT_WHISPER_NOT_LOGON, 2: CANNOT_WHISPER_DEST_REFUSE, 3: CANNOT_WHISPER_SELF_REFUSE, } # Exception of graphic device. error = dict( CREATE_WINDOW = GAME_INIT_ERROR_MAIN_WINDOW, CREATE_CURSOR = GAME_INIT_ERROR_CURSOR, CREATE_NETWORK = GAME_INIT_ERROR_NETWORK, CREATE_ITEM_PROTO = GAME_INIT_ERROR_ITEM_PROTO, CREATE_MOB_PROTO = GAME_INIT_ERROR_MOB_PROTO, CREATE_NO_DIRECTX = GAME_INIT_ERROR_DIRECTX, CREATE_DEVICE = GAME_INIT_ERROR_GRAPHICS_NOT_EXIST, CREATE_NO_APPROPRIATE_DEVICE = GAME_INIT_ERROR_GRAPHICS_BAD_PERFORMANCE, CREATE_FORMAT = GAME_INIT_ERROR_GRAPHICS_NOT_SUPPORT_32BIT, NO_ERROR = str() ) # Job information (none, skill_group1, skill_group2) JOBINFO_TITLE = [ [JOB_WARRIOR0, JOB_WARRIOR1, JOB_WARRIOR2,], [JOB_ASSASSIN0, JOB_ASSASSIN1, JOB_ASSASSIN2,], [JOB_SURA0, JOB_SURA1, JOB_SURA2,], [JOB_SHAMAN0, JOB_SHAMAN1, JOB_SHAMAN2,], ] #if app.ENABLE_WOLFMAN_CHARACTER: #JOBINFO_TITLE += [[JOB_WOLFMAN0,JOB_WOLFMAN1,JOB_WOLFMAN2,],] # Guild war description GUILDWAR_NORMAL_DESCLIST = (GUILD_WAR_USE_NORMAL_MAP, GUILD_WAR_LIMIT_30MIN, GUILD_WAR_WIN_CHECK_SCORE) # Guild war warp description GUILDWAR_WARP_DESCLIST = (GUILD_WAR_USE_BATTLE_MAP, GUILD_WAR_WIN_WIPE_OUT_GUILD, GUILD_WAR_REWARD_POTION) # Guild war flag description GUILDWAR_CTF_DESCLIST = (GUILD_WAR_USE_BATTLE_MAP, GUILD_WAR_WIN_TAKE_AWAY_FLAG1, GUILD_WAR_WIN_TAKE_AWAY_FLAG2, GUILD_WAR_REWARD_POTION) # Mode of pvp options MODE_NAME_LIST = (PVP_OPTION_NORMAL, PVP_OPTION_REVENGE, PVP_OPTION_KILL, PVP_OPTION_PROTECT,) # Title name of alignment TITLE_NAME_LIST = (PVP_LEVEL0, PVP_LEVEL1, PVP_LEVEL2, PVP_LEVEL3, PVP_LEVEL4, PVP_LEVEL5, PVP_LEVEL6, PVP_LEVEL7, PVP_LEVEL8,) # Horse levels LEVEL_LIST = (str(), HORSE_LEVEL1, HORSE_LEVEL2, HORSE_LEVEL3) # Horse health HEALTH_LIST = (HORSE_HEALTH0, HORSE_HEALTH1, HORSE_HEALTH2, HORSE_HEALTH3) # Use-skill messages USE_SKILL_ERROR_TAIL_DICT = { 'IN_SAFE': CANNOT_SKILL_SELF_IN_SAFE, 'NEED_TARGET': CANNOT_SKILL_NEED_TARGET, 'NEED_EMPTY_BOTTLE': CANNOT_SKILL_NEED_EMPTY_BOTTLE, 'NEED_POISON_BOTTLE': CANNOT_SKILL_NEED_POISON_BOTTLE, 'REMOVE_FISHING_ROD': CANNOT_SKILL_REMOVE_FISHING_ROD, 'NOT_YET_LEARN': CANNOT_SKILL_NOT_YET_LEARN, 'NOT_MATCHABLE_WEAPON': CANNOT_SKILL_NOT_MATCHABLE_WEAPON, 'WAIT_COOLTIME': CANNOT_SKILL_WAIT_COOLTIME, 'NOT_ENOUGH_HP': CANNOT_SKILL_NOT_ENOUGH_HP, 'NOT_ENOUGH_SP': CANNOT_SKILL_NOT_ENOUGH_SP, 'CANNOT_USE_SELF': CANNOT_SKILL_USE_SELF, 'ONLY_FOR_ALLIANCE': CANNOT_SKILL_ONLY_FOR_ALLIANCE, 'CANNOT_ATTACK_ENEMY_IN_SAFE_AREA': CANNOT_SKILL_DEST_IN_SAFE, 'CANNOT_APPROACH': CANNOT_SKILL_APPROACH, 'CANNOT_ATTACK': CANNOT_SKILL_ATTACK, 'ONLY_FOR_CORPSE': CANNOT_SKILL_ONLY_FOR_CORPSE, 'EQUIP_FISHING_ROD': CANNOT_SKILL_EQUIP_FISHING_ROD, 'NOT_HORSE_SKILL': CANNOT_SKILL_NOT_HORSE_SKILL, 'HAVE_TO_RIDE': CANNOT_SKILL_HAVE_TO_RIDE, } # Notify messages NOTIFY_MESSAGE = { 'CANNOT_EQUIP_SHOP': CANNOT_EQUIP_IN_SHOP, 'CANNOT_EQUIP_EXCHANGE': CANNOT_EQUIP_IN_EXCHANGE, } # Attack messages ATTACK_ERROR_TAIL_DICT = { 'IN_SAFE': CANNOT_ATTACK_SELF_IN_SAFE, 'DEST_IN_SAFE': CANNOT_ATTACK_DEST_IN_SAFE, } # Shot messages SHOT_ERROR_TAIL_DICT = { 'EMPTY_ARROW': CANNOT_SHOOT_EMPTY_ARROW, 'IN_SAFE': CANNOT_SHOOT_SELF_IN_SAFE, 'DEST_IN_SAFE': CANNOT_SHOOT_DEST_IN_SAFE, } # Skill messages USE_SKILL_ERROR_CHAT_DICT = { 'NEED_EMPTY_BOTTLE': SKILL_NEED_EMPTY_BOTTLE, 'NEED_POISON_BOTTLE': SKILL_NEED_POISON_BOTTLE, 'ONLY_FOR_GUILD_WAR': SKILL_ONLY_FOR_GUILD_WAR, } # Shop/private-shop messages SHOP_ERROR_DICT = { 'NOT_ENOUGH_MONEY': SHOP_NOT_ENOUGH_MONEY, 'SOLDOUT': SHOP_SOLDOUT, 'INVENTORY_FULL': SHOP_INVENTORY_FULL, 'INVALID_POS': SHOP_INVALID_POS, 'NOT_ENOUGH_MONEY_EX': SHOP_NOT_ENOUGH_MONEY_EX, } # Character status description STAT_MINUS_DESCRIPTION = { 'HTH-': STAT_MINUS_CON, 'INT-': STAT_MINUS_INT, 'STR-': STAT_MINUS_STR, 'DEX-': STAT_MINUS_DEX, } # Map names MINIMAP_ZONE_NAME_DICT = { 'metin2_map_a1': MAP_A1, 'map_a2': MAP_A2, 'metin2_map_a3': MAP_A3, 'metin2_map_b1': MAP_B1, 'map_b2': MAP_B2, 'metin2_map_b3': MAP_B3, 'metin2_map_c1': MAP_C1, 'map_c2': MAP_C2, 'metin2_map_c3': MAP_C3, 'map_n_snowm_01': MAP_SNOW, 'metin2_map_n_flame_01': MAP_FLAME, 'metin2_map_n_desert_01': MAP_DESERT, 'metin2_map_milgyo': MAP_TEMPLE, 'metin2_map_spiderdungeon': MAP_SPIDER, 'metin2_map_deviltower1': MAP_SKELTOWER, 'metin2_map_guild_01': MAP_AG, 'metin2_map_guild_02': MAP_BG, 'metin2_map_guild_03': MAP_CG, 'metin2_map_trent': MAP_TREE, 'metin2_map_trent02': MAP_TREE2, 'season1/metin2_map_WL_01': MAP_WL, 'season1/metin2_map_nusluck01': MAP_NUSLUCK, 'Metin2_map_CapeDragonHead': MAP_CAPE, 'metin2_map_Mt_Thunder': MAP_THUNDER, 'metin2_map_dawnmistwood': MAP_DAWN, 'metin2_map_BayBlackSand': MAP_BAY, } # Path of quest icon file def GetLetterImageName(): return "season1/icon/scroll_close.tga" def GetLetterOpenImageName(): return "season1/icon/scroll_open.tga" def GetLetterCloseImageName(): return "season1/icon/scroll_close.tga" # Sell item question def DO_YOU_SELL_ITEM(sellItemName, sellItemCount, sellItemPrice): return DO_YOU_SELL_ITEM2 % (sellItemName, sellItemCount, NumberToMoneyString(sellItemPrice)) if (sellItemCount > 1) else DO_YOU_SELL_ITEM1 % (sellItemName, NumberToMoneyString(sellItemPrice)) # Buy item question def DO_YOU_BUY_ITEM(buyItemName, buyItemCount, buyItemPrice): return DO_YOU_BUY_ITEM2 % (buyItemName, buyItemCount, buyItemPrice) if (buyItemCount > 1) else DO_YOU_BUY_ITEM1 % (buyItemName, buyItemPrice) # Notify when you can't attach a specific item. def REFINE_FAILURE_CAN_NOT_ATTACH(attachedItemName): return REFINE_FAILURE_CAN_NOT_ATTACH0 % (attachedItemName) def REFINE_FAILURE_NO_SOCKET(attachedItemName): return REFINE_FAILURE_NO_SOCKET0 % (attachedItemName) # Drop item question def REFINE_FAILURE_NO_GOLD_SOCKET(attachedItemName): return REFINE_FAILURE_NO_GOLD_SOCKET0 % (attachedItemName) # Drop item question def HOW_MANY_ITEM_DO_YOU_DROP(dropItemName, dropItemCount): return HOW_MANY_ITEM_DO_YOU_DROP2 % (dropItemName, dropItemCount) if (dropItemCount > 1) else HOW_MANY_ITEM_DO_YOU_DROP1 % (dropItemName) # Fishing notify when looks like the fish is hooked. def FISHING_NOTIFY(isFish, fishName): return FISHING_NOTIFY1 % (fishName) if isFish else FISHING_NOTIFY2 % (fishName) # Fishing notify when you capture a fish. def FISHING_SUCCESS(isFish, fishName): return FISHING_SUCCESS1 % (fishName) if isFish else FISHING_SUCCESS2 % (fishName) # Convert a integer amount into a string and add . as separator for money. def NumberToMoneyString(n): return '0 {:s}'.format(MONETARY_UNIT0) if (n <= 0) else '{:s} {:s}'.format('.'.join([(i - 3) < 0 and str(n)[:i] or str(n)[i - 3 : i] for i in range(len(str(n)) % 3, len(str(n)) + 1, 3) if i]), MONETARY_UNIT0) # Convert a integer amount into a string and add . as separator for secondary coin. def NumberToSecondaryCoinString(n): return '0 {:s}'.format(MONETARY_UNIT_JUN) if (n <= 0) else '{:s} {:s}'.format('.'.join([(i - 3) < 0 and str(n)[:i] or str(n)[i - 3: i] for i in range(len(str(n)) % 3, len(str(n)) + 1, 3) if i]), MONETARY_UNIT_JUN) # Return the title of alignment by points. def GetAlignmentTitleName(alignment): if alignment >= 12000: return TITLE_NAME_LIST[0] elif alignment >= 8000: return TITLE_NAME_LIST[1] elif alignment >= 4000: return TITLE_NAME_LIST[2] elif alignment >= 1000: return TITLE_NAME_LIST[3] elif alignment >= 0: return TITLE_NAME_LIST[4] elif alignment > -4000: return TITLE_NAME_LIST[5] elif alignment > -8000: return TITLE_NAME_LIST[6] elif alignment > -12000: return TITLE_NAME_LIST[7] return TITLE_NAME_LIST[8] # Convert seconds to Days-Hours-Minutes def SecondToDHM(time): if time < 60: if IsARABIC(): return '%.2f %s' % (time, SECOND) else: return '0' + MINUTE minute = int((time / 60) % 60) hour = int((time / 60) / 60) % 24 day = int(int((time / 60) / 60) / 24) text = '' if day > 0: text += str(day) + DAY text += ' ' if hour > 0: text += str(hour) + HOUR text += ' ' if minute > 0: text += str(minute) + MINUTE return text # Convert seconds to Hours-Minutes def SecondToHM(time): if time < 60: if IsARABIC(): return '%.2f %s' % (time, SECOND) else: return '0' + MINUTE minute = int((time / 60) % 60) hour = int((time / 60) / 60) text = '' if hour > 0: text += str(hour) + HOUR if hour > 0: text += ' ' if minute > 0: text += str(minute) + MINUTE return text This is the hidden content, please Sign In or Sign Up 43 1 1 1 1 8 48 Check my GitHub Profile Click to find all the threads started by me [TOOL] Text file loader + JSON Link to comment Share on other sites More sharing options...
Premium Syreldar 1875 Posted April 1, 2019 Premium Share Posted April 1, 2019 I suggest you to put the file inside a Quote, because we're unable to download attachments. At least, it doesn't let me 1 "Nothing's free in this life. Ignorant people have an obligation to make up for their ignorance by paying those who help them. Either you got the brains or cash, if you lack both you're useless." Syreldar Link to comment Share on other sites More sharing options...
Forum Moderator VegaS™ 10274 Posted April 1, 2019 Author Forum Moderator Share Posted April 1, 2019 Added a gist link for download. Fixed NumberToMoneyString format method. (thanks to @Syreldar) 2 Check my GitHub Profile Click to find all the threads started by me [TOOL] Text file loader + JSON Link to comment Share on other sites More sharing options...
Premium Hunger 472 Posted July 14, 2019 Premium Share Posted July 14, 2019 0714 17:03:19906 :: uiCharacter.py(line:430) __LoadWindow uiCharacter.py(line:257) __BindObject uicharacterdetails.py(line:45) __init__ uicharacterdetails.py(line:73) __LoadScript uicharacterdetails.py(line:88) __Initialize uicharacterdetails.py(line:99) CreateTooltip CharacterWindow.__LoadWindow - <type 'exceptions.AttributeError'>:'module' object has no attribute 'GetVariableName' 0714 17:03:19906 :: ============================================================================================================ 0714 17:03:19906 :: Abort!!!! 1 Link to comment Share on other sites More sharing options...
Honorable Member Mali 41873 Posted July 14, 2019 Honorable Member Share Posted July 14, 2019 43 minutes ago, Caramelito said: 0714 17:03:19906 :: uiCharacter.py(line:430) __LoadWindow uiCharacter.py(line:257) __BindObject uicharacterdetails.py(line:45) __init__ uicharacterdetails.py(line:73) __LoadScript uicharacterdetails.py(line:88) __Initialize uicharacterdetails.py(line:99) CreateTooltip CharacterWindow.__LoadWindow - <type 'exceptions.AttributeError'>:'module' object has no attribute 'GetVariableName' 0714 17:03:19906 :: ============================================================================================================ 0714 17:03:19906 :: Abort!!!! Look at your old locale and find GetVariableName and add to new file 1 Link to comment Share on other sites More sharing options...
Forum Moderator VegaS™ 10274 Posted November 25, 2019 Author Forum Moderator Share Posted November 25, 2019 Link has been updated. Check my GitHub Profile Click to find all the threads started by me [TOOL] Text file loader + JSON Link to comment Share on other sites More sharing options...
hardy89 15 Posted November 26, 2019 Share Posted November 26, 2019 thank you Some functions would be shorter and more efficient with certain functions ... Like : def SecondToHM(time): return " ".join(map(str, divmod(time, 60))) 1 Link to comment Share on other sites More sharing options...
Forum Moderator VegaS™ 10274 Posted November 26, 2019 Author Forum Moderator Share Posted November 26, 2019 22 minutes ago, hardy89 said: thank you Some functions would be shorter and more efficient with certain functions ... Like : def SecondToHM(time): return " ".join(map(str, divmod(time, 60))) I could rewrite all of the functions and structure but i don't do it because the scope was to clean it not to change all structure, i did this long time ago.. if you saw the date. Btw, It's funny how you talk about shorter and efficient functions in python while... The code everytime can be improved, i don't like maybe a lot of scripts from metin2, but that doesn't means i've to rewrite them, there's isn't so much performance for a python script, if we don't talk about loops, searching, sort etc, it's fine how is it right now. 2 Check my GitHub Profile Click to find all the threads started by me [TOOL] Text file loader + JSON Link to comment Share on other sites More sharing options...
Premium filipw1 1931 Posted November 26, 2019 Premium Share Posted November 26, 2019 5 minut temu, VegaS™ napisał: I could rewrite all of the functions and structure but i don't do it because the scope was to clean it not to change all structure, i did this some time ago. It's funny how you talk about shorter and efficient functions in python while...you've no idea about python Let's don't do off-topic. I don't get it. You did rewrite bunch of functions except for last 3. Almost 2 years passed since he asked you about that. I think you are a bit cocky Link to comment Share on other sites More sharing options...
Forum Moderator VegaS™ 10274 Posted November 26, 2019 Author Forum Moderator Share Posted November 26, 2019 27 minutes ago, filipw1 said: I don't get it. You did rewrite bunch of functions except for last 3. I didn't rewrote the functions, is the same code, maybe removed unused lines or put them inline. Let's take an example, this: def GetAlignmentTitleName(alignment): if alignment >= 12000: return TITLE_NAME_LIST[0] elif alignment >= 8000: return TITLE_NAME_LIST[1] elif alignment >= 4000: return TITLE_NAME_LIST[2] elif alignment >= 1000: return TITLE_NAME_LIST[3] elif alignment >= 0: return TITLE_NAME_LIST[4] elif alignment > -4000: return TITLE_NAME_LIST[5] elif alignment > -8000: return TITLE_NAME_LIST[6] elif alignment > -12000: return TITLE_NAME_LIST[7] return TITLE_NAME_LIST[8] We could do it as (just example, ignore the comparation): (without making a dictionary) def GetAlignmentTitleName(currentAlignment): for alignmentIndex, alignmentValue in enumerate((12000, 8000, 4000, 1000, 0, -4000, -8000, -12000)): if currentAlignment >= alignmentValue: return TITLE_NAME_LIST[alignmentIndex] return TITLE_NAME_LIST[-1] Do you think people will understand it so well what's the index if they don't know what the function does? That's why i didn't touch these functions, they've edited (like added alignment grades) and don't know how to extend it. Btw, if you want to discuss this, we can go in off-topic category, already is enough. 3 Check my GitHub Profile Click to find all the threads started by me [TOOL] Text file loader + JSON Link to comment Share on other sites More sharing options...
hardy89 15 Posted November 26, 2019 Share Posted November 26, 2019 Il y a 2 heures, VegaS™ a dit : I could rewrite all of the functions and structure but i don't do it because the scope was to clean it not to change all structure, i did this long time ago.. if you saw the date. Btw, It's funny how you talk about shorter and efficient functions in python while... The code everytime can be improved, i don't like maybe a lot of scripts from metin2, but that doesn't means i've to rewrite them, there's isn't so much performance for a python script, if we don't talk about loops, searching, sort etc, it's fine how is it right now. I did that a long time ago to... Sorry, bbut seeing that you had refactored some functions, I thought you had forgotten this one. I just give an another way to do this. il y a une heure, VegaS™ a dit : def GetAlignmentTitleName(currentAlignment): for alignmentIndex, alignmentValue in enumerate((12000, 8000, 4000, 1000, 0, -4000, -8000, -12000)): if currentAlignment >= alignmentValue: return TITLE_NAME_LIST[alignmentIndex] return TITLE_NAME_LIST[-1] Do you think people will understand it so well what's the index if they don't know what the function does? That's why i didn't touch these functions, they've edited (like added alignment grades) and don't know how to extend it. Btw, if you want to discuss this, we can go in off-topic category, already is enough. I think that people will understand better this code, even without actually understanding how it works that the huge ternary conditions of the other functions ... like : def NumberToMoneyString(n): return '0 {:s}'.format(MONETARY_UNIT0) if (n <= 0) else '{:s} {:s}'.format(('.'.join([(i - 3) < 0 and str(n)[:i] or str(n)[i - 3 : i] for i in range(len(str(n)) % 3, len(str(n)) + 1, 3) if i]), MONETARY_UNIT0)) Word to the wise... Link to comment Share on other sites More sharing options...
Forum Moderator VegaS™ 10274 Posted November 26, 2019 Author Forum Moderator Share Posted November 26, 2019 (edited) You're right, then let's refactor this shit. Ymir method: def NumberToMoneyString(n) : if n <= 0 : return "0 %s" % (MONETARY_UNIT0) return "%s %s" % ('.'.join([ i-3<0 and str(n)[:i] or str(n)[i-3:i] for i in range(len(str(n))%3, len(str(n))+1, 3) if i ]), MONETARY_UNIT0) def NumberToSecondaryCoinString(n, coinType) : if n <= 0: n = 0 coinTypeString = "" if coinType == shop.SHOP_COIN_TYPE_SECONDARY_COIN: coinTypeString = MONETARY_UNIT_JUN elif coinType == shop.SHOP_COIN_TYPE_BATTLE_POINT: coinTypeString = BATTLE_POINT elif app.ENABLE_10TH_EVENT and coinType == shop.SHOP_COIN_TYPE_10TH_EVENT: coinTypeString = TENTH_COIN else: return "Not Valied" return "%s %s" % ('.'.join([ i-3<0 and str(n)[:i] or str(n)[i-3:i] for i in range(len(str(n))%3, len(str(n))+1, 3) if i ]), coinTypeString) My method: This is the hidden content, please Sign In or Sign Up And yes, Ymir killed the python for no-reason. Edited August 25, 2022 by Metin2 Dev Core X - External 2 Internal 19 1 1 6 1 13 Check my GitHub Profile Click to find all the threads started by me [TOOL] Text file loader + JSON Link to comment Share on other sites More sharing options...
Premium filipw1 1931 Posted November 26, 2019 Premium Share Posted November 26, 2019 (edited) 4 godziny temu, VegaS™ napisał: You're right, then let's refactor this shit. Ymir method: def NumberToMoneyString(n) : if n <= 0 : return "0 %s" % (MONETARY_UNIT0) return "%s %s" % ('.'.join([ i-3<0 and str(n)[:i] or str(n)[i-3:i] for i in range(len(str(n))%3, len(str(n))+1, 3) if i ]), MONETARY_UNIT0) def NumberToSecondaryCoinString(n, coinType) : if n <= 0: n = 0 coinTypeString = "" if coinType == shop.SHOP_COIN_TYPE_SECONDARY_COIN: coinTypeString = MONETARY_UNIT_JUN elif coinType == shop.SHOP_COIN_TYPE_BATTLE_POINT: coinTypeString = BATTLE_POINT elif app.ENABLE_10TH_EVENT and coinType == shop.SHOP_COIN_TYPE_10TH_EVENT: coinTypeString = TENTH_COIN else: return "Not Valied" return "%s %s" % ('.'.join([ i-3<0 and str(n)[:i] or str(n)[i-3:i] for i in range(len(str(n))%3, len(str(n))+1, 3) if i ]), coinTypeString) My method: def NumberToMoneyString(value, currency=MONETARY_UNIT0): return "{:0,.0f} {}".format(value, currency).replace(',', '.') # Test localeInfo.NumberToMoneyString(1934263992) # 1.934.263.992 Yang localeInfo.NumberToMoneyString(200000, MONETARY_UNIT_JUN) # 200.000 Jun localeInfo.NumberToMoneyString(4210, BATTLE_POINT) # 4.210 Combat Points localeInfo.NumberToMoneyString(500, TENTH_COIN) # 500 Anniversary Coin(s) And yes, Ymir killed the python for no-reason. My guess is that string formating wasn't a thing when they did that code, so they coded it just to work somewhat good. Edited August 25, 2022 by Metin2 Dev Core X - External 2 Internal Link to comment Share on other sites More sharing options...
Forum Moderator VegaS™ 10274 Posted November 26, 2019 Author Forum Moderator Share Posted November 26, 2019 2 hours ago, filipw1 said: My guess is that string formating wasn't a thing when they did that code, so they coded it just to work somewhat good. The function NumberToSecondaryCoinString which i posted is recent in their root, format string exists since Python 2.6, 11 years ago. Who stop them to use it? Nobody, they do a lot of things in a hard-way, they don't use many builtin functions which doing the same thing even in 2019, they prefer to do it manually in a hard way , they like old ways. Btw, i don't see the reason why we talk about this since we talked about 'refactoring', which means advantages include improved code readability and reduced complexity, doesn't matter what they had before. I think it's enough for today, let's don't talk about this anymore here, i'll update the gist link when i've time with these functions modified, thanks for support. 1 2 Check my GitHub Profile Click to find all the threads started by me [TOOL] Text file loader + JSON Link to comment Share on other sites More sharing options...
Forum Moderator VegaS™ 10274 Posted February 6, 2020 Author Forum Moderator Share Posted February 6, 2020 (edited) Default code for SecondToXXX: Spoiler def SecondToDHM(time): if time < 60: if IsARABIC(): return '%.2f %s' % (time, SECOND) else: return '0' + MINUTE minute = int((time / 60) % 60) hour = int((time / 60) / 60) % 24 day = int(int((time / 60) / 60) / 24) text = '' if day > 0: text += str(day) + DAY text += ' ' if hour > 0: text += str(hour) + HOUR text += ' ' if minute > 0: text += str(minute) + MINUTE return text def SecondToHM(time): if time < 60: if IsARABIC(): return '%.2f %s' % (time, SECOND) else: return '0' + MINUTE minute = int((time / 60) % 60) hour = int((time / 60) / 60) text = '' if hour > 0: text += str(hour) + HOUR if hour > 0: text += ' ' if minute > 0: text += str(minute) + MINUTE return text My extendable version: (I wrote that fast, so, if there's a problem with it, write me a pm, let's don't spam the topic.) This is the hidden content, please Sign In or Sign Up Results: print sec2time(100000, "DHMS") >>> 1Days 3Hours 46Minutes 40Seconds print sec2time(10000, "HMS") >>> 2Hours 46Minutes 40Seconds print sec2time(1000, "MS") >>> 16Minutes 40Seconds print sec2time(1000, "M") >>> 16Minutes print sec2time(100, "S") >>> 40Seconds print sec2time(3600, "DHMS", True) >>> 0Days 1Hours 0Minutes 0Seconds print sec2time(3600, "DHMS") >>> 1Hours I still don't have the right time to update the module but i'll do it asap. Edited August 22, 2020 by VegaS™ 2 13 Check my GitHub Profile Click to find all the threads started by me [TOOL] Text file loader + JSON Link to comment Share on other sites More sharing options...
Hik 108 Posted February 9, 2020 Share Posted February 9, 2020 When I use your localeinfo.py I get this: LoadLocaleError(locale/de/locale_game.txt) Link to comment Share on other sites More sharing options...
Forum Moderator VegaS™ 10274 Posted February 9, 2020 Author Forum Moderator Share Posted February 9, 2020 (edited) 1 hour ago, Hik said: LoadLocaleError(locale/de/locale_game.txt) Change open method with pack_open in LoadLocaleFile. (for those who've that problem) Edited February 9, 2020 by VegaS™ 3 Check my GitHub Profile Click to find all the threads started by me [TOOL] Text file loader + JSON Link to comment Share on other sites More sharing options...
Hik 108 Posted February 9, 2020 Share Posted February 9, 2020 (edited) Thanks, I did it! For those with problems, here is the VegaS solution: lines = open (srcFileName, "r"). readlines () to lines = pack_open (srcFileName, "r"). readlines () Edited February 9, 2020 by Hik Link to comment Share on other sites More sharing options...
Recommended Posts