Jump to content

Fix - Quest item.set_socket(0, Value)


Recommended Posts

  • Active+ Member

Hello! Today I found that in lua the modification of item.set_socket(0, value) does not work.


Fixed:

	int item_set_socket(lua_State* L)
	{
		CQuestManager& q = CQuestManager::instance();
		if (q.GetCurrentItem() && lua_isnumber(L, 1) && lua_isnumber(L, 2))
		{
			int idx = (int)lua_tonumber(L, 1);
			int value = (int)lua_tonumber(L, 2);
			if (idx >= 0 && idx < ITEM_SOCKET_MAX_NUM)
				q.GetCurrentItem()->SetSocket(idx, value);
		}
		return 0;
	}


Original:

	int item_set_socket(lua_State* L)
	{
		CQuestManager& q = CQuestManager::instance();
		if (&q == NULL)
			return 0;

		LPITEM item = q.GetCurrentItem();

		if (item == NULL)
			return 0;

		if (item && lua_isnumber(L, 1) && lua_isnumber(L, 2))
		{
			int idx = (int) lua_tonumber(L, 1);
			int value = (int) lua_tonumber(L, 2);

			if (idx == NULL)
				return 0;

			if (value == NULL)
				return 0;

			if (idx >=0 && idx < ITEM_SOCKET_MAX_NUM)
				item->SetSocket(idx, value);
		}
		return 0;
	}


Explanation:
If the socket index is 0, it returns and does not run the code... fck logic.

			if (idx == NULL)
				return 0;

 

Edited by speze012
  • Metin2 Dev 3
  • Love 1
Link to comment
Share on other sites

  • Forum Moderator

Hello, thanks for the tutorial, but I would still advise you to keep the nullptr checks for relevant parts. I don't think it will go null, but you never know until it gets null.

	int item_set_socket(lua_State* L)
	{
		CQuestManager& q = CQuestManager::instance();
      
		LPITEM item = q.GetCurrentItem();

		if (item == NULL)
			return 0;

		if (item && lua_isnumber(L, 1) && lua_isnumber(L, 2))
		{
			int idx = (int) lua_tonumber(L, 1);
			int value = (int) lua_tonumber(L, 2);

			if (idx >=0 && idx < ITEM_SOCKET_MAX_NUM)
				item->SetSocket(idx, value);
		}
		return 0;
	}

 

Edited by Gurgarath
  • Good 2

Gurgarath
coming soon

Link to comment
Share on other sites

  • Premium

It was blocking also Set Value to 0.

			if (value == NULL)
				return 0;

My version:

	int item_set_socket(lua_State* L)
	{
		LPITEM item = CQuestManager::instance().GetCurrentItem();
		if (!item)
			return 0;

		if (lua_isnumber(L, 1) && lua_isnumber(L, 2))
		{
			const auto idx = static_cast<int>(lua_tonumber(L, 1));
			if (idx < 0 || idx >= ITEM_SOCKET_MAX_NUM)
				return 0;

			// Value can be 0 or negative.
			const auto value = static_cast<int>(lua_tonumber(L, 2));

			item->SetSocket(idx, value);
		}
		else
			sys_err("Passing bad argument from LUA.");

		return 0;
	}

 

Edited by WeedHex
  • Metin2 Dev 1
  • Good 2
Link to comment
Share on other sites

  • 2 weeks later...
  • Premium
define WEAPON_SHOP_DEALER 9001
define ARMOUR_SHOP_DEALER 9002
define TINCTURE_VNUM 71047
define SOCKETS_MAX_NUM 3

quest tincture_stone_add begin
    state start begin
        function GetItemSlotsNum()
            --
        end -- function

        function BuildStoneListForItemType(item_type)
            --
        end -- function

        function GetStoneFamily(stone_vnum)
            --
        end -- function

        function IsStoneFamilySocketed(stone_vnum)
            --
        end -- function

        function BuildAvailableStoneListForItemType(item_type)
             --
        end -- function

        when WEAPON_SHOP_DEALER.take or ARMOUR_SHOP_DEALER.take begin
            local npc_vnum = npc.get_race();
            say_title(string.format("%s:[ENTER]", mob_name(npc_vnum)))

            local item_type = item.get_type(); 
            if (npc_vnum == WEAPON_SHOP_DEALER and item_type ~= ITEM_TYPES.WEAPON) then
                say_reward("I only accept weapons.[ENTER]")
                return;

            elseif (npc_vnum == ARMOUR_SHOP_DEALER and item_type ~= ITEM_TYPES.ARMOR) then
                say_reward("I only accept armors.[ENTER]")
                return;
            end -- if/elseif

            local item_sub_type = item.get_sub_type();
            local invalid_weapon_subtypes = {
                ITEM_SUB_TYPES.WEAPONS.ARROW,
                ITEM_SUB_TYPES.WEAPONS.MOUNT_SPEAR,
                ITEM_SUB_TYPES.WEAPONS.QUIVER
            };
            if (npc_vnum == WEAPON_SHOP_DEALER and table_is_in(invalid_weapon_subtypes, item_sub_type)) then
                say_reward("I only accept valid weapons.[ENTER]")
                return;

            elseif (npc_vnum == ARMOUR_SHOP_DEALER and item_sub_type ~= ITEM_SUB_TYPES.ARMORS.BODY) then
                say_reward("I only accept valid armors.[ENTER]")
                return;
            end -- if/elseif

            if (pc.count_item(TINCTURE_VNUM) == 0) then
                say_reward("You require:")
                say_item_vnum(TINCTURE_VNUM);
                return;
            end -- if

            local slots_num = tincture_stone_add.GetItemSlotsNum();
            if (slots_num == 0) then
                say_reward("This item can't be socketed.[ENTER]")
                return;
            end -- if

            say(string.format("This item has %d possible slot%s.[ENTER]", slots_num, (slots_num > 1 and "s" or "")))
            local available_socket_ids, socket_vnum = {}, -1;
            for socket_id = 0, slots_num-1 do
                socket_vnum = item.get_socket(socket_id);
                if (socket_vnum > 1) then
                    color_say("lightgreen", string.format("Slot n.%d: %s;", socket_id + 1, item_name(socket_vnum)))
                else
                    say_reward(string.format("Slot n.%d: No stone;", socket_id + 1))
                    table.insert(available_socket_ids, socket_id);
                end -- if/else
            end -- for

            if (table.getn(available_socket_ids) == 0) then
                say_reward("[ENTER]There's already a stone in every available socket.[ENTER]")
                return;
            end -- if

            local available_stones_vnums = tincture_stone_add.BuildAvailableStoneListForItemType(item_type);
            if (table.getn(available_stones_vnums) == 0) then
                say_reward("[ENTER]You don't have any stone I can socket in.[ENTER]")
                return;
            end -- if

            say("[ENTER]Which stone do you want to add?")
            local available_stones_names = {};
            table.foreach(available_stones_vnums,
                function(_, stone_vnum)
                    table.insert(available_stones_names, item_name(stone_vnum));
                end -- function
            );
            table.insert(available_stones_names, "Abort");

            -- Window length management
            local available_stones_num = table.getn(available_stones_names);
            if (available_stones_num > 3) then
                say_size(350, 300 + 27 * math.min(5, available_stones_num - SOCKETS_MAX_NUM))
            else
                say("")
            end -- if/else

            local selected_stone = select_table(available_stones_names);
            if (selected_stone == table.getn(available_stones_names)) then
                return;
            end -- if

            pc.remove_item(TINCTURE_VNUM, 1);

            local selected_stone_vnum = available_stones_vnums[selected_stone];
            pc.remove_item(selected_stone_vnum, 1);
            item.set_socket(available_socket_ids[1], selected_stone_vnum);
        end -- when
    end -- state
end -- quest

This is an old quest I wrote. In order for the logic to work, the socket of index 0 must work.. and it does even on traditional kraizy files.

Are you sure this error is a thing? I'm pretty sure (although I didn't check) that some official quests also use that very same instruction.

Edited by Syreldar
  • Metin2 Dev 1
  • Think 1

 

"Nothing's free in this life.

Ignorant people have an obligation to make up for their ignorance by paying those who help them.

Either you got the brains or cash, if you lack both you're useless."

Syreldar

Link to comment
Share on other sites

  • Forum Moderator

Well, well, well.

Syreldar is absolutely right and we should have checked. On the original mainline and novaline, the "Original" function is your "Fixed" function. Your "Original" is a completely custom function that of course doesn't work because of NULL checks on integers. I thought it was an original shenanigans as it wouldn't be unlikely, but no. By default, everyone has a working function, this tutorial is by essence not necessary.

What sources do you use though?

Gurgarath
coming soon

Link to comment
Share on other sites

Announcements



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