NPC [TFS 1.1] Monster Tasks

Limos

Premium User
Joined
Jun 7, 2010
Messages
10,018
Best answers
7
Reaction score
2,959
Location
Netherlands
Tested with TFS 1.1.

With this script people can choose which task they want to do.
If you want premade tasks, you can use this one: https://otland.net/threads/collecting-items-and-monster-missions.230261/



Adonai.xml
Code:
<?xml version="1.0" encoding="UTF-8"?>
<npc name="Adonai" script="tasks.lua" walkinterval="2000" speed ="0" floorchange="0">
   <health now="100" max="100"/>
   <look type="433" head="58" body="113" legs="50" feet="78" addons="1" mount="688"/>
</npc>

tasks.lua
Code:
-- Monster Tasks by Limos
local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)
local xmsg = {}

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 storage = 62003

local monsters = {
   ["Dragons"] = {storage = 5010, mstorage = 19000, amount = 10, exp = 5000, items = {{id = 2157, count = 1}, {id = 2160, count = 3}}},
   ["Dragon Lords"] = {storage = 5011, mstorage = 19001, amount = 10, exp = 10000, items = {{id = 2492, count = 1}, {id = 2160, count = 5}}},
   ["Hydras"] = {storage = 5012, mstorage = 19002, amount = 10, exp = 18000, items = {{id = 2195, count = 1}, {id = 2157, count = 8}}},
   ["Demons"] = {storage = 5013, mstorage = 19003, amount = 10, exp = 20000, items = {{id = 2520, count = 1}, {id = 2160, count = 10}}}
}


local function getItemsFromTable(itemtable)
     local text = ""
     for v = 1, #itemtable do
         count, info = itemtable[v].count, ItemType(itemtable[v].id)
         local ret = ", "
         if v == 1 then
             ret = ""
         elseif v == #itemtable then
             ret = " and "
         end
         text = text .. ret
         text = text .. (count > 1 and count or info:getArticle()).." "..(count > 1 and info:getPluralName() or info:getName())
     end
     return text
end

local function Cptl(f, r)
     return f:upper()..r:lower()
end

function creatureSayCallback(cid, type, msg)

     local player, cmsg = Player(cid), msg:gsub("(%a)([%w_']*)", Cptl)
     if not npcHandler:isFocused(cid) then
         if msg == "hi" or msg == "hello" then
             npcHandler:addFocus(cid)
             if player:getStorageValue(storage) == -1 then
                 local text, n = "",  0
                 for k, x in pairs(monsters) do
                     if player:getStorageValue(x.mstorage) < x.amount then
                         n = n + 1
                         text = text .. ", "
                         text = text .. ""..x.amount.." {"..k.."}"
                     end
                 end
                 if n > 1 then
                     npcHandler:say("I have several tasks for you to kill monsters"..text..", which one do you choose? I can also show you a {list} with rewards and you can {stop} a task if you want.", cid)
                     npcHandler.topic[cid] = 1
                     xmsg[cid] = msg
                 elseif n == 1 then
                     npcHandler:say("I have one last task for you"..text..".", cid)
                     npcHandler.topic[cid] = 1
                 else
                     npcHandler:say("You already did all tasks, I have nothing for you to do anymore, good job though.", cid)
                 end
             elseif player:getStorageValue(storage) == 1 then
                 for k, x in pairs(monsters) do
                     if player:getStorageValue(x.storage) == 1 then
                         npcHandler:say("Did you kill "..x.amount.." "..k.."?", cid)
                         npcHandler.topic[cid] = 2
                         xmsg[cid] = k
                     end
                 end
             end
         else
             return false
         end
     elseif monsters[cmsg] and npcHandler.topic[cid] == 1 then
         if player:getStorageValue(monsters[cmsg].storage) == -1 then
             npcHandler:say("Good luck, come back when you killed "..monsters[cmsg].amount.." "..cmsg..".", cid)
             player:setStorageValue(storage, 1)
             player:setStorageValue(monsters[cmsg].storage, 1)
         else
             npcHandler:say("You already did the "..cmsg.." mission.", cid)
         end
         npcHandler.topic[cid] = 0
     elseif msgcontains(msg, "yes") and npcHandler.topic[cid] == 2 then
         local x = monsters[xmsg[cid]]
         if player:getStorageValue(x.mstorage) >= x.amount then
             npcHandler:say("Good job, here is your reward, "..getItemsFromTable(x.items)..".", cid)
             for g = 1, #x.items do
                 player:addItem(x.items[g].id, x.items[g].count)
             end
             player:addExperience(x.exp)
             player:setStorageValue(x.storage, 2)
             player:setStorageValue(storage, -1)
             npcHandler.topic[cid] = 3
         else
             npcHandler:say("You didn't kill them all, you still need to kill "..x.amount -(player:getStorageValue(x.mstorage) + 1).." "..xmsg[cid]..".", cid)
         end
     elseif msgcontains(msg, "task") and npcHandler.topic[cid] == 3 then
         local text, n = "",  0
         for k, x in pairs(monsters) do
             if player:getStorageValue(x.mstorage) < x.amount then
                 n = n + 1
                 text = text .. (n == 1 and "" or ", ")
                 text = text .. "{"..k.."}"
             end
         end
         if text ~= "" then
             npcHandler:say("Want to do another task? You can choose "..text..".", cid)
             npcHandler.topic[cid] = 1
         else
             npcHandler:say("You already did all tasks.", cid)
         end
     elseif msgcontains(msg, "no") and npcHandler.topic[cid] == 1 then
         npcHandler:say("Ok then.", cid)
         npcHandler.topic[cid] = 0
     elseif msgcontains(msg, "stop") then
         local text, n = "",  0
         for k, x in pairs(monsters) do
             if player:getStorageValue(x.mstorage) < x.amount then
                 n = n + 1
                 text = text .. (n == 1 and "" or ", ")
                 text = text .. "{"..k.."}"
                 if player:getStorageValue(x.storage) == 1 then
                      player:setStorageValue(x.storage, -1)
                 end
             end
         end
         if player:getStorageValue(storage) == 1 then
             npcHandler:say("Alright, let me know if you want to continue an other task, you can still choose "..text..".", cid)
         else
             npcHandler:say("You didn't start any new task yet, if you want to start one, you can choose "..text..".", cid)
         end
         player:setStorageValue(storage, -1)
         npcHandler.topic[cid] = 1
     elseif msgcontains(msg, "list") then
         local text = "Tasks\n\n"
         for k, x in pairs(monsters) do
             if player:getStorageValue(x.mstorage) < x.amount then
                 text = text ..k .." ["..(player:getStorageValue(x.mstorage) + 1).."/"..x.amount.."]:\n  Rewards:\n  "..getItemsFromTable(x.items).."\n  "..x.exp.." experience \n\n"
             else
                 text = text .. k .." [DONE]\n"
             end
         end
         player:showTextDialog(1949, "" .. text)
         npcHandler:say("Here you are.", cid)
     elseif msgcontains(msg, "bye") then
         npcHandler:say("Bye.", cid)
         npcHandler:releaseFocus(cid)
     else
         npcHandler:say("What?", cid)
     end
     return true
end

npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)




creaturescripts.xml
Code:
<event type="kill" name="Tasks" script="killtasks.lua"/>
login.lua
Code:
player:registerEvent("Tasks")
killtasks.lua
Code:
local config = {
     ['dragon'] = {amount = 10, storage = 19000, startstorage = 5010, startvalue = 1},
     ['dragon lord'] = {amount = 10, storage = 19001, startstorage = 5011, startvalue = 1},
     ['hydra'] = {amount = 10, storage = 19002, startstorage = 5012, startvalue = 1},
     ['demon'] = {amount = 10, storage = 19003, startstorage = 5013, startvalue = 1}
}
function onKill(player, target)
     local monster = config[target:getName():lower()]
     if target:isPlayer() or not monster or target:getMaster() then
         return true
     end
     local stor = player:getStorageValue(monster.storage)+1
     if stor < monster.amount and player:getStorageValue(monster.startstorage) >= monster.startvalue then
         player:setStorageValue(monster.storage, stor)
         player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, 'Task message: '..(stor +1)..' of '..monster.amount..' '..target:getName()..'s killed.')
     end
     if (stor +1) == monster.amount then
         player:sendTextMessage(MESSAGE_INFO_DESCR, 'Congratulations, you have killed '..(stor +1)..' '..target:getName()..'s and completed the '..target:getName()..'s mission.')
         player:setStorageValue(monster.storage, stor +1)
     end
     return true
end
 
Last edited:
OP
Limos

Limos

Premium User
Joined
Jun 7, 2010
Messages
10,018
Best answers
7
Reaction score
2,959
Location
Netherlands
How does it work

The NPC gives you several tasks, you can choose which one you want to do.
If you didn't kill all the monsters, the NPC will tell you how many you still have to kill.


You can ask for a list to see the rewards and what you already did.


You can stop with tasks to do an other one and continue them later.


The finished tasks won't be mentioned by the NPC anymore and will be shown as DONE in the list.



With the last task the NPC will say there is one more task and then all tasks are done.


Report bugs, also feel free to ask questions or give suggestions.
 
Last edited:

Evil Puncker

I'd rather kiss a rattlesnake
Joined
May 30, 2009
Messages
5,925
Best answers
33
Reaction score
1,874
Location
160,54,7
great one limos!
suggestion: use modal windows everywhere xDD
 

Queari

New Member
Joined
Feb 27, 2015
Messages
75
Best answers
0
Reaction score
0
Console​
Code:
>> Loading script systems

[Error - CreatureScript Interface]
data/creaturescripts/scripts/login.lua
Description:
data/creaturescripts/scripts/login.lua:6: attempt to index global 'player' (a nil value)
[Warning - Event::loadScript] Cannot load script (data/creaturescripts/scripts/login.lua)
Login.lua​
Code:
local config = {
    loginMessage = getConfigValue('loginMessage'),
    useFragHandler = getBooleanFromString(getConfigValue('useFragHandler'))
}

player:registerEvent("Tasks")

function onLogin(cid)
    local loss = getConfigValue('deathLostPercent')
    if(loss ~= nil) then
        doPlayerSetLossPercent(cid, PLAYERLOSS_EXPERIENCE, loss * 10)
    end
function onLogin(cid)
    registerCreatureEvent(cid, "WrathOfTheEmperor")
    return true
end
    local accountManager = getPlayerAccountManager(cid)
    if(accountManager == MANAGER_NONE) then
        local lastLogin, str = getPlayerLastLoginSaved(cid), config.loginMessage
        if(lastLogin > 0) then
            doPlayerSendTextMessage(cid, MESSAGE_STATUS_DEFAULT, str)
            str = "Your last visit was on " .. os.date("%a %b %d %X %Y", lastLogin) .. "."
        else
            str = str .. " Please choose your outfit."
            doPlayerSendOutfitWindow(cid)
        end

        doPlayerSendTextMessage(cid, MESSAGE_STATUS_DEFAULT, str)
    elseif(accountManager == MANAGER_NAMELOCK) then
        doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "Hello, it appears that your character has been namelocked, what would you like as your new name?")
    elseif(accountManager == MANAGER_ACCOUNT) then
        doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "Hello, type 'account' to manage your account and if you want to start over then type 'cancel'.")
    else
        doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "Hello, type 'account' to create an account or type 'recover' to recover an account.")
    end

    if(not isPlayerGhost(cid)) then
        doSendMagicEffect(getCreaturePosition(cid), CONST_ME_TELEPORT)
    end

    registerCreatureEvent(cid, "Mail")
    registerCreatureEvent(cid, "GuildMotd")

    registerCreatureEvent(cid, "Idle")
    if(config.useFragHandler) then
        registerCreatureEvent(cid, "SkullCheck")
    end
    registerCreatureEvent(cid, "inquisitionPortals")
    registerCreatureEvent(cid, "ReportBug")
       registerCreatureEvent(cid, "no-exp")
       registerCreatureEvent(cid, "aol")
       registerCreatureEvent(cid, "charge amulet")
      registerCreatureEvent(cid, "AdvanceSave")
       registerCreatureEvent(cid,'lvlup')
    registerCreatureEvent(cid, "ArenaKill")
    registerCreatureEvent(cid, "reward")
       registerCreatureEvent(cid, "reward120")
    registerCreatureEvent(cid, "PythiusTheRotten")
   
    -- if he did not make full arena 1 he must start from zero
    if getPlayerStorageValue(cid, 42309) < 1 then
        for i = 42300, 42309 do
            setPlayerStorageValue(cid, i, 0)
        end
    end
    -- if he did not make full arena 2 he must start from zero
    if getPlayerStorageValue(cid, 42319) < 1 then
        for i = 42310, 42319 do
            setPlayerStorageValue(cid, i, 0)
        end
    end
    -- if he did not make full arena 3 he must start from zero
    if getPlayerStorageValue(cid, 42329) < 1 then
        for i = 42320, 42329 do
            setPlayerStorageValue(cid, i, 0)
        end
    end
    if getPlayerStorageValue(cid, 42355) == -1 then
        setPlayerStorageValue(cid, 42355, 0) -- did not arena level
    end
    setPlayerStorageValue(cid, 42350, 0) -- time to kick 0
    setPlayerStorageValue(cid, 42352, 0) -- is not in arena 
    return true
end
 

Evil Puncker

I'd rather kiss a rattlesnake
Joined
May 30, 2009
Messages
5,925
Best answers
33
Reaction score
1,874
Location
160,54,7
@Queari are you sure you are using tfs 1.1? because your login script looks from 0.3/4
 
OP
Limos

Limos

Premium User
Joined
Jun 7, 2010
Messages
10,018
Best answers
7
Reaction score
2,959
Location
Netherlands
This is for TFS 1.1.
 
Last edited:

Queari

New Member
Joined
Feb 27, 2015
Messages
75
Best answers
0
Reaction score
0
Limos would you be able to change it, to make it work on trun 3777?
 
OP
Limos

Limos

Premium User
Joined
Jun 7, 2010
Messages
10,018
Best answers
7
Reaction score
2,959
Location
Netherlands
You can look what gives errors and what the TFS 0.2 functions are for that in the compat.lua of TFS 1.1.
Example player:getStorageValue: https://github.com/otland/forgottenserver/blob/master/data/lib/compat/compat.lua#L148
Most of the TFS 0.2 versions of the TFS 1.1 functions that are used here also work in TFS 0.4 because of the compat.lua in TFS 0.4.
So you can use those or use the compat.lua of TFS 0.4 as example to change the TFS 0.2 functions to TFS 0.4 functions.

Or use TFS 1.1.
 

zygus0001

Member
Joined
Feb 26, 2015
Messages
210
Best answers
0
Reaction score
8
Limos nice scripts but wher is line for change valu of kill monster?
 

Alkenix

New Member
Joined
Oct 2, 2008
Messages
26
Best answers
0
Reaction score
2
Location
Germany
Mh, epic system. But how to get an choice for an item collect quest as well into the script?
Just killing monsters is boring as quests..:p
It's maybe a stupid question, but where do i need to put the killtasks.lua?
Or is it an extension for the tasks.lua?

TFS 1.1
 
Last edited:

StreamSide

Joseluis Gonzalez
Support Team
Joined
Aug 31, 2007
Messages
3,350
Best answers
34
Reaction score
851
Location
Arica - Chile
Mh, epic system. But how to get an choice for an item collect quest as well into the script?
Just killing monsters is boring as quests..:p
u can always add lines and variables to the script and the config table
 

Alkenix

New Member
Joined
Oct 2, 2008
Messages
26
Best answers
0
Reaction score
2
Location
Germany
But how do I add a line to collect items to the script? o.ô
 
OP
Limos

Limos

Premium User
Joined
Jun 7, 2010
Messages
10,018
Best answers
7
Reaction score
2,959
Location
Netherlands
What did you had in mind? The NPC now lists the monsters you can still kill for the tasks.
Something like this?
Code:
I have several tasks for you, kill 10 Dragons, collect 15 vampire dusts, kill 20 Dragon Lords, kill 10 Demons, collect 8 behemoth claws, which one do you choose?
 

Alkenix

New Member
Joined
Oct 2, 2008
Messages
26
Best answers
0
Reaction score
2
Location
Germany
Yes. A mix. Or do you know a game where you only got tasks with "kill monster xy"?^^
So, how can I edit the npc of you to let him mix the tasks?

I mean, for sure i could use the old npc with the premade tasks, there is a mix given.
But common, this should work with the new version here as well, didn't it?
 

Hugofasima

Website: thenosegang.servegame.com
Joined
Jun 24, 2015
Messages
206
Best answers
0
Reaction score
22
Limos, the counting is not working here... No erros on distro.

I just killed 10 dragons and it shows "0" on list and sends me a msg "You didn't kill them all, you still need to kill 10 Dragons."
 
OP
Limos

Limos

Premium User
Joined
Jun 7, 2010
Messages
10,018
Best answers
7
Reaction score
2,959
Location
Netherlands
Limos, the counting is not working here... No erros on distro.

I just killed 10 dragons and it shows "0" on list and sends me a msg "You didn't kill them all, you still need to kill 10 Dragons."
You should get textmessages while you kill the monsters, if nothing happens, you can add print to the script to see if the server even loads the script.
Under function onKill: print("script load test")
If you don't get this message in your console when you kill something, it means the server isn't using the script, so make sure it's added correct and restart the server.
 
Top