Jump to content

martysama0134

Honorable Member
  • Posts

    613
  • Joined

  • Last visited

  • Days Won

    96
  • Feedback

    100%

Everything posted by martysama0134

  1. I don't think there are other alternatives than using a class(object) in python2. I've edited the code for supporting cython and uiscriptlocale as well: class LocaleInfoWrapper(object): def __init__(self, wrapped): self.wrapped = wrapped def __getattr__(self, name): try: return getattr(self.wrapped, name) except AttributeError: dbg.TraceError("Locale attribute not found: {}".format(name)) return name def __hybrid_import(name,globals=None,locals=None,fromlist=None, level=-1): if __USE_CYTHON__ and rootlib.isExist(name): if name in sys.modules: dbg.Tracen('importing from sys.modules %s' % name) return sys.modules[name] dbg.Tracen('importing from rootlib %s' % name) newmodule = rootlib.moduleImport(name) module_do(newmodule) if name.lower() in ("localeinfo", "uiscriptlocale"): newmodule = LocaleInfoWrapper(newmodule) sys.modules[name] = newmodule return newmodule else: filename = name + '.py' if pack.Exist(filename): if name in sys.modules: dbg.Tracen('importing from sys.modules %s' % name) return sys.modules[name] dbg.Tracen('importing from pack %s' % name) newmodule = _process_result(compile(pack_file(filename,'r').read(),filename,'exec'),name) module_do(newmodule) if name.lower() in ("localeinfo", "uiscriptlocale"): newmodule = LocaleInfoWrapper(newmodule) sys.modules[name] = newmodule return newmodule else: dbg.Tracen('importing from lib %s' % name) return old_import(name,globals,locals,fromlist)#, level) I'm also returning directly 'name' if not found.
  2. GetOriginalPart() check if you're using it properly in item.cpp
  3. I gave a quick glance to your system, and I found a potential issue I reported some time ago to another c++ dungeon: Directly storing the character ptr in the dungeon instance is one of the main reasons for instability. You should use a function like this: LPCHARACTER FindValidCharacter(const VID & vid) { if (!vid.GetID()) return nullptr; const auto ch = CHARACTER_MANAGER::instance().Find(vid.GetID()); return (ch && !ch->IsDead()) ? ch : nullptr; } ------------------------------------------------------------------------- The reason why I write dungeons in LUA, and functionality in C++ is because: The whole lua environment works fine out of the box I can delegate quick edits to other people who have little to no knowledge It's incredibly easy to crash the whole process in a c++ dungeon, in comparison to lua People don't know how to correctly manage memory in c++, so it would have been better if they sticked to a simpler already-managed environment The maintenance of a c++ dungeon gets incredibly tiresome, in comparison to lua ------------------------------------------------------------------------- I also suggest you to never use magic numbers like [8][2], and to stick with std::array & an enumeration list to prevent repeated code like this: ------------------------------------------------------------------------- Thanks for sharing.
  4. "reboot" now is "shutdown -r now". They changed the behavior in the last 7 years
  5. I think he's using some leaked / stolen version. My discord also has a new section now for my supporters
  6. v2.9 out! added --hiddenfiles and --skiphiddenfiles for folders/files that start with . or with the invisible attribute PackMakerLite.json with more comments
  7. I slightly refactored. You can also specify the poly vnum now. (I skipped the ReadMonsterDropItemGroup part) Here a patch: From c5da3c9abf1608347bb5bec5fae06213c75c1ae9 Mon Sep 17 00:00:00 2001 From: Marty Sama <[email protected]> Date: Thu, 16 Nov 2023 06:19:28 +0100 Subject: [PATCH] ENABLE_MOB_DROP_POLY s3ll_server/Srcs/Server/common/CommonDefines.h | 1 + s3ll_server/Srcs/Server/game/src/char_item.cpp | 44 ++++++++++++++++++---- s3ll_server/Srcs/Server/game/src/item_manager.h | 7 +++- .../Server/game/src/item_manager_read_tables.cpp | 10 ++++- 4 files changed, 50 insertions(+), 12 deletions(-) diff --git a/s3ll_server/Srcs/Server/common/CommonDefines.h b/s3ll_server/Srcs/Server/common/CommonDefines.h index e7bc400c..33b05884 100644 --- a/s3ll_server/Srcs/Server/common/CommonDefines.h +++ b/s3ll_server/Srcs/Server/common/CommonDefines.h @@ -91,6 +91,7 @@ enum eCommonDefines { ... ... ... +#define ENABLE_MOB_DROP_POLY // enable drop type 'poly' for special_item_group.txt (idx drop mobvnum pct customitemvnum) ... ... ... diff --git a/s3ll_server/Srcs/Server/game/src/char_item.cpp b/s3ll_server/Srcs/Server/game/src/char_item.cpp index 1900b5c4..a9631838 100644 --- a/s3ll_server/Srcs/Server/game/src/char_item.cpp +++ b/s3ll_server/Srcs/Server/game/src/char_item.cpp @@ -2023,11 +2023,16 @@ bool CHARACTER::UseItemEx(LPITEM item, TItemPos DestCell) case CSpecialItemGroup::POISON: ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»óÀÚ¿¡¼­ ³ª¿Â ³ì»ö ¿¬±â¸¦ µéÀ̸¶½ÃÀÚ µ¶ÀÌ ¿Â¸öÀ¸·Î ÆÛÁý´Ï´Ù!")); break; #ifdef ENABLE_WOLFMAN_CHARACTER case CSpecialItemGroup::BLEEDING: ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»óÀÚ¿¡¼­ ³ª¿Â ³ì»ö ¿¬±â¸¦ µéÀ̸¶½ÃÀÚ µ¶ÀÌ ¿Â¸öÀ¸·Î ÆÛÁý´Ï´Ù!")); break; #endif + #ifdef ENABLE_MOB_DROP_POLY + case CSpecialItemGroup::POLY: + ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»óÀÚ¿¡¼­ ¸ó½ºÅÍ°¡ ³ªÅ¸³µ½À´Ï´Ù!")); + break; + #endif case CSpecialItemGroup::MOB_GROUP: ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»óÀÚ¿¡¼­ ¸ó½ºÅÍ°¡ ³ªÅ¸³µ½À´Ï´Ù!")); break; @@ -2107,11 +2112,16 @@ bool CHARACTER::UseItemEx(LPITEM item, TItemPos DestCell) case CSpecialItemGroup::POISON: ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»óÀÚ¿¡¼­ ³ª¿Â ³ì»ö ¿¬±â¸¦ µéÀ̸¶½ÃÀÚ µ¶ÀÌ ¿Â¸öÀ¸·Î ÆÛÁý´Ï´Ù!")); break; #ifdef ENABLE_WOLFMAN_CHARACTER case CSpecialItemGroup::BLEEDING: ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»óÀÚ¿¡¼­ ³ª¿Â ³ì»ö ¿¬±â¸¦ µéÀ̸¶½ÃÀÚ µ¶ÀÌ ¿Â¸öÀ¸·Î ÆÛÁý´Ï´Ù!")); break; #endif + #ifdef ENABLE_MOB_DROP_POLY + case CSpecialItemGroup::POLY: + ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»óÀÚ¿¡¼­ ¸ó½ºÅÍ°¡ ³ªÅ¸³µ½À´Ï´Ù!")); + break; + #endif case CSpecialItemGroup::MOB_GROUP: ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»óÀÚ¿¡¼­ ¸ó½ºÅÍ°¡ ³ªÅ¸³µ½À´Ï´Ù!")); break; @@ -3728,11 +3738,16 @@ bool CHARACTER::UseItemEx(LPITEM item, TItemPos DestCell) case CSpecialItemGroup::POISON: ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»óÀÚ¿¡¼­ ³ª¿Â ³ì»ö ¿¬±â¸¦ µéÀ̸¶½ÃÀÚ µ¶ÀÌ ¿Â¸öÀ¸·Î ÆÛÁý´Ï´Ù!")); break; #ifdef ENABLE_WOLFMAN_CHARACTER case CSpecialItemGroup::BLEEDING: ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»óÀÚ¿¡¼­ ³ª¿Â ³ì»ö ¿¬±â¸¦ µéÀ̸¶½ÃÀÚ µ¶ÀÌ ¿Â¸öÀ¸·Î ÆÛÁý´Ï´Ù!")); break; #endif + #ifdef ENABLE_MOB_DROP_POLY + case CSpecialItemGroup::POLY: + ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»óÀÚ¿¡¼­ ¸ó½ºÅÍ°¡ ³ªÅ¸³µ½À´Ï´Ù!")); + break; + #endif case CSpecialItemGroup::MOB_GROUP: ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»óÀÚ¿¡¼­ ¸ó½ºÅÍ°¡ ³ªÅ¸³µ½À´Ï´Ù!")); break; @@ -7386,14 +7401,27 @@ bool CHARACTER::GiveItemFromSpecialItemGroup(DWORD dwGroupNum, std::vector<DWORD bSuccess = true; } break; #ifdef ENABLE_WOLFMAN_CHARACTER case CSpecialItemGroup::BLEEDING: { AttackedByBleeding(nullptr); bSuccess = true; } break; #endif + #ifdef ENABLE_MOB_DROP_POLY + case CSpecialItemGroup::POLY: + { + const auto polyVnum = iRarePct ? iRarePct : 70104; + item_get = AutoGiveItem(polyVnum, 1, 0); + if (item_get) + { + item_get->SetSocket(0, dwCount); + bSuccess = true; + } + } + break; + #endif case CSpecialItemGroup::MOB_GROUP: { const int sx = GetX() - number(300, 500); diff --git a/s3ll_server/Srcs/Server/game/src/item_manager.h b/s3ll_server/Srcs/Server/game/src/item_manager.h index 0c1e19ec..d8e604b9 100644 --- a/s3ll_server/Srcs/Server/game/src/item_manager.h +++ b/s3ll_server/Srcs/Server/game/src/item_manager.h @@ -39,9 +39,12 @@ class CSpecialItemGroup DRAIN_HP, POISON, MOB_GROUP, #ifdef ENABLE_WOLFMAN_CHARACTER BLEEDING, #endif + #ifdef ENABLE_MOB_DROP_POLY + POLY, + #endif }; enum ESIGType { NORMAL, PCT, QUEST, SPECIAL }; diff --git a/s3ll_server/Srcs/Server/game/src/item_manager_read_tables.cpp b/s3ll_server/Srcs/Server/game/src/item_manager_read_tables.cpp index 2a921bfb..d7c67863 100644 --- a/s3ll_server/Srcs/Server/game/src/item_manager_read_tables.cpp +++ b/s3ll_server/Srcs/Server/game/src/item_manager_read_tables.cpp @@ -239,12 +239,18 @@ bool ITEM_MANAGER::ReadSpecialDropItemFile(const char * c_pszFileName) { dwVnum = CSpecialItemGroup::POISON; } #ifdef ENABLE_WOLFMAN_CHARACTER else if (name == "bleeding") { dwVnum = CSpecialItemGroup::BLEEDING; } #endif + #ifdef ENABLE_MOB_DROP_POLY + else if (name == "poly") + { + dwVnum = CSpecialItemGroup::POLY; + } + #endif else if (name == "group") { dwVnum = CSpecialItemGroup::MOB_GROUP; Result:
  8. You're decreasing the level of security of the packets by using a static key. A man in the middle attack is possible to sniff the players' passwords. If after enabled you're getting DCs, open protocol.h and change this macro to this: #define DEFAULT_PACKET_BUFFER_SIZE (150*1024) //@warme015 prevent dc if there are many entities The alternative way would be to call buffer_adjust_size in desc.cpp
  9. Updated with the following changes: 1) """ Added support for #--# and the relative column aliases """ egr = EterGroupReader() egr.LoadFromFile('sample.txt') node = egr.FindNode("ApplyNumSettings", "Default", "basis") if node: print("GRADE_NORMAL", "has index", node.GetAliasIndex("GRADE_NORMAL"), "and value", node.GetAliasValue("GRADE_NORMAL")) print("GRADE_BRILLIANT", "has index", node.GetAliasIndex("GRADE_BRILLIANT"), "and value", node.GetAliasValue("GRADE_BRILLIANT")) print("GRADE_RARE", "has index", node.GetAliasIndex("GRADE_RARE"), "and value", node.GetAliasValue("GRADE_RARE")) print("GRADE_ANCIENT", "has index", node.GetAliasIndex("GRADE_ANCIENT"), "and value", node.GetAliasValue("GRADE_ANCIENT")) print("GRADE_LEGENDARY", "has index", node.GetAliasIndex("GRADE_LEGENDARY"), "and value", node.GetAliasValue("GRADE_LEGENDARY")) print("GRADE_MYTH", "has index", node.GetAliasIndex("GRADE_MYTH"), "and value", node.GetAliasValue("GRADE_MYTH")) egr.SaveToFile('sample-out.txt') Result: GRADE_NORMAL has index 0 and value 1 GRADE_BRILLIANT has index 1 and value 1 GRADE_RARE has index 2 and value 1 GRADE_ANCIENT has index 3 and value 2 GRADE_LEGENDARY has index 4 and value 2 GRADE_MYTH has index 5 and value 3 From .txt: Group ApplyNumSettings { Group Default { #--# GRADE_NORMAL GRADE_BRILLIANT GRADE_RARE GRADE_ANCIENT GRADE_LEGENDARY GRADE_MYTH basis 1 1 1 2 2 3 add_min 0 0 0 0 0 0 add_max 0 1 2 2 3 3 } } 2) """ Added find or create group def """ egr = MobDropItemHelper() egr.LoadFromFile('mob_drop_item.txt') group = FindOrCreateMobDropGroup(egr, 691, "limit") egr.AddIndexElement(group, [27001, 11, 6.12]) egr.AddIndexElement(group, [27002, 22, 12.34]) egr.AddIndexElement(group, [27003, 33, 18.56]) egr.PrintTree(group) egr.SaveToFile('mob_drop_item-out.txt') Result: Group Mob691TypeLimit: type: ['limit'] mob: [691] 1: [27001, 11, 6.12] 2: [27002, 22, 12.34] 3: [27003, 33, 18.56] 3) """ Added some functions to edit the MSM files """ #load a .msm and replace a specific shape from <old> to <new> egr = RaceDataHelper() egr.LoadFromFile('assassin_m.msm') egr.ReplaceShapeIndexValue(44114, 44115) egr.SaveToFile('assassin_m-out.msm')
  10. [Hidden Content] (M2DL) I've created a script that processes Eter Group files. It can load, save, edit, repair, mass-update, and more. Right now I'm using it for automatically repairing mob_drop_item.txt, and mass-updating the drops at once. It also preserves the comments made with '#' in their correct place, except for the comments in the root below other Groups. (they'll be moved on top) The tree of a loaded group file will be like: ScriptType: ['RaceDataScript'] BaseModelFileName: "d:/ymir work/pc/warrior/warrior_novice.GR2" Group CorDraconis(Mystical): Vnum: [51506] 1: [115000, 1, 1] 2: [125000, 1, 1] 3: [135000, 1, 1] 4: [145000, 1, 1] 5: [155000, 1, 1] 6: [165000, 1, 1] Group BodyChest: Vnum: [71203] 1: [50401, 1, 1] 2: [50402, 1, 1] 3: [50403, 1, 1] 4: [50404, 1, 1] 5: [50405, 1, 1] Group MentalChest: Vnum: [71205] 1: [50416, 1, 1] 2: [50417, 1, 1] 3: [50418, 1, 1] 4: [50419, 1, 1] 5: [50420, 1, 1] Group Cung_Mok: type: ['drop'] mob: [151] 1: [71151, 1, 100] 2: [71151, 1, 100] 3: [71151, 1, 100] 4: [71151, 1, 100] 5: [71151, 1, 100] 6: [71299, 1, 50] 7: [71740, 2, 50] 8: [1, 20000, 50] 9: [1, 30000, 30] Group ApplyNumSettings: Group Default: basis: [1, 1, 1, 2, 2, 3] add_min: [0, 0, 0, 0, 0, 0] add_max: [0, 1, 2, 2, 3, 3] Group NotSoDefault: basis: [1, 2, 3, 4, 5] add_min: [5, 4, 3, 2, 1] add_max: [11, 3, 5, 7, 22] Group MixedTypes: 1: ['MAX_SP', 500] 2: ['RESIST_WIND', 10] 3: ['ENCHANT_WIND', 10] Group HairData: PathName: "d:/ymir Work/pc/warrior/" HairDataCount: [999] Group HairData00: HairIndex: [0] Model: "hair/hair_1_1.gr2" SourceSkin: "hair/hair_1_1.dds" TargetSkin: "warrior_hair_01.dds" Group HairData01: HairIndex: [1] Model: "hair/hair_1_1.gr2" SourceSkin: "hair/hair_1_1.dds" TargetSkin: "warrior_hair_01_white.dds" Group HairData02: HairIndex: [2] Model: "hair/hair_1_1.gr2" SourceSkin: "hair/hair_1_1.dds" TargetSkin: "warrior_hair_01_gold.dds" Examples: if True: # load, print, and save egr = EterGroupReader() egr.LoadFromFile('sample.txt') egr.PrintTree() egr.SaveToFile('sample-out.txt') if True: # find node and print it egr = EterGroupReader() egr.LoadFromFile('sample.txt') node = egr.FindNode("ApplyNumSettings", "Default", "basis") if node: print("node {} found with value {}".format(node.key, node.value)) if True: # find node and edit it egr = EterGroupReader() egr.LoadFromFile('sample.txt') node = egr.FindNode("ApplyNumSettings", "Default", "basis") if node: node.value = [11, 22, 33, 44, 55, 66] egr.SaveToFile('sample-out.txt') if True: # iter all groups and sub groups egr = EterGroupReader() egr.LoadFromFile('sample.txt') # Create an instance of the iterator group_iterator = EterGroupIterator(egr, skipRoot=True) # Iterate over all groups using a lambda or function for group in group_iterator: print(f"Group Name: {group.name}") if True: # load mob_drop_item and print only the metins egr = MobDropItemHelper() egr.LoadFromFile('mob_drop_item.txt') for group in egr.GetGroupsOfMetins(): egr.PrintTree(group) print("HIGHEST", GetGroupHighestIndex(group)) egr.SaveToFile('mob_drop_item-out.txt') if True: # load mob_drop_item and add a red potion in the metin drops egr = MobDropItemHelper() egr.LoadFromFile('mob_drop_item.txt') for group in egr.GetGroupsOfMetinsAndDrop(): egr.AddIndexElement(group, [27001, 1, 6.6]) egr.PrintTree(group) egr.SaveToFile('mob_drop_item-out.txt') if True: # load mob_drop_item and add a red potion in vnum list egr = MobDropItemHelper() egr.LoadFromFile('mob_drop_item.txt') for group in egr.GetGroupsOf(lambda group: IsVnumInListGroup(group, [101, 105, 1059])): egr.AddIndexElement(group, [27001, 1, 6.6]) egr.PrintTree(group) egr.SaveToFile('mob_drop_item-out.txt') if True: # load mob_drop_item and check for errors egr = MobDropItemHelper() egr.LoadFromFile('mob_drop_item.txt') for group in egr.GetGroups(): valid, found = CheckValidContinuousGroupIndex(group) if not valid: egr.PrintTree(group) print(f"NOT VALID: Error at group '{group.name}' index {found}") break egr.SaveToFile('mob_drop_item-out.txt') if True: # load mob_drop_item and repair for index errors egr = MobDropItemHelper() egr.LoadFromFile('mob_drop_item.txt') for group in egr.GetGroups(): RepairContinuousGroupIndex(group) egr.SaveToFile('mob_drop_item-out.txt') If you have any suggestions, comment the topic.
  11. I created an auto-refresh feature every 5s: import app import ui import wndMgr import uiToolTip import localeInfo import dbg import sys, imp REFRESH_TIME = 5.0 MSG_STRING02 = "Tip: Press F11 to auto refresh: {}" def LoadModule(name): if name in sys.modules: del sys.modules[name] if name in locals(): del locals()[name] if name in globals(): del globals()[name] # Open the module file module_file_path = "{}.py".format(name) module_file = old_open(module_file_path, 'rb') # Load the module from the file module = imp.load_module(name, module_file, module_file_path, ('.py', 'rb', imp.PY_SOURCE)) 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+30 SLOT_WIDTH = 150 def __init__(self): ui.BoardWithTitleBar.__init__(self) self.wndScript = None self.autoRefresh = False self.nextRefresh = 0.0 ## 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("bio")#"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, 33) self.textLine.SetText("Tip: Press F10 to load / reload.") self.textLine.Show() ## Board > TextLine2 (Print Mouse Position) self.textLine2 = ui.TextLine() self.textLine2.SetParent(self) self.textLine2.SetFontName(localeInfo.UI_DEF_FONT) self.textLine2.SetWindowHorizontalAlignCenter() self.textLine2.SetHorizontalAlignCenter() self.textLine2.SetWindowVerticalAlignBottom() self.textLine2.SetVerticalAlignBottom() self.textLine2.SetPosition(0, 13) self.textLine2.SetText(MSG_STRING02.format("OFF")) self.textLine2.Show() def OnUpdate(self): if self.autoRefresh: if self.nextRefresh < app.GetTime(): self.nextRefresh = app.GetTime() + REFRESH_TIME self.__OnClickLoadButton() 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() elif key == app.DIK_F11: self.__OnClickToggleAutoRefresh() def __OnClickToggleAutoRefresh(self): self.autoRefresh = not self.autoRefresh self.textLine2.SetText(MSG_STRING02.format("ON" if self.autoRefresh else "OFF")) def __OnClickLoadButton(self): module_name = self.editLine.GetText() if not module_name: dbg.TraceError("Empty module name") return if self.wndScript: self.wndScript.Hide() del self.wndScript self.wndScript = None dbg.TraceError("Loading module: {}".format(module_name)) try: module = LoadModule(module_name) except Exception as error: dbg.TraceError("Error loading module: {}".format(error)) return self.wndScript = module.BioWindow() self.wndScript.Open() wndTestScript = TestScript() wndTestScript.Show()
  12. Someone had an issue with it using my client. I made it working, refresh too: reload.py import app import ui import wndMgr import uiToolTip import localeInfo import dbg import sys, imp def LoadModule(name): if name in sys.modules: del sys.modules[name] if name in locals(): del locals()[name] if name in globals(): del globals()[name] # Open the module file module_file_path = "{}.py".format(name) module_file = old_open(module_file_path, 'r') # Load the module from the file module = imp.load_module(name, module_file, module_file_path, ('.py', 'r', imp.PY_SOURCE)) 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("uibio")#"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: dbg.TraceError("Empty module name") return if self.wndScript: self.wndScript.Hide() del self.wndScript self.wndScript = None dbg.TraceError("Loading module: {}".format(module_name)) try: module = LoadModule(module_name) except Exception as error: dbg.TraceError("Error loading module: {}".format(error)) return self.wndScript = module.BioWindow() #EDIT WITH THE CORRECT WINDOW NAME self.wndScript.Open() wndTestScript = TestScript() wndTestScript.Show()
  13. The game is single-thread, so I highly recommend you to add the if (quest::CQuestManager::instance().GetPCForce(GetPlayerID())->IsRunning()) check before the for loop. It will be either always true, or always false.
  14. How to make it more pretty: common/length.h inside SItemPos struct (above IsEquipPosition()), paste: bool IsSamePosition(const SItemPos & other) const { return *this==other || ((INVENTORY == window_type || EQUIPMENT == window_type) && (INVENTORY == other.window_type || EQUIPMENT == other.window_type) && cell == other.cell); } game/src/char_item.cpp, at the beginning of CHARACTER::MoveItem function: bool CHARACTER::MoveItem(TItemPos Cell, TItemPos DestCell, uint8_t count) { if (Cell.IsSamePosition(DestCell)) // @fixme196 return false; I'd probably rename IsSamePosition to HasSamePosition, but ignore that.
  15. You're forgetting Mall: // PythonNetworkStream.cpp // 1. Search: Set(HEADER_GC_MALL_SET, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCItemSet), STATIC_SIZE_PACKET)); // 1. Replace with: Set(HEADER_GC_MALL_SET, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCItemSet2), STATIC_SIZE_PACKET));
  16. Without timers, or quest flags (persistent memory): [Hidden Content] (enumtype branch) [Hidden Content]blob/enumtype/PulseManager.h It stores something like 10 bytes per player (when they use it) in an std::unordered_map (hash map with O(1) access time). It's only stored in memory, and not shared to other cores (it's irrelevant for this case).
  17. This fixes the fog.tga issue too. I forgot to add this fix on the WE.
  18. If you want to calculate the size of the stone array automatically, you can use this function unsigned int BlueDragon_GetDragonStoneCount() { lua_State* L = quest::CQuestManager::instance().GetLuaState(); const int stack_top = lua_gettop(L); lua_getglobal(L, "BlueDragonSetting"); if (false == lua_istable(L, -1)) { lua_settop(L, stack_top); return 0; } lua_pushstring(L, "DragonStone"); lua_gettable(L, -2); if (false == lua_istable(L, -1)) { lua_settop(L, stack_top); sys_err("BlueDragon: no required table DragonStone"); return 0; } const unsigned int count = static_cast<unsigned int>(luaL_getn(L, -1)); lua_settop(L, stack_top); return count; } ty chatgpt for
  19. I did a small refactory, but I haven't tested it yet: diff --git a/s3ll_server/Srcs/Server/game/src/BlueDragon.cpp b/s3ll_server/Srcs/Server/game/src/BlueDragon.cpp index f8bfd0f5..7995fc09 100644 --- a/s3ll_server/Srcs/Server/game/src/BlueDragon.cpp +++ b/s3ll_server/Srcs/Server/game/src/BlueDragon.cpp @@ -135,9 +135,22 @@ int BlueDragon_Damage (LPCHARACTER me, LPCHARACTER pAttacker, int dam) if (nullptr == me || nullptr == pAttacker) return dam; - if (true == pAttacker->IsMonster() && 2493 == pAttacker->GetMobTable().dwVnum) + #ifdef ENABLE_BLUEDRAGON_RENEWAL + if (pAttacker->IsMonster() && BlueDragon::BossVnum == pAttacker->GetMobTable().dwVnum) { - for (int i=1 ; i <= 4 ; ++i) + for (int i=1; i <= BlueDragon::StoneCount; ++i) + { + const auto dwDragonStoneID = BlueDragon_GetIndexFactor("DragonStone", i, "vnum"); + const auto cnt = SECTREE_MANAGER::instance().GetMonsterCountInMap( me->GetMapIndex(), dwDragonStoneID); + if (cnt > 0) + return 0; + } + } + #endif + + if (pAttacker->IsMonster() && BlueDragon::BossVnum == pAttacker->GetMobTable().dwVnum) + { + for (int i=1; i <= BlueDragon::StoneCount; ++i) { if (ATK_BONUS == BlueDragon_GetIndexFactor("DragonStone", i, "effect_type")) { @@ -152,9 +165,9 @@ int BlueDragon_Damage (LPCHARACTER me, LPCHARACTER pAttacker, int dam) } } - if (true == me->IsMonster() && 2493 == me->GetMobTable().dwVnum) + if (me->IsMonster() && BlueDragon::BossVnum == me->GetMobTable().dwVnum) { - for (int i=1 ; i <= 4 ; ++i) + for (int i=1; i <= BlueDragon::StoneCount; ++i) { if (DEF_BONUS == BlueDragon_GetIndexFactor("DragonStone", i, "effect_type")) { @@ -172,9 +185,9 @@ int BlueDragon_Damage (LPCHARACTER me, LPCHARACTER pAttacker, int dam) } } - if (true == me->IsStone() && 0 != pAttacker->GetMountVnum()) + if (me->IsStone() && 0 != pAttacker->GetMountVnum()) { - for (int i=1 ; i <= 4 ; ++i) + for (int i=1; i <= BlueDragon::StoneCount; ++i) { if (me->GetMobTable().dwVnum == BlueDragon_GetIndexFactor("DragonStone", i, "vnum")) { diff --git a/s3ll_server/Srcs/Server/game/src/BlueDragon.h b/s3ll_server/Srcs/Server/game/src/BlueDragon.h index 25b7d5b4..d1a44149 100644 --- a/s3ll_server/Srcs/Server/game/src/BlueDragon.h +++ b/s3ll_server/Srcs/Server/game/src/BlueDragon.h @@ -1,5 +1,16 @@ +#ifndef BLUE_DRAGON_H +#define BLUE_DRAGON_H +#pragma once + +#define ENABLE_BLUEDRAGON_RENEWAL + +namespace BlueDragon { + constexpr int BossVnum = 2493; + constexpr int StoneCount = 4; +} extern int BlueDragon_StateBattle (LPCHARACTER); extern time_t UseBlueDragonSkill (LPCHARACTER, unsigned int); extern int BlueDragon_Damage (LPCHARACTER me, LPCHARACTER attacker, int dam); +#endif // BLUE_DRAGON_H diff --git a/s3ll_server/Srcs/Server/game/src/char.cpp b/s3ll_server/Srcs/Server/game/src/char.cpp index 9f564ea6..50692f6e 100644 --- a/s3ll_server/Srcs/Server/game/src/char.cpp +++ b/s3ll_server/Srcs/Server/game/src/char.cpp @@ -53,6 +53,7 @@ #include "BlueDragon_Binder.h" #include "skill_power.h" #include "buff_on_attributes.h" +#include "BlueDragon.h" #ifdef __PET_SYSTEM__ #include "PetSystem.h" @@ -2349,12 +2350,12 @@ EVENTFUNC(recovery_event) if (ch->IsAffectFlag(AFF_BLEEDING)) return PASSES_PER_SEC(MAX(1, ch->GetMobTable().bRegenCycle)); #endif - if (2493 == ch->GetMobTable().dwVnum) + if (BlueDragon::BossVnum == ch->GetMobTable().dwVnum) { int regenPct = BlueDragon_GetRangeFactor("hp_regen", ch->GetHPPct()); regenPct += ch->GetMobTable().bRegenPercent; - for (int i=1 ; i <= 4 ; ++i) + for (int i=1; i <= BlueDragon::StoneCount; ++i) { if (REGEN_PECT_BONUS == BlueDragon_GetIndexFactor("DragonStone", i, "effect_type")) { @@ -2382,9 +2383,9 @@ EVENTFUNC(recovery_event) return 0; } - if (2493 == ch->GetMobTable().dwVnum) + if (BlueDragon::BossVnum == ch->GetMobTable().dwVnum) { - for (int i=1 ; i <= 4 ; ++i) + for (int i=1; i <= BlueDragon::StoneCount; ++i) { if (REGEN_TIME_BONUS == BlueDragon_GetIndexFactor("DragonStone", i, "effect_type")) { diff --git a/s3ll_server/Srcs/Server/game/src/char_battle.cpp b/s3ll_server/Srcs/Server/game/src/char_battle.cpp index c71e535a..7fdc24b9 100644 --- a/s3ll_server/Srcs/Server/game/src/char_battle.cpp +++ b/s3ll_server/Srcs/Server/game/src/char_battle.cpp @@ -1472,7 +1472,7 @@ void CHARACTER::Dead(LPCHARACTER pkKiller, bool bImmediateDead) CloseMyShop(); CloseSafebox(); - if (IsMonster() && 2493 == GetMobTable().dwVnum) + if (IsMonster() && BlueDragon::BossVnum == GetMobTable().dwVnum) { if (pkKiller && pkKiller->GetGuild()) CDragonLairManager::instance().OnDragonDead(this, pkKiller->GetGuild()->GetID()); @@ -2092,6 +2092,13 @@ bool CHARACTER::Damage(LPCHARACTER pAttacker, int dam, EDamageType type) // retu } dam = BlueDragon_Damage(this, pAttacker, dam); + #ifdef ENABLE_BLUEDRAGON_RENEWAL + if (!dam) + { + SendDamagePacket(pAttacker, 0, DAMAGE_BLOCK); + return false; + } + #endif BYTE damageFlag = 0; diff --git a/s3ll_server/Srcs/Server/game/src/char_state.cpp b/s3ll_server/Srcs/Server/game/src/char_state.cpp index dc5b44ae..aae5dfc9 100644 --- a/s3ll_server/Srcs/Server/game/src/char_state.cpp +++ b/s3ll_server/Srcs/Server/game/src/char_state.cpp @@ -1008,7 +1008,7 @@ void CHARACTER::StateBattle() if (m_pkParty) m_pkParty->SendMessage(this, PM_ATTACKED_BY, 0, 0); - if (2493 == m_pkMobData->m_table.dwVnum) + if (BlueDragon::BossVnum == m_pkMobData->m_table.dwVnum) { m_dwStateDuration = BlueDragon_StateBattle(this); return; To display the changes side by side, paste it in [Hidden Content] like this: @ ASIKOOIt would be great if you could enable the DIFF patch syntax for code blocks. Edit: if you're using very old src, edit this: namespace BlueDragon { enum eBlueDragon { BossVnum = 2493, StoneCount = 4, }; }
  20. That check would remove IsAttacking, this is the correct one: if (rVictim.GetActorType() == TYPE_ENEMY && !isAttacking()) return FALSE; This check is only for mobs, so ignore npc/pet/door for now. I haven't tested the code, so I have no idea if isAttacking would remain true for delayed attacks.
  21. By task you mean "quest"? Anyway, a simple bot, or just lag can trigger this bug.
  22. 1) You're not using if __name__ == "__main__": 2) You're not using a function to encapsulate the code #noreusability 3) You're not skipping the non .quest files 4) You're including the full path and not the relative one (C:/Users/User/Desktop/Quests/Dungeons/deviltower_zone.quest -> Dungeons/deviltower_zone.quest) import os def create_quest_list(directory, output_file): with open(output_file, 'w') as f: for root, _, files in os.walk(directory): for filename in files: if filename.endswith('.quest'): rel_path = os.path.relpath(os.path.join(root, filename), directory) rel_path = rel_path.replace(os.sep, '/') f.write(rel_path + '\n') output_file = output_file.replace(os.sep, '/') print(f'File saved in {os.getcwd()}/{output_file}') if __name__ == "__main__": directory = r'C:\Users\User\Desktop\Quests' output_file = 'quest_list.txt' create_quest_list(directory, output_file) ty chatgpt Result: Meanwhile in freebsd: find ~/Desktop/Quests -name "*.quest" > quest_list.txt # without ./ find ~/Desktop/Quests -name "*.quest" -exec sh -c 'echo "{}" | sed "s|^./||"' \; > quest_list.txt ty chatgpt^2
  23. Check in player table if it's correctly storing both the skill levels and skill_group 0328 means skill grade P (0x03), skill level 40 (0x28) Every skill id takes 6 bytes (0328 0000 0000)
  24. You should mention which compiler, os, and arch you used too. Some cryptopp versions have internal crashes for different reasons. Also, cryptopp 8.7.0 from ports, pkg or from the official website?
  25. function say_blue ( name ) say ( color256 ( 0 , 0 , 255 ).. name .. color256 ( 0 , 0 , 255 )) end function say_red ( name ) say ( color256 ( 255 , 0 , 0 ).. name .. color256 ( 255 , 0 , 0 )) end function say_green ( name ) say ( color256 ( 0 , 238 , 0 ).. name .. color256 ( 0 , 238 , 0 )) end function say_gold ( name ) say ( color256 ( 255 , 215 , 0 ).. name .. color256 ( 255 , 215 , 0 )) end function say_black ( name ) say ( color256 ( 0 , 0 , 0 ).. name .. color256 ( 0 , 0 , 0 )) end function say_white ( name ) say ( color256 ( 255 , 255 , 255 ).. name .. color256 ( 255 , 255 , 255 )) end function say_yellow ( name ) say ( color256 ( 255 , 255 , 0 ).. name .. color256 ( 255 , 255 , 0 )) end function say_blue2 ( name ) say ( color256 ( 0 , 206 , 209 ).. name .. color256 ( 0 , 206 , 209 )) end in questlib.lua
×
×
  • 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.