Jump to content

Owsap

Honorable Member
  • Posts

    264
  • Joined

  • Last visited

  • Days Won

    29
  • Feedback

    91%

Everything posted by Owsap

  1. Download GitHub Repository Temporarily boosts the character's physical attack and / or skill damage. You can learn more about the system from the official wiki page. Thanks to @blackdragonx61 for the reversed effect position.
  2. As the title indicates, I'm sharing with everyone my test script for creating UI's, systems, etc... The advantage of this tool is that you don't need to restart your client every time you make a change which time is crucial. This tool will certainly help you tremendously if you know how to use it correctly. I will not go in much detail on how to use it because it's very basic and understandable. As long as you respect the primary class name and contain the default methods in the class, you're good. Otherwise, if you know what you're doing then you can modify the script to your liking. uiTestScript.py # # File : uiTestScript.py # Author : Owsap # Copyright (C) 2023 Owsap Development # import app import ui import wndMgr import uiToolTip import localeInfo """ # Example: # uiTest.py class TestWindow(ui.ScriptWindow): def __init__(self): ui.ScriptWindow.__init__(self) def __del__(self): ui.ScriptWindow.__del__(self) def Show(self): ui.ScriptWindow.Show(self) def Hide(self): ui.ScriptWindow.Hide(self) """ def LoadModule(name): import sys, imp if name in sys.modules: del sys.modules[name] if name in locals(): del locals()[name] if name in globals(): del globals()[name] module_info = imp.find_module(name) module = imp.load_module(name, *module_info) if not module in locals(): locals()[name] = module if not module in globals(): globals()[name] = module return module class TestScript(ui.BoardWithTitleBar): BOARD_WIDTH = 230 BOARD_HEIGHT = 80 SLOT_WIDTH = 150 def __init__(self): ui.BoardWithTitleBar.__init__(self) self.wndScript = None ## Item ToolTip self.tooltipItem = uiToolTip.ItemToolTip() self.tooltipItem.Hide() ## Board self.SetSize(self.BOARD_WIDTH, self.BOARD_HEIGHT) self.SetPosition(0, wndMgr.GetScreenHeight() - self.BOARD_HEIGHT) self.AddFlag("movable") self.SetTitleName("Test Script") self.SetCloseEvent(self.Hide) self.Show() ## Board > Slot Bar slotBar = ui.SlotBar() slotBar.SetParent(self) slotBar.SetSize(self.SLOT_WIDTH, 18) slotBar.SetPosition(13, 32) slotBar.Show() self.slotBar = slotBar ## Board > Slot Bar > EditLine editLine = ui.EditLine() editLine.SetParent(self.slotBar) editLine.SetSize(self.SLOT_WIDTH, 18) editLine.SetPosition(4, 3) editLine.SetMax(30) editLine.SetText("uiTest") editLine.Show() self.editLine = editLine ## Board > Load Button loadButton = ui.Button() loadButton.SetParent(self) loadButton.SetPosition(self.SLOT_WIDTH + 23, 32) loadButton.SetUpVisual("d:/ymir work/ui/public/small_button_01.sub") loadButton.SetOverVisual("d:/ymir work/ui/public/small_button_02.sub") loadButton.SetDownVisual("d:/ymir work/ui/public/small_button_03.sub") loadButton.SetEvent(self.__OnClickLoadButton) loadButton.SetText("Load") loadButton.Show() self.loadButton = loadButton ## Board > TextLine (Print Mouse Position) self.textLine = ui.TextLine() self.textLine.SetParent(self) self.textLine.SetFontName(localeInfo.UI_DEF_FONT) self.textLine.SetWindowHorizontalAlignCenter() self.textLine.SetHorizontalAlignCenter() self.textLine.SetWindowVerticalAlignBottom() self.textLine.SetVerticalAlignBottom() self.textLine.SetPosition(0, 13) self.textLine.SetText("Tip: Press F10 to load / reload.") self.textLine.Show() def __del__(self): ui.BoardWithTitleBar.__del__(self) del self.tooltipItem del self.tooltipSkill self.slotBar = None self.editLine = None self.loadButton = None self.textLine = None def Show(self): ui.BoardWithTitleBar.Show(self) def Hide(self): ui.BoardWithTitleBar.Hide(self) def OnKeyDown(self, key): if key == app.DIK_F10: self.__OnClickLoadButton() def __OnClickLoadButton(self): module_name = self.editLine.GetText() if not module_name: print("Empty module name") return if self.wndScript: self.wndScript.Hide() del self.wndScript self.wndScript = None try: module = LoadModule(module_name) except Exception as error: print("Error loading module: %s" % str(error)) return self.wndScript = module.TestWindow() #self.wndScript.SetItemToolTip(self.tooltipItem) self.wndScript.Show() wndTestScript = TestScript() wndTestScript.Show() Requirements In order to use this tool, you must make sure it executes the module when the client is started, if you're familiar with loginInfo.py, it's practically the same thing. Make sure you only enable this feature on a debug build for testing purposes. Simply add the script above on your main client directory and you're ready. """ 1. @ introLogin.py """ # Search if musicInfo.loginMusic != "": snd.SetMusicVolume(systemSetting.GetMusicVolume()) snd.FadeInMusic("BGM/"+musicInfo.loginMusic) # Add above self.__LoadTestFile("uiTestScript.py") """ 2. @ introLogin.py """ # Search def PopupDisplayMessage(self, msg): # Add above def __LoadTestFile(self, fileName): try: testScriptDict = {} execfile(fileName, testScriptDict) except: pass Here is an example of the uiTest.py file that will be loaded but you can load any other module that you add in your client main directory. Enjoy.
  3. Add this in your PythonPlayerModule.cpp, you should add it at the end of the file above "}". PyModule_AddIntConstant(poModule, "ITEM_SLOT_COUNT", c_ItemSlot_Count);
  4. Here is a little script that converts the translate.lua to the locale quest token including the placeholders for the string.format. Here is an example of the converstion. Keep in mind that this conversion is not 100% perfect and accurate so be aware that problems could occur. From what I've tested so far, all the individual checks I did where accurate. You will need to run the script along with the translate.lua and the locale_quest.txt, the file new_translate.lua will be generated.
  5. Added the Greek language, thanks to @ Kraaz Added the Hungarian language, thanks to @ SamuraiHUN Added suggestions by @Ludwig Improved some little things.
  6. First of all, thanks to @ Syreldar for bringing this matter to my attention and prompting me to examine this script more closely. As the title suggests, you may be curious about the specific improvements and fixes that were made, as well as the nature of this script. About the script and what it does. The pre_qc.py script serves as a pre-compiler, specifically designed for the quest language. In the quest language, only local variables are allowed, and it does not support the usage of global variables that extend across states, whens, or functions. The language's structure restricts the use of global "variables" in an efficient manner. Consequently, creating a function like "setting()" to emulate a global constant becomes inefficient. What was fixed? The main fix made in this script was about the incomplete group implementation which is defined as `define group` instead of `define`. With the fix, it is now possible not only to use `define group` correctly but also to index through these tables, similar to indexing a regular Lua table. However, dynamic indexing of the global table is not supported, meaning you cannot pass a local variable to index the table (e.g., table[i]). It is necessary to index by number. Another improvement made to the script pertains to strings. Previously, only contiguous strings without spaces were allowed. Now, it is possible to define strings that contain spaces. How to define global values? Defining them are very easy and simple, just put them at the top of your quest. They work very similar as C's preprocessor to allow the use of global constants. define MACRO_A 9009 define MACRO_B "Hello World" define group MACRO_C ["Hello", "World"] quest pre_qc_test begin state start begin when MACRO_A.chat.MACRO_B begin say_title(MACRO_B) -- "Hello World" say(string.format("%s %s", MACRO_C[1], MACRO_C[2])) -- "Hello World" local a = MACRO_C -- { "Hello", "World" } say_reward(string.format("%s %s!", a[1], a[2])) -- "Hello World!" --[[ for i = table.getn(MACRO_C), 1, -1 do print(MACRO_C[i]) -- UNSUPPORTED! end ]] end end end The Script The script itself remains largely unchanged in its original form. However, a few modifications have been made to enhance its functionality. Firstly, a main guard has been added to ensure proper execution. Additionally, the replace function has been edited to ensure the correct functioning of groups. Similarly, the my_split function has been modified to preserve strings accurately. Furthermore, the token list has been slightly adjusted to accommodate the specific "macros" that need to be replaced. However, it can be further extended if additional macros require replacement in the future. pre_qc.py # -*- coding: 949 -*- # 말 그대로 pre qc. # 우리 퀘스트 언어에는 지역 변수만이 있고, # state나, 심지어 when, function을 아우르는 전역 변수를 사용할 수 없다. # 전역 '변수'의 사용은 언어의 구조상 사용이 불가하고, 별 의미가 없다. # 하지만 전역 '상수'의 사용은 퀘스트 view 상으로 꼭 필요하기 때문에, # fuction setting () 과 같은 함수를 이용하여, # 매번 테이블을 생성하여 전역 상수를 흉내내어 사용하였다. # 이는 매우 비효율적이므로, # c의 preprocesser와 같이 pre qc를 만들어 전역 상수를 사용할 수 있도록 하였다. # 퀘스트를 qc로 컴파일 하기 전에 pre_qc.py를 통과하면, # pre_qc.py는 define 구문을 처리하고, 그 결과를 # pre_qc/filename에 저장한다. TOKEN_LIST = [ "-", "+", "*", "/", "<", ">", "!", "=", "~", "[", "]", "{", "}", "(", ")", "\t", "\n", "\r", " ", ",", ".", ] def split_by_quat(buf): p = False l = list(buf) l.reverse() s = "" res = [] while l: c = l.pop() if c == '"': if p == True: s += c res += [s] s = "" else: if len(s) != 0: res += [s] s = '"' p = not p elif c == "\\" and l[0] == '"': s += c s += l.pop() else: s += c if len(s) != 0: res += [s] return res def AddSepMiddleOfElement(l, sep): l.reverse() new_list = [l.pop()] while l: new_list.append(sep) new_list.append(l.pop()) return new_list def my_split_with_seps(s, seps): res = [s] for sep in seps: new_res = [] for r in res: sp = r.split(sep) sp = AddSepMiddleOfElement(sp, sep) new_res += sp res = new_res new_res = [] for r in res: if r != "": new_res.append(r) return new_res def my_split(s, seps): res = [] curr_token = "" is_quoted = False for c in s: if c == '"': if is_quoted: curr_token += c res.append(curr_token) curr_token = "" else: if curr_token != "": res.append(curr_token) curr_token = '"' is_quoted = not is_quoted elif c in seps and not is_quoted: if curr_token != "": res.append(curr_token) curr_token = "" else: curr_token += c if curr_token != "": res.append(curr_token) return res def MultiIndex(list, key): l = [] i = 0 for s in list: if s == key: l.append(i) i = i + 1 return l def Replace(lines, parameter_table, keys): r = [] for string in lines: l = split_by_quat(string) for s in l: if s[0] == '"': r += [s] else: tokens = my_split_with_seps(s, TOKEN_LIST) for key in keys: try: indices = MultiIndex(tokens, key) for i in indices: if len(parameter_table[key]) > 1: if tokens[i + 1] == "[" and tokens[i + 3] == "]": tokens[i] = parameter_table[key][int(tokens[i + 2]) - 1] tokens[i + 1:i + 4] = ["", "", ""] # [x] else: tokens[i] = "{ " + ", ".join(str(x) for x in parameter_table[key]) + " }" else: tokens[i] = parameter_table[key][0] except: pass r += tokens return r def MakeParameterTable(lines, parameter_table, keys): group_names = [] group_values = [] idx = 0 for line in lines: idx += 1 line = line.strip("\n") if (-1 != line.find("--")): line = line[0:line.find("--")] tokens = my_split(line, TOKEN_LIST) if len(tokens) == 0: continue if tokens[0] == "quest": start = idx break if tokens[0] == "define": if tokens[1] == "group": group_value = [] for value in tokens[3:]: if parameter_table.get(value, 0) != 0: value = parameter_table[value] group_value.append(value) parameter_table[tokens[2]] = group_value keys.append(tokens[2]) elif len(tokens) > 5: print("%d %s" % (idx, "Invalid syntax")) print("define <name> = <value>") print("define group <name> = [<val1>, <val2>, ...]") else: value = tokens[2] if parameter_table.get(value, 0) != 0: value = parameter_table[value] parameter_table[tokens[1]] = [value] keys.append(tokens[1]) parameter_table = dict(zip(group_names, group_values)) return start def run(path, file_name): parameter_table = dict() keys = [] path = path.strip("\n") if path == "": return lines = open(path).readlines() start = MakeParameterTable(lines, parameter_table, keys) if len(keys) == 0: return False lines = lines[start - 1:] r = Replace(lines, parameter_table, keys) f = open("pre_qc/" + file_name, "w") for s in r: f.write(s) return True if __name__ == "__main__": import sys if len(sys.argv) < 3: print("Usage: python pre_qc.py <input_file> <output_file>") else: run(sys.argv[1], sys.argv[2]) Input / Output Examples Input This is also an example of how you would use these global constants. Output This is the script file converted with the values of the global constants. Note that this will be the file that will be compiled.
  7. Special Item Group Creator A web tool created and designed to facilitate and save time. We have all been there, editing a giftbox and having to edit the index of the items, finding the virtual number (vnum), name, etc... These steps can be time wasting and sometimes frustrating so the point of this tool is to simply help you in that term. Let me introduce you to, An example of what it does, The previews of the web tool are self-explanatory and demonstrates exactly what it does. I have been tempted in the past to make this web tool but I never had the chance, but it's finally done! Enough talking about what it does and the story behind it, check it for yourself! You can access this tool via, [Hidden Content] More Information This web tool uses the latest available protos shared on M2Dev. There are currently 9 languages available to switch between. If you want to contribute in adding more languages or if you find any issues on current translations don't hesitate to contact me or reply on this topic. This tool is only focused on special item group, "special_item_group.txt". There is support for multiple drop types, you can find more information about them on the FAQ below the group type selection field. The tool will be updated every time there is a new proto and if there are any issues reported with the same. Finally, please take in consideration that this web tool is new and currently on a beta version, if you find any minority, please report the issue. . Hope you like it
  8. Here is a little update for the tooltips and a small correction for horizontal & vertical positions. EterLib/GrpTextInstance.cpp EterLib/GrpTextInstance.h EterLib/PythonWindow.cpp EterLib/PythonWindow.h Root/uiToolTip.py
  9. A little bit more information would be helpful, check your implementation of clip masking.
  10. Download Alternative download links → MEGA or Github Renewal of the quest page, now with categories for each quest. Here are some previous below, Before implementing, please continue reading the topic. In order to make the quest page renewal work properly you will need to implement the following features below released by @ Mali. Required Dependencies You can skip the feature below as I have already included it in the tutorial. .
  11. Try to rename the event to another thing for example, "minning". Also, try to see if you have any npc called "mine" in npclist.txt
  12. Thanks @ ReFresh, I fixed the tutorial.
  13. Updated Fixed issue with quest NPC VID reported by @ martysama0134. Added emotion event by request.
  14. I will correct that, I just noticed.
  15. I get what you mean, I didn't need to do that for the specific events because OnClick did that for me.
  16. Download Alternative download links → GitHub I couldn't find any of the events on the forum to avoid a double post so I decided to post it anyway in case it could be of use to someone. I will also update this topic with new events as needed and if requested. Quest Events / Triggers Fishing Mining Selling Buying Crafting Emoting See example below of how to use them. Usage Example
  17. For those that are using the 2018 root, system.py, change this in your file. This is a hot-fix for EOF issue when using the open method. @Chris90909090909090, @Ludwig, @JeeX ''' 1. @ system.py ''' # Search if mode == 'r': self.data = _chr(10).join(self.data.split(_chr(13) + _chr(10))) # Add above # 2020.04.05.Owsap - old_open support, Hot-fix EOF. if not self.data: tmp = old_open(filename) self.data = tmp and tmp.read() or ''
  18. ''' 1. ''' # Search def Show(self): ui.ScriptWindow.Show(self) self.SetTop() # Replace with def Show(self): ui.ScriptWindow.Show(self) self.SetTop() if app.__BL_MOUSE_WHEEL_TOP_WINDOW__: wndMgr.SetWheelTopWindow(self.hWnd) ''' 2. ''' # Search def RefreshLabel(self): # Add above if app.__BL_MOUSE_WHEEL_TOP_WINDOW__: def OnMouseWheelButtonUp(self): if self.ScrollBar: self.ScrollBar.OnUp() return True return False def OnMouseWheelButtonDown(self): if self.ScrollBar: self.ScrollBar.OnDown() return True return False
  19. I have to say, good work to @ Malifor achieving a new skill that is not easy to learn in a couple of days or weeks. RE requires a lot of exercise and patience and the fact you didn't quit and held to your journey through assembly makes you earn my respect . I also need to mention @ xP3NG3Rxfor his great contribution on this board and sharing his RE skills that has inspired all of us in learning something new.
  20. @JeeX You forgot to wrap MN between squared brackets, like this: say(format.string("[LC;99998;%s;[MN;%d];%d]", "Schwert", 101, 30)) Additional Information
  21. For anyone interested in also translating the hyperlink item name, you can do the following, although it's not official.
×
×
  • 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.