Jump to content

Valki

Active Member
  • Posts

    41
  • Joined

  • Last visited

  • Feedback

    100%

Posts posted by Valki

  1. On 1/28/2024 at 7:59 PM, UdvAtt108 said:

    Thank you for this source release, works perfectly. 🙂

     

    Upgrade the sound engine in Metin? I dont think its needed. "Miles" is old, yes, but up to date and does his job perfectly in this old game source and plays that minimal amount of music/effect. And with this source release (what i want to thank in this case too) u can make it and your client binary safer then before. For example, use it staticialy (with codec providers).

    You're 100% right, it's not necessary because miles is doing it's job more than perfectly. But I'd like to mention that if you want to go further than metin2 in the future (so if you're really interested in the programming part of it) it's better to know alternatives, other options too and if you can do it properly it also won't hurt since for example "FMOD" is also a great library to handle sounds in m2's source. But I'm really agreeing with you, because if you're not interested in these kind of stuffs then it's not necessary, even if other sound engines has better support than mss

    • Metin2 Dev 1
  2. 2 hours ago, Jettyx said:

    Regarding what happened: 

    The information about the Zenaris leak is true. The version from the Beta phase was leaked approximately a month ago. However, it's important to note that the database remained secure and was not compromised.

    I am no longer affiliated with the Zenaris Team. My contributions were primarily in the realms of graphic design, mapping, and environmental design. I worked for Graphics for 3 years. While some might not find it particularly impressive, the lack of resources regarding older DirectX9 and shader technologies posed significant challenges. A considerable amount of my time was dedicated to studying books and old documentation to overcome these obstacles.

    As for the coding aspect:
    The graphics of Zenaris are intentionally coded very bad/chaotic, like true is false sometimes, serving as my final safeguard. Only me and me knows what's inside and how the things are working. There are no defines. This complexity is the primary reason why no one has successfully implemented or extracted the graphics in the past month, except for two servers where I provided assistance. Additionally, even if someone were to understand the chaotic code from the leak, the graphics are plagued with numerous bugs, crashes, and other graphical issues, rendering them ineffective.

    In conclusion, I intend to continue my journey, focusing on updating and creating new graphics in service to others.
    Furthermore, I am committed to assisting others with my current implementations.

    Sad to hear this and I really understand, when I talked with friends I even said maybe 3 years was mostly learning shaders and rendering in dx9, great to hear that it was really because of that, because the server itself doesnt provide anything new except your shaders and graphics. Also, glad to hear that the code is complex enough so we won't see 15 """"full hd metin""""", except if they open servers from the zenaris files itself.

  3. 1 hour ago, nmeyo said:

    Ouch, looks like it’s real.

    Sad, @Jettyx bafta unchiule, data viitoare cu contract semnat.

    I don’t even want to think about working for 3 years on something to be set aside when payday comes. Disgusting.

     

    @ SpeachlessWhere is he moving his work now? So i Know where to spend my money 🤣

    Honestly? I don't know what was 3 years in it. As far as I know N2 was made in 5 years and if you look at it's source code it really looks like that. Looking at Zenaris's source and I only see the shader which is interesting in it, nothing else. 

  4. Hello!

    So I just noticed that if you want to join to the ship defense after the leader started AND the cooldown is enabled the other characters cannot connect (idk if it's fixed already or not, sorry if it is.) because the cooldown is put on the characters on creating the instance and when you're trying to join it's already on cooldown.

    Here's a fix for it:
     

    /// In ShipDefense.h add after:
    	bool IsRunning(const LPCHARACTER c_lpChar);
    /// This:
    	bool CanJoin(const LPCHARACTER c_lpChar);
    
    /// In ShipDefense.cpp add after:
    bool CShipDefenseManager::IsRunning(const LPCHARACTER c_lpChar)
    {
    	[...]
    }
    /// This:
    bool CShipDefenseManager::CanJoin(const LPCHARACTER c_lpChar)
    {
    	if (c_lpChar == nullptr)
    		return false;
    
    	const LPPARTY c_lpParty = c_lpChar->GetParty();
    	if (c_lpParty == nullptr)
    		return false;
    
    	if (m_mapShipDefense.empty())
    		return false;
    
    	ShipDefenseMap::const_iterator f = m_mapShipDefense.find(c_lpParty->GetLeaderPID());
    	if (f != m_mapShipDefense.end())
    		return true;
    
    	return false;
    }
    
    /// In questlua_shipdefense_mgr.cpp
    /// Add before:
    	void RegisterShipDefenseManagerFunctionTable()
        {
        	[...]
        }
    /// This:
    	int ship_defense_mgr_can_join(lua_State* L)
    	{
    		const LPCHARACTER c_lpChar = CQuestManager::instance().GetCurrentCharacterPtr();
    		if (c_lpChar == nullptr)
    		{
    			lua_pushboolean(L, false);
    			return 1;
    		}
    
    		CShipDefenseManager& rkShipDefenseMgr = CShipDefenseManager::instance();
    		lua_pushboolean(L, rkShipDefenseMgr.CanJoin(c_lpChar));
    		return 1;
    	}
    
    /// Add after:
    			{ "set_alliance_hp_pct", ship_defense_mgr_set_alliance_hp_pct },
    /// This:
    			{ "can_join", ship_defense_mgr_can_join},
    -- In quest_functions add:
    ship_defense_mgr.can_join
    
    -- In shipdefense.quest change this:
    if pc.getqf("cooldown") > get_time() then
    -- To this:
    if pc.getqf("cooldown") > get_time() and not ship_defense_mgr.can_join() then

     

    • Metin2 Dev 8
    • Love 1
    • Love 1
  5. 2 hours ago, Gurgarath said:

    Hello,

    Thank you, but I guess the tutorial is incomplete, can you provide us with "CanUnequipNow" function please? Also, is it possible to have a small gif of what it does exactly?

    Hi! Added what I forgot, also made a small video of what it actually does.

    • Love 1
  6. Hi!

    Today I'm sharing small changes about changing equipments. 

    I experienced that in metin2 basically it can't replace for example a two handed weapon (which is equipped) with a simple sword if there's an item in the next row under our item that we want to equip.

     

    Video of the result:

     

    Small explanation:

    So, if we want to make it work like we want we will need to check if basically it couldn't replace the inventory item with our equipped item then is there any space for that item, and if there is it can unequip it to that slot.

     

    So, let's get to the work.

    We will work in 2 files, char.h and char.cpp

    This is the hidden content, please

    • Metin2 Dev 63
    • Eyes 1
    • Good 10
    • Love 2
    • Love 16
  7. @ DDC

    Search for:

    #ifdef ENABLE_EMOJI_SYSTEM
    	if (m_emojiVector.empty() == false)
    	{
    		for(auto& rEmo : m_emojiVector)
    		{
    			if (rEmo.pInstance)
    			{
    				rEmo.pInstance->SetPosition(fStanX + rEmo.x, (fStanY + 7.0) - (rEmo.pInstance->GetHeight() / 2));
    				rEmo.pInstance->Render();
    			}
    		}
    	}
    #endif

    in GrpTextInstance.cpp's ::Render function and change it like that:

    #ifdef ENABLE_EMOJI_SYSTEM
    	if (m_emojiVector.empty() == false)
    	{
    		for(auto& rEmo : m_emojiVector)
    		{
    			if (rEmo.pInstance)
    			{
    				rEmo.pInstance->SetPosition(fStanX + rEmo.x, (fStanY + 7.0) - (rEmo.pInstance->GetHeight() / 2));
    #if defined(__BL_CLIP_MASK__)
    				if (pClipRect)
    					rEmo.pInstance->Render(pClipRect);
    				else
    					rEmo.pInstance->Render();
    #else
    				rEmo.pInstance->Render();
    #endif
    			}
    		}
    	}
    #endif

     

    • Metin2 Dev 1
    • Good 1
    • Love 1
  8. Hello!

    Quote

    Recently I was facing with a problem that it would take too much time to replace all the locale string in the source code, so I wrote a program for this.

    This program will read your file in ANSI, and will rewrite it (in a new folder) to ANSI, but will replace all the locale strings to the desired one.

    For this I used  "locale_string_vnum.txt" file from @ Owsap's LocaleString Builder, so if you already have custom locale strings then you should add it by yourself.

    It replaces the basic locale strings in your source code to STRINGS, so if you using some number based identification for this in your source or something like that you need to make some changes in the program.

    I tried to test it as much as I can, for me it works, but I recommend everyone (especially for those people who aren't using any version control like git or svn) to make a backup for your files and test it out well before you publish it if you have a currently running server.

    I tested it with VirusTotal, it rated 1/59, but the source code is in the package so you can check it anytime. 

    In the rar there's a basic folder setup for your files (you will need to put the same files in the output/files folder too, and the program will rewrite those files), but you can change it anytime.

     

    Links:

    This is the hidden content, please

    This is the hidden content, please

    • Metin2 Dev 36
    • Eyes 1
    • Cry 1
    • Smile Tear 1
    • Good 5
    • Love 1
    • Love 13
  9. Hello!

    I was testing something on my server and I had to use /i a tons, so I just extended it instead. With this extension you can get as many items as you want (of course with limitation of your max inventory space.)

    For this we will working in only one file, called "cmd_gm.cpp".

     

    So, in cmd_gm.cpp fine ACMD(do_item) and edit the following things in the function.

    Be careful, because there's a chance that you don't use "g_bItemCountLimit" but "MAX_ITEM_COUNT" (or something like that) instead.

    //Find this:
    	if (*arg2)
    	{
    		str_to_number(iCount, arg2);
    		iCount = MINMAX(1, iCount, g_bItemCountLimit);
    	}
    //And comment out iCount limitations like this:
    	if (*arg2)
    	{
    		str_to_number(iCount, arg2);
    		//iCount = MINMAX(1, iCount, g_bItemCountLimit);
    	}
    
    //Find this:
      if (item->IsDragonSoul())
      {
          [...]
      }
    
    //and after that add this:
    
    		else if (!item->IsStackable())
    		{
    			M2_DESTROY_ITEM(item);
    			for (int i = 0; i < iCount; i++)
    			{
    				LPITEM newItem = ITEM_MANAGER::instance().CreateItem(dwVnum, 1);
    				int iEmptyPos = ch->GetEmptyInventory(newItem->GetSize());
    
    				if (iEmptyPos != -1)
    				{
    					newItem->AddToCharacter(ch, TItemPos(INVENTORY, iEmptyPos));
    					LogManager::instance().ItemLog(ch, newItem, "GM", item->GetName());
    				}
    				else
    				{
    					M2_DESTROY_ITEM(item);
    					ch->ChatPacket(CHAT_TYPE_INFO, "Not enough inventory space.");
    					break;
    				}
    			}
    		}
    		else if (item->IsStackable() && iCount > g_bItemCountLimit)
    		{
    			M2_DESTROY_ITEM(item);
    			while (iCount != 0)
    			{
    				LPITEM newItem;
    				if (iCount >= g_bItemCountLimit)
    				{
    					newItem = ITEM_MANAGER::instance().CreateItem(dwVnum, g_bItemCountLimit);
    					iCount -= g_bItemCountLimit;
    				}
    				else
    				{
    					newItem = ITEM_MANAGER::instance().CreateItem(dwVnum, iCount);
    					iCount -= iCount;
    				}
    
    				int iEmptyPos = ch->GetEmptyInventory(newItem->GetSize());
    
    				if (iEmptyPos != -1)
    				{
    					newItem->AddToCharacter(ch, TItemPos(INVENTORY, iEmptyPos));
    					LogManager::instance().ItemLog(ch, newItem, "GM", item->GetName());
    				}
    				else
    				{
    					M2_DESTROY_ITEM(newItem);
    					ch->ChatPacket(CHAT_TYPE_INFO, "Not enough inventory space.");
    					break;
    				}
    			}
    		}
    • Metin2 Dev 1
    • Love 1
  10. This is the hidden content, please

    Metin2 Download

     

    Welcome folks!

    I brought you a small "system" (would call it modification instead), which will instantly pick up 45 (you can increase or decrease its size).

    My goal was not to send packets each time we're trying to pick up items. I did not test it for hours, so I wouldn't recommend using it on a live server without proper tests.

    So let's get started!

    First, we will start on the client side, and there we will work in the UserInterface project.

    Locale_inc.h:

    Spoiler
    Add: 
    #define ENABLE_FAST_PICKUP

     

    Packet.h:

    Spoiler
    Add:
    
    #ifdef ENABLE_FAST_PICKUP
        HEADER_CG_ITEM_PICKUP_ALL                    = 32,
    #endif
    
    After: 
    
        HEADER_CG_QUEST_CONFIRM                     = 31,
    
    Add:
    #ifdef ENABLE_FAST_PICKUP
    typedef struct command_item_pickup_all
    {
    	BYTE header;
    	DWORD vids[FAST_PICKUP_MAX_NUM];
    } TPacketCGItemPickUpAll;
    #endif
    After:
    typedef struct command_item_pickup
    {
    	BYTE header;
    	DWORD vid;
    } TPacketCGItemPickUp;

    PythonItem.h:

    Spoiler
    Add:
    #ifdef ENABLE_FAST_PICKUP
    		bool	GetCloseItems(const TPixelPosition& c_rPixelPosition, std::vector<DWORD>* pdwItemIDs, DWORD dwDistance = 300);
    #endif
    After:        
    bool	GetCloseItem(const TPixelPosition & c_rPixelPosition, DWORD* pdwItemID, DWORD dwDistance=300);          

     

    PythonItem.cpp

    Spoiler
    Add:
    #ifdef ENABLE_FAST_PICKUP
    bool CPythonItem::GetCloseItems(const TPixelPosition& c_rPixelPosition, std::vector<DWORD>* pdwItemIDs, DWORD dwDistance)
    {
    	DWORD dwCloseItemDistance = 1000 * 1000;
    
    	TGroundItemInstanceMap::iterator i;
    	int counter = 0;
    	pdwItemIDs->reserve(FAST_PICKUP_MAX_NUM);
    	for (i = m_GroundItemInstanceMap.begin(); i != m_GroundItemInstanceMap.end(); ++i)
    	{
    		if (counter == FAST_PICKUP_MAX_NUM)
    			return true;
    
    		TGroundItemInstance* pInstance = i->second;
    
    		DWORD dwxDistance = DWORD(c_rPixelPosition.x - pInstance->v3EndPosition.x);
    		DWORD dwyDistance = DWORD(c_rPixelPosition.y - (-pInstance->v3EndPosition.y));
    		DWORD dwDistance = DWORD(dwxDistance * dwxDistance + dwyDistance * dwyDistance);
    
    		if (dwDistance < dwCloseItemDistance)
    		{
    			pdwItemIDs->emplace_back(i->first);
    		}
    		counter++;
    	}
    
    	return true;
    }
    #endif
    After:
    bool CPythonItem::GetCloseMoney(const TPixelPosition & c_rPixelPosition, DWORD * pdwItemID, DWORD dwDistance)
    {
    	[...] 
    }

    PythonNetworkStream.h

    Spoiler
    Add:
    #ifdef ENABLE_FAST_PICKUP
    		bool SendItemPickUpAllPacket(TPacketCGItemPickUpAll& pack);
    #endif
    After:
    bool SendItemPickUpPacket(DWORD vid);

     

    PythonNetworkStreamPhaseGameItem.cpp

    Spoiler
    Add:
    #ifdef ENABLE_FAST_PICKUP
    bool CPythonNetworkStream::SendItemPickUpAllPacket(TPacketCGItemPickUpAll& pack)
    {
    	if (!__CanActMainInstance())
    		return true;
    
    	if (!Send(sizeof(TPacketCGItemPickUpAll), &pack))
    	{
    		Tracen("SendItemPickUpPacket Error");
    		return false;
    	}
    
    	return SendSequence();
    }
    #endif
    After:
    bool CPythonNetworkStream::SendItemPickUpPacket(DWORD vid)
    {
    	[...]
    }

    PythonPlayerInput.cpp:

    Spoiler
    Modify void CPythonPlayer::PickCloseItem() like this:
    void CPythonPlayer::PickCloseItem()
    {
    	CInstanceBase * pkInstMain = NEW_GetMainActorPtr();
    	if (!pkInstMain)
    		return;
    
    	TPixelPosition kPPosMain;
    	pkInstMain->NEW_GetPixelPosition(&kPPosMain);
    
    #ifndef ENABLE_FAST_PICKUP
    	DWORD dwItemID;
    #endif
    	CPythonItem& rkItem=CPythonItem::Instance();
    #ifdef ENABLE_FAST_PICKUP
    	std::vector<DWORD> itemIds;
    	if (!rkItem.GetCloseItems(kPPosMain, &itemIds, __GetPickableDistance()))
    		return;
    
    	TPacketCGItemPickUpAll pack;
    	pack.header = HEADER_CG_ITEM_PICKUP_ALL;
    	memset(pack.vids, 0, sizeof(pack.vids));
    
    	for (int i = 0; i < itemIds.size(); i++)
    	{
    		if (!itemIds[i] || itemIds[i] == 0)
    			continue;
    		pack.vids[i] = itemIds[i];
    	}
    
    	itemIds.clear();
    #else
    	if (!rkItem.GetCloseItem(kPPosMain, &dwItemID, __GetPickableDistance()))
    		return;
    #endif
    
    #ifdef ENABLE_FAST_PICKUP
    	CPythonNetworkStream& rkNetStream = CPythonNetworkStream::Instance();
    	rkNetStream.SendItemPickUpAllPacket(pack);
    #else
    	SendClickItemPacket(dwItemID);
    #endif
    }

    StdAfx.h

    Spoiler
    Add:
    #ifdef ENABLE_FAST_PICKUP
    	FAST_PICKUP_MAX_NUM = 45,
    #endif
    After:
    	PLAYER_NAME_MAX_LEN = 12,

     

     

     

    And now the server side.

    common/serivice.h or common/CommonDefines.h

    Spoiler
    Add:
    #define ENABLE_FAST_PICKUP

     

    common/length.h

    Spoiler
    Add:
    #ifdef ENABLE_FAST_PICKUP
    	FAST_PICKUP_MAX_NUM = 45,
    #endif
    After:
    BELT_INVENTORY_SLOT_COUNT = BELT_INVENTORY_SLOT_WIDTH * BELT_INVENTORY_SLOT_HEIGHT,

     

    packet.h

    Spoiler
    Add:
    #ifdef ENABLE_FAST_PICKUP
    	HEADER_CG_ITEM_PICKUP_ALL		= 32,
    #endif
    After:
    	HEADER_CG_QUEST_CONFIRM			= 31,
    
    Add:
    #ifdef ENABLE_FAST_PICKUP
    typedef struct command_item_pickup_all
    {
    	BYTE header;
    	DWORD vids[FAST_PICKUP_MAX_NUM];
    } TPacketCGItemPickupAll;
    #endif
    After:
    typedef struct command_item_pickup
    {
    	BYTE 	header;
    	DWORD	vid;
    } TPacketCGItemPickup;

     

    packet_info.cpp

    Spoiler
    Add:
    #ifdef ENABLE_FAST_PICKUP
    	Set(HEADER_CG_ITEM_PICKUP_ALL, sizeof(TPacketCGItemPickupAll), "ItemPickup", true);
    #endif
    After:
    	Set(HEADER_CG_ITEM_PICKUP, sizeof(TPacketCGItemPickup), "ItemPickup", true);

     

    input.h

    Spoiler
    Add:
    #ifdef ENABLE_FAST_PICKUP
    		void		ItemPickupAll(LPCHARACTER ch, const char* data);
    #endif
    After:
    		void		ItemPickup(LPCHARACTER ch, const char * data);

     

    input_main.cpp

    Spoiler
    Add:
    #ifdef ENABLE_FAST_PICKUP
    void CInputMain::ItemPickupAll(LPCHARACTER ch, const char* data)
    {
    	struct command_item_pickup_all* pinfo = (struct command_item_pickup_all*)data;
    	if (!ch)
    		return;
    
    	for (int i = 0; i < FAST_PICKUP_MAX_NUM; i++)
    	{
    		if (!ch->PickupItem(pinfo->vids[i]))
    			return;
    	}
    }
    #endif
    After:
    void CInputMain::ItemPickup(LPCHARACTER ch, const char * data)
    {
    	struct command_item_pickup * pinfo = (struct command_item_pickup*) data;
    	if (ch)
    		ch->PickupItem(pinfo->vid);
    }
          
    Add:
    #ifdef ENABLE_FAST_PICKUP
    		case HEADER_CG_ITEM_PICKUP_ALL:
    			if (!ch->IsObserverMode())
    				ItemPickupAll(ch, c_pData);
    			break;
    #endif     
    After:
    		case HEADER_CG_ITEM_PICKUP:
    			if (!ch->IsObserverMode())
    				ItemPickup(ch, c_pData);
    			break;

     

    Good look with the system and please if there's any bug leave a comment so I can fix it.

    Have a good day!

     

    • Metin2 Dev 55
    • Eyes 1
    • Dislove 1
    • Not Good 1
    • Think 1
    • Good 10
    • Love 1
    • Love 28
  11. This is the hidden content, please

    Metin2 Download

    Hello everyone!

     

    Today I saw a basic item system on metin2.download and I was wondering why not to make it with JSON.

    There are better ways to do this, but it can be a great start to learn some JSON for people (also, it's my first work with JSON file(s))

    Almost everything in the .rar, you just have to download and put the dependencies in the right folder, or if you change it don't forget to rewrite the AutoGiveItems.cpp's include.

    Links:

    Spoiler

    Virus Total: 

    This is the hidden content, please

    Git repository: 

    This is the hidden content, please

    AutoGiveItems: 

    This is the hidden content, please

     

    • Metin2 Dev 171
    • kekw 2
    • Eyes 1
    • Dislove 3
    • Angry 1
    • Smile Tear 1
    • Think 2
    • Confused 3
    • Lmao 1
    • Good 25
    • Love 5
    • Love 36
×
×
  • 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.