-
Posts
202 -
Joined
-
Last visited
-
Days Won
4 -
Feedback
0%
Content Type
Forums
Store
Third Party - Providers Directory
Feature Plan
Release Notes
Docs
Events
Posts posted by filipw1
-
-
-
Weird flex but OK. ImGui kinda useless in Metin2, at least I've not find any use
- 2
- 1
-
On 8/1/2023 at 10:13 PM, martysama0134 said:
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.
https://en.cppreference.com/w/cpp/language/operators
Operator overloading comes in handy with these
-
On 8/7/2023 at 5:15 AM, DemOnJR said:
Update to C++20
or idk if is the right one but is working...Edit the followin lines with your msm locations mine are inside root/msm/....
static std::vector<TRaceData> m_vecRaceData = { { RACE_WARRIOR_M, "msm/warrior_m.msm", "d:/ymir work/pc/warrior/intro/" }, { RACE_WARRIOR_W, "msm/warrior_w.msm", "d:/ymir work/pc2/warrior/intro/" }, { RACE_ASSASSIN_W, "msm/assassin_w.msm", "d:/ymir work/pc/assassin/intro/" }, { RACE_ASSASSIN_M, "msm/assassin_m.msm", "d:/ymir work/pc2/assassin/intro/" }, { RACE_SURA_M, "msm/sura_m.msm", "d:/ymir work/pc/sura/intro/" }, { RACE_SURA_W, "msm/sura_w.msm", "d:/ymir work/pc2/sura/intro/" }, { RACE_SHAMAN_W, "msm/shaman_w.msm", "d:/ymir work/pc/shaman/intro/" }, { RACE_SHAMAN_M, "msm/shaman_m.msm", "d:/ymir work/pc2/shaman/intro/" }, };
Thanks! I've updated repository with your contribution.
- 4
- 1
- 3
-
Open up kraizy.tgz, compile mainline release and you good to got, the best source out there. Add some fixes and you can go live and earn some juicy money (͡ ͡° ͜ つ ͡͡°)
- 1
-
The error says exactly what is wrong.
-
-
-
Look, you download and unpack it yourself
https://metin2.dev/topic/45-metin2-2004-beta-client/- 1
-
Good stuff, but I've got it already for 30 minutes. You should use map instead of vector to save some time on finding the right blend data in you data pool. Nice to see people getting rid of some old and ugly code.
- 2
-
I updated the github repository with some more code to reduce a lag when you enter the game cause by refreshing affect window many times. Please let me know if it improves something.
-
I did a program that creates sub files from given png files in directory. I find it really usefull as using dds files gain you better performence.
One I'll try to make a GUI for this to visualize results, but for me it's fine at current state as it gets the job done.You need to convert output png canva to dds manually.
Spoilerfrom pyglet import image import os import math ## https://metin2.dev/topic/21221-grid-class-python/ class Grid: def __init__(self, width, height): self.grid = [False] * (width * height) self.width = width self.height = height def __str__(self): output = "Grid {}x{} Information\n".format(self.width, self.height) for x in range(self.height): output += "%3d" % (x + 1) output += "\n" for row in range(self.height): output += "%3d" % (x +1) for col in range(self.width): output += "%3d" % (row * self.width + col) output += " 1" if self.grid[row * self.width + col] else " 0" output += "\n" return output def find_blank(self, width, height): if width > self.width or height > self.height: return -1, -1, -1 for row in range(self.height): for col in range(self.width): index = row * self.width + col if self.is_empty(index, width, height): return index, row, col return -1, -1, -1 def put(self, pos, width, height): if not self.is_empty(pos, width, height): return False for row in range(height): start = pos + (row * self.width) self.grid[start] = True col = 1 while col < width: self.grid[start + col] = True col += 1 return True def clear(self, pos, width, height): if pos < 0 or pos >= (self.width * self.height): return for row in range(height): start = pos + (row * self.width) self.grid[start] = True col = 1 while col < width: self.grid[start + col] = False col += 1 def is_empty(self, pos, width, height): if pos < 0: return False row = pos // self.width if (row + height) > self.height: return False if (pos + width) > ((row * self.width) + self.width): return False for row in range(height): start = pos + (row * self.width) if self.grid[start]: return False col = 1 while col < width: if self.grid[start + col]: return False col += 1 return True def get_size(self): return self.width * self.height def reset(self): self.grid = [False] * (self.width * self.height) version = "" while not (version.isdigit() and int(version) in (1, 2)): version = input("Select sub version (1 - load dds file from \"d:\\ymir work\\ui\\\" or 2 - load dds file from dir as sub files): ") version = float(version) ddsname = "" while not ddsname: ddsname = input("Enter dds file name (public_offlineshop for example): ") images = {} files = [f for f in os.listdir('.') if os.path.isfile(f)] for f in files: ext = f.split(".")[-1] if ext != "png": continue if f == f"{ddsname}.png": print(f"Skip {f}") continue print(f"Load file {f}") img = image.load(f) print("File loaded!") images[f] = img def sortImg(img): width, height = img[1].width, img[1].height return width images = sorted(images.items(), key=sortImg, reverse=True) max_width, max_height = images[0][1].width, images[0][1].height images = {key: value for key, value in images} for key, img in images.items(): width, height = img.width, img.height print(f"File name: {key}, image size: {width}x{height}") ## https://stackoverflow.com/questions/14267555/find-the-smallest-power-of-2-greater-than-or-equal-to-n-in-python def next_power_of_2(x): return 1 if x == 0 else 2**math.ceil(math.log2(x)) canva_width, canva_height = next_power_of_2(max_width), next_power_of_2(max_height) print(f"Likely size of canva: {canva_width}x{canva_height}") done = 0 canva = None while done < len(images): canva = image.Texture.create(width=canva_width, height=canva_height) grid = Grid(canva_width, canva_height) for key, img in images.items(): img_width, img_height = img.width, img.height pos, x, y = grid.find_blank(img_width, img_height) if x >= 0 and y >= 0: grid.put(pos, img_width, img_height) done += 1 try: canva.blit_into(img, y, x, 0) left = y top = canva_height - x - img_height right = left + img_width bottom = top + img_height print(f"Image size: {img_width}x{img_height}") print(f"Found position for image {key} on left {x}, right {x + img_width}, top {y}, bottom {y + img_height}") file_name = key.split(".")[0] with open(f"{file_name}.sub", "w") as f: f.write(f"title subImage\n") f.write(f"version {version:.1f}\n") f.write(f"image \"{ddsname}.dds\"\n") f.write(f"left {left}\ntop {top}\nright {right}\nbottom {bottom}\n") f.close() except: done = 0 if math.log2(canva_height) + 1 >= math.log2(canva_width): canva_width *= 2 else: canva_height *= 2 print(f"Run out of blank space. Increase canva size to {canva_width}x{canva_height}") break canva.save(f"{ddsname}.png")
- 1
- 1
-
To get smooth scrolling like this in music, guild symbol selection (and maybe some custom systems you already have idk), just replace ListBoxEx class.
Spoilerclass ListBoxEx(Window): class Item(Window): def __init__(self): Window.__init__(self) def __del__(self): Window.__del__(self) def SetParent(self, parent): Window.SetParent(self, parent) self.parent = proxy(parent) def OnMouseLeftButtonDown(self): self.parent.SelectItem(self) def OnRender(self): if self.parent.GetSelectedItem() == self: self.OnSelectedRender() def OnSelectedRender(self): x, y = self.GetGlobalPosition() grp.SetColor(grp.GenerateColor(0.0, 0.0, 0.7, 0.7)) grp.RenderBar(x, y, self.GetWidth(), self.GetHeight()) def __init__(self): Window.__init__(self) self.viewItemCount = 10 self.basePos = 0 self.itemHeight = 16 self.itemStep = 20 self.selItem = 0 self.itemList = [] self.onSelectItemEvent = lambda *arg: None if localeInfo.IsARABIC(): self.itemWidth = 130 else: self.itemWidth = 100 self.scrollBar = None self.__UpdateSize() def __del__(self): Window.__del__(self) def __UpdateSize(self): height = self.itemStep * self.__GetViewItemCount() self.SetSize(self.itemWidth, height) def IsEmpty(self): if len(self.itemList) == 0: return 1 return 0 def SetItemStep(self, itemStep): self.itemStep = itemStep self.__UpdateSize() def SetItemSize(self, itemWidth, itemHeight): self.itemWidth = itemWidth self.itemHeight = itemHeight self.__UpdateSize() def SetViewItemCount(self, viewItemCount): self.viewItemCount = viewItemCount def SetSelectEvent(self, event): self.onSelectItemEvent = event def SetBasePos(self, basePos): if app.__BL_CLIP_MASK__: self.basePos = basePos curbp = self.basePos itemheight = self.itemStep * len(self.itemList) myheight = self.GetHeight() if itemheight < myheight: curbp = 0 fromPos = curbp curPos = 0 toPos = curbp + self.GetHeight() for item in self.itemList: if curPos + self.itemStep < fromPos or curPos > toPos: item.Hide() else: item.Show() item.SetPosition(0, curPos - fromPos) curPos += self.itemStep else: for oldItem in self.itemList[self.basePos:self.basePos + self.viewItemCount]: oldItem.Hide() self.basePos = basePos pos = basePos for newItem in self.itemList[self.basePos:self.basePos + self.viewItemCount]: (x, y) = self.GetItemViewCoord(pos, newItem.GetWidth()) newItem.SetPosition(x, y) newItem.Show() pos += 1 def GetItemIndex(self, argItem): return self.itemList.index(argItem) def GetSelectedItem(self): return self.selItem def SelectIndex(self, index): if index >= len(self.itemList) or index < 0: self.selItem = None return try: self.selItem = self.itemList[index] except: pass def SelectItem(self, selItem): self.selItem = selItem self.onSelectItemEvent(selItem) def RemoveAllItems(self): for item in self.itemList: item.Hide() self.selItem = None self.itemList = [] if self.scrollBar: self.scrollBar.SetPos(0) def RemoveItem(self, delItem): if delItem == self.selItem: self.selItem = None self.itemList.remove(delItem) def AppendItem(self, newItem): newItem.SetParent(self) newItem.SetSize(self.itemWidth, self.itemHeight) if app.__BL_CLIP_MASK__: newItem.SetClippingMaskWindow(self) pos = len(self.itemList) if self.__IsInViewRange(pos): (x, y) = self.GetItemViewCoord(pos, newItem.GetWidth()) newItem.SetPosition(x, y) newItem.Show() else: newItem.Hide() self.itemList.append(newItem) def SetScrollBar(self, scrollBar): scrollBar.SetScrollEvent(__mem_func__(self.__OnScroll)) self.scrollBar = scrollBar def __OnScroll(self): if app.__BL_CLIP_MASK__: self.SetBasePos(int(self.scrollBar.GetPos() * (self.__GetItemCount() - 1) * self.itemStep)) else: self.SetBasePos(int(self.scrollBar.GetPos() * self.__GetScrollLen())) def __GetScrollLen(self): scrollLen = self.__GetItemCount() - self.__GetViewItemCount() if scrollLen < 0: return 0 return scrollLen def __GetViewItemCount(self): return self.viewItemCount def __GetItemCount(self): return len(self.itemList) def GetItemViewCoord(self, pos, itemWidth): if localeInfo.IsARABIC(): return (self.GetWidth() - itemWidth - 10, (pos - self.basePos) * self.itemStep) else: return (0, (pos - self.basePos) * self.itemStep) def __IsInViewRange(self, pos): if pos < self.basePos: return 0 if pos >= self.basePos + self.viewItemCount: return 0 return 1
- 2
- 4
- 5
-
Good job on reverse engineering it. Are you into this now or is this @ xP3NG3Rx contributing?
BTW is this Saul as a GTA V character on your profile picture?
- 1
- 1
-
7 hours ago, WeedHex said:
You can buy the real system from who made it for first.
If you read carefully a name of the topic you can actually see what this code is meant for.
-
-
36 minutes ago, LordZiege said:
Fix is fairly simple, just replace function (uiToolTip)
Spoilerdef __AdjustAttrMaxWidth(self, attrSlot): if 0 == attrSlot: return self.toolTipWidth maxWidth = self.toolTipWidth for i in xrange(player.ATTRIBUTE_SLOT_MAX_NUM): type = attrSlot[i][0] value = attrSlot[i][1] attrText = self.AppendTextLine(self.__GetAffectString(type, value)) (tW, _) = attrText.GetTextSize() self.childrenList.remove(attrText) self.toolTipHeight -= self.TEXT_LINE_HEIGHT maxWidth = max(tW + 12, maxWidth) return maxWidth
- 3
- 2
- 2
-
gmake dep
gmake clean
gmake
-
Yes, write more functions to simple one line fix, gj
- 1
-
1 hour ago, Jimmermania said:
Hello,thanks for your share.While compile, i have this error: ERROR
Check code, I missed one line
-
There is a problem, when you change position of horse riding skill in playersettingsmodule, you cannot use horse skills. For me, the way skills work on the client side of thing is really dumb, but they went even furher. I don't understand why, client checks if player has a horse riding level from the fixed skill slot, not from skill info itself.
SpoilerWithout my fix, it goes like this:
SpoilerWith fix:
SpoilerActual fix:
Spoiler// PythonPlayerInput.cpp // find: bool CPythonPlayer::__CanAttack() { [...] } // Replace with: extern const DWORD c_iSkillIndex_Riding; bool CPythonPlayer::__CanAttack() { if (__IsProcessingEmotion()) { return false; } if (IsOpenPrivateShop()) return false; if (IsObserverMode()) return false; CInstanceBase* pkInstMain = NEW_GetMainActorPtr(); if (!pkInstMain) return false; DWORD dwSkillIndex = 0; GetSkillSlotIndex(c_iSkillIndex_Riding, &dwSkillIndex); if (pkInstMain->IsMountingHorse() && pkInstMain->IsNewMount() && (GetSkillGrade(dwSkillIndex) < 1 && GetSkillLevel(dwSkillIndex) < 11)) { return false; } return pkInstMain->CanAttack(); } // PythonPlayerSkill.cpp // Find: bool CPythonPlayer::__CanUseSkill() { [...] } // Replace with: extern const DWORD c_iSkillIndex_Riding; bool CPythonPlayer::__CanUseSkill() { CInstanceBase* pkInstMain=NEW_GetMainActorPtr(); if (!pkInstMain) return false; if (IsObserverMode()) return false; DWORD dwSkillIndex = 0; GetSkillSlotIndex(c_iSkillIndex_Riding, &dwSkillIndex); if (pkInstMain->IsMountingHorse() && (GetSkillGrade(dwSkillIndex) < 1 && GetSkillLevel(dwSkillIndex) < 20)) { return false; } return pkInstMain->CanUseSkill(); }
- 4
- 5
- 1
-
-
@firewall I measured this, for me it takes 7 to 10 ms to load npclist so I thought it isn't a big deal.
-
Multi Text Line
in Features & Metin2 Systems
Posted · Edited by Metin2 Dev International
Core X - External 2 Internal
Vertical align broken
First line is aligned correctly but next ones are off.
Fixed