Jump to content

Sonitex

Premium
  • Posts

    522
  • Joined

  • Days Won

    12
  • Feedback

    100%

Posts posted by Sonitex

  1. Here are some functions that can help you out. I have some global variables for dungeon types so you might wanna adapt that to your own needs.

    		function CheckMembersItem()
    			if (is_test_server()) then
    				syschat("Skipping group item check due to debugging mode being enabled.")
    				return true
    			end
    			
    			local not_allowed_users = {}
    			local pids = {party.get_member_pids()}
    			
    			local item_vnum = ITEM_VNUM_HERE
    			
    			for i = 1, table.getn(pids) do
    				q.begin_other_pc_block(pids[i])
    				if (pc.count_item(item_vnum) < 1) then --and not pc.is_gm() then
    					table.insert(not_allowed_users, pc.get_name())
    				end
    				q.end_other_pc_block()
    			end
    
    			if table.getn(not_allowed_users) == 0 then
    				return true
    			end
    
    			if table.getn(not_allowed_users) > 0 then
    				say_npc()
    				say("The following players do not meet the item")
    				say("requirements.")
    				say("")
    				say("")
    				say_item_vnum(item_vnum)
    				say("")
    				say("")
    				for x = 1, table.getn(not_allowed_users), 1 do
    					say(color(1,1,0), "    " .. not_allowed_users[x])
    				end
    				return false
    			end
    			
    			-- Should never happen
    			return false
    		end
    		
    		function remove_entrance_item(dungeon_type)
    			local item_vnum = ITEM_VNUM_HERE
    			
    			if dungeon_type != DUNGEON_TYPE_SOLO then
    				local pids = {party.get_member_pids()}
    				
    				for i = 1, table.getn(pids) do
    					q.begin_other_pc_block(pids[i])
    					if not pc.is_gm() then
    						pc.remove_item(item_vnum, 1)
    					end
    					q.end_other_pc_block()
    				end
    			else
    				pc.remove_item(item_vnum, 1)
    			end
    		end

     

  2. I am just curious but this would purge the items from memory, right?

    If added at the end of the function at input_main.cpp?

    	for (auto const& item : s_vec_item)
    	{
    		M2_DESTROY_ITEM(item);
    	}
    Spoiler
    
    void CInputMain::TargetInfoLoad(LPCHARACTER ch, const char* c_pData)
    {
    	TPacketCGTargetInfoLoad* p = (TPacketCGTargetInfoLoad*)c_pData;
    	TPacketGCTargetInfo pInfo;
    	pInfo.header = HEADER_GC_TARGET_INFO;
    	static std::vector<LPITEM> s_vec_item;
    	s_vec_item.clear();
    	LPITEM pkInfoItem;
    	LPCHARACTER m_pkChrTarget = CHARACTER_MANAGER::instance().Find(p->dwVID);
    	
    	if (!ch || !m_pkChrTarget)
    		return;
    
    	if (ITEM_MANAGER::instance().CreateDropItemVector(m_pkChrTarget, ch, s_vec_item) && (m_pkChrTarget->IsMonster() || m_pkChrTarget->IsStone()))
    	{
    		if (s_vec_item.size() == 0);
    		else if (s_vec_item.size() == 1)
    		{
    			pkInfoItem = s_vec_item[0];
    			pInfo.dwVID	= m_pkChrTarget->GetVID();
    			pInfo.race = m_pkChrTarget->GetRaceNum();
    			pInfo.dwVnum = pkInfoItem->GetVnum();
    			pInfo.count = pkInfoItem->GetCount();
    			ch->GetDesc()->Packet(&pInfo, sizeof(TPacketGCTargetInfo));
    		}
    		else
    		{
    			int iItemIdx = s_vec_item.size() - 1;
    			while (iItemIdx >= 0)
    			{
    				pkInfoItem = s_vec_item[iItemIdx--];
    
    				if (!pkInfoItem)
    				{
    					sys_err("pkInfoItem null in vector idx %d", iItemIdx + 1);
    					continue;
    				}
    
    					pInfo.dwVID	= m_pkChrTarget->GetVID();
    					pInfo.race = m_pkChrTarget->GetRaceNum();
    					pInfo.dwVnum = pkInfoItem->GetVnum();
    					pInfo.count = pkInfoItem->GetCount();
    					ch->GetDesc()->Packet(&pInfo, sizeof(TPacketGCTargetInfo));
    			}
    		}
    	}
    
    	for (auto const& value : s_vec_item)
    	{
    		M2_DESTROY_ITEM(value);
    	}
    
    }

     

     

  3. 27 minutes ago, ReFresh said:

    @Syreldar I understand you but it's hard to read a code which you don't make by yourself, so easy thing is now the hardest thing.

    After four years you should be reading(at least) Metin2 code easily, this is not an excuse. Problem is, you do nothing on your own and always ask others to do it for you, literally. Not to brag or anything but I've started this p-server thing at the same year as you did and right now I am able to read, modify, add or remove code without any issues. That is because I wanted to learn and I eventually did. You should do the same. This is the truth, take it or leave it.

    • Love 1
  4. 	if (IsAffectFlag(AFF_MANASHIELD))
    	{
    		int iDamageSPPart = dam / 3;
    		int iDamageToSP = iDamageSPPart * GetPoint(POINT_MANASHIELD) / 100;
    		int iSP = GetSP();
    
    		if (iDamageToSP <= iSP)
    		{
    			PointChange(POINT_SP, -iDamageToSP);
    			dam -= iDamageSPPart;
    		}
    		else
    		{
    			PointChange(POINT_SP, -GetSP());
    			dam -= iSP * 100 / MAX(GetPoint(POINT_MANASHIELD), 1);
    		}
    	}

    As you can see, dam is the received damage and it is reduced by one third. I have no idea why YMIR added scaling for this skill if it was always constant and description in client is wrong as well... 

    You could modify it and get damage reduction from skill power by adding this. Please note that this was just a quick guess, it may not work or I even miss understood something...

    iDamageSPPart is an int type percentage of damage that should be reduced(I believe ?).

    		CSkillProto* pkSk = CSkillManager::instance().Get(SKILL_MANASHILED);
    
    		if (NULL != pkSk)
    		{
    			pkSk->SetPointVar("k", 1.0f * GetSkillPower(SKILL_MANASHILED) / 100.0f);
    			pkSk->SetPointVar("iq", GetPoint(POINT_IQ));
    
    			int iDamageSPPart = static_cast<int>(pkSk->kPointPoly.Eval());
    		}
            
            	dam -= (dam / 100) * iDamageSPPart

     

    • Love 1
  5. In item_manager_read_tables.cpp search for:

    bool ITEM_MANAGER::ReadSpecialDropItemFile(const char * c_pszFileName)

    Inside find this, it may not be same as yours:

    		else
    		{
    			CSpecialItemGroup * pkGroup = M2_NEW CSpecialItemGroup(iVnum, type);
    			for (int k = 1; k < 256; ++k)
    			{
    				char buf[4];
    				snprintf(buf, sizeof(buf), "%d", k);
    
    				if (loader.GetTokenVector(buf, &pTok))
    				{
    					const std::string& name = pTok->at(0);
    					DWORD dwVnum = 0;
    
    					if (!GetVnumByOriginalName(name.c_str(), dwVnum))
    					{
    						if (name == "exp")
    						{
    							dwVnum = CSpecialItemGroup::EXP;
    						}
    						else if (name == "mob")
    						{
    							dwVnum = CSpecialItemGroup::MOB;
    						}
    						else if (name == "slow")
    						{
    							dwVnum = CSpecialItemGroup::SLOW;
    						}
    						else if (name == "drain_hp")
    						{
    							dwVnum = CSpecialItemGroup::DRAIN_HP;
    						}
    						else if (name == "poison")
    						{
    							dwVnum = CSpecialItemGroup::POISON;
    						}
    						else if (name == "bleed")
    						{
    							dwVnum = CSpecialItemGroup::BLEED;
    						}
    						else if (name == "group")
    						{
    							dwVnum = CSpecialItemGroup::MOB_GROUP;
    						}
    						else
    						{
    							str_to_number(dwVnum, name.c_str());
    							if (!ITEM_MANAGER::instance().GetTable(dwVnum))
    							{
    								sys_err("ReadSpecialDropItemFile : there is no item %s : node %s", name.c_str(), stName.c_str());
    								M2_DELETE(pkGroup);
    
    								return false;
    							}
    						}
    					}

    And add this below <if (name == "exp")>

    						else if (name == "yang")
    						{
    							dwVnum = CSpecialItemGroup::GOLD;
    						}

    I just tested it so it should work fine :=) 

    • Love 1
  6. 13 hours ago, hachiwari said:

    3500? How did you calculate this number?

    Actually I was wrong, there would have to be more than or equal to 10000 dungeons of same type because, (mapIndex * 10000 + 10000) / 10000 > mapIndex and we wouldn't get original mapIndex but mapIndex+1 or more, depends on dungeon instances. For some reason I thought it would round up the number, but it's type is integer so it is not possible ?‍♂️ so I just said 3500 just to give an idea. I apologise for that.

     

    16 hours ago, JarajTo said:

    I believe that more than 3500 dungeon instances of same type are possible.

     

    Nice one

    Sure, I would love to see that happen. There isn't a server with more than 3000 unique players right now, but you would need more than 10000 unique players(as I corrected myself earlier), each one creating their own dungeon, good luck with that one.

    1 hour ago, Chyu ^^ said:

    Don't fix bugs by creating new bugs.

    If you are referring to having more than 10000 dungeons, it is just not possible, if not I'd love to hear those 'new bugs' and will happily fix them.

    • Love 1
  7. Hey community!

    When you specify which music you want to play in your dungeon map at settings.lua, it is always getting replaced with previous map's one(From which you were teleported to). This is happening because each dungeon has it's own unique map index and game cannot locate it from settings.

    Here is a simple fix to get original index of that map, it should work as long as you do not have like 10000 dungeon instances of same type, which isn't possible with current Metin2 player count I believe.

    In char.cpp search for:

    void CHARACTER::MainCharacterPacket()

    Replace this variable with the following:

    const unsigned mapIndex = GetMapIndex();
    
    const unsigned mapIndex = GetMapIndex() < 10000 ? GetMapIndex() : GetMapIndex() / 10000;

    Greetings,

    Sonitex

    • Confused 2
    • Love 7
  8. 2 hours ago, Tatsumaru said:

    I did not do it for all the characters because I did not need it.
    PS: At the request of one user

     

    Not the hero we deserve but the hero we need :) Amazing work!

    • Love 1
  9. On 8/31/2018 at 6:01 PM, zeimpekis9 said:

    Thanks for the release dude!!
    Maybe you could the same for shops, mounts, pets? I mean to hide them?

    Thanks for your time

    void CInstanceBase::Update()
    
    
    if (IsPet())
    	{
    		if (CPythonSystem::instance().IsHidePets())
    		{
    			if (!IsAffect(AFFECT_INVISIBILITY))
    			{
    				__SetAffect(AFFECT_INVISIBILITY, true);
    				m_kAffectFlagContainer.Set(AFFECT_INVISIBILITY, true);
    			}
    		}
    		else
    		{
    			if (IsAffect(AFFECT_INVISIBILITY))
    			{
    				__SetAffect(AFFECT_INVISIBILITY, false);
    				m_kAffectFlagContainer.Set(AFFECT_INVISIBILITY, false);
    			}
    		}
    	}

     

    • Love 2
  10. 25 minutes ago, brtk23 said:

    Thanks for the answer :)

    I'm already familiar with the 3ds max and I'm trying to do something but as I've seen in metin it teleports one immediately on top of an object (bridges) if you try to walk under it, that's why I'm not sure whether it would work or not, but I'll definitely try to do so, thanks.

    I've got another question: I've done my first (well not first, but the first I'll try to import onto the server) map but I don't know how to set up the "map borders/collisions" (where you can and can't walk), I've heard of metin2 map tool but it's done through painting on a 2d map. So my question is: does worldedit have this kind of option already?

    Yeah it has that feature already built in and it is very easy to use.

    vcDFcab.png

    It is under "A" section, first you select brush shape and size. Then you select what kind of block type you would like to apply to terrain, either water surface, block collision or block any kind of battle action in the area. With "Edit" button you can apply those 3 to the map while "Eraser" obviously removes them. Happy mapping :D (You can add multiple types on the same area)

    • Love 1
  11. There is a tutorial on this forum about different waters in different maps and functions exactly as you said.-> [HowTo]Get different watertypes  (For some reason I cannot link the topic)

    Collisions are set with 3ds program and are exported there too. There should be some tutorials regarding that, but it is pretty easy to learn to be honest.

    Greetings, Sonitex

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