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

Request your Enhanced NPC here!

jeybi

New Member
Joined
Oct 6, 2008
Messages
39
Reaction score
1
Hello otlanders, as some of you know the brand new Enhanced NPC System is now part of the TFS project. Since we would like to make it more popular, I am creating this thread, where you can request me any kind of NPC you would like to see (for fun, academic or comparison porpouses), and I'll answer every request with one or two posible implementations.

Keep in mind that I'll use the latest (private) version of the system, so you might not be able to test the NPC with your Enhanced NPC System copy (temporary)!

Post your ideas or the code of a Jiddo's npc to be translated!

Examples so far:

Prison Guard Npc
The first one would be a prison guard npc. Normally he'd just talk to you about the prison, the people in the prison and just information about the town in general.

BUT! When a world event would be happening, say for example.. a prisoner escaped from his jail.. he would have a completely different set of responses, plus a quest line for finding the escaped prisoner.

AI.DeclarativeTalk (Conversation) implementation:
Lua:
local Guard = AI.SocialNpc:New()

Guard.config = {
	jailbreakStorage = 12345,
	questStorage = 54321
}

Guard.GreetReply = function(talk)	
	if getGlobalStorageValue(Guard.config.jailbreakStorage) == -1 then
		talk:Say("Hello |PLAYERNAME|, I don't have too much time to spent talking as I'm the only guard here")
	else 
		talk:Say("What!? There has been a leak I can't speak for long..")
		-- This is the switch for the normal/leaked speech
		talk:SetVar('prisonBreak', true)
	end
end

Guard.Conversation = {
	-- This response is the same every time
	{['job|occupation'] = "For years I have been the sole guard of this prison"},
	
	-- We handle all quest 'paths' here
	{['quest|mission|help'] = {	
		-- Quest in development/over
		{[HasStorage(Guard.config.questStorage)] = {
			-- Quest over, we don't care if theres a leak or not since the player already completed the quest
			{[Equal(GetStorage(Guard.config.questStorage), 3)] = "I don't have more quests for you, thanks again!"},
			
			-- Quest finished (by another script) but awaiting reward, we don't care if theres a leak or not since the player wants his reward
			{[Equal(GetStorage(Guard.config.questStorage), 2)] = function(talk)
				talk:End("You did it! Take this")
				doPlayerAddMoney(talk.player, 10000)
				-- State 3, "quest completed"
				doPlayerSetStorageValue(talk.player, Guard.config.questStorage, 3)
			end},
			
			-- Quest state must be 1(just started not completed) then
			{[Default] = {
				-- Prisoner event still going, but player wants to cheat us!
				{[HasVar('prisonBreak')] = "You haven't found Sirius! Come back when you have some clues"},
				
				-- Prison event finished and this player didnt completed the quest, we 'reset' it, the next time the prisoner escape, the quest is available again
				{[Default] = 
					"I'm sorry, everything has been a missunderstanding, Sirius never left the prison, thank you anyway",
					RemoveStorage(Guard.config.questStorage)
				}
			}}
		}},
		
		-- No quest in development
		{[Default] = {
			-- Leak, offer quest
			{[HasVar('prisonBreak')] = Ask("As you know Sirius has escaped, if you can find him the Minister will be grateful, Do you want to help us?", 
					-- Yes
					{End("Thank you, if you got any news, don't hesitate to tell me!"), 
					 SetStorage(Guard.config.questStorage, 1)},					
					
					-- No
					End("Ok, then don't waste my time..")
			)},
			
			-- No leak, just be cocky
			{[Default] = "Being a guard is a stressful job, even so, I do not need your help"}
		}}
	}},
		
	-- Lines when someone escaped
	{[HasVar('prisonBreak')] = {
		{['prison'] = "Can't you see what happens? Sirius Black has escaped!"},
		{['sirius'] = "We will need all the resources available to find him.."},
		{['jason|statham'] = "All the prisoners are locked down, don't worry"}
	}},
	
	-- Normal lines
	{['prison'] = "This prison was founded several centuries ago, but no prisoner has ever escaped it, all thanks to my excellent work as a guard"},
	{['sirius'] = "A big mouth, he has never left this prison"},
	{['jason|statham'] = "A tough guy, he was imprisoned for killing the king's son"},
}

Guard:Register()
 
Last edited:
Well, here are a few ideas..

First NPC - Prison Guard NPC (world event only quest line)

The first one would be a prison guard npc. Normally he'd just talk to you about the prison, the people in the prison and just information about the town in general.

BUT! When a world event would be happening, say for example.. a prisoner escaped from his jail.. he would have a completely different set of responses, plus a quest line for finding the escaped prisoner.

I would guess you would just have his response change based off of a global storage value.



Second NPC - Boat NPC

This would be a boat npc. But not just a normal boat npc. He would only let you travel to certain towns if you had a passport/visa (storage value..) for that specific town. Additionally if you had done a quest (for example, a postman-style quest) you would have a discount on the cost of travel.

Third NPC - Shop Keeper NPC

On my server, I made a quest line with the magic shops that when you do a task for all the shops you get a discount on shop items, AND expands the inventory of the shop. I'd like to see an example of this.


Fourth NPC - Embassy NPC (passport quest)

As I mentioned with the boat npc, you'd have to get a passport to access towns. I would like an example of an npc that would give you a quest line to get your passport stamped for that town.

For example, he'd first have you collect 20 pieces of meat, and a golden mug of beer to give to him, second part of the quest he'd have you kill 30 carrion worms, and third part he'd have you deliver a package to another npc and lastly he'd just charge you 1000 gold to get the passport stamped.


Fifth NPC - Engraver

This npc would engrave (set a description) on an item you own. He would tell you to hold the item in your right hand slot, and would ask you what you'd want to engrave on the weapon. The player could have his name engraved on it (ex: "This item is owned by Sportacus") or a custom description of up to 30 characters long. This would also cost money.
 
Last edited:
Bump, prison guard npc done.

As you can see the quest part becomes a bit blury, thats because there's no quest/mission support atm. I'll update the post for an alternative version of the prison guard (using AI.Talk instead of AI.DeclarativeTalk) and the rest of the requested NPCs.

The next implementation will feature better interactions, as the AI.DeclarativeTalk (current example) is just an abreviation of the current NPC if/else code.

I would like to see your own implementations if possible, so we can compare the in and outs of every way of scripting.

P.S: The guard npc wont run with the alpha version (the one posted in the release thread) becasue a) I haven't tested it and b) It uses features from my own latest copy, I'll upload a new library version soon, for those interested in testing the final product.
 
From the looks of it, it seems to be more confusing/difficult than Jiddo's system.
But I guess that's just me, it was a pain in the ass to get used to Jiddo's system when he first released it years back, but I eventually mastered it.
Hopefully I can do the same with this system, you should release a couple basic NPCs such as shop, conversation and quest.
I know you have a couple examples, but they are too confusing to learn from, try something easier to understand.
 
@up
Yea, is not only you, but I'd to agree that it does look strange at a first glance. Thats primarydue 2 factors:
a) Being a 'declarative syntax' embeded in a language that does not support such thing, makes it look like a heavy/neverseen structure
b) The declarative syntax is not meant for NPCs like this one, Im only doing both implementations because I want to show the versatility of the library. Im updating the first post soon with another posible implementation.

The syntax exposed in the first example is meant to replace these things:
Lua:
.. callback...

if msgcontains(msg, 'job') or msgcontains(msg, 'occupation') then
     npcHandler:say('bla bla', cid)

elseif msgcontains(msg, 'prison') then
     npcHandler:say('bla bla 2', cid)
end

..

With:

Lua:
Npc.Conversation = {
    {['job|occupation'] = "bla bla"},
    {['prison'] = "bla bla 2"}
}

As you can see it serves its purpose just fine, you can however, at the cost of readability, add fairly complex nested interactions in this way.

Also another thing is that the system currently only does what the actual system can, but the way is coded allows us to expand it easily and add tons of new features. Alternatively, you can (with some minor changes) copy paste old code:

Lua:
local Npc = AI.SocialNpc:New()

Npc.AddCallback(AI.BasicNpc.Events.OnHear, function(event)
   local cid, msg = event.cid, event.msg

   if(not Npc:IsTalkActive(cid)) then
       return false
   end

   if msgcontains(msg, "job")  or msgcontains(msg, "occupation") then
         Npc:SayTo("bla bla", cid)
   elseif msgcontains(msg, "prison") then
         Npc:SayTo("bla bla2", cid)
   end 
   return true
end)

Npc:Register()

This way you don't use any of the new features for conversations but still got the fancy stuff like (future) waypoint walking, shorter code and other benefits.

Shop and Quest behaviours are not ready yet, but I'll add loads of examples, you can be sure!
 
Okay, it does not seem too bad, just gonna take some getting used to.
 
is it possible for a ncp seller selling a item that requires other items as currency and still be able to be bought through trade window. for example fire sword would cost 50 royal steel and 1 demon dust.
 
Back
Top