• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

Lua TFS 1.2 Quest System Issue

Lava Titan

Developer
Joined
Jul 25, 2009
Messages
1,529
Solutions
1
Reaction score
85
Location
Portugal
Heyo I created a "unique" quest system for my server it works 100% the way it is atm, but I'm having a issue, I can't realize how to make it give multiple rewards instead of just one reward, and if it gives multiple rewards, how to assign an aid to just one of those rewards :X

Any suggestions?

Code:
local config = {
    [40000] = {rewards = {2092, 1}, set_aid = 1, aid = 61000, storage = 40000, msg = ""},
    [40001] = {rewards = {2092, 1}, set_aid = 0, aid = 0, storage = 40001, msg = ""}
}

function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    local names = ""
    local chest_uid = config[item:getUniqueId()]
    local ma_arround = getCustomSpectators(player:getPosition(), false, false, true, false, 7, 7, 7, 7)

    if not player:isPlayer() then
    return true
    end

    for i = 1, #ma_arround do
        if(names == "") then
            names = ma_arround[i]:getName()
        else
            names = names .. "\n"..ma_arround[i]:getName()
        end
    end

    if #ma_arround <= 0 then
        if player:getFreeCapacity() >= ItemType(chest_uid.rewards[1]):getWeight() then
            if player:getStorageValue(chest_uid.storage) <= 0 then
                if chest_uid.set_aid == 1 then
                    player:setStorageValue(chest_uid.storage, 1)
                    player:addItem(1987, 1):addItem(chest_uid.rewards[1], chest_uid.rewards[2]):setActionId(chest_uid.aid)
                    player:sendTextMessage(MESSAGE_INFO_DESCR, "You received a "..ItemType(chest_uid.rewards[1]):getName()..".")
                else
                    player:setStorageValue(chest_uid.storage, 1)
                    player:addItem(1987, 1):addItem(chest_uid.rewards[1], chest_uid.rewards[2])
                    player:sendTextMessage(MESSAGE_INFO_DESCR, "You received a "..ItemType(chest_uid.rewards[1]):getName()..".")
                end
            else
                player:sendTextMessage(MESSAGE_INFO_DESCR, "You already completed this quest.")
            end
        else
            player:sendTextMessage(MESSAGE_INFO_DESCR, "Your cap is too low.")
        end
    else
        player:showTextDialog(item:getId(), "You cannot receive your rewards before kill the following monsters:\n\n"..names.."", false, 999)
    end
return true
end
 
Solution
Code:
local function bind(func, ...)
    local args = {...}
    return function()
        return func(unpack(args))
    end
end

local function filter(list, predicate)
    local ret = {}
    for _, v in ipairs(list) do
        if predicate(v) then
            table.insert(ret, v)
        end
    end
    return ret
end

local function map(list, predicate)
    local ret = {}
    for _, v in ipairs(list) do
        table.insert(ret, predicate(v))
    end
    return ret
end

local config = {
    [40000] = {
        rewards = {
            -- 1x item(2092) with actionId(61000)
            function(player)
                local item = Game.createItem(2092, 1)
                item:setActionId(61000)
                -- If you want a personalized...
Code:
local function bind(func, ...)
    local args = {...}
    return function()
        return func(unpack(args))
    end
end

local function filter(list, predicate)
    local ret = {}
    for _, v in ipairs(list) do
        if predicate(v) then
            table.insert(ret, v)
        end
    end
    return ret
end

local function map(list, predicate)
    local ret = {}
    for _, v in ipairs(list) do
        table.insert(ret, predicate(v))
    end
    return ret
end

local config = {
    [40000] = {
        rewards = {
            -- 1x item(2092) with actionId(61000)
            function(player)
                local item = Game.createItem(2092, 1)
                item:setActionId(61000)
                -- If you want a personalized description
                -- item:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, 'This item was awarded to ' .. player:getName() .. ' because he is badass.')
                return item
            end
        },

        storage = 40000,
        message = 'You have received a bone key.'
    },

    [40001] = {
        rewards = {
            -- 1x item(2092)
            bind(Game.createItem, 2092, 1),
            -- 50k
            bind(Game.createItem, 2160, 5)
        },

        storage = 40001,
        message = 'You have received a bag containing a bone key and 5 crystal coins.'
    }
}

function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    local chest = config[item:getUniqueId()]
    if not chest or #chest.rewards == 0 then
        return true
    end

    if player:getStorageValue(chest.storage) > 0 then
        player:sendTextMessage(MESSAGE_INFO_DESCR, 'You have already completed this quest.')
        return true
    end

    local monsters = filter(Game.getSpectators(player:getPosition()), function(creature) return creature:isMonster() end)
    if #monsters > 0 then
        local names = map(monsters, function(monster) return monster:getName() end)
        player:showTextDialog(item:getId(), 'You cannot receive your rewards before killing the following monsters:\n\n' .. table.concat(names, '\n'), false, 999)
        return true
    end

    local bag = Game.createItem(ITEM_BAG)
    for _, func in ipairs(chest.rewards) do
        bag:addItemEx(func(player))
    end

    local ret = player:addItemEx(bag)
    if ret == RETURNVALUE_NOERROR then
        player:setStorageValue(chest.storage, 1)
        player:sendTextMessage(MESSAGE_INFO_DESCR, chest.message)
    else
        player:sendTextMessage(MESSAGE_INFO_DESCR, Game.getReturnMessage(ret))
    end
    return true
end

I took the time to remake your script because the idea is cool and it might be useful for others, these are the main changes:
  • Instead of storing a table with an itemId and count/subType, the rewards table contains functions that will return an item, that way you can customize the item however you like. There is an example in the code of an item with custom actionId (and personalized description if you're into that).
  • Errors are properly handed when giving the reward to the player (e.g not enough capacity, not enough room, etc)
Let me know if anything isn't working as it should.

Edit: another version with automatic content description http://pastebin.com/tY7NUFJn
 
Last edited:
Solution
Can you use this line instead so we can see what is going on:
Code:
local monsters = filter(Game.getSpectators(player:getPosition()), function(creature) print(creature:getName()); return creature:isMonster() end)
 
Back
Top