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

NPC Collecting items and monster missions

Limos

Senator
Premium User
Joined
Jun 7, 2010
Messages
10,013
Solutions
8
Reaction score
3,056
Location
Netherlands
Tested with TFS 1.0 and TFS 1.1.

Requested by giddy92.
Based on the collecting items missions NPC Mitrox.


mJ0JHC5G0.png



Soraya.xml
Code:
<?xml version="1.0" encoding="UTF-8"?>
<npc name="Soraya" script="missions.lua" walkinterval="2000" floorchange="0">
     <health now="100" max="100"/>
     <look type="471" head="59" body="132" legs="0" feet="57" addons="0"/>
     <parameters>
         <parameter key="message_greet" value="Hello |PLAYERNAME|."/>
     </parameters>
</npc>


missions.lua
Code:
-- Collecting items and monster missions by Limos
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 missions = {
   [1] = {
     items = {
       {id = 5890, count = 12},
       {id = 5878, count = 20},
       {id = 5894, count = 8}
     },
     message = "Great, for your first mission you need to collect some items, I need",
     level = 15, -- minimum level voor this mission
     rewarditems = {
       {id = 2160, count = 1},
       {id = 2152, count = 1}
     },
     rewardexp = 15000
   },
   [2] = {
     monsters = {
       {name = "Rats", count = 20, storage = 21900},
       {name = "Rotworms", count = 26, storage = 21901}
     },
     message = "Thanks, for your next mission kill",
     level = 30,
     rewarditems = {
       {id = 2160, count = 5}
     },
     rewardexp = 40000
   },
   [3] = {
     items = {
       {id = 5920, count = 45},
       {id = 5877, count = 22}
     },
     message = "Awesome, now get",
     level = 50,
     rewarditems = {
       {id = 2160, count = 15}
     },
     rewardexp = 100000
   },
   [4] = {
     monsters = {
       {name = "Dragon Lords", count = 25, storage = 21902}
     },
     message = "Good job, now kill",
     level = 70,
     rewarditems = {
       {id = 2160, count = 25}
     },
     rewardexp = 200000
   },
   [5] = {
     items = {
       {id = 5906, count = 35},
       {id = 5882, count = 42},
       {id = 4850, count = 1}
     },
     message = "Good, now your final mission, there are a few more items you need to get,",
     level = 100,
     rewarditems = {
       {id = 2160, count = 50}
     },
     rewardexp = 450000
   }
}

local storage = 45551

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

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

     local player = Player(cid)
     local x = missions[player:getStorageValue(storage)]

     if msgcontains(msg, 'mission') or msgcontains(msg, 'quest') then
         if player:getStorageValue(storage) == -1 then
             selfSay("I have several missions for you, do you accept the challenge?", cid)
             npcHandler.topic[cid] = 1
         elseif x then
             if player:getLevel() >= x.level then
                 selfSay("Did you "..(x.items and "get "..getItemsMonstersFromTable(x.items) or "kill "..getItemsMonstersFromTable(x.monsters)).."?", cid)
                 npcHandler.topic[cid] = 1
             else
                 selfSay("The mission I gave you is for level "..x.level..", come back later.", cid)
             end
         else
             selfSay("You already did all the missions, great job though.", cid)
             npcHandler:releaseFocus(cid)
         end
     elseif msgcontains(msg, 'yes') and npcHandler.topic[cid] == 1 then
         if player:getStorageValue(storage) == -1 then
             player:setStorageValue(storage, 1)
             local x = missions[player:getStorageValue(storage)]
             selfSay(x.message.." "..getItemsMonstersFromTable(x.items or x.monsters)..".", cid)
         elseif x then
             local imtable = x.items or x.monsters
             local amount = 0
             for it = 1, #imtable do
                 local check = x.items and player:getItemCount(imtable[it].id) or player:getStorageValue(imtable[it].storage)
                 if check >= imtable[it].count then
                     amount = amount + 1
                 end
             end
             if amount == #imtable then
                 if x.items then
                     for it = 1, #x.items do
                         player:removeItem(x.items[it].id, x.items[it].count)
                     end
                 end
                 if x.rewarditems then
                     for r = 1, #x.rewarditems do
                         player:addItem(x.rewarditems[r].id, x.rewarditems[r].count)
                     end
                     player:sendTextMessage(MESSAGE_EVENT_DEFAULT, "You received "..getItemsMonstersFromTable(x.rewarditems)..".")
                 end
                 if x.rewardexp then
                     player:addExperience(x.rewardexp)
                     player:sendTextMessage(MESSAGE_EVENT_DEFAULT, "You received "..x.rewardexp.." experience.")
                 end
                 player:setStorageValue(storage, player:getStorageValue(storage) + 1)
                 local x = missions[player:getStorageValue(storage)]
                 if x then
                     selfSay(x.message.." "..getItemsMonstersFromTable(x.items or x.monsters)..".", cid)
                 else
                     selfSay("Well done! You did a great job on all your missions.", cid)
                 end
             else
                 local n = 0
                 for i = 1, #imtable do
                     local check = x.items and player:getItemCount(imtable[i].id) or player:getStorageValue(imtable[i].storage)
                     if check < imtable[i].count then
                         n = n + 1
                     end
                 end
                 local text = ""
                 local c = 0
                 for v = 1, #imtable do
                     local check = x.items and player:getItemCount(imtable[v].id) or player:getStorageValue(imtable[v].storage)
                     if check < imtable[v].count then
                         c = c + 1
                         local ret = ", "
                         if c == 1 then
                             ret = ""
                         elseif c == n then
                             ret = " and "
                         end
                         text = text .. ret
                         if x.items then
                             local count, info = imtable[v].count - player:getItemCount(imtable[v].id), ItemType(imtable[v].id)
                             text = text .. (count > 1 and count or info:getArticle()).." "..(count > 1 and info:getPluralName() or info:getName())
                         else
                             local count = imtable[v].count - (player:getStorageValue(imtable[v].storage) + 1)
                             text = text .. count.." "..imtable[v].name
                         end
                     end
                 end
                 selfSay(x.items and "You don't have all items, you still need to get "..text.."." or "You didn't kill all monsters, you still need to kill "..text..".", cid)
             end
         end
         npcHandler.topic[cid] = 0
     elseif msgcontains(msg, 'no') and npcHandler.topic[cid] == 1 then
         selfSay("Oh well, I guess not then.", cid)
         npcHandler.topic[cid] = 0
     end
     return true
end

npcHandler:setMessage(MESSAGE_FAREWELL, "Bye!")
npcHandler:setMessage(MESSAGE_WALKAWAY, "Good bye, have a nice day!")
npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())

For older versions: http://pastebin.com/frSUfSrp
 
586.gif


creaturescripts.xml
Code:
<event type="kill" name="Missions" script="killmissions.lua"/>


login.lua
Code:
player:registerEvent("Missions")


killmissions.lua
Code:
local config = {
     ['rat'] = {amount = 20, storage = 21900, startstorage = 45551, startvalue = 2},
     ['rotworm'] = {amount = 26, storage = 21901, startstorage = 45551, startvalue = 2},
     ['dragon lord'] = {amount = 25, storage = 21902, startstorage = 45551, startvalue = 4}
}
function onKill(player, target)
     local player, target = Player(player), Creature(target) -- for TFS 1.0, delete this line if you use 1.1
     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

For older versions: https://otland.net/threads/npc-mission.211063/#post-2022378


How does it work:

The NPC will give several missions, some with items, others with monsters.
If the player doesn't have all items or didn't kill all monsters, it will say which items are still missing or which monsters and how many the player still has to kill.
If the mission is completed the player will get the reward and the NPC will give the next mission.
lRaeuhirt.png


The amount of missions, items, monsters, level, rewards and text are as example, you can change this in the local missions table.
Which mission is for monsters or items doesn't matter, so you can also do all missions with items or all missions with monsters.
 
This NPC gives several missions, you can choose missions with monsters or items. It's easy to edit the missions for more, less or different missions since you only need to edit the table.
It says exactly which items are missing if players didn't get them all and which and how many monsters still need to be killed if players didn't kill them all.
This can be useful especially if the list of items and monsters is quite long and people won't always remember what exactly they already got or killed.
 
586.gif


creaturescripts.xml
Code:
<event type="kill" name="Missions" script="killmissions.lua"/>


login.lua
Code:
player:registerEvent("Missions")


killmissions.lua
Code:
local config = {
     ['rat'] = {amount = 20, storage = 21900, startstorage = 45551, startvalue = 2},
     ['rotworm'] = {amount = 26, storage = 21901, startstorage = 45551, startvalue = 2},
     ['dragon lord'] = {amount = 25, storage = 21902, startstorage = 45551, startvalue = 4}
}
function onKill(cid, target)
     local player, creature = Player(cid), Creature(target)
     local monster = config[creature:getName():lower()]
     if creature:isPlayer() or not monster or creature:getMaster() then
         return true
     end
     if (player:getStorageValue(monster.storage)+1) < monster.amount and player:getStorageValue(monster.startstorage) >= monster.startvalue then
         player:setStorageValue(monster.storage, player:getStorageValue(monster.storage) + 1)
         player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, 'Task message: '..(player:getStorageValue(monster.storage)+1)..' of '..monster.amount..' '..creature:getName()..'s killed.')
     end
     if (player:getStorageValue(monster.storage)+1) == monster.amount then
         player:sendTextMessage(MESSAGE_INFO_DESCR, 'Congratulations, you have killed '..(player:getStorageValue(monster.storage)+1)..' '..creature:getName()..'s and completed the '..creature:getName()..'s mission.')
         player:setStorageValue(monster.storage, player:getStorageValue(monster.storage) + 1)
     end
     return true
end

For older versions: https://otland.net/threads/npc-mission.211063/#post-2022378


How does it work:

The NPC will give several missions, some with items, others with monsters.
If the player doesn't have all items or didn't kill all monsters, it will say which items are still missing or which monsters and how many the player still has to kill.
If the mission is completed the player will get the reward and the NPC will give the next mission.
lRaeuhirt.png


The amount of missions, items, monsters, level, rewards and text are as example, you can change this in the local missions table.
Which mission is for monsters or items doesn't matter, so you can also do all missions with items or all missions with monsters.
Thanks for your release but i found error when i killed monster
Code:
[21/03/2015 18:58:30] [Error - CreatureScript Interface]
[21/03/2015 18:58:30] data/creaturescripts/scripts/norma.lua:onKill
[21/03/2015 18:58:30] Description:
[21/03/2015 18:58:30] data/creaturescripts/scripts/norma.lua:7: attempt to call global 'isSummon' (a nil value)
[21/03/2015 18:58:30] stack traceback:
[21/03/2015 18:58:30]     data/creaturescripts/scripts/norma.lua:7: in function <data/creaturescripts/scripts/norma.lua:5>
norma.lua
Code:
local config = {
     ['rat'] = {amount = 20, storage = 21900, startstorage = 5002, startvalue = 1},
     ['rotworm'] = {amount = 26, storage = 21901, startstorage = 5002, startvalue = 1}
}
function onKill(cid, target)
     local monster = config[getCreatureName(target):lower()]
     if isPlayer(target) or not monster or isSummon(target) then
         return true
     end

     if (getPlayerStorageValue(cid, monster.storage)+1) < monster.amount and getPlayerStorageValue(cid, monster.startstorage) >= monster.startvalue then
         setPlayerStorageValue(cid, monster.storage, getPlayerStorageValue(cid, monster.storage) + 1)
         doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, 'Task message: '..(getPlayerStorageValue(cid, monster.storage)+1)..' of '..monster.amount..' '..getCreatureName(target)..'s killed.')
     end
     if (getPlayerStorageValue(cid, monster.storage)+1) == monster.amount then
         doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, 'Congratulations, you have killed '..(getPlayerStorageValue(cid, monster.storage)+1)..' '..getCreatureName(target)..'s and completed the '..getCreatureName(target)..'s mission.')
         setPlayerStorageValue(cid, monster.storage, getPlayerStorageValue(cid, monster.storage) + 1)
     end
     return true
end
TFS 0.3.6
 
For all versions older than TFS 0.4 (so will also work on TFS 0.3.6 because of the compat.lua)
Code:
function isSummon(cid)
     return (isCreature(cid) == TRUE and (getCreatureMaster(cid) ~= cid)) and TRUE or FALSE
end

TFS 0.3.6
Code:
function isSummon(cid)
     return getCreatureMaster(cid) ~= cid
end

TFS 0.4
Code:
function isSummon(cid)
     return getCreatureMaster(cid) ~= nil
end

Add it to data/lib/050-function.lua.
 
For all versions older than TFS 0.4 (so will also work on TFS 0.3.6 because of the compat.lua)
Code:
function isSummon(cid)
     return (isCreature(cid) == TRUE and (getCreatureMaster(cid) ~= cid)) and TRUE or FALSE
end

TFS 0.3.6
Code:
function isSummon(cid)
     return getCreatureMaster(cid) ~= cid
end

TFS 0.4
Code:
function isSummon(cid)
     return getCreatureMaster(cid) ~= nil
end

Add it to data/lib/050-function.lua.
Error is solved but when i kill the monster it doesn't calculate anything :S
NPC.lua
Code:
        [2] = {
                monsters = {
                        {name = "Rat", count = 20, storage = 21900},
                        {name = "Rotworm", count = 26, storage = 21901}
                },
Norma.lua
Code:
local config = {
     ['rat'] = {amount = 20, storage = 21900, startstorage = 5002, startvalue = 1},
     ['rotworm'] = {amount = 26, storage = 21901, startstorage = 5002, startvalue = 1}
}
:S
 
The startstorage needs to be the storage from the NPC and the startvalue the number of the mission.
So if you use the storage from the NPC script I posted, the startstorage should 45551 and the startvalue 2 since it's mission 2.
 
The startstorage needs to be the storage from the NPC and the startvalue the number of the mission.
So if you use the storage from the NPC script I posted, the startstorage should 45551 and the startvalue 2 since it's mission 2.
Thanks

@Limos
Sorry for double posts but those missions once for ever i mean i need it to make everyday
 
Last edited by a moderator:
Make sure the storage for the monsters isn't used yet somewhere else and you also have to use that storage in the creaturescript.
 
Make sure the storage for the monsters isn't used yet somewhere else and you also have to use that storage in the creaturescript.
I'm sure from that :S its was working perfectly but it's bugged now when i made changes that you said
 
If you can continue without killing monsters this means you already have the storage from the monsters so you can just change it to something else.
 
If you can continue without killing monsters this means you already have the storage from the monsters so you can just change it to something else.
Sorry but still not working :S i changed the storage to 45690 and i tried again but still same thing :( are you sure that my code on it is correct? cuz i don't know what is the problem now
 
I mean the monster storage in the NPC, so in the local missions table.
You need to change it both in the npc and in the creatirescript if you want to change the storage numbers.
 
Back
Top