Yamaken
Pro OpenTibia Developer
- Joined
- Jul 27, 2013
- Messages
- 534
- Solutions
- 4
- Reaction score
- 431
If you already worked with Npcs code you may already have the opinion that bulding a npc is a mess. KeywordHandler may be not powerful enough, talkState[cid]/npcHandler.topic[cid] is a ugly and cumbersome manner of handling topics. Another thing is the fact that some config are on the npc xml file and the rest is in the lua file. And we don't forget the code that glue xml and lua file.
So i'm doing a code research looking foward for a better manner of building Npcs. Its important to build global servers and even more important if someone is building a lot of Npcs for their own rpg server.
Basically we have a declarative manner of building the npcs. This small code almost represents the xml file, with keywords, messages(message_greet, message_walkaway, etc), shop/trade list, voices, etc. Its means the NPC is now only one lua file, istead of a lua file + xml file.
I believe using lua tables in a declarative manner is way better than using commands to setup keywords or messages:
Ugly examples:
The npc variable that has been created by NPC function is just npcHandler. Of course, with a little hack in lua we can make npcHandler works like the Npc class in tfs 1.x which means we can just:
Another important thing is how we handle topics. Istead of using talkstate/npcHandler.topic, i did build a module that handles topics(i'm using the declarative style using tables again):
Topics and sub topics, with conditions to answer the topic and actions when the conditions are met. We can have all types of conditions(haveMoney, haveItem, storage, etc) and all types of actions(giveMoney, giveItem, storage, etc).
A complete working example is here:
Beatrice:
http://pastebin.com/GA8PZj4x
(the trade list is just a example, it has been taken from djins)
Chondur:
http://pastebin.com/EZwyM42g
And orts old style implementation(messy):
https://github.com/orts/server/blob/master/data/npc/Chondur.xml
https://github.com/orts/server/blob/master/data/npc/scripts/Chondur.lua
Hope you guys can critize it. Thanks.
Ps: I'm doing this topic not because i'm willing to sell or release this lib, i'm doing that because i think its very important we research about new ways of building things in OTs which give us power, clearness and of course save our time.
So i'm doing a code research looking foward for a better manner of building Npcs. Its important to build global servers and even more important if someone is building a lot of Npcs for their own rpg server.
Basically we have a declarative manner of building the npcs. This small code almost represents the xml file, with keywords, messages(message_greet, message_walkaway, etc), shop/trade list, voices, etc. Its means the NPC is now only one lua file, istead of a lua file + xml file.
Code:
local npc = NPC({
name = "Chondur",
messages = {
greet = "Be greeted, child. What do you want in an old shaman's hut?",
farewell = "Good bye.",
walkway = "Good bye!",
sendTrade = "Well, I currently buy mysterious and enigmatic voodoo skulls and a few other things I might need for my rituals."
},
keywords = {
["rituals"] = "Hm. I don't think you need another one of my counterspells to cross the barrier on Goroma.",
},
voices = {
timeout = 16,
chance = 100,
"Selling general goods and paperware! Come to my shop!"
},
shop = {
{id = 5669, buy = 0, sell = 4000, name= "Mysterious Voodoo Skull"},
{id = 5670, buy = 0, sell = 4000, name= "Enigmatic Voodoo Skull"},
{id = 9969, buy = 0, sell = 4000, name= "black skull"},
{id = 2798, buy = 0, sell = 500, name= "blood herb"},
{id = 9447, buy = 0, sell = 10000, name= "blood goblet"},
}
})
I believe using lua tables in a declarative manner is way better than using commands to setup keywords or messages:
Ugly examples:
Code:
--to setup messages
npcHandler:setMessage(MESSAGE_GREET, 'Hi! What is it, that d\'ye {want}?')
--to give a simple answer, a lot of code
keywordHandler:addKeyword({'ribbit'}, StdModule.say, {npcHandler = npcHandler, text = "Pyrale? That idiot transformed me into an human once. But my wife came and kissed me, so I'm a frog again."})
The npc variable that has been created by NPC function is just npcHandler. Of course, with a little hack in lua we can make npcHandler works like the Npc class in tfs 1.x which means we can just:
Code:
local npc = NPC({declarative data goes here})
npc:setLight()
npc:getName()
npc:getOutfit()
npc:setOutfit()
--and all functions that Npc and Creature class have
--npc handler functions:
npc:addModule()
npc:addFocus()
--etc
Another important thing is how we handle topics. Istead of using talkstate/npcHandler.topic, i did build a module that handles topics(i'm using the declarative style using tables again):
Code:
npc.topicHandler:addTopic({
word = {"footballs", "football"},
answer = "Do you want to buy a football for 111 gold?",
topics = {
{
word = "yes",
answer = "Here it is.",
reset = true,
condition = {
topicCondition.haveMoney(111, "You don't have enough money."),
},
action = {
topicAction.giveItem(2109, 1),
topicAction.removeMoney(111)
},
},
{
word = "no",
answer = "Oh, but it's fun to play!",
reset = true
}
}
})
Topics and sub topics, with conditions to answer the topic and actions when the conditions are met. We can have all types of conditions(haveMoney, haveItem, storage, etc) and all types of actions(giveMoney, giveItem, storage, etc).
A complete working example is here:
Beatrice:
http://pastebin.com/GA8PZj4x
(the trade list is just a example, it has been taken from djins)
Chondur:
http://pastebin.com/EZwyM42g
And orts old style implementation(messy):
https://github.com/orts/server/blob/master/data/npc/Chondur.xml
https://github.com/orts/server/blob/master/data/npc/scripts/Chondur.lua
Hope you guys can critize it. Thanks.
Ps: I'm doing this topic not because i'm willing to sell or release this lib, i'm doing that because i think its very important we research about new ways of building things in OTs which give us power, clearness and of course save our time.