• 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 Task system issues

SixNine

Active Member
Joined
Dec 12, 2018
Messages
442
Reaction score
40
The issues im talking about

  1. Doesnt give rewards (no errors)
  2. Once you take task it says You must kill: (51) rats('s). when it should say You must kill: (50) rats('s). (so basically it adds one more for some reason)
  3. Issue with creature count it says
22:57 (2) Rats LvL 1 left.
22:57 (1) Rats LvL 1 left.
22:57 (0) Rats LvL 1 left.
22:57 You have finished the Undeads task.

when it should be

22:57 (2) Rrats LvL 1 left.
22:57 (1) Rats LvL 1 left.
22:57 You have finished the Undeads task.

Code
Lua:
local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)

function onCreatureAppear(cid)              npcHandler:onCreatureAppear(cid)            end
function onCreatureDisappear(cid)           npcHandler:onCreatureDisappear(cid)         end
function onCreatureSay(cid, type, msg)      npcHandler:onCreatureSay(cid, type, msg)    end
function onThink()                          npcHandler:onThink()                        end

local tasks = {
    [1] = {id = 1, levelReq = 1, msg = "{Rats} have been terrorizing the undergrounds of west. I need you to {kill 50 of them}.",
        name = {"Rats", "rats", "1"},
        monsters = {
            [1] = {name = "rats", amount = 50, storage = 6601}
        },
        exp = 10000,
        itemRewards = {{2160, 25}, {2152, 1}}
        },
    [2] = {id = 2, levelReq = 5, msg = "Some Message.",
        name = {"orcs", "Orcs", "2"},
        monsters = {
            [1] = {name = "Orc", amount = 50, storage = 6602}
        },
        exp = 50000,
        itemRewards = {{2152, 5}}
        }
}

local taskStorage = 6500

function creatureSayCallback(cid, type, msg)
    if not npcHandler:isFocused(cid) then
        return false
    end

    local player = Player(cid)
    if not player then return true end
    
    if msg and msg == "tasks" or msg == "mission" then
        local text = "Tasks: "
        for i = 1, #tasks do
            if i == #tasks then
                text = text..""..tasks[i].name[1].."."
            else
                text = text..""..tasks[i].name[1]..", "
            end
        end
        
        selfSay(text, cid)
        return true
        
    elseif msg and msg ~= "cancel" then
        local TASK = nil
        
        for i = 1, #tasks do
            if isInArray(tasks[i].name, msg) then
                TASK = tasks[i]
                break
            end
        end
        
        if not TASK then return true end
        
        local playerTask = tasks[player:getStorageValue(taskStorage)]
        
        if player:getStorageValue(taskStorage) == nil or player:getStorageValue(taskStorage) == -1 then
            player:setStorageValue(taskStorage, TASK.id)
            selfSay(TASK.msg, cid)
            return true
        end
            
        if player:getStorageValue(taskStorage) ~= playerTask.id then
            selfSay("You must complete the "..playerTask.name[1].." task first. You can also {clear task}.", cid)
            return true
    
        else
            local isComplete = true
        
            for i = 1, #TASK.monsters do
                if player:getStorageValue(TASK.monsters[i].storage) ~= TASK.monsters[i].amount then
                    isComplete = false
                    break
                end
            end
        
            if not isComplete then
              local text = "First you have to finish your current task: "
                    for i = 1, #playerTask.monsters do
                        if i == #playerTask.monsters then
                            text = text.."("..playerTask.monsters[i].amount - player:getStorageValue(playerTask.monsters[i].storage)..") "..playerTask.monsters[i].name.."('s)."
                        else
                            text = text.."("..playerTask.monsters[i].amount - player:getStorageValue(playerTask.monsters[i].storage)..") "..playerTask.monsters[i].name.."('s), "
                        end
                    end
                        
                selfSay(text, cid)
                return true
                
            else
            
                player:setStorageValue(taskStorage, -1)
                for i = 1, #TASK.monsters do
                    player:setStorageValue(TASK.monsters[i].storage, -1)
                end
                if TASK.exp then
                    player:addExperience(TASK.exp)
                end
                
                if TASK.itemRewards then
                    player:addItem(TASK.itemRewards[1], TASK.itemRewards[2])
                end
                
                selfSay("You have completed the "..TASK.name[1].." task!", cid)
                return true
            end
        end
        
    elseif msg == "cancel" then
        local TASK = tasks[player:getStorageValue(taskStorage)]
        
        if not TASK then
            selfSay("You do not have a task.", cid)
        else
            player:setStorageValue(taskStorage, -1)
            for i = 1, #TASK.monsters do
                player:setStorageValue(TASK.monsters[i].storage, -1)
            end
            selfSay("You are no longer doing the "..TASK.name[1].." task.", cid)
            return true
        end
    end
    return true
end

npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())

Lua:
local tasks = {
    [1] = {taskName = "Undeads",
        monsters = {
            [1] = {name = {"Rat LvL 1", "Rat LvL 2", "Rat  LvL 3"}, amount = 50, storage = 6601}
        }
    }
}

local taskStorage = 6500

-- Don't touch --
for i = 1, #tasks do
    for x = 1, #tasks[i].monsters do
        for z = 1, #tasks[i].monsters[x].name do
            tasks[i].monsters[x].name[z] = tasks[i].monsters[x].name[z]:lower()
        end
    end
end
----------------

function onKill(creature, target)
    if not creature:isPlayer() then return true end
    
    if not target:isMonster() or target:getMaster() then return true end
    
    local player = Player(creature)
    
    if player:getStorageValue(taskStorage) ~= nil and player:getStorageValue(taskStorage) ~= -1 then
        local TASK = tasks[player:getStorageValue(taskStorage)]
            
        if not TASK then return true end
        
        local MONSTERTABLE = nil
        
        for i = 1, #TASK.monsters do
            if isInArray(TASK.monsters[i].name, target:getName():lower()) then
                MONSTERTABLE = TASK.monsters[i]
                break
            end
        end
        
        if not MONSTERTABLE then return true end

            if player:getStorageValue(MONSTERTABLE.storage) < MONSTERTABLE.amount then
                player:setStorageValue(MONSTERTABLE.storage, player:getStorageValue(MONSTERTABLE.storage) + 1)
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "("..MONSTERTABLE.amount - player:getStorageValue(MONSTERTABLE.storage)..") "..target:getName().." left.")
            else
                local isComplete = true
                for i = 1, #TASK.monsters do
                    if player:getStorageValue(TASK.monsters[i].storage) ~= TASK.monsters[i].amount then
                        isComplete = false
                        break
                    end
                end
                
                if isComplete then
                    player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You have finished the "..TASK.taskName.." task.")
                else
                    local text = "[Task]: "
                    
                    for i = 1, #TASK.monsters do
                        if player:getStorageValue(TASK.monsters[i].storage) ~= TASK.monsters[i].amount then
                            if i == #TASK.monsters then
                                text = text.."("..TASK.monsters[i].amount - player:getStorageValue(TASK.monsters[i].storage)..") "..TASK.monsters[i].name[1].."."
                            else
                                text = text.."("..TASK.monsters[i].amount - player:getStorageValue(TASK.monsters[i].storage)..") "..TASK.monsters[i].name[1]..", "
                            end
                        end
                    end
                
                    player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, text)
                end
            end
    end
return true
end
 
Solution
I don't understand where the problem is. Can you be more specific what the npc is doing wrong
Post automatically merged:

Nvm, I found it

Lua:
local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)

function onCreatureAppear(cid)              npcHandler:onCreatureAppear(cid)            end
function onCreatureDisappear(cid)           npcHandler:onCreatureDisappear(cid)         end
function onCreatureSay(cid, type, msg)      npcHandler:onCreatureSay(cid, type, msg)    end
function onThink()                          npcHandler:onThink()                        end

local tasks = {
    [1] = {id = 1, levelReq = 1, msg = "{Rats} have been terrorizing the undergrounds of west. I...
Sorry I couldn't help with rewards. There was no reason for it not to work from the code. It must be something related to your server only.
Yea probably but its weird because in different systems using exact same method pretty much
Can you show the function pls?
Yea i can. I think its this one but there is a lot of parts of it, not even sure because its not me who created this feature
Lua:
   if rewards.addItem and next(rewards.addItem) then
        local receivedItem, itemsWorth = 0, 0
        local itemsText = ""

        if not newContainer then
            newContainer = doCreateItemEx(1987, 1)
        end

        for k, item in ipairs(rewards.addItem) do
            local itemChance = item.chance
            if not itemChance or itemChance <= 0 then
                itemChance = 100
            end

            local randomChance = math.random(1, 100)
            if itemChance >= randomChance then
                itemsText = itemsText .. (item.count > 1 and (item.count .. 'x ') or '') .. ItemType(item.id):getName()
                if k ~= #rewards.addItem then
                    itemsText = itemsText .. ', '
                end             

                doAddContainerItem(newContainer, item.id, item.count)  
            end  
        end/code]
 
data/lib/tasksystem.lua
Lua:
taskSystem = {
    baseStorage = 460000, -- saves current task by monsters[ID]
    countStorage = 460001,  -- saves current progress
    corpseId = 3987, --to show on Message

    monsters = {
        [1] = {name = 'Cave Rat', needKills = 100, rewards = {addExperience = 2500, addMoney = 2000}},
        [2] = {name = 'Rotworm', needKills = 10, rewards = {addExperience = 7500, addMoney = 3000}},
        [3] = {name = 'Orc', needKills = 10, rewards = {addExperience = 8000, addMoney = 3000}},
        [4] = {name = 'Dwarf', needKills = 10, rewards = {addExperience = 15000, addMoney = 4000}},
        [5] = {name = 'Dwarf Guard', needKills = 10, rewards = {addExperience = 18000, addMoney = 5000}},
        [6] = {name = 'Ghoul', needKills = 10, rewards = {addExperience = 25000, addMoney = 6000}}
   }
}

taskSystem.__index = taskSystem

function taskSystem:getTask(taskId)
    return self.monsters[taskId]
end

function taskSystem:getTaskIdByName(monsterName)
    for i, x in pairs(self.monsters) do
        if (x.name:lower() == monsterName) then
            return i
        end
    end
end

function taskSystem:getTaskById(taskId)
    return self.monsters[taskId]
end

function taskSystem:getPlayerTaskId(player)
    local player = Player(player)
    if not player then
        return false
    end

    return math.max(0, player:getStorageValue(self.baseStorage))
end

function taskSystem:setPlayerTaskId(player, taskId)
    local player = Player(player)
    if not player then
        return false
    end

    player:setStorageValue(self.baseStorage, taskId)
end

function taskSystem:startTask(player, taskId)
    local player = Player(player)
    if not player then
        return false
    end
      
    self:setPlayerTaskId(player, taskId)
end

function taskSystem:fillTaskKills(player, task)
    local player = Player(player)
    if not player then
        return false
    end

    player:setStorageValue(self.countStorage, task.needKills)
end

function taskSystem:getTaskKills(player)
    local player = Player(player)
    if not player then
        return false
    end

    return math.max(0, player:getStorageValue(self.countStorage))
end

function taskSystem:setTaskKills(player, count)
    local player = Player(player)
    if not player then
        return false
    end

    player:setStorageValue(self.countStorage, count)
end

function taskSystem:hasFinishedTask(player, task)
    local player = Player(player)
    if not player then
        return false
    end

    return self:getTaskKills(player) >= task.needKills
end

function taskSystem:giveReward(player, task)
    local player = Player(player)
    if not player then
        return false
    end

    local description = {}
    local rewards = task.rewards

    if rewards.addExperience then
        description[#description + 1] = string.format("%d experience points (s)", rewards.addExperience)
        player:addExperience(rewards.addExperience / Game.getExperienceStage(player:getLevel()))
    end

    if rewards.addMoney then
        description[#description + 1] = string.format("%d money (s)", rewards.addMoney)
        player:addMoney(rewards.addMoney)
    end     

    player:sendTextMessage(MESSAGE_EVENT_ADVANCE, string.format("[Task System] You have finished %s task and received %s for it!", task.name, table.concat(description, "\n")))
end

function taskSystem:finishTask(player, task)
    local player = Player(player)
    if not player then
        return false
    end

    self:setTaskKills(player, 0)
    self:setPlayerTaskId(player, 0)
    self:giveReward(player, task)
end

function taskSystem:sendTaskList(player)
    local player = Player(player)
    if not player then
        return false
    end

    local message = ''
    local taskId = self:getPlayerTaskId(player)
    if taskId ~= 0 then 
        local playerTaskKills = self:getTaskKills(player)
        local task = self:getTaskById(taskId)

        if playerTaskKills >= task.needKills then
            message = string.format("You have finished %s. Type '!task reward' to get prize.", task.name)
        else
            message = string.format("You have to kill %s.\n Current kills: %s/%s", task.name, playerTaskKills, task.needKills)
        end

        player:showTextDialog(self.corpseId, message)
        return true
    else
        local tasks = {}
        for k, task in ipairs(self.monsters) do
            message = string.format("%d. %s -%d kills", k, task.name, task.needKills)
            tasks[#tasks + 1] = message
        end

        player:showTextDialog(self.corpseId, table.concat(tasks, "\n"))
        return true
    end

    return true
end
global.lua
Code:
dofile('data/lib/taskSystem.lua')
data/creaturescripts/scripts/tasksystem.lua
Code:
function onKill(player, target)
    local targetMonster = target:isMonster()
    if not targetMonster or target:getMaster() then
        return true
    end

    local taskId = taskSystem:getPlayerTaskId(player)
    if taskId <= 0 then
        return true
    end

    local currentTask = taskSystem:getTaskById(taskId)
    if currentTask and next(currentTask) then
        local counter = taskSystem:getTaskKills(player)
        if counter >= currentTask.needKills then
            return true
        end

        local targetName = target:getName()
        if currentTask.name:lower() == targetName:lower() then
            counter = counter + 1
            taskSystem:setTaskKills(player, counter)

            if counter < currentTask.needKills then
                player:sendTextMessage(MESSAGE_EVENT_ADVANCE, string.format("[Task System] You have killed %d/%d %s.", counter, currentTask.needKills, currentTask.name .. "s"))
            elseif counter == currentTask.needKills then
                player:sendTextMessage(MESSAGE_EVENT_ADVANCE, string.format("[Task System] Congratulations! You have killed enough %s.", currentTask.name .. "s"))
            end
        end
    end

    return true
end
data/creaturescripts/creaturescripts.xml ( also mention it in login.lua aswell)
Code:
    <event type="kill" name="TaskKill" script="taskKill.lua"/>
data/talkactions/scripts/tasksystem.lua
Code:
function onSay(player, words, param)
    if (not param or param == '') then
        taskSystem:sendTaskList(player)
        return false
    end

    local split = param:split(",")

    local currentTaskId = taskSystem:getPlayerTaskId(player)
    if (param == 'cancel') then
        if currentTaskId ~= 0 then
            player:sendTextMessage(MESSAGE_STATUS_SMALL, '[Task System] You have canceled your task.')
            taskSystem:setPlayerTaskId(player, 0)
            taskSystem:setTaskKills(player, 0)
        else
            player:sendTextMessage(MESSAGE_STATUS_SMALL, '[Task System] You are not doing any task.')
        end
    elseif (param == 'fill') then
        if player:getGroup():getAccess() and player:getAccountType() >= ACCOUNT_TYPE_GOD then
            if currentTaskId ~= 0 then
                local task = taskSystem:getTaskById(currentTaskId)
                taskSystem:fillTaskKills(player, task)
                player:sendTextMessage(MESSAGE_STATUS_SMALL, '[Task System] Task has been filled.')
            else
                player:sendTextMessage(MESSAGE_STATUS_SMALL, '[Task System] You are not doing any task.')
            end
        end
    elseif (param == 'reward') then
        if currentTaskId ~= 0 then
            local task = taskSystem:getTaskById(currentTaskId)
            local playerTaskKills = taskSystem:getTaskKills(player)

            if playerTaskKills >= task.needKills then
                taskSystem:finishTask(player, task)
            else
                player:sendTextMessage(MESSAGE_STATUS_SMALL, '[Task System] You haven\'t finished this task yet.')
            end
        else
            player:sendTextMessage(MESSAGE_STATUS_SMALL, '[Task System] You are not doing any task.')
        end

    else
        local taskId = taskSystem:getTaskIdByName(param:lower())
        if taskId then
            if currentTaskId ~= 0 then
                player:sendTextMessage(MESSAGE_STATUS_SMALL, '[Task System] You are already doing a task.')
                return false
            end

            local task = taskSystem:getTaskById(taskId)
            if task then
                taskSystem:startTask(player, taskId)
                player:sendTextMessage(MESSAGE_EVENT_ADVANCE, string.format("You have started %s task", task.name))
            end
        else
            player:sendTextMessage(MESSAGE_STATUS_SMALL, '[Task System] Invalid task name.')
        end
    end

    return false
end
data/talkactions/talkactions.xml
Code:
    <talkaction words="!tasks" separator =" " script="tasks.lua"/>
Thank you for sharing! Is there a possibility that you could post the taskkill.lua file too? =)
 
Back
Top