Jump to content

filipw1

Premium
  • Posts

    202
  • Joined

  • Last visited

  • Days Won

    4
  • Feedback

    0%

Posts posted by filipw1

  1. image.png?width=798&height=465

    Weird flex but OK. ImGui kinda useless in Metin2, at least I've not find any use 

    • Confused 2
    • Lmao 1
  2. 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 

  3. On 8/7/2023 at 5:15 AM, DemOnJR said:

    Update to C++20 

    This is the hidden content, please
     or 
    This is the hidden content, please
    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/" },
    };

    Tests
    Wihout:
    spacer.png
    With CPP PSM:
    spacer.png

    Thanks! I've updated repository with your contribution.

    • Metin2 Dev 4
    • Good 1
    • Love 3
  4. For all the years I had been actively dismissing the problem of the misaligned cursor in the text edit box when centred. The day finally came that I fixed it.

    Broken 😒

       editline_broken.gif

    Fixed 🤪

     editline_fixed.gif

     

    This is the hidden content, please

     

    • Metin2 Dev 71
    • Eyes 2
    • Good 11
    • Love 1
    • Love 15
  5. When you set a text in a textline and then change font name, text disappear.

       

    Before fix:

    before_fix.png

    With fix:

    after_fix.png

     

    This is the hidden content, please

    • Metin2 Dev 33
    • Good 9
    • Love 9
  6. 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.

    Spoiler
    from 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")

     

     

    • Metin2 Dev 1
    • Good 1
  7. scrollowanie_masne_fest.gif

    To get smooth scrolling like this in music, guild symbol selection (and maybe some custom systems you already have idk), just replace ListBoxEx class.

    Spoiler

    https://pastebin.com/MwRS82jG

     

    class 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

     

    • Metin2 Dev 2
    • Good 4
    • Love 5
  8. 36 minutes ago, LordZiege said:

    i found a litle problem with very long bonuses

    gzb3z.png

    Bez-tytulu-1.png

    Fix is fairly simple, just replace function (uiToolTip)

    Spoiler
    	def __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

     

     

    • Metin2 Dev 3
    • Good 2
    • Love 2
  9. 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. 

    Spoiler

    .png

     

    Without my fix, it goes like this:

    Spoiler

    .gif

    With fix:

    Spoiler

    2022-07-22-12-53-42.gif

     

    Actual 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();
    }

     


     

    • Metin2 Dev 4
    • Good 5
    • Love 1
×
×
  • 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.