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

RevScripts Item task quest TFS 1.3

Icaraii

Well-Known Member
Joined
Jan 5, 2020
Messages
469
Solutions
1
Reaction score
58
Hello guys, I would like a quest that works similar to tasks of tibia. What I need consists of the player talking to a npc and ask for a task, the npc then ask if the player want to deliver weapons, equipaments or supplies. Depending on player choice, a list will appear (just like tibia task) and the player can get the task to deliver the items.

- If player say weapons, the npc will say "Would you like to deliver swords, axes, clubs, claws, daggers, bows, crossbows, guns or wands?"
-- If player say swords, then a list of items will appear according to level, just like tibia. Example: Player level 1 to 9 will appear 3 knife, 2 wooden sword or 1 combat knife. Player level 10 to 30 will appear 2 sabres or 1 carlin sword.
-- If player say axes, clubs, claws, daggers, bows, crossbows, guns or wands it will follow the example above.

- If player say equipaments, the npc will say "Would you like to deliver helmets, armor, legs, boots, rings, amulets, shields or spellbooks?"
-- If player say helmets, armor, legs, boots, rings, amulets, shields or spellbooks it will follow the example of sword.

- If player say supplies, the npc will say "would you like to deliver backpacks, foods, potions or explosives?"
-- If player say backpacks, foods, potions or explosives it will follow the example of sword.

Players can get only one task at a time, but there is no cooldown between delivering one task and getting another.
Each task will have a different reward, that include exp, money, items, outfits, addons and mounts.

I know it seems a lot, but it does not have much differences from tibia task.
 
Solution
Hello guys, I would like a quest that works similar to tasks of tibia. What I need consists of the player talking to a npc and ask for a task, the npc then ask if the player want to deliver weapons, equipaments or supplies. Depending on player choice, a list will appear (just like tibia task) and the player can get the task to deliver the items.

- If player say weapons, the npc will say "Would you like to deliver swords, axes, clubs, claws, daggers, bows, crossbows, guns or wands?"
-- If player say swords, then a list of items will appear according to level, just like tibia. Example: Player level 1 to 9 will appear 3 knife, 2 wooden sword or 1 combat knife. Player level 10 to 30 will appear 2 sabres or 1 carlin sword.
-- If player...
You can use this NPC as sample to do what you need. It is an item task NPC made for TFS 0.4/0.3.7 that I had in my old server.
I know this is not the request but maybe it helps somehow. Just change the 0.4 functions to 1.3 or paste as it is, because TFS 1.3 should have backward compatibility ;)

Lua:
local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)
local talkState = {}
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 talkUser = NPCHANDLER_CONVBEHAVIOR == CONVERSATION_DEFAULT and 0 or cid
if(msgcontains(msg, 'quest')) then
selfSay('Ok, you can started "first mission"?', cid)
end
---------------------------------------------------------
if(msgcontains(msg, 'first mission')) then
selfSay('Please bring me 10 "meat"', cid)
talkState[talkUser] = 1
elseif(msgcontains(msg, 'meat') and talkState[talkUser] == 1) then
if (getPlayerStorageValue(cid,100) > 0) then
selfSay('You finished this mission.', cid)
else
if(doPlayerRemoveItem(cid, 2666, 10) == TRUE) then
setPlayerStorageValue(cid,100,1)
doPlayerAddExperience(cid,1000)
selfSay('Thank you! You can started "second mission".. (you received 1000 points of experience)', cid)
else
selfSay('You must have more items', cid)
end
end
return true
end
---------------------------------------------------------
if(msgcontains(msg, 'second mission')) then
selfSay('Please bring me 10 "ham"', cid)
talkState[talkUser] = 1
elseif(msgcontains(msg, 'ham') and talkState[talkUser] == 1) then
if (getPlayerStorageValue(cid,101) > 0) then
selfSay('You finished this mission.', cid)
else
if(doPlayerRemoveItem(cid, 2671, 10) == TRUE) then
setPlayerStorageValue(cid,101,1)
doPlayerAddExperience(cid,1000)
selfSay('Thank you! You can started "third mission".. (you received 1000 points of experience)', cid)
else
selfSay('You must have more items', cid)
end
end
return true
end
---------------------------------------------------------
if(msgcontains(msg, 'third mission')) then
selfSay('Please bring me 20 "ultimate health potions"', cid)
talkState[talkUser] = 1
elseif(msgcontains(msg, 'ultimate health potions') and talkState[talkUser] == 1) then
if (getPlayerStorageValue(cid,102) > 0) then
selfSay('You finished this mission.', cid)
else
if(doPlayerRemoveItem(cid, 8473, 20) == TRUE) then
setPlayerStorageValue(cid,102,1)
doPlayerAddExperience(cid,1000)
selfSay('Thank you! You finished all missions. (you received 1000 points of experience)', cid)
else
selfSay('You must have more items', cid)
end
end
return true
end
---------------------------------------------------------
if(msgcontains(msg, 'fourth mission')) then
selfSay('Please bring me 20 "undead hearts"', cid)
talkState[talkUser] = 1
elseif(msgcontains(msg, 'heart') and talkState[talkUser] == 1) then
if (getPlayerStorageValue(cid,103) > 0) then
selfSay('You finished this mission.', cid)
else
if(doPlayerRemoveItem(cid, 11361, 20) == TRUE) then
setPlayerStorageValue(cid,103,1)
doPlayerAddExperience(cid,1000000)
selfSay('Thank you! You finished all missions. (you received 1000000 points of experience)', cid)
else
selfSay('You must have more items', cid)
end
end
return true
end
---------------------------------------------------------
if(msgcontains(msg, 'fifth mission')) then
selfSay('Please bring me 100 "great mana potions"', cid)
talkState[talkUser] = 1
elseif(msgcontains(msg, 'mana potions') and talkState[talkUser] == 1) then
if (getPlayerStorageValue(cid,104) > 0) then
selfSay('You finished this mission.', cid)
else
if(doPlayerRemoveItem(cid, 7590, 100) == TRUE) then
setPlayerStorageValue(cid,104,1)
doPlayerAddExperience(cid,100000)
selfSay('Thank you! You finished all missions. (you received 100000 points of experience)', cid)
else
selfSay('You must have more items', cid)
end
end
return true
end
---------------------------------------------------------
if(msgcontains(msg, 'sixth mission')) then
selfSay('Please bring me 10 "mastermind shields"', cid)
talkState[talkUser] = 1
elseif(msgcontains(msg, 'mastermind shield') and talkState[talkUser] == 1) then
if (getPlayerStorageValue(cid,105) > 0) then
selfSay('You finished this mission.', cid)
else
if(doPlayerRemoveItem(cid, 2519, 10) == TRUE) then
setPlayerStorageValue(cid,105,1)
doPlayerAddExperience(cid,1000000)
selfSay('Thank you! You finished all missions. (you received 1000000 points of experience)', cid)
else
selfSay('You must have more items', cid)
end
end
return true
end

---------------------------------------------------------
if(msgcontains(msg, 'seventh mission')) then
selfSay('Please bring me 100 "crystal coins"', cid)
talkState[talkUser] = 1
elseif(msgcontains(msg, 'crystal coin') and talkState[talkUser] == 1) then
if (getPlayerStorageValue(cid,106) > 0) then
selfSay('You finished this mission.', cid)
else
if(doPlayerRemoveItem(cid, 2160, 100) == TRUE) then
setPlayerStorageValue(cid,106,1)
doPlayerAddExperience(cid,10000000)
selfSay('Thank you! You finished all missions. (you received 5000000 points of experience)', cid)
else
selfSay('You must have more items', cid)
end
end
return true
end---------------------------------------------------------
if(msgcontains(msg, 'eight mission')) then
selfSay('Please bring me 100 "magic plate armors"', cid)
talkState[talkUser] = 1
elseif(msgcontains(msg, 'magic plate armors') and talkState[talkUser] == 1) then
if (getPlayerStorageValue(cid,107) > 0) then
selfSay('You finished this mission.', cid)
else
if(doPlayerRemoveItem(cid, 2472, 100) == TRUE) then
setPlayerStorageValue(cid,107,1)
doPlayerAddExperience(cid,30000000)
selfSay('Thank you! You finished all missions. (you received 30000000 points of experience)', cid)
else
selfSay('You must have more items', cid)
end
end
return true
end
---------------------------------------------------------
if(msgcontains(msg, 'ninth mission')) then
selfSay('Please bring me 100 "fire axes"', cid)
talkState[talkUser] = 1
elseif(msgcontains(msg, 'fire axes') and talkState[talkUser] == 1) then
if (getPlayerStorageValue(cid,108) > 0) then
selfSay('You finished this mission.', cid)
else
if(doPlayerRemoveItem(cid, 2432, 100) == TRUE) then
setPlayerStorageValue(cid,108,1)
doPlayerAddExperience(cid,10000000)
selfSay('Thank you! You finished all missions. (you received 10000000 points of experience)', cid)
else
selfSay('You must have more items', cid)
end
end
return true
end
---------------------------------------------------------
if(msgcontains(msg, 'tenth mission')) then
selfSay('Please bring me 100 "coming soon"', cid)
talkState[talkUser] = 1
elseif(msgcontains(msg, 'coming soon') and talkState[talkUser] == 1) then
if (getPlayerStorageValue(cid,109) > 0) then
selfSay('You finished this mission.', cid)
else
if(doPlayerRemoveItem(cid, 2160, 1000) == TRUE) then
setPlayerStorageValue(cid,109,1)
doPlayerAddExperience(cid,100000)
selfSay('Thank you! You finished all missions. (you received 10000 points of experience)', cid)
else
selfSay('You must have more items', cid)
end
end
return true
end
end
npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())

Regards!
 
You can use this NPC as sample to do what you need. It is an item task NPC made for TFS 0.4/0.3.7 that I had in my old server.
I know this is not the request but maybe it helps somehow. Just change the 0.4 functions to 1.3 or paste as it is, because TFS 1.3 should have backward compatibility ;)

Lua:
local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)
local talkState = {}
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 talkUser = NPCHANDLER_CONVBEHAVIOR == CONVERSATION_DEFAULT and 0 or cid
if(msgcontains(msg, 'quest')) then
selfSay('Ok, you can started "first mission"?', cid)
end
---------------------------------------------------------
if(msgcontains(msg, 'first mission')) then
selfSay('Please bring me 10 "meat"', cid)
talkState[talkUser] = 1
elseif(msgcontains(msg, 'meat') and talkState[talkUser] == 1) then
if (getPlayerStorageValue(cid,100) > 0) then
selfSay('You finished this mission.', cid)
else
if(doPlayerRemoveItem(cid, 2666, 10) == TRUE) then
setPlayerStorageValue(cid,100,1)
doPlayerAddExperience(cid,1000)
selfSay('Thank you! You can started "second mission".. (you received 1000 points of experience)', cid)
else
selfSay('You must have more items', cid)
end
end
return true
end
---------------------------------------------------------
if(msgcontains(msg, 'second mission')) then
selfSay('Please bring me 10 "ham"', cid)
talkState[talkUser] = 1
elseif(msgcontains(msg, 'ham') and talkState[talkUser] == 1) then
if (getPlayerStorageValue(cid,101) > 0) then
selfSay('You finished this mission.', cid)
else
if(doPlayerRemoveItem(cid, 2671, 10) == TRUE) then
setPlayerStorageValue(cid,101,1)
doPlayerAddExperience(cid,1000)
selfSay('Thank you! You can started "third mission".. (you received 1000 points of experience)', cid)
else
selfSay('You must have more items', cid)
end
end
return true
end
---------------------------------------------------------
if(msgcontains(msg, 'third mission')) then
selfSay('Please bring me 20 "ultimate health potions"', cid)
talkState[talkUser] = 1
elseif(msgcontains(msg, 'ultimate health potions') and talkState[talkUser] == 1) then
if (getPlayerStorageValue(cid,102) > 0) then
selfSay('You finished this mission.', cid)
else
if(doPlayerRemoveItem(cid, 8473, 20) == TRUE) then
setPlayerStorageValue(cid,102,1)
doPlayerAddExperience(cid,1000)
selfSay('Thank you! You finished all missions. (you received 1000 points of experience)', cid)
else
selfSay('You must have more items', cid)
end
end
return true
end
---------------------------------------------------------
if(msgcontains(msg, 'fourth mission')) then
selfSay('Please bring me 20 "undead hearts"', cid)
talkState[talkUser] = 1
elseif(msgcontains(msg, 'heart') and talkState[talkUser] == 1) then
if (getPlayerStorageValue(cid,103) > 0) then
selfSay('You finished this mission.', cid)
else
if(doPlayerRemoveItem(cid, 11361, 20) == TRUE) then
setPlayerStorageValue(cid,103,1)
doPlayerAddExperience(cid,1000000)
selfSay('Thank you! You finished all missions. (you received 1000000 points of experience)', cid)
else
selfSay('You must have more items', cid)
end
end
return true
end
---------------------------------------------------------
if(msgcontains(msg, 'fifth mission')) then
selfSay('Please bring me 100 "great mana potions"', cid)
talkState[talkUser] = 1
elseif(msgcontains(msg, 'mana potions') and talkState[talkUser] == 1) then
if (getPlayerStorageValue(cid,104) > 0) then
selfSay('You finished this mission.', cid)
else
if(doPlayerRemoveItem(cid, 7590, 100) == TRUE) then
setPlayerStorageValue(cid,104,1)
doPlayerAddExperience(cid,100000)
selfSay('Thank you! You finished all missions. (you received 100000 points of experience)', cid)
else
selfSay('You must have more items', cid)
end
end
return true
end
---------------------------------------------------------
if(msgcontains(msg, 'sixth mission')) then
selfSay('Please bring me 10 "mastermind shields"', cid)
talkState[talkUser] = 1
elseif(msgcontains(msg, 'mastermind shield') and talkState[talkUser] == 1) then
if (getPlayerStorageValue(cid,105) > 0) then
selfSay('You finished this mission.', cid)
else
if(doPlayerRemoveItem(cid, 2519, 10) == TRUE) then
setPlayerStorageValue(cid,105,1)
doPlayerAddExperience(cid,1000000)
selfSay('Thank you! You finished all missions. (you received 1000000 points of experience)', cid)
else
selfSay('You must have more items', cid)
end
end
return true
end

---------------------------------------------------------
if(msgcontains(msg, 'seventh mission')) then
selfSay('Please bring me 100 "crystal coins"', cid)
talkState[talkUser] = 1
elseif(msgcontains(msg, 'crystal coin') and talkState[talkUser] == 1) then
if (getPlayerStorageValue(cid,106) > 0) then
selfSay('You finished this mission.', cid)
else
if(doPlayerRemoveItem(cid, 2160, 100) == TRUE) then
setPlayerStorageValue(cid,106,1)
doPlayerAddExperience(cid,10000000)
selfSay('Thank you! You finished all missions. (you received 5000000 points of experience)', cid)
else
selfSay('You must have more items', cid)
end
end
return true
end---------------------------------------------------------
if(msgcontains(msg, 'eight mission')) then
selfSay('Please bring me 100 "magic plate armors"', cid)
talkState[talkUser] = 1
elseif(msgcontains(msg, 'magic plate armors') and talkState[talkUser] == 1) then
if (getPlayerStorageValue(cid,107) > 0) then
selfSay('You finished this mission.', cid)
else
if(doPlayerRemoveItem(cid, 2472, 100) == TRUE) then
setPlayerStorageValue(cid,107,1)
doPlayerAddExperience(cid,30000000)
selfSay('Thank you! You finished all missions. (you received 30000000 points of experience)', cid)
else
selfSay('You must have more items', cid)
end
end
return true
end
---------------------------------------------------------
if(msgcontains(msg, 'ninth mission')) then
selfSay('Please bring me 100 "fire axes"', cid)
talkState[talkUser] = 1
elseif(msgcontains(msg, 'fire axes') and talkState[talkUser] == 1) then
if (getPlayerStorageValue(cid,108) > 0) then
selfSay('You finished this mission.', cid)
else
if(doPlayerRemoveItem(cid, 2432, 100) == TRUE) then
setPlayerStorageValue(cid,108,1)
doPlayerAddExperience(cid,10000000)
selfSay('Thank you! You finished all missions. (you received 10000000 points of experience)', cid)
else
selfSay('You must have more items', cid)
end
end
return true
end
---------------------------------------------------------
if(msgcontains(msg, 'tenth mission')) then
selfSay('Please bring me 100 "coming soon"', cid)
talkState[talkUser] = 1
elseif(msgcontains(msg, 'coming soon') and talkState[talkUser] == 1) then
if (getPlayerStorageValue(cid,109) > 0) then
selfSay('You finished this mission.', cid)
else
if(doPlayerRemoveItem(cid, 2160, 1000) == TRUE) then
setPlayerStorageValue(cid,109,1)
doPlayerAddExperience(cid,100000)
selfSay('Thank you! You finished all missions. (you received 10000 points of experience)', cid)
else
selfSay('You must have more items', cid)
end
end
return true
end
end
npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())

Regards!

Thanks man, that will help a lot. I will try to make it run in TFS 1.3
 
Hello guys, I would like a quest that works similar to tasks of tibia. What I need consists of the player talking to a npc and ask for a task, the npc then ask if the player want to deliver weapons, equipaments or supplies. Depending on player choice, a list will appear (just like tibia task) and the player can get the task to deliver the items.

- If player say weapons, the npc will say "Would you like to deliver swords, axes, clubs, claws, daggers, bows, crossbows, guns or wands?"
-- If player say swords, then a list of items will appear according to level, just like tibia. Example: Player level 1 to 9 will appear 3 knife, 2 wooden sword or 1 combat knife. Player level 10 to 30 will appear 2 sabres or 1 carlin sword.
-- If player say axes, clubs, claws, daggers, bows, crossbows, guns or wands it will follow the example above.

- If player say equipaments, the npc will say "Would you like to deliver helmets, armor, legs, boots, rings, amulets, shields or spellbooks?"
-- If player say helmets, armor, legs, boots, rings, amulets, shields or spellbooks it will follow the example of sword.

- If player say supplies, the npc will say "would you like to deliver backpacks, foods, potions or explosives?"
-- If player say backpacks, foods, potions or explosives it will follow the example of sword.

Players can get only one task at a time, but there is no cooldown between delivering one task and getting another.
Each task will have a different reward, that include exp, money, items, outfits, addons and mounts.

I know it seems a lot, but it does not have much differences from tibia task.

I have no idea how real Tibia's stuff works, but based on your explanation, I did what sounded logical.

I've setup the swords area as your example described, and did my best to green-text the rest of the functions, so you can finish the rest of the table on your own.

View attachment bandicam 2021-09-15 18-42-25-531.mp4

Forgot to include it in the video, but yes, he got the mount, outfit, and first addon. (and a quick bugfix for the fish amount. xP)
Untitled.png

my test npc
XML:
<?xml version="1.0" encoding="UTF-8"?>
<npc name="Test" script="test.lua" walkinterval="2000" floorchange="0">
	<health now="100" max="100" />
	<look type="139" head="20" body="39" legs="45" feet="7" addons="0" />
</npc>
it's 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

local randomGreeting = {
	"Welcome back |PLAYERNAME|. Are you looking for a {task}?",
	"How are you today |PLAYERNAME|? Ask me for a {task}.",
	"Are you looking for a {task}, |PLAYERNAME|?"
}
local taskReplies = {}
local taskStorages = {45000, 45001, 45002, 45003} -- {task, choice, playerLevel, decision}
local tasks = {

	--[[
	Ensure that all tasks/choices/decisions are lowercase only. Do not use capitals.
	
	{task = "task 1",
		{choice = "choice 1",
			{levelRange = {1, 9}, -- level 1 to 9
				{decision = "decision 1",
					deliveryDetails = {
						{itemid = 1111, amount = 1}, -- will automatically fetch name of itemid
						{itemid = 2222, amount = 2}
					},
					rewards = {
						experience = 100,
						money = 100, -- automatically converts to gold/plat/crystal
						outfit = {outfitName = "name", looktypeMale = 111, looktypeFemale = 222},
						addon = {outfitName = "name", looktypeMale = 111, looktypeFemale = 222, addon = 1}, -- addon 1 or 2 -> or 3 (both)
						mount = {mountName = "name", mountId = 1},
						items = {
							{itemid = 1111, amount = {1, 1}}, -- amount = {minimum, maximum}
							{itemid = 2222, amount = {2, 2}}
						}
					}
				}
			}
		}
	}
	]]--
	
	-- weapons
	{task = "weapons",
		{choice = "swords",
			{levelRange = {1, 9},
				{decision = "package one",
					deliveryDetails = {
						{itemid = 2403, amount = 3}, -- knife
						{itemid = 2148, amount = 50} -- gold coins
					},
					rewards = {
						experience = 1000000,
						money = 10203, -- automatically converts to gold/plat/crystal
						outfit = {outfitName = "noble", looktypeMale = 132, looktypeFemale = 140},
						addon = {outfitName = "noble", looktypeMale = 132, looktypeFemale = 140, addon = 1}, -- addon 1 or 2 -> or 3 (both)
						mount = {mountName = "widow queen", mountId = 1},
						items = {
							{itemid = 2461, amount = {1, 1}}, -- amount = {minimum, maximum}
							{itemid = 2467, amount = {1, 1}},
							{itemid = 2649, amount = {1, 1}},
							{itemid = 2643, amount = {1, 1}},
							{itemid = 2667, amount = {5, 10}}
						}
					}
				},
				{decision = "package two",
					deliveryDetails = {
						{itemid = 13829, amount = 2}
					},
					rewards = {
						experience = 200 -- you can remove rewards from the list, to make it less cluttered
					}
				},
				{decision = "package three",
					deliveryDetails = {
						{itemid = 2404, amount = 1}
					}, 
					rewards = {} -- if a task has no rewards, just leave it empty like this
				}
			},
			
			{levelRange = {10, 30},
				{decision = "package four",
					deliveryDetails = {
						{itemid = 2385, amount = 2}
					},
					rewards = {
						experience = 100
					}
				},
				{decision = "package five",
					deliveryDetails = {
						{itemid = 2395, amount = 1}
					},
					rewards = {
						experience = 100
					}
				},
			}
		},
		{choice = "axes",
			{levelRange = {1, 9},
				{decision = "decision 1",
					deliveryDetails = {
						{itemid = 1111, amount = 1}
					},
					rewards = {
						experience = 100,
					}
				}
			}
		},
		{choice = "clubs",
			{levelRange = {1, 9},
				{decision = "decision 1",
					deliveryDetails = {
						{itemid = 1111, amount = 1}
					},
					rewards = {
						experience = 100,
					}
				}
			}
		},
		{choice = "claws",
			{levelRange = {1, 9},
				{decision = "decision 1",
					deliveryDetails = {
						{itemid = 1111, amount = 1}
					},
					rewards = {
						experience = 100,
					}
				}
			}
		},
		{choice = "daggers",
			{levelRange = {1, 9},
				{decision = "decision 1",
					deliveryDetails = {
						{itemid = 1111, amount = 1}
					},
					rewards = {
						experience = 100,
					}
				}
			}
		},
		{choice = "bows",
			{levelRange = {1, 9},
				{decision = "decision 1",
					deliveryDetails = {
						{itemid = 1111, amount = 1}
					},
					rewards = {
						experience = 100,
					}
				}
			}
		},
		{choice = "crossbows",
			{levelRange = {1, 9},
				{decision = "decision 1",
					deliveryDetails = {
						{itemid = 1111, amount = 1}
					},
					rewards = {
						experience = 100,
					}
				}
			}
		},
		{choice = "guns",
			{levelRange = {1, 9},
				{decision = "decision 1",
					deliveryDetails = {
						{itemid = 1111, amount = 1}
					},
					rewards = {
						experience = 100,
					}
				}
			}
		},
		{choice = "wands",
			{levelRange = {1, 9},
				{decision = "decision 1",
					deliveryDetails = {
						{itemid = 1111, amount = 1}
					},
					rewards = {
						experience = 100,
					}
				}
			}
		}
	},
	
	-- equipment
	{task = "equipment",
		{choice = "choice 1",
			{levelRange = {1, 9},
				{decision = "decision 1",
					deliveryDetails = {
						{itemid = 1111, amount = 1}
					},
					rewards = {
						experience = 100,
					}
				}
			}
		}
	},
	
	-- supplies
	{task = "supplies",
		{choice = "choice 1",
			{levelRange = {1, 9},
				{decision = "decision 1",
					deliveryDetails = {
						{itemid = 1111, amount = 1}
					},
					rewards = {
						experience = 100,
					}
				}
			}
		}
	}
}

local function indexTask(msg)
	local index = 0
	for i = 1, #tasks do
		if msg == tasks[i].task then
			index = i
			break
		end
	end
	return index
end

local function indexChoice(cid, msg)
	local index = 0
	local task = tasks[taskReplies[cid].taskIndex]
	for i = 1, #task do
		if msg == task[i].choice then
			index = i
			break
		end
	end
	return index
end

local function indexLevel(cid)
	local index = 0
	local task = tasks[taskReplies[cid].taskIndex][taskReplies[cid].choiceIndex]
	local player = Player(cid)
	local level = player:getLevel()
	for i = 1, #task do
		if level >= task[i].levelRange[1] and level <= task[i].levelRange[2] then
			index = i
			break
		end
	end
	return index
end

local function indexDecision(cid, msg)
	local index = 0
	local task = tasks[taskReplies[cid].taskIndex][taskReplies[cid].choiceIndex][taskReplies[cid].levelIndex]
	for i = 1, #task do
		if msg == task[i].decision then
			index = i
			break
		end
	end
	return index
end

local function listTasks()
	local text = ""
	for i = 1, #tasks do
		if text ~= "" then
			if #tasks == i then
				text = text .. " or "
			else
				text = text .. ", "
			end
		end
		text = text .. "{" .. tasks[i].task .. "}"
	end
	return text
end

local function listChoices(cid)
	local text = ""
	local task = tasks[taskReplies[cid].taskIndex]
	for i = 1, #task do
		if text ~= "" then
			if #task == i then
				text = text .. " or "
			else
				text = text .. ", "
			end
		end
		text = text .. "{" .. task[i].choice .. "}"
	end
	return text
end

local function listDecisions(cid)
	local text = ""
	local task = tasks[taskReplies[cid].taskIndex][taskReplies[cid].choiceIndex][taskReplies[cid].levelIndex]
	for i = 1, #task do
		if text ~= "" then
			if #task == i then
				text = text .. " or "
			else
				text = text .. ", "
			end
		end
		text = text .. "{" .. task[i].decision .. "}"
		
		local delivery = task[i].deliveryDetails
		local deliveryText = " ("
		for n = 1, #delivery do
			if deliveryText ~= " (" then
				deliveryText = deliveryText .. ", "
			end
			deliveryText = deliveryText .. delivery[n].amount .. " " .. (delivery[n].amount == 1 and ItemType(delivery[n].itemid):getName() or ItemType(delivery[n].itemid):getPluralName())
		end
		text = text .. deliveryText .. ")"
	end
	return text
end

local function getChosenTaskDeliveryDetails(chosenTask)
	local text = chosenTask.decision	
	local delivery = chosenTask.deliveryDetails
	local deliveryText = " ("
	for i = 1, #delivery do
		if deliveryText ~= " (" then
			deliveryText = deliveryText .. ", "
		end
		deliveryText = deliveryText .. delivery[i].amount .. " " .. (delivery[i].amount == 1 and ItemType(delivery[i].itemid):getName() or ItemType(delivery[i].itemid):getPluralName())
	end
	text = text .. deliveryText .. ")"
	return text
end

local function findMissingDeliveryItems(cid, chosenTask)
	local delivery = chosenTask.deliveryDetails
	local missingItems = ""
	local player = Player(cid)
	for i = 1, #delivery do
		if player:getItemCount(delivery[i].itemid) < delivery[i].amount then
			if missingItems ~= "" then
				missingItems = missingItems .. ", "
			end
			local missingAmount = delivery[i].amount - player:getItemCount(delivery[i].itemid)
			missingItems = missingItems .. missingAmount .. " " .. (missingAmount == 1 and ItemType(delivery[i].itemid):getName() or ItemType(delivery[i].itemid):getPluralName())
		end
	end
	return missingItems
end

local function removeDeliveryItems(cid, chosenTask)
	local delivery = chosenTask.deliveryDetails
	local player = Player(cid)
	for i = 1, #delivery do
		player:removeItem(delivery[i].itemid, delivery[i].amount)
	end
	return
end

local function deliverRewards(cid, chosenTask)	
	local text = ""
	local rewardList = chosenTask.rewards
	local player = Player(cid)
	
	if rewardList.experience then
		if text ~= "" then
			text = text .. ", "
		end
		text = rewardList.experience .. " experience"
		player:addExperience(rewardList.experience)
	end
	
	if rewardList.money then
		if text ~= "" then
			text = text .. ", "
		end
		text = text .. rewardList.money .. " gold coins"
		player:addMoney(rewardList.money)
	end
	
	if rewardList.outfit then
		if text ~= "" then
			text = text .. ", "
		end
		text = text .. rewardList.outfit.outfitName .. " outfit"
		player:addOutfit(rewardList.outfit.looktypeMale)
		player:addOutfit(rewardList.outfit.looktypeFemale)
	end
	
	if rewardList.addon then
		if text ~= "" then
			text = text .. ", "
		end
		text = text .. (rewardList.addon.addon == 1 and "first" or rewardList.addon.addon == 2 and "second" or "first and second") .. " addon for the " .. rewardList.addon.outfitName .. " outfit"
		player:addOutfitAddon(rewardList.addon.looktypeMale, rewardList.addon.addon)
		player:addOutfitAddon(rewardList.addon.looktypeFemale, rewardList.addon.addon)
	end
	
	if rewardList.mount then
		if text ~= "" then
			text = text .. ", "
		end
		text = text .. rewardList.mount.mountName .. " mount"
		player:addMount(rewardList.mount.mountId)
	end
	
	if rewardList.items then
		rewardList = rewardList.items
		local randAmount
		for i = 1, #rewardList do
			randAmount = math.random(rewardList[i].amount[1], rewardList[i].amount[2])
			if randAmount > 0 then
				if text ~= "" then
					text = text .. ", "
				end
				text = text .. randAmount .. " " .. (randAmount == 1 and ItemType(rewardList[i].itemid):getName() or ItemType(rewardList[i].itemid):getPluralName())
				player:addItem(rewardList[i].itemid, randAmount, true)
			end
		end
	end
	
	if text == "" then
		text = "No reward for this task."
	end
	return text
end

local function greetCallback(cid)	
	npcHandler:setMessage(MESSAGE_GREET, randomGreeting[math.random(#randomGreeting)])
	return true
end

local function creatureSayCallback(cid, type, msg)
	if not npcHandler:isFocused(cid) then
		return false
	end
	
	local player = Player(cid)
	msg = msg:lower()
	
	-- if no task started
	if player:getStorageValue(taskStorages[1]) == -1 then
		if msgcontains(msg, "task") then
			npcHandler:say("Would you like to deliver " .. listTasks() .. "?", cid)
			npcHandler.topic[cid] = 1
			return true
		
		elseif npcHandler.topic[cid] == 1 then
			local taskIndex = indexTask(msg)
			if taskIndex == 0 then
				npcHandler:say("That's not on my list of items to deliver. Would you prefer to deliver " .. listTasks() .. "?", cid)
				return true
			end
			
			taskReplies[cid].taskIndex = taskIndex
			npcHandler:say("Would you like to deliver " .. listChoices(cid) .. "?", cid)
			npcHandler.topic[cid] = 2
			return true
		
		elseif npcHandler.topic[cid] == 2 then
			local choiceIndex = indexChoice(cid, msg)
			if choiceIndex == 0 then
				npcHandler:say("That's not on my list of items to deliver. Would you prefer to deliver " .. listChoices(cid) .. "?", cid)
				return true
			end
			taskReplies[cid].choiceIndex = choiceIndex
			
			local levelIndex = indexLevel(cid)
			if levelIndex == 0 then
				npcHandler:say("I don't have any " .. msg .. " that you can deliver at your current level. Try another option.", cid)
				return true
			end
			
			taskReplies[cid].levelIndex = levelIndex
			npcHandler:say("Would you like to deliver " .. listDecisions(cid) .. "?", cid)
			npcHandler.topic[cid] = 3
			return true
			
		elseif npcHandler.topic[cid] == 3 then
			local decisionIndex = indexDecision(cid, msg)
			if decisionIndex == 0 then
				npcHandler:say("That's not on my list of items to deliver. Would you prefer to deliver " .. listDecisions(cid) .. "?", cid)
				return true
			end
			
			taskReplies[cid].decisionIndex = decisionIndex
			npcHandler:say("Alright. Ask me about your {task} when you are ready to deliver.", cid)
			player:setStorageValue(taskStorages[1], taskReplies[cid].taskIndex)
			player:setStorageValue(taskStorages[2], taskReplies[cid].choiceIndex)
			player:setStorageValue(taskStorages[3], taskReplies[cid].levelIndex)
			player:setStorageValue(taskStorages[4], taskReplies[cid].decisionIndex)
			taskReplies[cid] = {}
			npcHandler.topic[cid] = 0
			return true
			
		end
	
	-- if task started
	else
		local task = player:getStorageValue(taskStorages[1])
		local choice = player:getStorageValue(taskStorages[2])
		local level = player:getStorageValue(taskStorages[3])
		local decision = player:getStorageValue(taskStorages[4])
		local chosenTask = tasks[task][choice][level][decision]
		
		if msgcontains(msg, "task") then
			npcHandler:say("Do you want to {deliver} " .. chosenTask.decision .. ", {confirm} the delivery details or {cancel} the delivery task?", cid)
			npcHandler.topic[cid] = 1
			return true
			
		elseif npcHandler.topic[cid] == 1 then
			if msgcontains(msg, "cancel") then
				npcHandler:say("Are you sure you want to cancel your task?", cid)
				npcHandler.topic[cid] = 2
				return true
			end
			if msgcontains(msg, "confirm") then
				npcHandler:say("You need to deliver " .. getChosenTaskDeliveryDetails(chosenTask) .. ".", cid)
				return true
			end
			if msgcontains(msg, "deliver") then
				npcHandler:say("You are you ready to deliver " .. chosenTask.decision .. "?", cid)
				npcHandler.topic[cid] = 3
				return true
			end
			npcHandler:say("Sorry? Do you want to {deliver}, {confirm} or {cancel}?", cid)
			return true
			
		elseif npcHandler.topic[cid] == 2 then
			if not msgcontains(msg, "yes") then
				npcHandler:say("Whew! Thought you were going to quit on me! Let me know when you want to {deliver} your task.", cid)
				npcHandler.topic[cid] = 1
				return true
			end
			
			npcHandler:say("Alright. Your delivery task has been cancelled. You can choose a new {task} when you are ready.", cid)
			player:setStorageValue(taskStorages[1], -1)
			player:setStorageValue(taskStorages[2], -1)
			player:setStorageValue(taskStorages[3], -1)
			player:setStorageValue(taskStorages[4], -1)
			npcHandler.topic[cid] = 0
			
		elseif npcHandler.topic[cid] == 3 then
			if not msgcontains(msg, "yes") then
				npcHandler:say("Another time, then.", cid)
				npcHandler.topic[cid] = 1
				return true
			end
			
			local missingItems = findMissingDeliveryItems(cid, chosenTask)
			if missingItems ~= "" then
				npcHandler:say("You are missing some items for the delivery. (missing: " .. missingItems .. ") Let me know when you want to {deliver} your task.", cid)
				npcHandler.topic[cid] = 1
				return true
			end
			removeDeliveryItems(cid, chosenTask)
			
			local rewardList = deliverRewards(cid, chosenTask)
			npcHandler:say("Thanks for the quick delivery! Here's your compensation.\n(" .. rewardList .. ")\nYou can choose a new {task} when you are ready.", cid)
			
			player:setStorageValue(taskStorages[1], -1)
			player:setStorageValue(taskStorages[2], -1)
			player:setStorageValue(taskStorages[3], -1)
			player:setStorageValue(taskStorages[4], -1)
			npcHandler.topic[cid] = 0
		
		end
	end
	
	
	return true
end

local function onAddFocus(cid)
	npcHandler.topic[cid] = 0
	taskReplies[cid] = {}
end

local function onReleaseFocus(cid)
	npcHandler.topic[cid] = 0
	taskReplies[cid] = {}
end

npcHandler:setCallback(CALLBACK_ONADDFOCUS, onAddFocus)
npcHandler:setCallback(CALLBACK_ONRELEASEFOCUS, onReleaseFocus)


npcHandler:setCallback(CALLBACK_GREET, greetCallback)
npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())
 
Last edited:
Solution
That's awesome, thank you so much. I have a question, I see that after you delivery the first package, it didn't appear for the player to get the same task again. Is it possible to be able to repeat task?
 
That's awesome, thank you so much. I have a question, I see that after you delivery the first package, it didn't appear for the player to get the same task again. Is it possible to be able to repeat task?
He leveled out of the old level range, so got the new level range delivery options.

but tldr, yes you can repeat as many times as you want.

Example: Player level 1 to 9 will appear 3 knife, 2 wooden sword or 1 combat knife.
Player level 10 to 30 will appear 2 sabres or 1 carlin sword.
 
Like always you are making great scripts, thanks man. For some reason I didn't get the outfit, the addon and neither the mount, but that ain't a problem, I will just put the itens for outfit, addon and mount to be dropped as item reward.
 
Like always you are making great scripts, thanks man. For some reason I didn't get the outfit, the addon and neither the mount, but that ain't a problem, I will just put the itens for outfit, addon and mount to be dropped as item reward.
Regular outfit rules still apply.
If it's a premium outfit and you don't have premium you will still receive the outfit/mount/addon but won't be able to wear it.
 
I have no idea how real Tibia's stuff works, but based on your explanation, I did what sounded logical.

I've setup the swords area as your example described, and did my best to green-text the rest of the functions, so you can finish the rest of the table on your own.

View attachment 62115

Forgot to include it in the video, but yes, he got the mount, outfit, and first addon. (and a quick bugfix for the fish amount. xP)
View attachment 62116

my test npc
XML:
<?xml version="1.0" encoding="UTF-8"?>
<npc name="Test" script="test.lua" walkinterval="2000" floorchange="0">
    <health now="100" max="100" />
    <look type="139" head="20" body="39" legs="45" feet="7" addons="0" />
</npc>
it's 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

local randomGreeting = {
    "Welcome back |PLAYERNAME|. Are you looking for a {task}?",
    "How are you today |PLAYERNAME|? Ask me for a {task}.",
    "Are you looking for a {task}, |PLAYERNAME|?"
}
local taskReplies = {}
local taskStorages = {45000, 45001, 45002, 45003} -- {task, choice, playerLevel, decision}
local tasks = {

    --[[
    Ensure that all tasks/choices/decisions are lowercase only. Do not use capitals.
  
    {task = "task 1",
        {choice = "choice 1",
            {levelRange = {1, 9}, -- level 1 to 9
                {decision = "decision 1",
                    deliveryDetails = {
                        {itemid = 1111, amount = 1}, -- will automatically fetch name of itemid
                        {itemid = 2222, amount = 2}
                    },
                    rewards = {
                        experience = 100,
                        money = 100, -- automatically converts to gold/plat/crystal
                        outfit = {outfitName = "name", looktypeMale = 111, looktypeFemale = 222},
                        addon = {outfitName = "name", looktypeMale = 111, looktypeFemale = 222, addon = 1}, -- addon 1 or 2 -> or 3 (both)
                        mount = {mountName = "name", mountId = 1},
                        items = {
                            {itemid = 1111, amount = {1, 1}}, -- amount = {minimum, maximum}
                            {itemid = 2222, amount = {2, 2}}
                        }
                    }
                }
            }
        }
    }
    ]]--
  
    -- weapons
    {task = "weapons",
        {choice = "swords",
            {levelRange = {1, 9},
                {decision = "package one",
                    deliveryDetails = {
                        {itemid = 2403, amount = 3}, -- knife
                        {itemid = 2148, amount = 50} -- gold coins
                    },
                    rewards = {
                        experience = 1000000,
                        money = 10203, -- automatically converts to gold/plat/crystal
                        outfit = {outfitName = "noble", looktypeMale = 132, looktypeFemale = 140},
                        addon = {outfitName = "noble", looktypeMale = 132, looktypeFemale = 140, addon = 1}, -- addon 1 or 2 -> or 3 (both)
                        mount = {mountName = "widow queen", mountId = 1},
                        items = {
                            {itemid = 2461, amount = {1, 1}}, -- amount = {minimum, maximum}
                            {itemid = 2467, amount = {1, 1}},
                            {itemid = 2649, amount = {1, 1}},
                            {itemid = 2643, amount = {1, 1}},
                            {itemid = 2667, amount = {5, 10}}
                        }
                    }
                },
                {decision = "package two",
                    deliveryDetails = {
                        {itemid = 13829, amount = 2}
                    },
                    rewards = {
                        experience = 200 -- you can remove rewards from the list, to make it less cluttered
                    }
                },
                {decision = "package three",
                    deliveryDetails = {
                        {itemid = 2404, amount = 1}
                    },
                    rewards = {} -- if a task has no rewards, just leave it empty like this
                }
            },
          
            {levelRange = {10, 30},
                {decision = "package four",
                    deliveryDetails = {
                        {itemid = 2385, amount = 2}
                    },
                    rewards = {
                        experience = 100
                    }
                },
                {decision = "package five",
                    deliveryDetails = {
                        {itemid = 2395, amount = 1}
                    },
                    rewards = {
                        experience = 100
                    }
                },
            }
        },
        {choice = "axes",
            {levelRange = {1, 9},
                {decision = "decision 1",
                    deliveryDetails = {
                        {itemid = 1111, amount = 1}
                    },
                    rewards = {
                        experience = 100,
                    }
                }
            }
        },
        {choice = "clubs",
            {levelRange = {1, 9},
                {decision = "decision 1",
                    deliveryDetails = {
                        {itemid = 1111, amount = 1}
                    },
                    rewards = {
                        experience = 100,
                    }
                }
            }
        },
        {choice = "claws",
            {levelRange = {1, 9},
                {decision = "decision 1",
                    deliveryDetails = {
                        {itemid = 1111, amount = 1}
                    },
                    rewards = {
                        experience = 100,
                    }
                }
            }
        },
        {choice = "daggers",
            {levelRange = {1, 9},
                {decision = "decision 1",
                    deliveryDetails = {
                        {itemid = 1111, amount = 1}
                    },
                    rewards = {
                        experience = 100,
                    }
                }
            }
        },
        {choice = "bows",
            {levelRange = {1, 9},
                {decision = "decision 1",
                    deliveryDetails = {
                        {itemid = 1111, amount = 1}
                    },
                    rewards = {
                        experience = 100,
                    }
                }
            }
        },
        {choice = "crossbows",
            {levelRange = {1, 9},
                {decision = "decision 1",
                    deliveryDetails = {
                        {itemid = 1111, amount = 1}
                    },
                    rewards = {
                        experience = 100,
                    }
                }
            }
        },
        {choice = "guns",
            {levelRange = {1, 9},
                {decision = "decision 1",
                    deliveryDetails = {
                        {itemid = 1111, amount = 1}
                    },
                    rewards = {
                        experience = 100,
                    }
                }
            }
        },
        {choice = "wands",
            {levelRange = {1, 9},
                {decision = "decision 1",
                    deliveryDetails = {
                        {itemid = 1111, amount = 1}
                    },
                    rewards = {
                        experience = 100,
                    }
                }
            }
        }
    },
  
    -- equipment
    {task = "equipment",
        {choice = "choice 1",
            {levelRange = {1, 9},
                {decision = "decision 1",
                    deliveryDetails = {
                        {itemid = 1111, amount = 1}
                    },
                    rewards = {
                        experience = 100,
                    }
                }
            }
        }
    },
  
    -- supplies
    {task = "supplies",
        {choice = "choice 1",
            {levelRange = {1, 9},
                {decision = "decision 1",
                    deliveryDetails = {
                        {itemid = 1111, amount = 1}
                    },
                    rewards = {
                        experience = 100,
                    }
                }
            }
        }
    }
}

local function indexTask(msg)
    local index = 0
    for i = 1, #tasks do
        if msg == tasks[i].task then
            index = i
            break
        end
    end
    return index
end

local function indexChoice(cid, msg)
    local index = 0
    local task = tasks[taskReplies[cid].taskIndex]
    for i = 1, #task do
        if msg == task[i].choice then
            index = i
            break
        end
    end
    return index
end

local function indexLevel(cid)
    local index = 0
    local task = tasks[taskReplies[cid].taskIndex][taskReplies[cid].choiceIndex]
    local player = Player(cid)
    local level = player:getLevel()
    for i = 1, #task do
        if level >= task[i].levelRange[1] and level <= task[i].levelRange[2] then
            index = i
            break
        end
    end
    return index
end

local function indexDecision(cid, msg)
    local index = 0
    local task = tasks[taskReplies[cid].taskIndex][taskReplies[cid].choiceIndex][taskReplies[cid].levelIndex]
    for i = 1, #task do
        if msg == task[i].decision then
            index = i
            break
        end
    end
    return index
end

local function listTasks()
    local text = ""
    for i = 1, #tasks do
        if text ~= "" then
            if #tasks == i then
                text = text .. " or "
            else
                text = text .. ", "
            end
        end
        text = text .. "{" .. tasks[i].task .. "}"
    end
    return text
end

local function listChoices(cid)
    local text = ""
    local task = tasks[taskReplies[cid].taskIndex]
    for i = 1, #task do
        if text ~= "" then
            if #task == i then
                text = text .. " or "
            else
                text = text .. ", "
            end
        end
        text = text .. "{" .. task[i].choice .. "}"
    end
    return text
end

local function listDecisions(cid)
    local text = ""
    local task = tasks[taskReplies[cid].taskIndex][taskReplies[cid].choiceIndex][taskReplies[cid].levelIndex]
    for i = 1, #task do
        if text ~= "" then
            if #task == i then
                text = text .. " or "
            else
                text = text .. ", "
            end
        end
        text = text .. "{" .. task[i].decision .. "}"
      
        local delivery = task[i].deliveryDetails
        local deliveryText = " ("
        for n = 1, #delivery do
            if deliveryText ~= " (" then
                deliveryText = deliveryText .. ", "
            end
            deliveryText = deliveryText .. delivery[n].amount .. " " .. (delivery[n].amount == 1 and ItemType(delivery[n].itemid):getName() or ItemType(delivery[n].itemid):getPluralName())
        end
        text = text .. deliveryText .. ")"
    end
    return text
end

local function getChosenTaskDeliveryDetails(chosenTask)
    local text = chosenTask.decision  
    local delivery = chosenTask.deliveryDetails
    local deliveryText = " ("
    for i = 1, #delivery do
        if deliveryText ~= " (" then
            deliveryText = deliveryText .. ", "
        end
        deliveryText = deliveryText .. delivery[i].amount .. " " .. (delivery[i].amount == 1 and ItemType(delivery[i].itemid):getName() or ItemType(delivery[i].itemid):getPluralName())
    end
    text = text .. deliveryText .. ")"
    return text
end

local function findMissingDeliveryItems(cid, chosenTask)
    local delivery = chosenTask.deliveryDetails
    local missingItems = ""
    local player = Player(cid)
    for i = 1, #delivery do
        if player:getItemCount(delivery[i].itemid) < delivery[i].amount then
            if missingItems ~= "" then
                missingItems = missingItems .. ", "
            end
            local missingAmount = delivery[i].amount - player:getItemCount(delivery[i].itemid)
            missingItems = missingItems .. missingAmount .. " " .. (missingAmount == 1 and ItemType(delivery[i].itemid):getName() or ItemType(delivery[i].itemid):getPluralName())
        end
    end
    return missingItems
end

local function removeDeliveryItems(cid, chosenTask)
    local delivery = chosenTask.deliveryDetails
    local player = Player(cid)
    for i = 1, #delivery do
        player:removeItem(delivery[i].itemid, delivery[i].amount)
    end
    return
end

local function deliverRewards(cid, chosenTask)  
    local text = ""
    local rewardList = chosenTask.rewards
    local player = Player(cid)
  
    if rewardList.experience then
        if text ~= "" then
            text = text .. ", "
        end
        text = rewardList.experience .. " experience"
        player:addExperience(rewardList.experience)
    end
  
    if rewardList.money then
        if text ~= "" then
            text = text .. ", "
        end
        text = text .. rewardList.money .. " gold coins"
        player:addMoney(rewardList.money)
    end
  
    if rewardList.outfit then
        if text ~= "" then
            text = text .. ", "
        end
        text = text .. rewardList.outfit.outfitName .. " outfit"
        player:addOutfit(rewardList.outfit.looktypeMale)
        player:addOutfit(rewardList.outfit.looktypeFemale)
    end
  
    if rewardList.addon then
        if text ~= "" then
            text = text .. ", "
        end
        text = text .. (rewardList.addon.addon == 1 and "first" or rewardList.addon.addon == 2 and "second" or "first and second") .. " addon for the " .. rewardList.addon.outfitName .. " outfit"
        player:addOutfitAddon(rewardList.addon.looktypeMale, rewardList.addon.addon)
        player:addOutfitAddon(rewardList.addon.looktypeFemale, rewardList.addon.addon)
    end
  
    if rewardList.mount then
        if text ~= "" then
            text = text .. ", "
        end
        text = text .. rewardList.mount.mountName .. " mount"
        player:addMount(rewardList.mount.mountId)
    end
  
    if rewardList.items then
        rewardList = rewardList.items
        local randAmount
        for i = 1, #rewardList do
            randAmount = math.random(rewardList[i].amount[1], rewardList[i].amount[2])
            if randAmount > 0 then
                if text ~= "" then
                    text = text .. ", "
                end
                text = text .. randAmount .. " " .. (randAmount == 1 and ItemType(rewardList[i].itemid):getName() or ItemType(rewardList[i].itemid):getPluralName())
                player:addItem(rewardList[i].itemid, randAmount, true)
            end
        end
    end
  
    if text == "" then
        text = "No reward for this task."
    end
    return text
end

local function greetCallback(cid)  
    npcHandler:setMessage(MESSAGE_GREET, randomGreeting[math.random(#randomGreeting)])
    return true
end

local function creatureSayCallback(cid, type, msg)
    if not npcHandler:isFocused(cid) then
        return false
    end
  
    local player = Player(cid)
    msg = msg:lower()
  
    -- if no task started
    if player:getStorageValue(taskStorages[1]) == -1 then
        if msgcontains(msg, "task") then
            npcHandler:say("Would you like to deliver " .. listTasks() .. "?", cid)
            npcHandler.topic[cid] = 1
            return true
      
        elseif npcHandler.topic[cid] == 1 then
            local taskIndex = indexTask(msg)
            if taskIndex == 0 then
                npcHandler:say("That's not on my list of items to deliver. Would you prefer to deliver " .. listTasks() .. "?", cid)
                return true
            end
          
            taskReplies[cid].taskIndex = taskIndex
            npcHandler:say("Would you like to deliver " .. listChoices(cid) .. "?", cid)
            npcHandler.topic[cid] = 2
            return true
      
        elseif npcHandler.topic[cid] == 2 then
            local choiceIndex = indexChoice(cid, msg)
            if choiceIndex == 0 then
                npcHandler:say("That's not on my list of items to deliver. Would you prefer to deliver " .. listChoices(cid) .. "?", cid)
                return true
            end
            taskReplies[cid].choiceIndex = choiceIndex
          
            local levelIndex = indexLevel(cid)
            if levelIndex == 0 then
                npcHandler:say("I don't have any " .. msg .. " that you can deliver at your current level. Try another option.", cid)
                return true
            end
          
            taskReplies[cid].levelIndex = levelIndex
            npcHandler:say("Would you like to deliver " .. listDecisions(cid) .. "?", cid)
            npcHandler.topic[cid] = 3
            return true
          
        elseif npcHandler.topic[cid] == 3 then
            local decisionIndex = indexDecision(cid, msg)
            if decisionIndex == 0 then
                npcHandler:say("That's not on my list of items to deliver. Would you prefer to deliver " .. listDecisions(cid) .. "?", cid)
                return true
            end
          
            taskReplies[cid].decisionIndex = decisionIndex
            npcHandler:say("Alright. Ask me about your {task} when you are ready to deliver.", cid)
            player:setStorageValue(taskStorages[1], taskReplies[cid].taskIndex)
            player:setStorageValue(taskStorages[2], taskReplies[cid].choiceIndex)
            player:setStorageValue(taskStorages[3], taskReplies[cid].levelIndex)
            player:setStorageValue(taskStorages[4], taskReplies[cid].decisionIndex)
            taskReplies[cid] = {}
            npcHandler.topic[cid] = 0
            return true
          
        end
  
    -- if task started
    else
        local task = player:getStorageValue(taskStorages[1])
        local choice = player:getStorageValue(taskStorages[2])
        local level = player:getStorageValue(taskStorages[3])
        local decision = player:getStorageValue(taskStorages[4])
        local chosenTask = tasks[task][choice][level][decision]
      
        if msgcontains(msg, "task") then
            npcHandler:say("Do you want to {deliver} " .. chosenTask.decision .. ", {confirm} the delivery details or {cancel} the delivery task?", cid)
            npcHandler.topic[cid] = 1
            return true
          
        elseif npcHandler.topic[cid] == 1 then
            if msgcontains(msg, "cancel") then
                npcHandler:say("Are you sure you want to cancel your task?", cid)
                npcHandler.topic[cid] = 2
                return true
            end
            if msgcontains(msg, "confirm") then
                npcHandler:say("You need to deliver " .. getChosenTaskDeliveryDetails(chosenTask) .. ".", cid)
                return true
            end
            if msgcontains(msg, "deliver") then
                npcHandler:say("You are you ready to deliver " .. chosenTask.decision .. "?", cid)
                npcHandler.topic[cid] = 3
                return true
            end
            npcHandler:say("Sorry? Do you want to {deliver}, {confirm} or {cancel}?", cid)
            return true
          
        elseif npcHandler.topic[cid] == 2 then
            if not msgcontains(msg, "yes") then
                npcHandler:say("Whew! Thought you were going to quit on me! Let me know when you want to {deliver} your task.", cid)
                npcHandler.topic[cid] = 1
                return true
            end
          
            npcHandler:say("Alright. Your delivery task has been cancelled. You can choose a new {task} when you are ready.", cid)
            player:setStorageValue(taskStorages[1], -1)
            player:setStorageValue(taskStorages[2], -1)
            player:setStorageValue(taskStorages[3], -1)
            player:setStorageValue(taskStorages[4], -1)
            npcHandler.topic[cid] = 0
          
        elseif npcHandler.topic[cid] == 3 then
            if not msgcontains(msg, "yes") then
                npcHandler:say("Another time, then.", cid)
                npcHandler.topic[cid] = 1
                return true
            end
          
            local missingItems = findMissingDeliveryItems(cid, chosenTask)
            if missingItems ~= "" then
                npcHandler:say("You are missing some items for the delivery. (missing: " .. missingItems .. ") Let me know when you want to {deliver} your task.", cid)
                npcHandler.topic[cid] = 1
                return true
            end
            removeDeliveryItems(cid, chosenTask)
          
            local rewardList = deliverRewards(cid, chosenTask)
            npcHandler:say("Thanks for the quick delivery! Here's your compensation.\n(" .. rewardList .. ")\nYou can choose a new {task} when you are ready.", cid)
          
            player:setStorageValue(taskStorages[1], -1)
            player:setStorageValue(taskStorages[2], -1)
            player:setStorageValue(taskStorages[3], -1)
            player:setStorageValue(taskStorages[4], -1)
            npcHandler.topic[cid] = 0
      
        end
    end
  
  
    return true
end

local function onAddFocus(cid)
    npcHandler.topic[cid] = 0
    taskReplies[cid] = {}
end

local function onReleaseFocus(cid)
    npcHandler.topic[cid] = 0
    taskReplies[cid] = {}
end

npcHandler:setCallback(CALLBACK_ONADDFOCUS, onAddFocus)
npcHandler:setCallback(CALLBACK_ONRELEASEFOCUS, onReleaseFocus)


npcHandler:setCallback(CALLBACK_GREET, greetCallback)
npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())
Hi mr sorry for bumping thread again but this comes out in console while saying task to the npc using tfs 1.4.1
Code:
Lua Script Error: [Npc interface]
data/npc/scripts/legion.lua:onCreatureSay
data/npc/scripts/legion.lua:526: attempt to index a nil value
stack traceback:
        [C]: in function '__index'
        data/npc/scripts/legion.lua:526: in function 'callback'
        data/npc/lib/npcsystem/npchandler.lua:411: in function 'onCreatureSay'
        data/npc/scripts/legion.lua:7: in function <data/npc/scripts/legion.lua:7>
 
Hi mr sorry for bumping thread again but this comes out in console while saying task to the npc using tfs 1.4.1
Code:
Lua Script Error: [Npc interface]
data/npc/scripts/legion.lua:onCreatureSay
data/npc/scripts/legion.lua:526: attempt to index a nil value
stack traceback:
        [C]: in function '__index'
        data/npc/scripts/legion.lua:526: in function 'callback'
        data/npc/lib/npcsystem/npchandler.lua:411: in function 'onCreatureSay'
        data/npc/scripts/legion.lua:7: in function <data/npc/scripts/legion.lua:7>
Only way this should be possible is if the storages on line 16 are being used elsewhere in your server.

Change them to storages you aren't using, and try again.
 
Back
Top