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

Quest NPC (give x amount of x item = access)

FenX

Advanced OT User
Joined
Jul 8, 2019
Messages
360
Solutions
1
Reaction score
159
Hello everyone!

Just got a small request, tried the search option but unfortunately didn't manage to find anything that I'm looking for, perhaps I've overlooked something and it is available here on otland already in that case if it is I'd be very grateful for directions to a topic that could help me out!

Anyways, back to the request...

Request:
- Quest NPC that gives a mission in which you have to bring back X amount of X item to the NPC to complete it
- On speaking with the NPC and using the keyword "mission", NPC says e.g. "bring me back X amount of X, are you up for the challenge?", on player response "yes" etc. player is given the mission to complete
- On returning to NPC and using keyword "mission" NPC says e.g. "Did you get what I asked for?", on player response "yes" etc. NPC responds "___" and gives player access to certain area
Edit: Also possible to have multiple items?


From what I know so far and have learnt, I presume that on completion of the mission the NPC will grant the player a storage value which will grant the player access to e.g. a certain teleport, tile etc.

Second part of request:
Now obviously I imagine an actions script is required. So for example, teleport/tile etc with actionid xxxx will check if the player has the storage value from the mission, if they do it will allow them to pass, if not they will not be allowed to pass.


I will go through different quests and their code to see if I could edit anything like this myself but if anybody is up for the challenge and fancies writing a little bit of code for me I'd be greatly thankful for their effort!

Thanks!!

EDIT:

TFS 1.2
 
Last edited:
Solution
S
tfs 1.x
npc/scripts/missions.lua
Lua:
-- 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 = 25376, count = 100},
       {id = 25378, count = 100}
     },
     message = "Great, for your first mission you need to collect some items, I need",
     level = 100000, -- minimum level voor...
Hello everyone!

Just got a small request, tried the search option but unfortunately didn't manage to find anything that I'm looking for, perhaps I've overlooked something and it is available here on otland already in that case if it is I'd be very grateful for directions to a topic that could help me out!

Anyways, back to the request...

Request:
- Quest NPC that gives a mission in which you have to bring back X amount of X item to the NPC to complete it
- On speaking with the NPC and using the keyword "mission", NPC says e.g. "bring me back X amount of X, are you up for the challenge?", on player response "yes" etc. player is given the mission to complete
- On returning to NPC and using keyword "mission" NPC says e.g. "Did you get what I asked for?", on player response "yes" etc. NPC responds "___" and gives player access to certain area
Edit: Also possible to have multiple items?


From what I know so far and have learnt, I presume that on completion of the mission the NPC will grant the player a storage value which will grant the player access to e.g. a certain teleport, tile etc.

Second part of request:
Now obviously I imagine an actions script is required. So for example, teleport/tile etc with actionid xxxx will check if the player has the storage value from the mission, if they do it will allow them to pass, if not they will not be allowed to pass.


I will go through different quests and their code to see if I could edit anything like this myself but if anybody is up for the challenge and fancies writing a little bit of code for me I'd be greatly thankful for their effort!

Thanks!!
What server version?
 
tfs 1.x
npc/scripts/missions.lua
Lua:
-- 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 = 25376, count = 100},
       {id = 25378, count = 100}
     },
     message = "Great, for your first mission you need to collect some items, I need",
     level = 100000, -- minimum level voor this mission
     rewarditems = {
       {id = 22728, count = 2}
     },
     rewardexp = 75500000
   },
   [2] = {
     monsters = {
       {name = "Rats", count = 250, storage = 21900},
       {name = "Rotworms", count = 500, storage = 21901}
     },
     message = "Thanks, for your next mission kill",
     level = 100000,
     rewarditems = {
       {id = 23542, count = 2}
     },
     rewardexp = 95500000
   },
   [3] = {
     items = {
       {id = 25380, count = 100},
       {id = 25376, count = 100},
       {id = 25378, count = 100}
     },
     message = "Awesome, now get",
     level = 100000,
     rewarditems = {
       {id = 21245, count = 2}
     },
     rewardexp = 115500000
   },
}

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())
npc/mission.xml
Code:
<?xml version="1.0" encoding="UTF-8"?>
<npc name="Mission" script="missions.lua" walkinterval="2000" walkradius="0" 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|, I'am giving missions to those who are intrested in crafting for rare items needed to continue crating, take your first {mission} now."/>
     </parameters>
</npc>
creaturescripts/scripts/missions.lua
Code:
local config = {
     ['deathstrike'] = {amount = 1, storage = 21900, startstorage = 45551, startvalue = 2},
     ['rotworm'] = {amount = 500, storage = 21901, startstorage = 45551, startvalue = 2},
     ['dragon lord'] = {amount = 25, storage = 21902, startstorage = 45551, startvalue = 4}
}
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, '[Crafting Task]: '..(stor +1)..' of '..monster.amount..' '..target:getName()..'s killed.')
     end
     if (stor +1) == monster.amount then
         player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, '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
don't forget to register this script in creaturescripts.xml & login.lua
 
Solution
What server version?

TFS 1.2, I apologise for that, forgot to mention it in the post.

tfs 1.x
npc/scripts/missions.lua
Lua:
-- 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 = 25376, count = 100},
       {id = 25378, count = 100}
     },
     message = "Great, for your first mission you need to collect some items, I need",
     level = 100000, -- minimum level voor this mission
     rewarditems = {
       {id = 22728, count = 2}
     },
     rewardexp = 75500000
   },
   [2] = {
     monsters = {
       {name = "Rats", count = 250, storage = 21900},
       {name = "Rotworms", count = 500, storage = 21901}
     },
     message = "Thanks, for your next mission kill",
     level = 100000,
     rewarditems = {
       {id = 23542, count = 2}
     },
     rewardexp = 95500000
   },
   [3] = {
     items = {
       {id = 25380, count = 100},
       {id = 25376, count = 100},
       {id = 25378, count = 100}
     },
     message = "Awesome, now get",
     level = 100000,
     rewarditems = {
       {id = 21245, count = 2}
     },
     rewardexp = 115500000
   },
}

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())
npc/mission.xml
Code:
<?xml version="1.0" encoding="UTF-8"?>
<npc name="Mission" script="missions.lua" walkinterval="2000" walkradius="0" 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|, I'am giving missions to those who are intrested in crafting for rare items needed to continue crating, take your first {mission} now."/>
     </parameters>
</npc>
creaturescripts/scripts/missions.lua
Code:
local config = {
     ['deathstrike'] = {amount = 1, storage = 21900, startstorage = 45551, startvalue = 2},
     ['rotworm'] = {amount = 500, storage = 21901, startstorage = 45551, startvalue = 2},
     ['dragon lord'] = {amount = 25, storage = 21902, startstorage = 45551, startvalue = 4}
}
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, '[Crafting Task]: '..(stor +1)..' of '..monster.amount..' '..target:getName()..'s killed.')
     end
     if (stor +1) == monster.amount then
         player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, '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
don't forget to register this script in creaturescripts.xml & login.lua

Thanks! I'll surely look into this and play around with it <3
 
TFS 1.2, I apologise for that, forgot to mention it in the post.



Thanks! I'll surely look into this and play around with it <3
Don't forget to set this thread as solved so members can check it when they want to apply for the same request
 
Any ideas on how I would set a reward for what Im looking for? So on completion player would receive access to a certain teleport. Other than that, the system itself is good.
 
You can easily check for the storage of the completed quest when the player steps into that teleport. I guess you could do that using a movement script, like this one:
Code:
function onStepIn(creature, item, position, fromPosition)
local storage = yourStorageHere
local tpAid = teleportActionId
local portal_exit = Position(1309, 542, 7)
local player = creature:getPlayer()
   
    if player == nil then
        return false
    end
    if item.actionid == tpAid and player:getStorageValue(storage) == 1 then
       
        position:sendMagicEffect(CONST_ME_MAGIC_BLUE)
        player:teleportTo(portal_exit)
        portal_exit:sendMagicEffect(CONST_ME_TELEPORT)
    elseif player:getStorageValue(33051) == -1 then
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Something prevents you from stepping into the teleport.")
        player:teleportTo(fromPosition)
        fromPosition:sendMagicEffect(CONST_ME_TELEPORT)
    end
    return true
end

And register the movement on movements.xml
Code:
<movevent event="StepIn" itemid="thePortalItemId" script="portal.lua" />
 
Any ideas on how I would set a reward for what Im looking for? So on completion player would receive access to a certain teleport. Other than that, the system itself is good.
would it be a floor with action that the player will not take the storage to pass it unless he do the quest? -- already one made it lol
 
You can easily check for the storage of the completed quest when the player steps into that teleport. I guess you could do that using a movement script, like this one:
Code:
function onStepIn(creature, item, position, fromPosition)
local storage = yourStorageHere
local tpAid = teleportActionId
local portal_exit = Position(1309, 542, 7)
local player = creature:getPlayer()
  
    if player == nil then
        return false
    end
    if item.actionid == tpAid and player:getStorageValue(storage) == 1 then
      
        position:sendMagicEffect(CONST_ME_MAGIC_BLUE)
        player:teleportTo(portal_exit)
        portal_exit:sendMagicEffect(CONST_ME_TELEPORT)
    elseif player:getStorageValue(33051) == -1 then
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Something prevents you from stepping into the teleport.")
        player:teleportTo(fromPosition)
        fromPosition:sendMagicEffect(CONST_ME_TELEPORT)
    end
    return true
end

And register the movement on movements.xml
Code:
<movevent event="StepIn" itemid="thePortalItemId" script="portal.lua" />

Much love for that <3. Thanks you to both again. Easy to edit to tile id?
 
In general you could probably also download any recent rl map datapack and check out the script for Grizzly Adams. Should function similar to what you are looking for and includes lots of examples :)
 
In general you could probably also download any recent rl map datapack and check out the script for Grizzly Adams. Should function similar to what you are looking for and includes lots of examples :)

That's a fair point, thanks for mentioning :eek:
 
tfs 1.x
npc/scripts/missions.lua
Lua:
-- 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 = 25376, count = 100},
       {id = 25378, count = 100}
     },
     message = "Great, for your first mission you need to collect some items, I need",
     level = 100000, -- minimum level voor this mission
     rewarditems = {
       {id = 22728, count = 2}
     },
     rewardexp = 75500000
   },
   [2] = {
     monsters = {
       {name = "Rats", count = 250, storage = 21900},
       {name = "Rotworms", count = 500, storage = 21901}
     },
     message = "Thanks, for your next mission kill",
     level = 100000,
     rewarditems = {
       {id = 23542, count = 2}
     },
     rewardexp = 95500000
   },
   [3] = {
     items = {
       {id = 25380, count = 100},
       {id = 25376, count = 100},
       {id = 25378, count = 100}
     },
     message = "Awesome, now get",
     level = 100000,
     rewarditems = {
       {id = 21245, count = 2}
     },
     rewardexp = 115500000
   },
}

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())
npc/mission.xml
Code:
<?xml version="1.0" encoding="UTF-8"?>
<npc name="Mission" script="missions.lua" walkinterval="2000" walkradius="0" 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|, I'am giving missions to those who are intrested in crafting for rare items needed to continue crating, take your first {mission} now."/>
     </parameters>
</npc>
creaturescripts/scripts/missions.lua
Code:
local config = {
     ['deathstrike'] = {amount = 1, storage = 21900, startstorage = 45551, startvalue = 2},
     ['rotworm'] = {amount = 500, storage = 21901, startstorage = 45551, startvalue = 2},
     ['dragon lord'] = {amount = 25, storage = 21902, startstorage = 45551, startvalue = 4}
}
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, '[Crafting Task]: '..(stor +1)..' of '..monster.amount..' '..target:getName()..'s killed.')
     end
     if (stor +1) == monster.amount then
         player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, '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
don't forget to register this script in creaturescripts.xml & login.lua

Got an issue registering the last script properly. As I understand, this script will send a message on every kill made and once the mission is also finished. I can't get it to work, 100% made a mistake.

This is my xml:
XML:
<event type="kill" name="missions" script="missions.lua"/>

This is my login.lua:
Lua:
local events = {
    'ParasiteWarzone',
    'ElementalSpheresOverlords',
    'BigfootBurdenVersperoth',
    'BigfootBurdenWiggler',
    'SvargrondArenaKill',
    'NewFrontierShardOfCorruption',
    'NewFrontierTirecz',
    'ServiceOfYalaharDiseasedTrio',
    'ServiceOfYalaharAzerus',
    'ServiceOfYalaharQuaraLeaders',
    'InquisitionBosses',
    'InquisitionUngreez',
    'KillingInTheNameOfKills',
    'KillingInTheNameOfKillss',
    'KillingInTheNameOfKillsss',
    'MastersVoiceServants',
    'SecretServiceBlackKnight',
    'ThievesGuildNomad',
    'WotELizardMagistratus',
    'WotELizardNoble',
    'WotEKeeper',
    'WotEBosses',
    'WotEZalamon',
    'WarzoneThree',
    'PlayerDeath',
    'AdvanceSave',
    'bossesWarzone',
    'AdvanceRookgaard',
    'PythiusTheRotten',
    'DropLoot',
    'Yielothax',
    'BossParticipation',
    'Energized Raging Mage',
    'Raging Mage',
    'DeathCounter',
    'KillCounter',
    'bless1',
    'lowerRoshamuul',
    'SpikeTaskQuestCrystal',
    'SpikeTaskQuestDrillworm',
    'petlogin',
    'petthink',
    'UpperSpikeKill',
    'MiddleSpikeKill',
    'LowerSpikeKill',
    'BossesForgotten',
    'ReplicaServants',
    'EnergyPrismDeath',
    'AstralPower',
    'BossesKill',
    'TheShattererKill',
    'BossesHero',
    'DragonsKill',
    'deeplingBosses',
    'imbueDamage',
    'theGreatDragonHuntKill',
    'missions'

Need some help making it work! Other than that like I previously said the system works perfectly.

ALSO!

Lua:
function onStepIn(creature, item, position, fromPosition)
local storage = yourStorageHere
local tpAid = teleportActionId
local portal_exit = Position(1309, 542, 7)
local player = creature:getPlayer()
 
    if player == nil then
        return false
    end
    if item.actionid == tpAid and player:getStorageValue(storage) == 1 then
     
        position:sendMagicEffect(CONST_ME_MAGIC_BLUE)
        player:teleportTo(portal_exit)
        portal_exit:sendMagicEffect(CONST_ME_TELEPORT)
    elseif player:getStorageValue(33051) == -1 then
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Something prevents you from stepping into the teleport.")
        player:teleportTo(fromPosition)
        fromPosition:sendMagicEffect(CONST_ME_TELEPORT)
    end
    return true
end

Could anybody be able to edit this so that it's for a tile? So, when stepping on a tile with actionid xxxx checks for storage etc.

<3

EDIT:

I'm also having difficulty making the teleport script work. I'd appreciate some explanation on how I would edit it to make it work.
 
Last edited:
Bump

Still need support on making this script work:
Lua:
local config = {
     ['deathstrike'] = {amount = 1, storage = 21900, startstorage = 45551, startvalue = 2},
     ['rotworm'] = {amount = 500, storage = 21901, startstorage = 45551, startvalue = 2},
     ['dragon lord'] = {amount = 25, storage = 21902, startstorage = 45551, startvalue = 4}
}
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, '[Crafting Task]: '..(stor +1)..' of '..monster.amount..' '..target:getName()..'s killed.')
     end
     if (stor +1) == monster.amount then
         player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, '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
Registered it in .xml and login.lua as shown above, doesn't display any message in-game, 0 console errors.
 
Last edited:
Bump

First of all I thought that "MESSAGE_STATUS_CONSOLE_ORANGE" is not in const.h source. So I checked it but it is and I also tested the script with other message types and still nothing.

Perhaps it's something to do with client side? I'm using Tibia 12 client so could that maybe be the cause of this issue?

Still need support on it, any help is appreciated!
 
I have a problem with the script where if a player has completed the first Monster Kill Mission, and then proceeds to do the next mission which could be a Collect Item Quest, Completes that aswell and then accepts the third mission which is his Second Monster Kill Mission.

Obviously the monsters count correctly on the first Kill mission as he could complete the second mission which was an Item collecting mission.

But on his Third mission (Second Monster kill) The kills are not counted.

This is my config.

Creaturescript Config
Lua:
local config = {
     ['afflicted charger'] = {amount = 50, storage = 21900, startstorage = 45551, startvalue = 2},
     ['afflicted walker'] = {amount = 50, storage = 21901, startstorage = 45553, startvalue = 2},
     ['master viper'] = {amount = 45, storage = 21904, startstorage = 45554, startvalue = 2},
     ['gorgon'] = {amount = 55, storage = 21905, startstorage = 45557, startvalue = 2},
     ['hydromancer'] = {amount = 60, storage = 21906, startstorage = 45559, startvalue = 2}
}

NPC Script Config
Lua:
local missions = {
   [1] = {
     items = {
       {id = 20128, count = 1}
     },
     message = "Gandalf has lost his staff while exploring the tomb of Manamully, could you help me retrieve it?",
     level = 50, -- minimum level for this mission
     rewarditems = {
       {id = 26143, count = 5}
     },
     rewardexp = 1000000
   },
   [2] = {
     monsters = {
       {name = "afflicted charger", count = 50, storage = 21900},
       {name = "afflicted walker", count = 50, storage = 21901}
     },
     message = "Thanks, for your next mission kill",
     level = 100,
     rewarditems = {
       {id = 26143, count = 5}
     },
     rewardexp = 2000000
   },
   [3] = {
     items = {
       {id = 10502, count = 1}
     },
     message = "So here's the thing... i accidentally threw my wedding ring into the pits of quetzalcoatl, could you go get it for me?",
     level = 125,
     rewarditems = {
       {id = 26143, count = 10}
     },
     rewardexp = 4000000
   },
   [4] = {
     monsters = {
       {name = "master viper", count = 45, storage = 21904},
       {name = "gorgon", count = 55, storage = 21905},
       {name = "hydromancer", count = 60, storage = 21906}
     },
     message = "Thanks, for your next mission kill",
     level = 150,
     rewarditems = {
       {id = 26143, count = 15}
     },
     rewardexp = 8000000
   },
   [5] = {
     items = {
       {id = 10720, count = 1}
     },
     message = "Im sending you on a mission to get an amulet crafted by Mixcoatl. Could you please get me this amulet?",
     level = 175,
     rewarditems = {
       {id = 26143, count = 10}
     },
     rewardexp = 6000000
   },
   [6] = {
     items = {
       {id = 26484, count = 10}
     },
     message = "Your next mission is to get me 10 essence of benitoite. I'll make it pure for you.",
     level = 200,
     rewarditems = {
       {id = 26489, count = 1}
     },
     rewardexp = 8000000
   },
}

local storage = 45551
 
Back
Top