Jump to content
Maintenance : Final step ×

questlua_game.cpp : adding new LUA quest function


Go to solution Solved by im4x8061,

Recommended Posts

  • Premium

I was trying to get a new quest function that combines the "drop_item_with_ownership" from questlua_game.cpp with the "item_set_value" function from questlua_item.cpp. The file compiles just fine but when trying to call the new function from a *.quest file and compiling quests, the function is said to be not declared.

I did the following in questlua_game.cpp:

	int game_drop_item_with_attr_own(lua_State* L)
	{
		LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr();

		LPITEM item = NULL;
		switch (lua_gettop(L))
		{
		case 1:
			item = ITEM_MANAGER::instance().CreateItem((DWORD) lua_tonumber(L, 1));
			break;
		case 2:
		case 3:
		case 4:
		case 5:
		case 6:
		case 7:
		case 8:
			item = ITEM_MANAGER::instance().CreateItem((DWORD) lua_tonumber(L, 1), (int) lua_tonumber(L, 2));
			break;
		default:
			return 0;
		}

		if (item == NULL)
		{
			return 0;
		}

		if (lua_isnumber(L, 3))
		{
			int sec = (int) lua_tonumber(L, 3);
			if (sec <= 0)
			{
				item->SetOwnership(ch);
			}
			else
			{
				item->SetOwnership(ch, sec);
			}
		}
		else
		{
			item->SetOwnership(ch);
		}

		// Set attributes if provided
		for (int i = 4; i <= lua_gettop(L); i += 3)
		{
			if (lua_isnumber(L, i) && lua_isnumber(L, i + 1) && lua_isnumber(L, i + 2))
			{
				int index = (int) lua_tonumber(L, i);
				int apply_type = (int) lua_tonumber(L, i + 1);
				int apply_value = (int) lua_tonumber(L, i + 2);
				item->SetForceAttribute(index, apply_type, apply_value);
			}
		}

		PIXEL_POSITION pos;
		pos.x = ch->GetX() + number(-200, 200);
		pos.y = ch->GetY() + number(-200, 200);

		item->AddToGround(ch->GetMapIndex(), pos);
		item->StartDestroyEvent();

		return 0;
	}	

	int game_web_mall(lua_State* L)
	{
		LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr();

		if ( ch != NULL )
		{
			do_in_game_mall(ch, const_cast<char*>(""), 0, 0);
		}
		return 0;
	}

void RegisterGameFunctionTable()
{
    luaL_reg game_functions[] = 
    {
        { "get_safebox_level",			game_get_safebox_level			},
        { "request_make_guild",			game_request_make_guild			},
        { "set_safebox_level",			game_set_safebox_level			},
        { "open_safebox",				game_open_safebox				},
        { "open_mall",					game_open_mall					},
        { "get_event_flag",				game_get_event_flag				},
        { "set_event_flag",				game_set_event_flag				},
        { "drop_item",					game_drop_item					},
        { "drop_item_with_ownership",	game_drop_item_with_ownership	},
        { "drop_item_with_attr_own",	game_drop_item_with_attr_own	},
        { "open_web_mall",				game_web_mall					},

        { NULL,					NULL				}
    };

		CQuestManager::instance().AddLuaFunctionTable("game", game_functions);
	}
}

and added the function into the quest_functions file. But no matter what I do, the functions are not recognized. Even when chaning the name of existing functions, the new names are not availble, but the old names. Could anyone tell me, what I am doing wrong?

Best regards

Edited by im4x8061
Link to comment
Share on other sites

  • Premium
19 minutes ago, Punszz said:

 

Add them in quest_functions

locale/service/quest/quest_functions file

I did do that, as I found this hint in multiple posts already, but without any effect. I thought, that there may be some cache I have to clear manually first? I used `gameclean`command to delete all binaries and recompiled without effect.

Link to comment
Share on other sites

  • Premium
  • Solution
Posted (edited)

There was a typo, that took some time to be found...

If anyone is interested in dropping items with attributes and ownership:

queslua_game.cpp

Spoiler

    int game_drop_item_with_attr_own(lua_State* L)
    {
        LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr();
        if (!ch)
        {
            lua_pushnumber(L, 0);
            return 1;
        }

        LPITEM item = NULL;
        switch (lua_gettop(L))
        {
        case 1: // Only item ID
            item = ITEM_MANAGER::instance().CreateItem((DWORD)lua_tonumber(L, 1));
            break;
        case 2: // Item ID and count
            item = ITEM_MANAGER::instance().CreateItem((DWORD)lua_tonumber(L, 1), (int)lua_tonumber(L, 2));
            break;
        case 3: // Item ID, count, and ownership duration
            item = ITEM_MANAGER::instance().CreateItem((DWORD)lua_tonumber(L, 1), (int)lua_tonumber(L, 2));
            break;
        case 4: // Item ID, count, ownership duration, and attributes
            item = ITEM_MANAGER::instance().CreateItem((DWORD)lua_tonumber(L, 1), (int)lua_tonumber(L, 2));
            break;
        default:
            lua_pushnumber(L, 0); // Invalid argument count
            return 1;
        }

        if (!item)
        {
            lua_pushnumber(L, 0); // Failed to create item
            return 1;
        }

        // Set Ownership
        if (lua_isnumber(L, 3))
        {
            int sec = (int)lua_tonumber(L, 3);
            if (sec <= 0)
                item->SetOwnership(ch);
            else
                item->SetOwnership(ch, sec);
        }
        else
            item->SetOwnership(ch);

        // Handle Attributes (4th argument as a table)
        if (lua_istable(L, 4))
        {
            int max_attributes = 5; // Maximum of 5 attributes
            for (int i = 1; i <= max_attributes; ++i)
            {
                lua_pushnumber(L, i);    
                lua_gettable(L, 4);      
                if (lua_istable(L, -1))   
                {
                    lua_pushnumber(L, 1); 
                    lua_gettable(L, -2);   
                    int attrIndex = (int)lua_tonumber(L, -1);
                    lua_pop(L, 1);       

                    lua_pushnumber(L, 2);  
                    lua_gettable(L, -2);  
                    int attrType = (int)lua_tonumber(L, -1);
                    lua_pop(L, 1);         

                    lua_pushnumber(L, 3);  
                    lua_gettable(L, -2);   
                    int attrValue = (int)lua_tonumber(L, -1);
                    lua_pop(L, 1);        

                    // Apply attribute to the item
                    item->SetForceAttribute(attrIndex, attrType, attrValue);
                }
                lua_pop(L, 1); // Pop the value retrieved by lua_gettable
            }
        }

        // Drop Item
        PIXEL_POSITION pos;
        pos.x = ch->GetX() + number(-200, 200);
        pos.y = ch->GetY() + number(-200, 200);

        item->AddToGround(ch->GetMapIndex(), pos);
        item->StartDestroyEvent();

        lua_pushnumber(L, item->GetID()); // Return the item's ID
        return 1;
    }   

Obviously: quick and dirty. if you feel like it, you can implement the functionality of handling 4 function arguments into the already existing `int game_drop_item_with_ownership(lua_State* L)`but this one is up to you.

Also: add `{ "drop_item_with_attr_own",    game_drop_item_with_attr_own    },`in `void RegisterGameFunctionTable()`and add the function in `server/share/locale/xxx/quest/quest_functions` as `game.drop_item_with_attr_own`.

The quest call can look like this:

Spoiler

quest drop begin
    state start begin
        when 101.kill begin
            local attributes = {
                { 0, 3, 15 },  -- Attribute at index 0, bonus_id, value
                { 1, 5, 15 },  -- Attribute at index 1, bonus_id, value
                { 2, 6, 15 }   -- Attribute at index 2, bonus_id, value
            }
            game.drop_item_with_attr_own(19, 1, 60, attributes) -- Drop item with custom attributes: game.drop_item_with_attr_own(item_vnum, number of items, second until name vanishes, attributes table
        end
    end
end

 

 

 

Edited by im4x8061
  • Good 1
Link to comment
Share on other sites

18 hours ago, im4x8061 said:

There was a typo, that took some time to be found...

If anyone is interested in dropping items with attributes and ownership:

queslua_game.cpp

  Reveal hidden contents

    int game_drop_item_with_attr_own(lua_State* L)
    {
        LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr();
        if (!ch)
        {
            lua_pushnumber(L, 0);
            return 1;
        }

        LPITEM item = NULL;
        switch (lua_gettop(L))
        {
        case 1: // Only item ID
            item = ITEM_MANAGER::instance().CreateItem((DWORD)lua_tonumber(L, 1));
            break;
        case 2: // Item ID and count
            item = ITEM_MANAGER::instance().CreateItem((DWORD)lua_tonumber(L, 1), (int)lua_tonumber(L, 2));
            break;
        case 3: // Item ID, count, and ownership duration
            item = ITEM_MANAGER::instance().CreateItem((DWORD)lua_tonumber(L, 1), (int)lua_tonumber(L, 2));
            break;
        case 4: // Item ID, count, ownership duration, and attributes
            item = ITEM_MANAGER::instance().CreateItem((DWORD)lua_tonumber(L, 1), (int)lua_tonumber(L, 2));
            break;
        default:
            lua_pushnumber(L, 0); // Invalid argument count
            return 1;
        }

        if (!item)
        {
            lua_pushnumber(L, 0); // Failed to create item
            return 1;
        }

        // Set Ownership
        if (lua_isnumber(L, 3))
        {
            int sec = (int)lua_tonumber(L, 3);
            if (sec <= 0)
                item->SetOwnership(ch);
            else
                item->SetOwnership(ch, sec);
        }
        else
            item->SetOwnership(ch);

        // Handle Attributes (4th argument as a table)
        if (lua_istable(L, 4))
        {
            int max_attributes = 5; // Maximum of 5 attributes
            for (int i = 1; i <= max_attributes; ++i)
            {
                lua_pushnumber(L, i);    
                lua_gettable(L, 4);      
                if (lua_istable(L, -1))   
                {
                    lua_pushnumber(L, 1); 
                    lua_gettable(L, -2);   
                    int attrIndex = (int)lua_tonumber(L, -1);
                    lua_pop(L, 1);       

                    lua_pushnumber(L, 2);  
                    lua_gettable(L, -2);  
                    int attrType = (int)lua_tonumber(L, -1);
                    lua_pop(L, 1);         

                    lua_pushnumber(L, 3);  
                    lua_gettable(L, -2);   
                    int attrValue = (int)lua_tonumber(L, -1);
                    lua_pop(L, 1);        

                    // Apply attribute to the item
                    item->SetForceAttribute(attrIndex, attrType, attrValue);
                }
                lua_pop(L, 1); // Pop the value retrieved by lua_gettable
            }
        }

        // Drop Item
        PIXEL_POSITION pos;
        pos.x = ch->GetX() + number(-200, 200);
        pos.y = ch->GetY() + number(-200, 200);

        item->AddToGround(ch->GetMapIndex(), pos);
        item->StartDestroyEvent();

        lua_pushnumber(L, item->GetID()); // Return the item's ID
        return 1;
    }   

Obviously: quick and dirty. if you feel like it, you can implement the functionality of handling 4 function arguments into the already existing `int game_drop_item_with_ownership(lua_State* L)`but this one is up to you.

Also: add `{ "drop_item_with_attr_own",    game_drop_item_with_attr_own    },`in `void RegisterGameFunctionTable()`and add the function in `server/share/locale/xxx/quest/quest_functions` as `game.drop_item_with_attr_own`.

The quest call can look like this:

  Reveal hidden contents

quest drop begin
    state start begin
        when 101.kill begin
            local attributes = {
                { 0, 3, 15 },  -- Attribute at index 0, bonus_id, value
                { 1, 5, 15 },  -- Attribute at index 1, bonus_id, value
                { 2, 6, 15 }   -- Attribute at index 2, bonus_id, value
            }
            game.drop_item_with_attr_own(19, 1, 60, attributes) -- Drop item with custom attributes: game.drop_item_with_attr_own(item_vnum, number of items, second until name vanishes, attributes table
        end
    end
end

 

 

 

If you want to get an good answe then ask a good question.. You first said this " it says that function not declared" which i provided fix... not working your quest function is different than undeclared

Link to comment
Share on other sites

  • Premium
7 hours ago, Punszz said:

If you want to get an good answe then ask a good question.. You first said this " it says that function not declared" which i provided fix... not working your quest function is different than undeclared

Excuse me? I am sorry if I offended you, but I stated the question correctly and even acknoledged your reply.

But your reply was not the answer to my question. The answer was: There was a typo in my code hence the function name in quest_function did not match my function call. It just took me some time to realize this, as this happened in a copy&paste mistake.

My issue was not providing the whole code here, as you may have found this mistake much sooner than I have.

Link to comment
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
×
×
  • 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.