Jump to content

Ken

Inactive Member
  • Posts

    726
  • Joined

  • Last visited

  • Days Won

    44
  • Feedback

    0%

Posts posted by Ken

  1. M2 Download Center

    This is the hidden content, please
    ( Internal )

    Hey everyone, it's a nice day to share something ^_^ I just wrote Grid class in python language. You can use it as fast moving into the window with this or something else.

    Spoiler
    
    
    """
        This module was written by Ken for metin2dev.org (Please don't try to change it.)
        
        Note:
            Use reset function instead of deleting the object and creating it again. (That's more easy)        
    """
    
    
    class Grid:
        """
            Args:
                width (int): Grid's width.
                height (int): Grid's height.
    
            Attributes:
                grid (list): The list will hold the position empty or not information.
                width (int): Grid's width
                height (int): Grid's height
        """
    
        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 row in range(self.height):
                for col in range(self.width):
                    output += "Status of %d: " % (row * self.width + col)
                    output += "NotEmpty, " if self.grid[row *
                                                       self.width + col] else "Empty, "
                output += "\n"
    
            return output
    
        def find_blank(self, width, height):
            """
                Args:
                    width (int): The item's width you can call width item.GetItemSize()[0]
                    height (int): The item's height you can call width item.GetItemSize()[1]
    
                Returns:
                    int: The return value would be an int if successful. Otherwise -1.
            """
            if width > self.width or height > self.height:
                return -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
    
            return -1
    
        def put(self, pos, width, height):
            """
                Args:
                    pos (int): Position of the item to put.
                    width (int): The item's width you can call width item.GetItemSize()[0]
                    height (int): The item's height you can call width item.GetItemSize()[1]
    
                Returns:
                    bool: The return value. True for success, False otherwise.
            """
            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):
            """
                Args:
                    pos (int): Position of the item to put.
                    width (int): The item's width you can call width item.GetItemSize()[0]
                    height (int): The item's height you can call width item.GetItemSize()[1]
    
                Returns:
                    There is nothing to return
            """
            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):
            """
                Args:
                    pos (int): Position of the item to put.
                    width (int): The item's width you can call width item.GetItemSize()[0]
                    height (int): The item's height you can call width item.GetItemSize()[1]
    
                Returns:
                    bool: The return value. True for success, False otherwise.
            """
            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):
            """
                Returns:
                    int: The return value will give you maximum capacity of grid. (width * height)
            """
            return self.width * self.height
    
        def reset(self):
            """
                With this function, you can reset instead of deleting it and create again.
            """
            self.grid = [False] * (self.width * self.height)

     

    Usage:

    from grid import Grid
    import item
    import chat
    
    grid = Grid(width=5, height=9)
    
    item.SelectItem(11299)
    (width, height) = item.GetItemSize()
    
    available_position = grid.find_blank(width, height)
    if available_position == -1:
      chat.AppendChat(chat.CHAT_TYPE_INFO, "There is no available position.")
      return
    
    chat.AppendChat(chat.CHAT_TYPE_INFO, "Available position is %d" % (available_position))

    Best Regards

    Ken

    • Metin2 Dev 10
    • Smile Tear 1
    • Good 4
    • Love 18
  2. Hi everyone, I would like to share a memory leak fix about pack type Hybrid, Hybrid with SDB and panama. I saw it while analyzing Webzen's new pack type.

    EterPack.cpp

    Search this:

    		if( !m_pCSHybridCryptPolicy->DecryptMemory(std::string(filename), static_cast<const BYTE*>(*data), index->data_size, *zObj) )
    		{
    			return false;
    		}

    Replace with this

    		if( !m_pCSHybridCryptPolicy->DecryptMemory(std::string(filename), static_cast<const BYTE*>(*data), index->data_size, *zObj) )
    		{
    			delete zObj;
    			return false;
    		}

    Search this:

    			if( !m_pCSHybridCryptPolicy->GetSupplementaryDataBlock(std::string(filename), pSDBData, iSDBSize) )
    			{
    				return false;
    			}

    Replace with this

    			if( !m_pCSHybridCryptPolicy->GetSupplementaryDataBlock(std::string(filename), pSDBData, iSDBSize) )
    			{
    				delete zObj;
    				return false;
    			}

     

    Search this:

    	else if (COMPRESSED_TYPE_PANAMA == index->compressed_type)
    	{
    		CLZObject * zObj = new CLZObject;
    		__Decrypt_Panama(filename, static_cast<const BYTE*>(*data), index->data_size, *zObj);
    		out_file.BindLZObjectWithBufferedSize(zObj);
    		*data = zObj->GetBuffer();
    	}

    Replace with this:

    	else if (COMPRESSED_TYPE_PANAMA == index->compressed_type)
    	{
    		CLZObject * zObj = new CLZObject;
    		if (!__Decrypt_Panama(filename, static_cast<const BYTE*>(*data), index->data_size, *zObj))
    		{
    			delete zObj;
    			return false;
    		}
    
    		out_file.BindLZObjectWithBufferedSize(zObj);
    		*data = zObj->GetBuffer();
    	}

    Best Regards

    Ken

    • Metin2 Dev 2
    • Confused 2
    • Love 27
  3. Hi, everyone today I would like to share a fix which Webzen has made with you. The fix is about the target position. Ymir is not checking if the target is on horse or not. It would be useful for range attacks.

    Find this:

    D3DXVECTOR3 CActorInstance::OnGetFlyTargetPosition()
    {
    	D3DXVECTOR3 v3Center;
    	if (m_fRadius<=0)
    	{
    		BuildBoundingSphere();
    		v3Center = m_v3Center;
    	}
    	else
    	{
    		v3Center = m_v3Center;
    	}
    
    	D3DXVec3TransformCoord(&v3Center, &v3Center, &GetTransform());
    	return v3Center;
    }

    Replace with this:

    D3DXVECTOR3 CActorInstance::OnGetFlyTargetPosition()
    {
    	D3DXVECTOR3 v3Center;
    	if (m_fRadius <= 0)
    		BuildBoundingSphere();
    	
    	v3Center = m_v3Center;
    	D3DXVec3TransformCoord(&v3Center, &v3Center, &GetTransform());
    	
    	if (__IsMountingHorse())	
    		v3Center.z += 110.0f;
    
    	return v3Center;
    }

    Best Regards

    Ken

    • Love 21
  4. Psuedo-Code ;

    signed int __stdcall CPythonNonPlayer::GetMonsterHitRange(char a1)
    {
      signed int v2; // [esp+0h] [ebp-1Ch]
      int v3; // [esp+18h] [ebp-4h]
    
      v3 = sub_3236B90(a1);
      if ( !v3 )
        return 70.0;
      if ( *(v3 + 272) )
        v2 = *(v3 + 272);
      else
        v2 = 100;
      return v2;
    }

    Reversed function:

    float CPythonNonPlayer::GetMonsterHitRangeByVnum(DWORD raceVnum) const
    {
    	const TMobTable * p = GetTable(raceVnum);
    	if (!p)
    		return 70.0f;
    	
    	if (p->hitRange)
    		return p->hitRange;
    	
    	return 100.0f;
    }
    

    Best Regards

    Ken

    • Love 2
  5. Hey, I would like to share a small function for fish event. You can find this function in uiMiniGameFishEvent.py (The uncythonized root files) too.

    Spoiler

     

    Step 1:

    Find this line in PythonWindowManagerModule.cpp

    
    
    { "SetAttachingFlag",			wndMgrSetAttachingFlag,								METH_VARARGS },

    Then add this line

    
    
    { "SetDisableDeattach",			wndMgrSetDisableDeattach,							METH_VARARGS },

    Step 2:

    Find this line in PythonWindowManagerModule.cpp

    
    
    PyObject * wndMgrSetAttachingFlag(PyObject * poSelf, PyObject * poArgs)
    {
    	BOOL bFlag;
    	if (!PyTuple_GetInteger(poArgs, 0, &bFlag))
    		return Py_BuildException();
    
    	UI::CWindowManager::Instance().SetAttachingFlag(bFlag);
    	return Py_BuildNone();
    }

    Then add this line

    
    
    PyObject * wndMgrSetDisableDeattach(PyObject * poSelf, PyObject * poArgs)
    {
    	BOOL bFlag;
    	if (!PyTuple_GetInteger(poArgs, 0, &bFlag))
    		return Py_BuildException();
    
    	UI::CWindowManager::Instance().SetDisableDeattach(bFlag);
    	return Py_BuildNone();
    }

     

    Step 3:

    Find this line in PythonWindowManager.h

    
    
    void		SetAttachingFlag(BOOL bFlag);

    Then add this line

    
    
    void		SetDisableDeattach(BOOL bFlag);

    Step 4:

    Find this line in PythonWindowManager.h

    
    
    			BOOL					m_bAttachingFlag;

    Then add this line

    
    
    			BOOL					m_disableDeattach;

    Step 5:

    Find this line in PythonWindowManager.cpp

    
    
    m_bAttachingFlag(FALSE),

    Then add this line

    
    
    		m_disableDeattach(FALSE),

    Step 6:

    Find this line in PythonWindowManager.cpp

    
    
    	void CWindowManager::SetAttachingFlag(BOOL bFlag)
    	{
    		m_bAttachingFlag = bFlag;
    	}

    Then add this line

    
    
    	void CWindowManager::SetDisableDeattach(BOOL bFlag)
    	{
    		m_disableDeattach = bFlag;
    	}

    Final step:

    Find void CWindowManager::DeattachIcon() in PythonWindowManager.cpp and replace with this.

    
    
    	void CWindowManager::DeattachIcon()
    	{
    		if (!m_disableDeattach)
    		{
    			SetAttachingFlag(FALSE);
    			if (m_poMouseHandler)
    				PyCallClassMemberFunc(m_poMouseHandler, "DeattachObject", BuildEmptyTuple());
    		}
    	}

     

     

     

    Best Regards

    Ken

    • Love 6
  6. Webzen didn't create a new function to return m_FriendNameMap. They just make m_FriendNameMap public. (It was protected before). Also, you can use const_iterator instead of iterator. (You're not modifying it.)

    Here is the reversed version of webzen's function.

    This version is for c++11

    Spoiler
    
    PyObject * messengerGetFriendNames(PyObject * poSelf, PyObject * poArgs)
    {
    	const CPythonMessenger & messenger = CPythonMessenger::Instance();	
    	PyObject * mainTuple = PyTuple_New(messenger.m_FriendNameMap.size());	
    	
    	uint32_t pos = 0;
    	for (const auto friendName : messenger.m_FriendNameMap)
    	{
    		PyTuple_SetItem(mainTuple, pos, PyString_FromString(friendName.c_str()));
    		++pos;
    	}
    
    	return mainTuple;
    }

     

    This is for c++03

    Spoiler
    
    PyObject * messengerGetFriendNames(PyObject * poSelf, PyObject * poArgs)
    {
    	const CPythonMessenger & messenger = CPythonMessenger::Instance();	
    	PyObject * mainTuple = PyTuple_New(messenger.m_FriendNameMap.size());	
    	
    	int pos = 0;
    	for (std::set<std::string>::const_iterator it = messenger.m_FriendNameMap.begin(); it != messenger.m_FriendNameMap.end(); ++it)
    	{
    		PyTuple_SetItem(mainTuple, pos, PyString_FromString(it->c_str()));
    		++pos;
    	}
    
    	return mainTuple;
    }

     

    PS:

    This function has come with a system that called mailbox. 

    Best Regards

    Ken

    • Love 2
  7. std::string GetFirstLineFromFile(std::string stFileName)
    {
    	std::ifstream file(stFileName.c_str(), std::ios::in);
    	if (!file.is_open())
    		return "Can not open the file";
    
    	std::string stLine = "";
    	if (!getline(file, stLine))
    		return "Can not get the first line!";
    
    	return stLine;
    }

    It will get the first line of the file. You can use this anywhere you want. (Don't forget to include fstream and string libraries)

    Best Regards

    Ken

  8. Hi, everyone. Most people know when you are trying to connect the server with a lot of people, the server can not respond to you or something might go wrong. This example is same for warp too. Webzen did something about this too and I'd like to share it with you.

    What are exactly are we doing?

    If the client can not connect to the server, the client will wait one second to connect the server again.

    Open NetStream.cpp. Find Connect function and replace with this

    bool CNetworkStream::Connect(const CNetworkAddress& c_rkNetAddr, int limitSec)
    {
    	Clear();
    
    	m_addr = c_rkNetAddr;
    
    	m_sock = socket(AF_INET, SOCK_STREAM, 0);
    
    	if (m_sock == INVALID_SOCKET)
    	{
    		Clear();
    		OnConnectFailure();
    		return false;
    	}
    
    	DWORD arg = 1;
    	ioctlsocket(m_sock, FIONBIO, &arg);	// Non-blocking mode
    
    	if (connect(m_sock, reinterpret_cast<PSOCKADDR>(&m_addr), m_addr.GetSize()) == SOCKET_ERROR)
    	{
    		int error = WSAGetLastError();
    
          	// If something went wrong, the client will wait one second to connect the server again.
          	// Of course, it will clear and setting up everything again.
    		if (error != WSAEWOULDBLOCK)
    		{
    			Sleep(1000);
    			Clear();
    			m_sock = socket(AF_INET, SOCK_STREAM, 0);
    			if (m_sock == INVALID_SOCKET)
    			{
    				Clear();
    				OnConnectFailure();
    				return false;
    
    			}
    
    			ioctlsocket(m_sock, FIONBIO, &arg);
    			if (connect(m_sock, reinterpret_cast<PSOCKADDR>(&m_addr), m_addr.GetSize()) == SOCKET_ERROR)
    			{
    				Tracen("error != WSAEWOULDBLOCK");
    				Clear();
    				OnConnectFailure();
    				return false;
    			}
    		}
    	}
    
    	m_connectLimitTime = time(NULL) + limitSec;
    	return true;	
    }

    Best Regards

    Ken

    • Love 17
  9. The quest must know what's there in the item shop.

    • You can create an array for this in questlib.lua or the quest.
    • You can use a query to fetch what's there in the item shop. (I do not recommend this method because it might be a lag in the game.)
      • You must cache it even If you want.

    Then you can check it with pc.get_wear()

    • You can create an array for this in the quest or questlib.lua (I gave an example)

    The last thing is to combine all of them

    quest xxx begin
    	state start begin			
    		when login with pc.get_map_index() == xx begin
    			-- You can use a query to fetch the item vnums from the table. (I still do not recommend this method if you are not using cache method)
    			local blockedItems = { 11209, 11409, 11609, 11809 }
    			
    			-- Wear positions, is exist in common/length.h if you want to check it out.
    			local wearPositions = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 19, 20, 21, 22 }
    			
    			-- Make a loop and check every wear position and check is equal to the blocked items in array or not.		
    			for i = 1, table.getn(blockedItems), 1 do
    				for j = 1, table.getn(wearPositions), 1 do
    					if (pc.get_wear(wearPositions[j]) == blockedItems[i]) then
    						chat("You can't..")
    						return
    					end
    				end
    			end
    		end
    	end
    end

     

    Best Regards

    Ken

    • Love 1
  10. You're playing a multiplayer game. The member might lose his connection sometimes because of the internet provider or unknown packets. You can't pay this to the party members. If you do, most people are going to insult you in the game. Anyway, thanks for sharing with us.

    Best Regards

    Ken

    • Love 3
  11. Hey, @Horinna thanks for feeding back. About the last bug, the system is not doing the same things for the companion. To fix this;

    Find this line in messenger_manager.cpp

    	m_Relation[account].erase(companion);
    	m_InverseRelation[companion].erase(account);

    And add this code blog

    	m_Relation[companion].erase(account);
    	m_InverseRelation[account].erase(companion);

    Best Regards

    Ken

    • Love 3
×
×
  • 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.