• 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!

TFS 1.X+ [TFS 1.4] Advanced Quest Script for multiple reward - problem.

Crest

New Member
Joined
Mar 25, 2008
Messages
18
Reaction score
2
Location
Poland
Hello,

need some help with advanced quest script from here.

I add all of .lua files to correct folders, add uid in map editor, tfs don't show any error in console but when I want from one chest get item and some exp it didn't work. I get only item, nothing more.

Here is my .lua
Lua:
questChests = {
    ---------------------------------------------------------
   -- Example Quest Box 1
   ---------------------------------------------------------
   [20007] = {
    storageUnique = 2108,
    items = {
        [1] = {type = "item", item = 2160, count = 1},
      },
   },

   [20000] = {
    storageUnique = 2000,
    items = {
        [1] = {type = "item", item = 2434, count = 1},
        [2] = {type = "experience", amount = 10000},
      },
   },
}

and one more from scripts/actions/quest_chests.lua

Lua:
function capAll(str)
return (str:gsub("(%l)(%w*)", function(a,b) return string.upper(a)..b end))
end

local advanceChest = Action()

function advanceChest.onUse(player, item, fromPosition, itemEx, toPosition)
-----------------------------------------------------------------------------------
-- Local Variables --
-----------------------------------------------------------------------------------
local questChest = item:getUniqueId()
-----------------------------------------------------------------------------------
-- Check if player has already opened box --
-----------------------------------------------------------------------------------
if player:getStorageValue(questChest) == 1 then
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The chest is empty.")
toPosition:sendMagicEffect(10)
return true
end

local storageOne = questChests[questChest].storageUnique
-----------------------------------------------------------------------------------
-- Check if player has already opened box multiple chest only 1 reward --
-----------------------------------------------------------------------------------
if player:getStorageValue(storageOne) == 1 then
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The chest is empty.")
toPosition:sendMagicEffect(10)
return true
end


-- Give rewward if player has not yet opened box --

-----------------------------------------------------------------------------------
for i = 1, #questChests[questChest].items do
local rewardType = questChests[questChest].items.type
-----------------------------------------------------------------------------------
-- Item Type Reward --
-----------------------------------------------------------------------------------
if rewardType == "item" then
local item = questChests[questChest].items.item
local count = questChests[questChest].items.count
player:addItem(item, count)
player:say("You have found ["..count.."x] "..capAll(getItemName(item)), TALKTYPE_MONSTER_SAY)
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You have found ["..count.."x] "..capAll(getItemName(item)))
end
-----------------------------------------------------------------------------------
-- Experience Type Reward --
-----------------------------------------------------------------------------------
if rewardType == "experience" then
local amount = questChests[questChest].items.amount
player:addExperience(amount)
player:say(amount.." EXP gained!", TALKTYPE_MONSTER_SAY)
player:getPosition():sendMagicEffect(CONST_ME_STUN)
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You gained "..amount.." experience points.")
end
-----------------------------------------------------------------------------------
-- Outfit Type Reward --
-----------------------------------------------------------------------------------
if rewardType == "outfit" then
local outfitName = questChests[questChest].items.name
local maleOutfit = questChests[questChest].items.maleId
local femaleOutfit = questChests[questChest].items.femaleId
if player:getSex() == 0 then
player:addOutfit(femaleOutfit)
else
player:addOutfit(maleOutfit)
end
player:say("You have found "..outfitName.." outfit.", TALKTYPE_MONSTER_SAY)
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You have found "..outfitName.." outfit.")
end
-----------------------------------------------------------------------------------
-- Addon Type Reward --
-----------------------------------------------------------------------------------
if rewardType == "addon" then
local outfitName = questChests[questChest].items.outfit
local addon = questChests[questChest].items.addonNumber
local maleAddon = questChests[questChest].items.maleId
local femaleAddon = questChests[questChest].items.femaleId
if player:getSex() == 0 then
player:addOutfitAddon(femaleAddon, addon)
else
player:addOutfitAddon(maleAddon, addon)
end
if addon == 1 then
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You have found the first "..outfitName.." outfit addon.")
elseif addon == 2 then
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You have found the second "..outfitName.." outfit addon.")
elseif addon == 3 then
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You have found the third "..outfitName.." outfit addon.")
end
end
-----------------------------------------------------------------------------------
-- Mount Type Reward --
-----------------------------------------------------------------------------------
if rewardType == "mount" then
local mountName = questChests[questChest].items.mountName
local mountId = questChests[questChest].items.mountId
player:addMount(mountId)
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You have unlocked the "..mountName.." mount.")
end




-----------------------------------------------------------------------------------
-- Add in any cooldowns/storages --
-----------------------------------------------------------------------------------
player:setStorageValue(questChest, 1)
player:setStorageValue(storageOne, 1)
return true
end
end

for i = 20000, 21000 do
advanceChest:uid(i)
end

advanceChest:register()


Any idea why this script didn't work?
 
Last edited:
Solution
B
Hmm...well that's a funny issue xD

Perhaps it could be the fact the storage values are being set numerous times inside the for loop? Although I don't see how that would affect the several array items as the storage checks are being done beforehand. @Xikini

Oh i see now...the return true is being done inside the for loop.....i cant believe it took me that long to see it.

Solution is here @Crest
Lua:
function capAll(str)
    return (str:gsub("(%l)(%w*)", function(a,b) return string.upper(a)..b end))
end

local advanceChest = Action()
function advanceChest.onUse(player, item, fromPosition, itemEx, toPosition)

    local questChest = item:getUniqueId()
    if player:getStorageValue(questChest) == 1 then...
Youre looping through a for loop, but don't reference the index, so most things will be null or default to the initial index.

Line 36 should be :
Lua:
local rewardType = questChests[questChest].items[i].type

You could then add below it something like this:
Lua:
local rewardData = questChests[questChest].items[i]

and then if you wanted to get the experience, you would just do:
Lua:
local experience = rewardData.amount

keep in mind, you will have to replace everything that used the old reference, so things like item becomes local item = rewardData.item and count becomes local count = rewardData.count

-------------------------------------------------


If you're unable to figure it out, or are too lazy :D, here it is:
Lua:
function capAll(str)
    return (str:gsub("(%l)(%w*)", function(a,b) return string.upper(a)..b end))
end

local advanceChest = Action()
function advanceChest.onUse(player, item, fromPosition, itemEx, toPosition)

    local questChest = item:getUniqueId()
    if player:getStorageValue(questChest) == 1 then
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The chest is empty.")
        toPosition:sendMagicEffect(10)
    return true
    end

    local storageOne = questChests[questChest].storageUnique
    if player:getStorageValue(storageOne) == 1 then
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The chest is empty.")
        toPosition:sendMagicEffect(10)
    return true
    end

    for i = 1, #questChests[questChest].items do
    
        local rewardData = questChests[questChest].items[i]
        local rewardType = rewardData.type

        if rewardType == "item" then
            local item = rewardData.item
            local count = rewardData.count
            player:addItem(item, count)
            player:say("You have found ["..count.."x] "..capAll(getItemName(item)), TALKTYPE_MONSTER_SAY)
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You have found ["..count.."x] "..capAll(getItemName(item)))
        end

        if rewardType == "experience" then
            local amount = rewardData.amount
            player:addExperience(amount)
            player:say(amount.." EXP gained!", TALKTYPE_MONSTER_SAY)
            player:getPosition():sendMagicEffect(CONST_ME_STUN)
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You gained "..amount.." experience points.")
        end

        if rewardType == "outfit" then
            local outfitName = rewardData.name
            local maleOutfit = rewardData.maleId
            local femaleOutfit = rewardData.femaleId
            if player:getSex() == 0 then
                player:addOutfit(femaleOutfit)
            else
                player:addOutfit(maleOutfit)
            end
            player:say("You have found "..outfitName.." outfit.", TALKTYPE_MONSTER_SAY)
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You have found "..outfitName.." outfit.")
        end

        if rewardType == "addon" then
            local outfitName = rewardData.outfit
            local addon = rewardData.addonNumber
            local maleAddon = rewardData.maleId
            local femaleAddon = rewardData.femaleId
            
            if player:getSex() == 0 then
                player:addOutfitAddon(femaleAddon, addon)
            else
                player:addOutfitAddon(maleAddon, addon)
            end
            
            if addon == 1 then
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You have found the first "..outfitName.." outfit addon.")
            elseif addon == 2 then
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You have found the second "..outfitName.." outfit addon.")
            elseif addon == 3 then
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You have found the third "..outfitName.." outfit addon.")
            end       
        end

        if rewardType == "mount" then
            local mountName = rewardData.mountName
            local mountId = rewardData.mountId
            player:addMount(mountId)
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You have unlocked the "..mountName.." mount.")
        end

        player:setStorageValue(questChest, 1)
        player:setStorageValue(storageOne, 1)
        return true
    end
    
end

for i = 20000, 21000 do
    advanceChest:uid(i)
end

advanceChest:register()

Untested. Oh and in the future, please indent/use tabbing.
 
Last edited by a moderator:
Looks like a copy-paste issue, where all of the [i] 's turned into italics. (you can see in OP's post, that his last line of text is all italic)

--
I found the original issue and posted it in the thread. Here.

Posting here for clarity, as well.

Lua:
questChests = {
    ---------------------------------------------------------
    -- Example Quest Box 1
    ---------------------------------------------------------
    [20007] = {
        storageUnique = 2108,
        minLevel = 1,
        items = {
            [1] = {type = "item", item = 2160, count = 1},
        },
    },
    
    [20000] = {
        storageUnique = 2000,
        minLevel = 1,
        items = {
            [1] = {type = "item", item = 2434, count = 1},
            [2] = {type = "experience", amount = 10000},
        },
    },
}
Lua:
function capAll(str)
    return (str:gsub("(%l)(%w*)", function(a,b) return string.upper(a)..b end))
end

local advanceChest = Action()

function advanceChest.onUse(player, item, fromPosition, itemEx, toPosition)
    -----------------------------------------------------------------------------------
    -- Local Variables --
    -----------------------------------------------------------------------------------
    local questChest = item:getUniqueId()
    -----------------------------------------------------------------------------------
    -- Check if player has already opened box --
    -----------------------------------------------------------------------------------
    if player:getStorageValue(questChest) == 1 then
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The chest is empty.")
        toPosition:sendMagicEffect(10)
        return true
    end
    
    local storageOne = questChests[questChest].storageUnique
    -----------------------------------------------------------------------------------
    -- Check if player has already opened box multiple chest only 1 reward --
    -----------------------------------------------------------------------------------
    if player:getStorageValue(storageOne) == 1 then
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The chest is empty.")
        toPosition:sendMagicEffect(10)
        return true
    end 
    
    -----------------------------------------------------------------------------------
    -- Check if player meets level requirment
    -----------------------------------------------------------------------------------
    local playerLevel = player:getLevel()
    local minLevel = questChests[questChest].minLevel
    if questChests[questChest].minLevel < playerLevel then
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You need to be level "..minLevel.." to open this chest.")
        return true
    end
    -----------------------------------------------------------------------------------
    
    -- Give rewward if player has not yet opened box --
    
    -----------------------------------------------------------------------------------
    for i = 1, #questChests[questChest].items do
        local rewardType = questChests[questChest].items[i].type
        -----------------------------------------------------------------------------------
        -- Item Type Reward --
        -----------------------------------------------------------------------------------
        if rewardType == "item" then
            local item = questChests[questChest].items[i].item
            local count = questChests[questChest].items[i].count
            player:addItem(item, count)
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You earned ["..count.."x] "..capAll(getItemName(item)))
        end
        -----------------------------------------------------------------------------------
        -- Experience Type Reward --
        -----------------------------------------------------------------------------------
        if rewardType == "experience" then
            local amount = questChests[questChest].items[i].amount
            player:addExperience(amount)
            player:say(amount.." EXP gained!", TALKTYPE_MONSTER_SAY)
            player:getPosition():sendMagicEffect(CONST_ME_STUN)
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You gained "..amount.." experience points.")
        end
        -----------------------------------------------------------------------------------
        -- Outfit Type Reward --
        -----------------------------------------------------------------------------------
        if rewardType == "outfit" then
            local outfitName = questChests[questChest].items[i].name
            local maleOutfit = questChests[questChest].items[i].maleId
            local femaleOutfit = questChests[questChest].items[i].femaleId
            if player:getSex() == 0 then
                player:addOutfit(femaleOutfit)
            else
                player:addOutfit(maleOutfit)
            end
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You gained the "..outfitName.." outfit.")
        end
        -----------------------------------------------------------------------------------
        -- Addon Type Reward --
        -----------------------------------------------------------------------------------
        if rewardType == "addon" then
            local outfitName = questChests[questChest].items[i].outfit
            local addon = questChests[questChest].items[i].addonNumber
            local maleAddon = questChests[questChest].items[i].maleId
            local femaleAddon = questChests[questChest].items[i].femaleId
            if player:getSex() == 0 then
                player:addOutfitAddon(femaleAddon, addon)
            else
                player:addOutfitAddon(maleAddon, addon)
            end
            if addon == 1 then
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You gained the first "..outfitName.." outfit addon.")
            elseif addon == 2 then
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You gained the second "..outfitName.." outfit addon.")
            elseif addon == 3 then
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You gained the third "..outfitName.." outfit addon.")
            end
        end
        -----------------------------------------------------------------------------------
        -- Mount Type Reward --
        -----------------------------------------------------------------------------------
        if rewardType == "mount" then
            local mountName = questChests[questChest].items[i].mountName
            local mountId = questChests[questChest].items[i].mountId
            player:addMount(mountId)
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You have unlocked the "..mountName.." mount.")
        end
    
                
    
    
        -----------------------------------------------------------------------------------
        -- Add in any cooldowns/storages --
        -----------------------------------------------------------------------------------
        player:setStorageValue(questChest, 1)
        player:setStorageValue(storageOne, 1)
    end
    return true
end

for i = 20000, 21000 do
    advanceChest:uid(i)
end

advanceChest:register()
 
Last edited:
Hmm...well that's a funny issue xD

Perhaps it could be the fact the storage values are being set numerous times inside the for loop? Although I don't see how that would affect the several array items as the storage checks are being done beforehand. @Xikini

Oh i see now...the return true is being done inside the for loop.....i cant believe it took me that long to see it.

Solution is here @Crest
Lua:
function capAll(str)
    return (str:gsub("(%l)(%w*)", function(a,b) return string.upper(a)..b end))
end

local advanceChest = Action()
function advanceChest.onUse(player, item, fromPosition, itemEx, toPosition)

    local questChest = item:getUniqueId()
    if player:getStorageValue(questChest) == 1 then
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The chest is empty.")
        toPosition:sendMagicEffect(10)
    return true
    end

    local storageOne = questChests[questChest].storageUnique
    if player:getStorageValue(storageOne) == 1 then
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The chest is empty.")
        toPosition:sendMagicEffect(10)
    return true
    end

    for i = 1, #questChests[questChest].items do
    
        local rewardData = questChests[questChest].items[i]
        local rewardType = rewardData.type

        if rewardType == "item" then
            local item = rewardData.item
            local count = rewardData.count
            player:addItem(item, count)
            player:say("You have found ["..count.."x] "..capAll(getItemName(item)), TALKTYPE_MONSTER_SAY)
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You have found ["..count.."x] "..capAll(getItemName(item)))
        end

        if rewardType == "experience" then
            local amount = rewardData.amount
            player:addExperience(amount)
            player:say(amount.." EXP gained!", TALKTYPE_MONSTER_SAY)
            player:getPosition():sendMagicEffect(CONST_ME_STUN)
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You gained "..amount.." experience points.")
        end

        if rewardType == "outfit" then
            local outfitName = rewardData.name
            local maleOutfit = rewardData.maleId
            local femaleOutfit = rewardData.femaleId
            if player:getSex() == 0 then
                player:addOutfit(femaleOutfit)
            else
                player:addOutfit(maleOutfit)
            end
            player:say("You have found "..outfitName.." outfit.", TALKTYPE_MONSTER_SAY)
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You have found "..outfitName.." outfit.")
        end

        if rewardType == "addon" then
            local outfitName = rewardData.outfit
            local addon = rewardData.addonNumber
            local maleAddon = rewardData.maleId
            local femaleAddon = rewardData.femaleId
            
            if player:getSex() == 0 then
                player:addOutfitAddon(femaleAddon, addon)
            else
                player:addOutfitAddon(maleAddon, addon)
            end
            
            if addon == 1 then
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You have found the first "..outfitName.." outfit addon.")
            elseif addon == 2 then
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You have found the second "..outfitName.." outfit addon.")
            elseif addon == 3 then
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You have found the third "..outfitName.." outfit addon.")
            end       
        end

        if rewardType == "mount" then
            local mountName = rewardData.mountName
            local mountId = rewardData.mountId
            player:addMount(mountId)
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You have unlocked the "..mountName.." mount.")
        end
    end
    player:setStorageValue(questChest, 1)
    player:setStorageValue(storageOne, 1)
    return true
end

for i = 20000, 21000 do
    advanceChest:uid(i)
end

advanceChest:register()
 
Solution
Hmm...well that's a funny issue xD

Perhaps it could be the fact the storage values are being set numerous times inside the for loop? Although I don't see how that would affect the several array items as the storage checks are being done beforehand. @Xikini
The storages being set multiple times won't matter too much. Should probably put them outside the loop, but 🤷‍♂️

The issue was that the return true was inside the loop, after the storages, thus the loop could only ever do 1 iteration, before stopping.
Hence he'd get the item, but not the experience, since experience would be given on the 2nd loop through, but would always stop on loop 1.
 
@Xikini @Boy67

Lua:
21:40 You have found [1x] Crystal Coin
21:40 You gained 20000 experience points.
21:40 You have found assassin outfit.
21:40 You have found the first assassin outfit addon.
21:40 You have found the second assassin outfit addon.

Yep, it's work now. Thanks a lot for help.
 
@Xikini @Boy67

Lua:
21:40 You have found [1x] Crystal Coin
21:40 You gained 20000 experience points.
21:40 You have found assassin outfit.
21:40 You have found the first assassin outfit addon.
21:40 You have found the second assassin outfit addon.

Yep, it's work now. Thanks a lot for help.
What should I be writing on the chests in map editor?
Post automatically merged:

What should I be writing on the chests in map editor?
Never mind I figured it out. You write the unique ID as 20000 and 20007 (this example) in map editor leaving action ID empty. If you want the player to only pick one of the rewards then put the same number in the "storageUnique = ".
 
Last edited:
Back
Top