CreatureEvent [TFS 1.2] Task System

rwxsu

Computer Engineer
Joined
Mar 31, 2018
Messages
85
Best answers
3
Reaction score
119
Location
Jugoslavija
Task System For TFS 1.2


Features:
* You can add as many tasks as you want
* You can add as many rewards as you want for each task
* You can add multiple monsters to a task, so it registers the kill on different monsters (e.g. dragon and dragon lord)
* You can change the name of the task
* You can choose what the NPC will tell the player for each task


See How Here:






7 simple steps


Add the NPC: data/npc/Tarr.xml
XML:
<?xml version="1.0" encoding="UTF-8"?>
<npc name="Tarr" script="Task.lua" walkinterval="2000" floorchange="0">
    <health now="100" max="100" />
    <look type="430" head="114" body="132" legs="95" feet="132" addons="1" />
    <parameters>
        <parameter key="message_greet" value="|PLAYERNAME|, need a task?" />
        <parameter key="message_walkaway" value="COME BACK WHEN YOU ARE PREPARED!" />
        <parameter key="message_farewell" value="COME BACK WHEN YOU ARE PREPARED!" />
    </parameters>
</npc>


Add the NPC script: data/npc/scripts/Task.lua
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

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

    if msgcontains(msg, 'task') or msgcontains(msg, 'mission') then
        task:new(player, npcHandler)
    end

    if msgcontains(msg, 'reset') then
        task:reset(player, npcHandler)
    end

    return true
end

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


Add the lib: data/lib/custom/task.lua
Lua:
------------------------------------------------------
--                   Firestorm by rwxsu             --
------------------------------------------------------
--               License: do as you please          --
------------------------------------------------------

debug = true -- Debug mode for developers
reset = true -- Reset tasks by saying 'reset' to npc


task = {
    storage = {
        onTask         = 6522000,
        monstersLeft = 6522001,
        completed    = 6522002,
        getFinished  = 6522003,
    },
    tasks = { -- You can add as many tasks as you want
        [1] = {
            name = "Slimy Worms", -- Name of Task
            description = "The slimy rotworms in the sewers are destroying the city. Please kill some of them for me.", -- What the NPC tells the player to do
            monsters = { -- You can add as many monsters as you want
                "Rotworm",
                "Carrion Worm",
            },
            toKill = 4, -- How many monsters the player needs to kill
            rewards = {    -- You can add as many rewards as you want
                [1] = {
                    name = "crystal coin",
                    itemid = 2160,
                    count = 3,
                },
                [2] = {
                    name = "magic sword",
                    itemid = 2400,
                    count = 1,
                },
            },
        },
        [2] = {
            name = "Firebreathers",
            description = "Dragons.. dragons.. dragons...", 
            monsters = {
                "Dragon",
                "Dragon Lord",
            },
            toKill = 3,
            rewards = {
                [1] = {
                    name = "crystal coin",
                    itemid = 2160,
                    count = 10,
                },
            },
        },
        [3] = {
            name = "Demonz",
            description = "Big, red and magical.", 
            monsters = {
                "Demon",
            },
            toKill = 1,
            rewards = {
                [1] = {
                    name = "crystal coin",
                    itemid = 2160,
                    count = 50,
                },
            },
        },
    },
}

task.__index = task

-- Finds out what the last task the player did was, if any,
-- and gives the player a new task
function task:new(player, npcHandler) 
    if task:getCompleted(player) > 0 then
        task:reward(player, npcHandler)
        task:set(player, 0)
        return false
    end

    if task:onTask(player) > 0 then
        npcHandler:say("You already have a task.", player:getId())
        task:debug(player:getName() .. " is already on a task " .. task.tasks[task:onTask(player)].name  .. ".")
        return false
    end

    local lastFinished = task:getFinished(player)
    if lastFinished == #task.tasks then
        npcHandler:say("You have completed all the tasks!", player:getId())
        return false
    end

    local newTask = lastFinished + 1
    task:set(player, newTask)
    npcHandler:say(task.tasks[newTask].description, player:getId())
    return true
end

-- Sets the task provided 't' to the player provided
function task:set(player, t)
    if player:setStorageValue(task.storage.onTask, t) then       
        if t == 0 then
            task:debug(player:getName() .. " is no longer on task.")
            return false
        end
        task:debug(player:getName() .. " started task " .. task.tasks[t].name .. ".")
       
        if player:setStorageValue(task.storage.monstersLeft, task.tasks[t].toKill) then
            return true
        end
    end   
    return false
end

function task:setCompleted(player, t)
    if player:setStorageValue(task.storage.completed, t) then
        if t == 0 then
            return true
        end
        return true
    end
    return false
end

function task:getCompleted(player)
    return player:getStorageValue(task.storage.completed)
end

function task:getMonstersLeft(player)
    return player:getStorageValue(task.storage.monstersLeft)
end

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

function task:setFinished(player, t)
    if player:setStorageValue(task.storage.getFinished, t) then
        task:debug(player:getName() .. " finished task " .. task.tasks[t].name)
        return true
    end
    return false
end

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

-- Checks if the monster killed was a task monster
function task:onKill(player, target)
    currentTask = task:onTask(player)
    for i = 1, #task.tasks[currentTask].monsters do
        if string.lower(target:getName()) == string.lower(task.tasks[currentTask].monsters[i]) then
           
            if task:getMonstersLeft(player) < 1 then
                return false
            end

            player:setStorageValue(task.storage.monstersLeft, task:getMonstersLeft(player) - 1)
            if task:getMonstersLeft(player) == 0 then
                if task:setCompleted(player, currentTask) then
                    player:sendTextMessage(MESSAGE_STATUS_WARNING, "You have completed your task.")
                    task:debug(string.format("%s has completed %s.", player:getName(), task.tasks[currentTask].name))
                    return true
                end
            end

            player:sendTextMessage(MESSAGE_STATUS_WARNING, "You killed a " .. string.lower(target:getName()) .. ". Only " .. task:getMonstersLeft(player) .. " left to kill!")
            task:debug(player:getName() .. " killed a " .. string.lower(target:getName()) .. ". " .. task:getMonstersLeft(player) .. " monsters left.") 
            return true
        end
    end
    return false
end

function task:reward(player, npcHandler)
    local t = task:onTask(player)
    for i = 1, #task.tasks[t].rewards do
        player:addItem(task.tasks[t].rewards[i].itemid, task.tasks[t].rewards[i].count)
        player:sendTextMessage(MESSAGE_STATUS_WARNING, string.format("You received %dx %s(s).", task.tasks[t].rewards[i].count, task.tasks[t].rewards[i].name))
        task:debug(string.format(player:getName() .. " received %dx %s(s).", task.tasks[t].rewards[i].count, task.tasks[t].rewards[i].name))
    end

    npcHandler:say("Here you go!", player:getId())

    task:onTask(player, 0)
    task:setCompleted(player, 0)
    task:setFinished(player, t)
    return true
end

-- Toggle true/false at the top of this lua file
-- Resets the tasks for the provided player
function task:reset(player, npcHandler)
    if reset then
        player:setStorageValue(task.storage.onTask, 0)
        player:setStorageValue(task.storage.monstersLeft, 0)
        player:setStorageValue(task.storage.completed, 0)
        player:setStorageValue(task.storage.getFinished, 0)
        npcHandler:say("You have reseted all the tasks.", player:getId())
        task:debug(player:getName() .. " reseted his tasks.")
    end
end

-- Toggle true/false at the top of this lua file
function task:debug(string)
    if debug then
        string = "[TASK] " .. string
        print(string)
    end
end



Remember to add this in data/lib/lib.lua
Lua:
dofile('data/lib/custom/task.lua')


Add the onKill in data/creaturescripts/scripts/task.lua
Code:
function onKill(player, target, lastHit)
    if not (task:onTask(player) > 0) then
        return false
    end

    if not player:isPlayer() then
        return false
    end

    task:onKill(player, target)
    return true 
end


Link it with your xml: data/creaturescripts/creaturescripts.xml
XML:
<event type="kill" name="Task" script="task.lua" />


Lastly don't forget to register the event in data/creaturescripts/scripts/login.lua
Lua:
player:registerEvent("Task")



That's it! Hope you enjoy it,
rwxsu
 

Lyky

Active Member
Joined
May 27, 2014
Messages
204
Best answers
8
Reaction score
46
works just fine - i see the use for it.
 

God Nixez

Excellent OT User
Joined
Sep 20, 2009
Messages
399
Best answers
0
Reaction score
16
Great script *Easy to config - awesome debug information"
using it on my upcoming project TFS 1,2
ty @rwxsu
 

Catalyst

whoU
Joined
May 12, 2017
Messages
64
Best answers
3
Reaction score
14
Location
No Idea.
Sadly, when i utevo res a monster it counts as a task monster. :/
 

Lyky

Active Member
Joined
May 27, 2014
Messages
204
Best answers
8
Reaction score
46
i'd still be inefficient to kill your summons to progress.

~ mana used vs progress.
 
OP
rwxsu

rwxsu

Computer Engineer
Joined
Mar 31, 2018
Messages
85
Best answers
3
Reaction score
119
Location
Jugoslavija
Sadly, when i utevo res a monster it counts as a task monster. :/

Replace the code in data/creaturescripts/scripts/task.lua with this:
Lua:
function onKill(player, target, lastHit)
    if not (task:onTask(player) > 0) then
        return false
    end

    if not player:isPlayer() then
        return false
    end

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

    task:onKill(player, target)
    return true 
end

The only difference is:
Lua:
if target:getMaster() ~= nil then return false end
Thank you for your feedback,
rwxsu
 

God Nixez

Excellent OT User
Joined
Sep 20, 2009
Messages
399
Best answers
0
Reaction score
16


Replace the code in data/creaturescripts/scripts/task.lua with this:
Lua:
function onKill(player, target, lastHit)
    if not (task:onTask(player) > 0) then
        return false
    end

    if not player:isPlayer() then
        return false
    end

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

    task:onKill(player, target)
    return true 
end

The only difference is:
Lua:
if target:getMaster() ~= nil then return false end
Thank you for your feedback,
rwxsu
Sweet, Thank you :)

/Nixez
 

icekis

Member
Joined
Jan 18, 2018
Messages
84
Best answers
0
Reaction score
5
Hi!

how can i reward with experience or storage?
 
OP
rwxsu

rwxsu

Computer Engineer
Joined
Mar 31, 2018
Messages
85
Best answers
3
Reaction score
119
Location
Jugoslavija
Hi!

how can i reward with experience or storage?
It's not implemented in this script, but you can do it like this:

- Under reward, set itemid to 0 and set the count to how much experience you want the player to get
- Then in the task:reward() function's for-loop, you do a check to see if itemid is 0, and if it is reward the player with count experience and return the function.
 

nuviusz

New Member
Joined
Sep 26, 2018
Messages
1
Best answers
0
Reaction score
0
Hi, is it possible to change a bit code in files to let players decide which task they want to do?
 

Xizze

New Member
Joined
Nov 3, 2008
Messages
2
Best answers
0
Reaction score
0
Hello, is there any way to connect this to the Quest log in TFS 1.2?

If my 1st task is rotworms, 2nd orcs, 3rd dargons.......

I want my quest log to say something like:
Tasks
Mission 1: Rots (Completed)
Mission 2: Orcs (Completed)
Mission 3: Dragons

The storagevalues now seems to be reused of what i can make sense of in the code.

Hope you understand what i am trying to say :rolleyes:
 

Drs1705

Well-Known Member
Joined
Dec 26, 2011
Messages
69
Best answers
0
Reaction score
14
I made a reset enhancement so that the player doesn't reset missions infinitely.

in task lib
Code:
task = {
    storage = {
        onTask         = 6522000,
        monstersLeft = 6522001,
        completed    = 6522002,
        getFinished  = 6522003,
        resetTime  = 6522004, -- Reset Storage
    },
in lib fuctions task:reset add
Code:
function task:reset(player, npcHandler)
    if player:getStorageValue(task.storage.resetTime) - os.time() <= 0 then
        if reset then
            player:setStorageValue(task.storage.resetTime, os.time() + 3600) -- 3600 seconds = 1 hour to reset
            player:setStorageValue(task.storage.onTask, 0)
            player:setStorageValue(task.storage.monstersLeft, 0)
            player:setStorageValue(task.storage.completed, 0)
            player:setStorageValue(task.storage.getFinished, 0)
            npcHandler:say("You have reseted all the tasks, wait 12 hours to reset again.", player:getId())
            task:debug(player:getName() .. " reseted his tasks.")
        end
    else
    player:sendTextMessage(MESSAGE_STATUS_WARNING,"[TASK] Wait 1 hour to be able to reset mission.")
    end
en
 

Haskys

Member
Joined
Jul 19, 2019
Messages
97
Best answers
0
Reaction score
8
Location
Poland
I made a reset enhancement so that the player doesn't reset missions infinitely.

in task lib
Code:
task = {
    storage = {
        onTask         = 6522000,
        monstersLeft = 6522001,
        completed    = 6522002,
        getFinished  = 6522003,
        resetTime  = 6522004, -- Reset Storage
    },
in lib fuctions task:reset add
Code:
function task:reset(player, npcHandler)
    if player:getStorageValue(task.storage.resetTime) - os.time() <= 0 then
        if reset then
            player:setStorageValue(task.storage.resetTime, os.time() + 3600) -- 3600 seconds = 1 hour to reset
            player:setStorageValue(task.storage.onTask, 0)
            player:setStorageValue(task.storage.monstersLeft, 0)
            player:setStorageValue(task.storage.completed, 0)
            player:setStorageValue(task.storage.getFinished, 0)
            npcHandler:say("You have reseted all the tasks, wait 12 hours to reset again.", player:getId())
            task:debug(player:getName() .. " reseted his tasks.")
        end
    else
    player:sendTextMessage(MESSAGE_STATUS_WARNING,"[TASK] Wait 1 hour to be able to reset mission.")
    end
en


Which file should I add this (below) code to?
Also to data/lib/custom/task.lua ?

Lua:
function task:reset(player, npcHandler)
    if player:getStorageValue(task.storage.resetTime) - os.time() <= 0 then
        if reset then
            player:setStorageValue(task.storage.resetTime, os.time() + 3600) -- 3600 seconds = 1 hour to reset
            player:setStorageValue(task.storage.onTask, 0)
            player:setStorageValue(task.storage.monstersLeft, 0)
            player:setStorageValue(task.storage.completed, 0)
            player:setStorageValue(task.storage.getFinished, 0)
            npcHandler:say("You have reseted all the tasks, wait 12 hours to reset again.", player:getId())
            task:debug(player:getName() .. " reseted his tasks.")
        end
    else
    player:sendTextMessage(MESSAGE_STATUS_WARNING,"[TASK] Wait 1 hour to be able to reset mission.")
    end
end
 

Drs1705

Well-Known Member
Joined
Dec 26, 2011
Messages
69
Best answers
0
Reaction score
14
Replace Second First code for Second in task lib
Which file should I add this (below) code to?
Also to data/lib/custom/task.lua ?

Lua:
function task:reset(player, npcHandler)
    if player:getStorageValue(task.storage.resetTime) - os.time() <= 0 then
        if reset then
            player:setStorageValue(task.storage.resetTime, os.time() + 3600) -- 3600 seconds = 1 hour to reset
            player:setStorageValue(task.storage.onTask, 0)
            player:setStorageValue(task.storage.monstersLeft, 0)
            player:setStorageValue(task.storage.completed, 0)
            player:setStorageValue(task.storage.getFinished, 0)
            npcHandler:say("You have reseted all the tasks, wait 12 hours to reset again.", player:getId())
            task:debug(player:getName() .. " reseted his tasks.")
        end
    else
    player:sendTextMessage(MESSAGE_STATUS_WARNING,"[TASK] Wait 1 hour to be able to reset mission.")
    end
end
 
Top