• 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.2] Automatic Task System

Hey can somebody change this?
When player type !task NAME he will see how many he killed? big spam on chat now.
Post automatically merged:

@@ UPDATE it did it
lib/custom/task.lua:
Lua:
function tasks:onKill(player, target)
    isTaskCreature, currentTask = tasks:killedCreatureIsTaskMonster(player, target)

        if isTaskCreature then
            if tasks:getMonstersLeft(player, currentTask) < 1 then
                return false
            end

            player:setStorageValue(tasks:getMonstersStorage(currentTask), tasks:getMonstersLeft(player, currentTask) - 1)
            if tasks:getMonstersLeft(player, currentTask) == 0 then
                if tasks:setCompleted(player, currentTask, 1) then
                    player:sendTextMessage(messageType, "You have completed your task.")
                    tasks:rewardPlayer(player, currentTask)
                    return true
                end
            end
            if
            tasks:getMonstersLeft(player, currentTask) % 10 == 0 or tasks[currentTask].toKill - tasks:getMonstersLeft(player, currentTask) == 1 then
            player:sendTextMessage(messageType, "You killed " .. tasks[currentTask].toKill - tasks:getMonstersLeft(player, currentTask) .. " of " .. tasks[currentTask].toKill .. " " .. string.lower(target:getName()) .. ".")
            return true
            end
    end
    return false
end

we are going to player:sendTextMessage(messageType, "You killed " .. tasks[currentTask].toKill - tasks:getMonstersLeft(player, currentTask) .. " of " .. tasks[currentTask].toKill .. " " .. string.lower(target:getName()) .. ".")
then put it in function: if tasks:getMonstersLeft(player, currentTask) % 10 == 0 or tasks[currentTask].toKill - tasks:getMonstersLeft(player, currentTask) == 1 then player:sendTextMessage(messageType, "You killed " .. tasks[currentTask].toKill - tasks:getMonstersLeft(player, currentTask) .. " of " .. tasks[currentTask].toKill .. " " .. string.lower(target:getName()) .. ".") return true end
now, we will see FIRST killed monster, and 10,20,30..
 
Last edited:
Lua Script Error: [CreatureScript Interface]
data/creaturescripts/scripts/login.lua:eek:nLogin
data/lib/custom/task.lua:436: attempt to call method 'setCanceled' (a nil value)
stack traceback:
[C]: in function 'setCanceled'
data/lib/custom/task.lua:436: in function 'dropTask'
data/lib/custom/task.lua:393: in function 'updateTasks'
data/creaturescripts/scripts/login.lua:21: in function <data/creaturescripts/scripts/login.lua:1>

what wrong?
 
Automatic Task System for TFS 1.2
Based on Task System of @rwxsu

Features:
  • Task automatically start as soon as player reachs the required level
  • Tasks getting dropped as soon as players level is high enough or to low
  • Easy to add/remove new tasks (Set: name, minlevel, maxlevel, monsters, toKill and rewards types)
  • Choose between rewarding with experience/items or even storages
  • Add multiple monsters to a task (e.g rats, cave rats or troll, swamp troll, etc.)
  • Set a task name for each task
  • As soon as player reachs the required level for a task, he will get a new list of all tasks displayed
  • Displaying how many kills for a task is left after each kill

View attachment 33604


Add in data/creaturescripts/creaturescripts.xml
XML:
<!-- Task -->
<event type="kill" name="TaskSystem" script="task/taskSystem.lua"/>

Create in data/creaturescripts/task/taskSystem.lua
Lua:
function onKill(player, target, lastHit)
    if not (tasks:onTask(player) > 0) then
        return false
    end

    if not player:isPlayer() then
        return false
    end

    if target:getMaster() ~= nil then
        return false
    end

    tasks:onKill(player, target)
    return true
end

Register Task System Event in data/creaturescripts/login.lua
Lua:
player:registerEvent("TaskSystem")

Set config(somewhere at the bottom) for Task System in data/creaturescripts/login.lua
Lua:
    if player:getStorageValue(2038) == 1 then -- Task System register if still has task
        player:registerEvent("TaskKill")
    end
    tasks:updateTasks(player)

Set Task System in data/creaturescripts/levelSave.lua
Lua:
function onAdvance(player, skill, oldLevel, newLevel)
        if skill == SKILL_LEVEL and newLevel > oldLevel then
        tasks:updateTasks(player)
        player:save()
    end

    return true
end

Set Task System in data/lib/lib.lua
Lua:
-- Execute Task System Library
dofile('data/lib/custom/task.lua')

Create file for Task System in data/lib/custom/task.lua
Lua:
messageType = MESSAGE_STATUS_CONSOLE_BLUE

tasks = { -- You can add as many tasks as you want
    [1] = {
        name = "Rats", -- Name of Task
        minlevel = 1,
        maxlevel = 15,
        monsters = { -- You can add as many monsters as you want
            "Rat",
            "Cave Rat",
        },
        toKill = 25, -- How many monsters the player needs to kill
        rewards = { -- You can add as many rewards as you want
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2152,
                count = 7,
            },
            [2] = {
                type = "exp",
                experience = 8000,
            },
        },
    },
    [2] = {
        name = "Trolls",
        minlevel = 8,
        maxlevel = 25,
        monsters = {
            "Troll",
        },
        toKill = 20,
        rewards = {
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2152,
                count = 5,
            },
            [2] = {
                type = "exp",
                experience = 5000,
            },
        },
    },
    [3] = {
        name = "Rotworms",
        minlevel = 8,
        maxlevel = 25,
        monsters = {
            "Rotworm",
        },
        toKill = 25,
        rewards = {
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2152,
                count = 10,
            },
            [2] = {
                type = "exp",
                experience = 10000,
            },
        },
    },
    [4] = {
        name = "Skeletons",
        minlevel = 8,
        maxlevel = 20,
        monsters = {
            "Skeleton",
        },
        toKill = 15,
        rewards = {
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2152,
                count = 5,
            },
            [2] = {
                type = "exp",
                experience = 5000,
            },
        },
    },
    [5] = {
        name = "Cyclops",
        minlevel = 15,
        maxlevel = 35,
        monsters = {
            "Cyclops",
        },
        toKill = 50,
        rewards = {
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2152,
                count = 25,
            },
            [2] = {
                type = "exp",
                experience = 15000,
            },
        },
    },
    [6] = {
        name = "Amazons",
        minlevel = 15,
        maxlevel = 35,
        monsters = {
            "Amazon",
        },
        toKill = 35,
        rewards = {
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2152,
                count = 20,
            },
            [2] = {
                type = "exp",
                experience = 10000,
            },
        },
    },
    [7] = {
        name = "Valkyries",
        minlevel = 15,
        maxlevel = 35,
        monsters = {
            "Valkyrie",
        },
        toKill = 35,
        rewards = {
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2152,
                count = 30,
            },
            [2] = {
                type = "exp",
                experience = 13000,
            },
            [3] = {
                type = "storage",
                storageId = 5001,
                storageValue = 1,
            },
        },
    },
    [8] = {
        name = "Scarabs",
        minlevel = 12,
        maxlevel = 35,
        monsters = {
            "Scarab",
        },
        toKill = 25,
        rewards = {
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2152,
                count = 20,
            },
            [2] = {
                type = "exp",
                experience = 15000,
            },
        },
    },
    [9] = {
        name = "Dragons",
        minlevel = 30,
        maxlevel = 50,
        monsters = {
            "Dragon",
        },
        toKill = 30,
        rewards = {
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2152,
                count = 30,
            },
            [2] = {
                type = "exp",
                experience = 35000,
            },
        },
    },
    [10] = {
        name = "Dragon Lords",
        minlevel = 45,
        maxlevel = 100,
        monsters = {
            "Dragon Lord",
        },
        toKill = 50,
        rewards = {
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2160,
                count = 3,
            },
            [2] = {
                type = "exp",
                experience = 70000,
            },
        },
    },
    [11] = {
        name = "Hydras",
        minlevel = 45,
        maxlevel = 100,
        monsters = {
            "Hydra",
        },
        toKill = 50,
        rewards = {
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2160,
                count = 3,
            },
            [2] = {
                type = "exp",
                experience = 70000,
            },
        },
    },
    [12] = {
        name = "Heros",
        minlevel = 40,
        maxlevel = 100,
        monsters = {
            "Hero",
        },
        toKill = 50,
        rewards = {
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2160,
                count = 5,
            },
            [2] = {
                type = "exp",
                experience = 50000,
            },
        },
    },
    [13] = {
        name = "Warlocks",
        minlevel = 50,
        maxlevel = 130,
        monsters = {
            "Warlock",
        },
        toKill = 100,
        rewards = {
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2160,
                count = 6,
            },
            [2] = {
                type = "exp",
                experience = 150000,
            },
        },
    },
    [14] = {
        name = "Necromancers",
        minlevel = 45,
        maxlevel = 90,
        monsters = {
            "Necromancer",
        },
        toKill = 70,
        rewards = {
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2160,
                count = 5,
            },
            [2] = {
                type = "exp",
                experience = 100000,
            },
        },
    },
    [15] = {
        name = "Behemoths",
        minlevel = 50,
        maxlevel = 130,
        monsters = {
            "Behemoth",
        },
        toKill = 70,
        rewards = {
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2160,
                count = 5,
            },
            [2] = {
                type = "exp",
                experience = 100000,
            },
        },
    },
    [16] = {
        name = "Demons",
        minlevel = 80,
        maxlevel = 160,
        monsters = {
            "Demon",
        },
        toKill = 130,
        rewards = {
            [1] = {
                type = "item",
                name = "crystal coin",
                itemid = 2160,
                count = 10,
            },
            [2] = {
                type = "exp",
                experience = 750000,
            },
        },
    },
}

tasks.__index = tasks

function tasks:getOnTaskStorage(task)
    return tonumber(6520000 + (task * 10))
end

function tasks:getMonstersStorage(task)
    return tonumber(6520001 + (task * 10))
end

function tasks:getCompletedStorage(task)
    return tonumber(6520002 + (task * 10))
end

function tasks:getFinishedStorage(task)
    return tonumber(6520003 + (task * 10))
end

function tasks:getCanceledStorage(task)
    return tonumber(6520004 + (task * 10))
end

-- Check if values are between a given value
function tasks:isAvailable(value, min, max)
    return (value >= min and value <= max)
end

-- Check available tasks and delete inactiv tasks
function tasks:updateTasks(player)
    local availableTasks = {}
    for i = 1, #tasks do
        if player:getStorageValue(tasks:getFinishedStorage(i)) ~= 1 then
            if player:getStorageValue(tasks:getCanceledStorage(i)) ~= 1 then
                if tasks:isAvailable(player:getLevel(), tasks[i].minlevel, tasks[i].maxlevel) then
                    table.insert(availableTasks, i)
                    table.insert(availableTasks, ",")
                end
            end
        end
    end

    if not table.empty(availableTasks) then
        tasks:startTask(player, availableTasks)
    end
    tasks:dropTask(player)
end

--Starts available tasks
function tasks:startTask(player, taskTable)
    local t = string.split(table.concat(taskTable), ",")
        player:sendTextMessage(messageType, "++++++++ Automatical Task System ++++++++")
        for i,x in pairs(t) do
            local task = tonumber(x)
            player:sendTextMessage(messageType, "++++++++ Task started ++++++++")
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_RED, "Task Name: ".. tasks[task].name .." - Kill: ".. tasks[task].toKill .."x ".. tasks:getMonsters(task) .."")
            if not tasks:hasTaskAlready(player, task) then
                tasks:setTask(player, task, 1)
            end
        end
end

--Start task
function tasks:setTask(player, task, set)
    if player:setStorageValue(tasks:getOnTaskStorage(task), set) then
        if player:setStorageValue(tasks:getMonstersStorage(task), tasks[task].toKill) then
            return true
        end
    end
    return false
end

--Check if player already have this task
function tasks:hasTaskAlready(player, task)
        if player:getStorageValue(tasks:getOnTaskStorage(task)) == 1 then
            return true
        end
    return false
end

--Drop outdated tasks (because of level up/down)
function tasks:dropTask(player)
    for i = 1, #tasks do
        if player:getStorageValue(tasks:getFinishedStorage(i)) ~= 1 and player:getStorageValue(tasks:getCanceledStorage(i)) ~= 1 then
            if not (tasks:isAvailable(player:getLevel(), tasks[i].minlevel, tasks[i].maxlevel)) then
                if tasks:hasTaskAlready(player, i) then
                    player:sendTextMessage(messageType, "++++++++ Task Automatical canceled (Your level is to high/low) ++++++++")
                    player:sendTextMessage(MESSAGE_STATUS_CONSOLE_RED, "Task Name: ".. tasks[i].name .."")
                    tasks:setCanceled(player, i, 1)
                end
            end
        end
    end
end

-- Gives out a list of monsters of the task
function tasks:getMonsters(task)
    local taskMonsters = {}
    local monsters = ""
    for i = 1, #tasks[task].monsters do
        table.insert(taskMonsters, tasks[task].monsters[i])
        table.insert(taskMonsters, ", ")
    end

    if not table.empty(taskMonsters) then
        monsters = table.concat(taskMonsters)
    end
    monsters = monsters:sub(1, -3)
    return monsters
end

-- Set task as completed
function tasks:setCompleted(player, task, set)
    if player:setStorageValue(tasks:getCompletedStorage(task), set) then
        if task == 0 then
            return true
        end
        return true
    end
    return false
end

-- Get completed tasks from player
function tasks:getCompleted(player, task)
    return player:getStorageValue(tasks:getCompletedStorage(task))
end

-- Check how many monsters are left to kill
function tasks:getMonstersLeft(player, task)
    return player:getStorageValue(tasks:getMonstersStorage(task))
end

-- Checks if the player is currently doing a task
-- And returns the task the player is doing
function tasks:onTask(player)
    for i = 1, #tasks do
        if player:getStorageValue(tasks:getOnTaskStorage(i)) == 1 then
            return i
        end
    end
    return 0
end

-- Set canceled task
function tasks:setCaneled(player, task, set)
    if player:setStorageValue(tasks:getCanceledStorage(task), set) then
            player:setStorageValue(tasks:getOnTaskStorage(task), 0)
            player:setStorageValue(tasks:getMonstersStorage(task), 0)
            player:setStorageValue(tasks:getCompletedStorage(task), 0)
            player:setStorageValue(tasks:getFinishedStorage(task), 0)
        return true
    end
    return false
end

-- Set task as finished
function tasks:setFinished(player, task, set)
    if player:setStorageValue(tasks:getFinishedStorage(task), set) then
        return true
    end
    return false
end

-- Checks if the player has finished a task
-- And returns the task that is finished
function tasks:getFinished(player)
    for i = 1, #tasks do
        if player:getStorageValue(tasks:getFinishedStorage(i)) == 1 then
            return i
        end
    end
    return 0
end

-- Get all tasks player has
function tasks:getTasksFromPlayer(player)
    local allPlayerTasks = {}
    for i = 1, #tasks do
        if player:getStorageValue(tasks:getOnTaskStorage(i)) == 1 and player:getStorageValue(tasks:getFinishedStorage(i)) ~= 1 then
            table.insert(allPlayerTasks, i)
            table.insert(allPlayerTasks, ",")
        end
    end

    if not table.empty(allPlayerTasks) then
        return allPlayerTasks
    end
end

-- Check if killing creature is a task monster
function tasks:killedCreatureIsTaskMonster(player, target)
    local allTasks = tasks:getTasksFromPlayer(player)
    local playerTasks = string.split(table.concat(allTasks), ",")

    for i,x in pairs(playerTasks) do
        local task = tonumber(x)
        for i = 1, #tasks[task].monsters do
            if string.lower(target:getName()) == string.lower(tasks[task].monsters[i]) then
                return true, task
            end
        end
    end
    return false
end

-- Checks if the monster killed was a task monster
function tasks:onKill(player, target)
    isTaskCreature, currentTask = tasks:killedCreatureIsTaskMonster(player, target)

        if isTaskCreature then
            if tasks:getMonstersLeft(player, currentTask) < 1 then
                return false
            end

            player:setStorageValue(tasks:getMonstersStorage(currentTask), tasks:getMonstersLeft(player, currentTask) - 1)
            if tasks:getMonstersLeft(player, currentTask) == 0 then
                if tasks:setCompleted(player, currentTask, 1) then
                    player:sendTextMessage(messageType, "You have completed your task.")
                    tasks:rewardPlayer(player, currentTask)
                    return true
                end
            end

            player:sendTextMessage(messageType, "You killed " .. tasks[currentTask].toKill - tasks:getMonstersLeft(player, currentTask) .. " of " .. tasks[currentTask].toKill .. " " .. string.lower(target:getName()) .. ".")
            return true
    end
    return false
end

-- Reward player after finishing task
function tasks:rewardPlayer(player, t)
    for i = 1, #tasks[t].rewards do
        if tasks[t].rewards[i].type == "item" then
            player:sendTextMessage(messageType, string.format("You received %dx %s(s).", tasks[t].rewards[i].count, tasks[t].rewards[i].name))
            player:addItem(tasks[t].rewards[i].itemid, tasks[t].rewards[i].count)
        end
        if tasks[t].rewards[i].type == "exp" then
            player:sendTextMessage(messageType, string.format("You received %dx experience.", tasks[t].rewards[i].experience))
            player:addExperience(tasks[t].rewards[i].experience, false)
        end
        if tasks[t].rewards[i].type == "storage" then
            player:sendTextMessage(messageType, string.format("You received a storage reward.", tasks[t].rewards[i].experience))
            player:setStorageValue(tasks[t].rewards[i].storageId, tasks[t].rewards[i].storageValue)
        end
    end

    tasks:setTask(player, t, 0)
    tasks:setCompleted(player, t, 0)
    tasks:setFinished(player, t, 1)
    return true
end

-- Toggle true/false at the top of this lua file
-- Resets the tasks for the provided player
function tasks:reset(player, task)
    if reset then
        player:setStorageValue(tasks:getOnTaskStorage(task), 0)
        player:setStorageValue(tasks:getMonstersStorage(task), 0)
        player:setStorageValue(tasks:getCompletedStorage(task), 0)
        player:setStorageValue(tasks:getFinishedStorage(task), 0)
        player:setStorageValue(tasks:getCanceledStorage(task), 0)
    end
end
Still next task system dont work for me,
[Warning - Event::checkScript] Can not load script: scripts/task.lua
cannot open data/creaturescripts/scripts/task.lua: No such file or directory
[Warning - Event::checkScript] Can not load script: scripts/my_script.lua
cannot open data/globalevents/scripts/my_script.lua: No such file or directory
 
Is there a way to make the same task multiple times?
Example:
Kill 100 Rats, get x reward
Kill 200 Rats, get x y reward (these are not additional kills)
 
would be possible to add task channel? that way the message wouldn't be spamming in default channel
 
would be possible to add task channel? that way the message wouldn't be spamming in default channel
For that you would need to know which channel you want it to show. This system has been made for a oldschool server (7.x).

Take a look here: (first line of script)
Lua:
messageType = MESSAGE_STATUS_CONSOLE_BLUE
and change it to the channel you want it to display.
 
For that you would need to know which channel you want it to show. This system has been made for a oldschool server (7.x).

Take a look here: (first line of script)
Lua:
messageType = MESSAGE_STATUS_CONSOLE_BLUE
and change it to the channel you want it to display.
i think hat's the color of the message but not where the message is sent
 
How do i use this with an npc instead? and there's a way to choose which that players want to do?
 
Last edited:
Hello! I'm getting this error when i try this


Lua:
Lua Script Error: [CreatureScript Interface]
data/creaturescripts/scripts/login.lua:onLogin
data/lib/custom/task.lua:389: attempt to call field 'empty' (a nil value)
stack traceback:
        [C]: in function 'empty'
        data/lib/custom/task.lua:389: in function 'updateTasks'
        data/creaturescripts/scripts/login.lua:51: in function <data/creaturescripts/scripts/login.lua:1>

Dose anyone know what seems to be the problem? Thank you =)
 
What is guys?

Code:
Lua Script Error: [CreatureScript Interface]
2022-02-22 14:39:10 -  data/creaturescripts/scripts/login.lua:onLogin
2022-02-22 14:39:10 -  data/lib/custom/task.lua:389: attempt to call field 'empty' (a nil value)
2022-02-22 14:39:10 -  stack traceback:
2022-02-22 14:39:10 -   [C]: in function 'empty'
2022-02-22 14:39:10 -   data/lib/custom/task.lua:389: in function 'updateTasks'
2022-02-22 14:39:10 -   data/creaturescripts/scripts/login.lua:50: in function <data/creaturescripts/scripts/login.lua:1>

Why?
 
This system works on TFS 1.4, needed to fix the typo and add the fix to global.lua
 
Hello! I'm getting this error when i try this


Lua:
Lua Script Error: [CreatureScript Interface]
data/creaturescripts/scripts/login.lua:onLogin
data/lib/custom/task.lua:389: attempt to call field 'empty' (a nil value)
stack traceback:
        [C]: in function 'empty'
        data/lib/custom/task.lua:389: in function 'updateTasks'
        data/creaturescripts/scripts/login.lua:51: in function <data/creaturescripts/scripts/login.lua:1>

Dose anyone know what seems to be the problem? Thank you =)
Its missing on global function (inside global.lua) which is used by serveral lua scripts or can be used by them. So you have to add this in your global.lua:


Lua:
table.append = table.insert
table.empty = function (t)
    return next(t) == nil
end

table.find = function (table, value)
    for i, v in pairs(table) do
        if(v == value) then
            return i
        end
    end

    return nil
end

table.count = function (table, item)
    local count = 0
    for i, n in pairs(table) do
        if(item == n) then
            count = count + 1
        end
    end

    return count
end
table.countElements = table.count

table.getCombinations = function (table, num)
    local a, number, select, newlist = {}, #table, num, {}
    for i = 1, select do
        a[#a + 1] = i
    end

    local newthing = {}
    while(true) do
        local newrow = {}
        for i = 1, select do
            newrow[#newrow + 1] = table[a[i]]
        end

        newlist[#newlist + 1] = newrow
        i = select
        while(a[i] == (number - select + i)) do
            i = i - 1
        end

        if(i < 1) then
            break
        end

        a[i] = a[i] + 1
        for j = i, select do
            a[j] = a[i] + j - i
        end
    end

    return newlist
end

function table.serialize(x, recur)
    local t = type(x)
    recur = recur or {}

    if(t == nil) then
        return "nil"
    elseif(t == "string") then
        return string.format("%q", x)
    elseif(t == "number") then
        return tostring(x)
    elseif(t == "boolean") then
        return t and "true" or "false"
    elseif(getmetatable(x)) then
        error("Can not serialize a table that has a metatable associated with it.")
    elseif(t == "table") then
        if(table.find(recur, x)) then
            error("Can not serialize recursive tables.")
        end
        table.append(recur, x)

        local s = "{"
        for k, v in pairs(x) do
            s = s .. "[" .. table.serialize(k, recur) .. "]"
            s = s .. " = " .. table.serialize(v, recur) .. ","
        end
        s = s .. "}"
        return s
    else
        error("Can not serialize value of type '" .. t .. "'.")
    end
end

function table.unserialize(str)
    return loadstring("return " .. str)()
end
Post automatically merged:

Automatic Task System for TFS 1.2
Based on Task System of @rwxsu

Features:
  • Task automatically start as soon as player reachs the required level
  • Tasks getting dropped as soon as players level is high enough or to low
  • Easy to add/remove new tasks (Set: name, minlevel, maxlevel, monsters, toKill and rewards types)
  • Choose between rewarding with experience/items or even storages
  • Add multiple monsters to a task (e.g rats, cave rats or troll, swamp troll, etc.)
  • Set a task name for each task
  • As soon as player reachs the required level for a task, he will get a new list of all tasks displayed
  • Displaying how many kills for a task is left after each kill

View attachment 33604


Add in data/creaturescripts/creaturescripts.xml
XML:
<!-- Task -->
<event type="kill" name="TaskSystem" script="task/taskSystem.lua"/>

Create in data/creaturescripts/task/taskSystem.lua
Lua:
function onKill(player, target, lastHit)
    if not (tasks:onTask(player) > 0) then
        return false
    end

    if not player:isPlayer() then
        return false
    end

    if target:getMaster() ~= nil then
        return false
    end

    tasks:onKill(player, target)
    return true
end

Register Task System Event in data/creaturescripts/login.lua
Lua:
player:registerEvent("TaskSystem")

Set config(somewhere at the bottom) for Task System in data/creaturescripts/login.lua
Lua:
    if player:getStorageValue(2038) == 1 then -- Task System register if still has task
        player:registerEvent("TaskKill")
    end
    tasks:updateTasks(player)

Set Task System in data/creaturescripts/levelSave.lua
Lua:
function onAdvance(player, skill, oldLevel, newLevel)
        if skill == SKILL_LEVEL and newLevel > oldLevel then
        tasks:updateTasks(player)
        player:save()
    end

    return true
end

Set Task System in data/lib/lib.lua
Lua:
-- Execute Task System Library
dofile('data/lib/custom/task.lua')

Create file for Task System in data/lib/custom/task.lua
Lua:
messageType = MESSAGE_STATUS_CONSOLE_BLUE

tasks = { -- You can add as many tasks as you want
    [1] = {
        name = "Rats", -- Name of Task
        minlevel = 1,
        maxlevel = 15,
        monsters = { -- You can add as many monsters as you want
            "Rat",
            "Cave Rat",
        },
        toKill = 25, -- How many monsters the player needs to kill
        rewards = { -- You can add as many rewards as you want
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2152,
                count = 7,
            },
            [2] = {
                type = "exp",
                experience = 8000,
            },
        },
    },
    [2] = {
        name = "Trolls",
        minlevel = 8,
        maxlevel = 25,
        monsters = {
            "Troll",
        },
        toKill = 20,
        rewards = {
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2152,
                count = 5,
            },
            [2] = {
                type = "exp",
                experience = 5000,
            },
        },
    },
    [3] = {
        name = "Rotworms",
        minlevel = 8,
        maxlevel = 25,
        monsters = {
            "Rotworm",
        },
        toKill = 25,
        rewards = {
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2152,
                count = 10,
            },
            [2] = {
                type = "exp",
                experience = 10000,
            },
        },
    },
    [4] = {
        name = "Skeletons",
        minlevel = 8,
        maxlevel = 20,
        monsters = {
            "Skeleton",
        },
        toKill = 15,
        rewards = {
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2152,
                count = 5,
            },
            [2] = {
                type = "exp",
                experience = 5000,
            },
        },
    },
    [5] = {
        name = "Cyclops",
        minlevel = 15,
        maxlevel = 35,
        monsters = {
            "Cyclops",
        },
        toKill = 50,
        rewards = {
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2152,
                count = 25,
            },
            [2] = {
                type = "exp",
                experience = 15000,
            },
        },
    },
    [6] = {
        name = "Amazons",
        minlevel = 15,
        maxlevel = 35,
        monsters = {
            "Amazon",
        },
        toKill = 35,
        rewards = {
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2152,
                count = 20,
            },
            [2] = {
                type = "exp",
                experience = 10000,
            },
        },
    },
    [7] = {
        name = "Valkyries",
        minlevel = 15,
        maxlevel = 35,
        monsters = {
            "Valkyrie",
        },
        toKill = 35,
        rewards = {
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2152,
                count = 30,
            },
            [2] = {
                type = "exp",
                experience = 13000,
            },
            [3] = {
                type = "storage",
                storageId = 5001,
                storageValue = 1,
            },
        },
    },
    [8] = {
        name = "Scarabs",
        minlevel = 12,
        maxlevel = 35,
        monsters = {
            "Scarab",
        },
        toKill = 25,
        rewards = {
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2152,
                count = 20,
            },
            [2] = {
                type = "exp",
                experience = 15000,
            },
        },
    },
    [9] = {
        name = "Dragons",
        minlevel = 30,
        maxlevel = 50,
        monsters = {
            "Dragon",
        },
        toKill = 30,
        rewards = {
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2152,
                count = 30,
            },
            [2] = {
                type = "exp",
                experience = 35000,
            },
        },
    },
    [10] = {
        name = "Dragon Lords",
        minlevel = 45,
        maxlevel = 100,
        monsters = {
            "Dragon Lord",
        },
        toKill = 50,
        rewards = {
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2160,
                count = 3,
            },
            [2] = {
                type = "exp",
                experience = 70000,
            },
        },
    },
    [11] = {
        name = "Hydras",
        minlevel = 45,
        maxlevel = 100,
        monsters = {
            "Hydra",
        },
        toKill = 50,
        rewards = {
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2160,
                count = 3,
            },
            [2] = {
                type = "exp",
                experience = 70000,
            },
        },
    },
    [12] = {
        name = "Heros",
        minlevel = 40,
        maxlevel = 100,
        monsters = {
            "Hero",
        },
        toKill = 50,
        rewards = {
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2160,
                count = 5,
            },
            [2] = {
                type = "exp",
                experience = 50000,
            },
        },
    },
    [13] = {
        name = "Warlocks",
        minlevel = 50,
        maxlevel = 130,
        monsters = {
            "Warlock",
        },
        toKill = 100,
        rewards = {
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2160,
                count = 6,
            },
            [2] = {
                type = "exp",
                experience = 150000,
            },
        },
    },
    [14] = {
        name = "Necromancers",
        minlevel = 45,
        maxlevel = 90,
        monsters = {
            "Necromancer",
        },
        toKill = 70,
        rewards = {
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2160,
                count = 5,
            },
            [2] = {
                type = "exp",
                experience = 100000,
            },
        },
    },
    [15] = {
        name = "Behemoths",
        minlevel = 50,
        maxlevel = 130,
        monsters = {
            "Behemoth",
        },
        toKill = 70,
        rewards = {
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2160,
                count = 5,
            },
            [2] = {
                type = "exp",
                experience = 100000,
            },
        },
    },
    [16] = {
        name = "Demons",
        minlevel = 80,
        maxlevel = 160,
        monsters = {
            "Demon",
        },
        toKill = 130,
        rewards = {
            [1] = {
                type = "item",
                name = "crystal coin",
                itemid = 2160,
                count = 10,
            },
            [2] = {
                type = "exp",
                experience = 750000,
            },
        },
    },
}

tasks.__index = tasks

function tasks:getOnTaskStorage(task)
    return tonumber(6520000 + (task * 10))
end

function tasks:getMonstersStorage(task)
    return tonumber(6520001 + (task * 10))
end

function tasks:getCompletedStorage(task)
    return tonumber(6520002 + (task * 10))
end

function tasks:getFinishedStorage(task)
    return tonumber(6520003 + (task * 10))
end

function tasks:getCanceledStorage(task)
    return tonumber(6520004 + (task * 10))
end

-- Check if values are between a given value
function tasks:isAvailable(value, min, max)
    return (value >= min and value <= max)
end

-- Check available tasks and delete inactiv tasks
function tasks:updateTasks(player)
    local availableTasks = {}
    for i = 1, #tasks do
        if player:getStorageValue(tasks:getFinishedStorage(i)) ~= 1 then
            if player:getStorageValue(tasks:getCanceledStorage(i)) ~= 1 then
                if tasks:isAvailable(player:getLevel(), tasks[i].minlevel, tasks[i].maxlevel) then
                    table.insert(availableTasks, i)
                    table.insert(availableTasks, ",")
                end
            end
        end
    end

    if not table.empty(availableTasks) then
        tasks:startTask(player, availableTasks)
    end
    tasks:dropTask(player)
end

--Starts available tasks
function tasks:startTask(player, taskTable)
    local t = string.split(table.concat(taskTable), ",")
        player:sendTextMessage(messageType, "++++++++ Automatical Task System ++++++++")
        for i,x in pairs(t) do
            local task = tonumber(x)
            player:sendTextMessage(messageType, "++++++++ Task started ++++++++")
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_RED, "Task Name: ".. tasks[task].name .." - Kill: ".. tasks[task].toKill .."x ".. tasks:getMonsters(task) .."")
            if not tasks:hasTaskAlready(player, task) then
                tasks:setTask(player, task, 1)
            end
        end
end

--Start task
function tasks:setTask(player, task, set)
    if player:setStorageValue(tasks:getOnTaskStorage(task), set) then
        if player:setStorageValue(tasks:getMonstersStorage(task), tasks[task].toKill) then
            return true
        end
    end
    return false
end

--Check if player already have this task
function tasks:hasTaskAlready(player, task)
        if player:getStorageValue(tasks:getOnTaskStorage(task)) == 1 then
            return true
        end
    return false
end

--Drop outdated tasks (because of level up/down)
function tasks:dropTask(player)
    for i = 1, #tasks do
        if player:getStorageValue(tasks:getFinishedStorage(i)) ~= 1 and player:getStorageValue(tasks:getCanceledStorage(i)) ~= 1 then
            if not (tasks:isAvailable(player:getLevel(), tasks[i].minlevel, tasks[i].maxlevel)) then
                if tasks:hasTaskAlready(player, i) then
                    player:sendTextMessage(messageType, "++++++++ Task Automatical canceled (Your level is to high/low) ++++++++")
                    player:sendTextMessage(MESSAGE_STATUS_CONSOLE_RED, "Task Name: ".. tasks[i].name .."")
                    tasks:setCanceled(player, i, 1)
                end
            end
        end
    end
end

-- Gives out a list of monsters of the task
function tasks:getMonsters(task)
    local taskMonsters = {}
    local monsters = ""
    for i = 1, #tasks[task].monsters do
        table.insert(taskMonsters, tasks[task].monsters[i])
        table.insert(taskMonsters, ", ")
    end

    if not table.empty(taskMonsters) then
        monsters = table.concat(taskMonsters)
    end
    monsters = monsters:sub(1, -3)
    return monsters
end

-- Set task as completed
function tasks:setCompleted(player, task, set)
    if player:setStorageValue(tasks:getCompletedStorage(task), set) then
        if task == 0 then
            return true
        end
        return true
    end
    return false
end

-- Get completed tasks from player
function tasks:getCompleted(player, task)
    return player:getStorageValue(tasks:getCompletedStorage(task))
end

-- Check how many monsters are left to kill
function tasks:getMonstersLeft(player, task)
    return player:getStorageValue(tasks:getMonstersStorage(task))
end

-- Checks if the player is currently doing a task
-- And returns the task the player is doing
function tasks:onTask(player)
    for i = 1, #tasks do
        if player:getStorageValue(tasks:getOnTaskStorage(i)) == 1 then
            return i
        end
    end
    return 0
end

-- Set canceled task
function tasks:setCaneled(player, task, set)
    if player:setStorageValue(tasks:getCanceledStorage(task), set) then
            player:setStorageValue(tasks:getOnTaskStorage(task), 0)
            player:setStorageValue(tasks:getMonstersStorage(task), 0)
            player:setStorageValue(tasks:getCompletedStorage(task), 0)
            player:setStorageValue(tasks:getFinishedStorage(task), 0)
        return true
    end
    return false
end

-- Set task as finished
function tasks:setFinished(player, task, set)
    if player:setStorageValue(tasks:getFinishedStorage(task), set) then
        return true
    end
    return false
end

-- Checks if the player has finished a task
-- And returns the task that is finished
function tasks:getFinished(player)
    for i = 1, #tasks do
        if player:getStorageValue(tasks:getFinishedStorage(i)) == 1 then
            return i
        end
    end
    return 0
end

-- Get all tasks player has
function tasks:getTasksFromPlayer(player)
    local allPlayerTasks = {}
    for i = 1, #tasks do
        if player:getStorageValue(tasks:getOnTaskStorage(i)) == 1 and player:getStorageValue(tasks:getFinishedStorage(i)) ~= 1 then
            table.insert(allPlayerTasks, i)
            table.insert(allPlayerTasks, ",")
        end
    end

    if not table.empty(allPlayerTasks) then
        return allPlayerTasks
    end
end

-- Check if killing creature is a task monster
function tasks:killedCreatureIsTaskMonster(player, target)
    local allTasks = tasks:getTasksFromPlayer(player)
    local playerTasks = string.split(table.concat(allTasks), ",")

    for i,x in pairs(playerTasks) do
        local task = tonumber(x)
        for i = 1, #tasks[task].monsters do
            if string.lower(target:getName()) == string.lower(tasks[task].monsters[i]) then
                return true, task
            end
        end
    end
    return false
end

-- Checks if the monster killed was a task monster
function tasks:onKill(player, target)
    isTaskCreature, currentTask = tasks:killedCreatureIsTaskMonster(player, target)

        if isTaskCreature then
            if tasks:getMonstersLeft(player, currentTask) < 1 then
                return false
            end

            player:setStorageValue(tasks:getMonstersStorage(currentTask), tasks:getMonstersLeft(player, currentTask) - 1)
            if tasks:getMonstersLeft(player, currentTask) == 0 then
                if tasks:setCompleted(player, currentTask, 1) then
                    player:sendTextMessage(messageType, "You have completed your task.")
                    tasks:rewardPlayer(player, currentTask)
                    return true
                end
            end

            player:sendTextMessage(messageType, "You killed " .. tasks[currentTask].toKill - tasks:getMonstersLeft(player, currentTask) .. " of " .. tasks[currentTask].toKill .. " " .. string.lower(target:getName()) .. ".")
            return true
    end
    return false
end

-- Reward player after finishing task
function tasks:rewardPlayer(player, t)
    for i = 1, #tasks[t].rewards do
        if tasks[t].rewards[i].type == "item" then
            player:sendTextMessage(messageType, string.format("You received %dx %s(s).", tasks[t].rewards[i].count, tasks[t].rewards[i].name))
            player:addItem(tasks[t].rewards[i].itemid, tasks[t].rewards[i].count)
        end
        if tasks[t].rewards[i].type == "exp" then
            player:sendTextMessage(messageType, string.format("You received %dx experience.", tasks[t].rewards[i].experience))
            player:addExperience(tasks[t].rewards[i].experience, false)
        end
        if tasks[t].rewards[i].type == "storage" then
            player:sendTextMessage(messageType, string.format("You received a storage reward.", tasks[t].rewards[i].experience))
            player:setStorageValue(tasks[t].rewards[i].storageId, tasks[t].rewards[i].storageValue)
        end
    end

    tasks:setTask(player, t, 0)
    tasks:setCompleted(player, t, 0)
    tasks:setFinished(player, t, 1)
    return true
end

-- Toggle true/false at the top of this lua file
-- Resets the tasks for the provided player
function tasks:reset(player, task)
    if reset then
        player:setStorageValue(tasks:getOnTaskStorage(task), 0)
        player:setStorageValue(tasks:getMonstersStorage(task), 0)
        player:setStorageValue(tasks:getCompletedStorage(task), 0)
        player:setStorageValue(tasks:getFinishedStorage(task), 0)
        player:setStorageValue(tasks:getCanceledStorage(task), 0)
    end
end
Hey buddy, how can I set more than one level os task? Like kill 25x rats, after finish kill 100x rats, after finish kill 400x rats? If you can make for me just one example I can update all here.
 
Its missing on global function (inside global.lua) which is used by serveral lua scripts or can be used by them. So you have to add this in your global.lua:


Lua:
table.append = table.insert
table.empty = function (t)
    return next(t) == nil
end

table.find = function (table, value)
    for i, v in pairs(table) do
        if(v == value) then
            return i
        end
    end

    return nil
end

table.count = function (table, item)
    local count = 0
    for i, n in pairs(table) do
        if(item == n) then
            count = count + 1
        end
    end

    return count
end
table.countElements = table.count

table.getCombinations = function (table, num)
    local a, number, select, newlist = {}, #table, num, {}
    for i = 1, select do
        a[#a + 1] = i
    end

    local newthing = {}
    while(true) do
        local newrow = {}
        for i = 1, select do
            newrow[#newrow + 1] = table[a[i]]
        end

        newlist[#newlist + 1] = newrow
        i = select
        while(a[i] == (number - select + i)) do
            i = i - 1
        end

        if(i < 1) then
            break
        end

        a[i] = a[i] + 1
        for j = i, select do
            a[j] = a[i] + j - i
        end
    end

    return newlist
end

function table.serialize(x, recur)
    local t = type(x)
    recur = recur or {}

    if(t == nil) then
        return "nil"
    elseif(t == "string") then
        return string.format("%q", x)
    elseif(t == "number") then
        return tostring(x)
    elseif(t == "boolean") then
        return t and "true" or "false"
    elseif(getmetatable(x)) then
        error("Can not serialize a table that has a metatable associated with it.")
    elseif(t == "table") then
        if(table.find(recur, x)) then
            error("Can not serialize recursive tables.")
        end
        table.append(recur, x)

        local s = "{"
        for k, v in pairs(x) do
            s = s .. "[" .. table.serialize(k, recur) .. "]"
            s = s .. " = " .. table.serialize(v, recur) .. ","
        end
        s = s .. "}"
        return s
    else
        error("Can not serialize value of type '" .. t .. "'.")
    end
end

function table.unserialize(str)
    return loadstring("return " .. str)()
end
Post automatically merged:


Hey buddy, how can I set more than one level os task? Like kill 25x rats, after finish kill 100x rats, after finish kill 400x rats? If you can make for me just one example I can update all here.

You should be able by adding a new entry such as:
Lua:
    [10] = {
        name = "Rats Advanced", -- Name of Task
        minlevel = 1,
        maxlevel = 15,
        monsters = { -- You can add as many monsters as you want
            "Rat",
            "Cave Rat",
        },
        toKill = 100, -- How many monsters the player needs to kill
        rewards = { -- You can add as many rewards as you want
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2152,
                count = 10,
            },
            [2] = {
                type = "exp",
                experience = 16000,
            },
        },
    },

If you looking to have a 'following' task, there is no option for that.
 
You should be able by adding a new entry such as:
Lua:
    [10] = {
        name = "Rats Advanced", -- Name of Task
        minlevel = 1,
        maxlevel = 15,
        monsters = { -- You can add as many monsters as you want
            "Rat",
            "Cave Rat",
        },
        toKill = 100, -- How many monsters the player needs to kill
        rewards = { -- You can add as many rewards as you want
            [1] = {
                type = "item",
                name = "platinum coin",
                itemid = 2152,
                count = 10,
            },
            [2] = {
                type = "exp",
                experience = 16000,
            },
        },
    },

If you looking to have a 'following' task, there is no option for that.
I cant tell to just start one when finish other, right?
 
Back
Top