Advertisement
Guest User

keywordhandler.lua

a guest
Jun 20th, 2017
114
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.62 KB | None | 0 0
  1. -- This file is part of Jiddo's advanced NpcSystem v3.0x. This npcsystem is free to use by anyone, for any purpuse.
  2. -- Initial release date: 2007-02-21
  3. -- Credits: Jiddo, honux(I'm using a modified version of his Find function).
  4. -- Please include full credits whereever you use this system, or parts of it.
  5. -- For support, questions and updates, please consult the following thread:
  6. -- http://opentibia.net/topic/59592-release-advanced-npc-system-v30a/
  7.  
  8. if(KeywordHandler == nil) then
  9.  
  10. BEHAVIOR_SIMPLE = 1 -- Does not support nested keywords. If you choose this setting you must use a variable such as 'talkState' to keep track of how to handle keywords.
  11. BEHAVIOR_NORMAL = 2 -- Default behvaior. If a sub-keyword is not found, then the root is searched, not the parent hierarchy,
  12. BEHAVIOR_NORMAL_EXTENDED = 3 -- Same as BEHAVIOR_NORMAL but it also searches through the last node's parent.
  13. BEHAVIOR_COMPLEX = 4 -- Extended behavior. It a sub-keyword is not found, then the entire keyword hierarchy is searched upwards intil root is reached.
  14.  
  15.  
  16. -- BEHAVIOR_NORMAL_EXTENDED is recommended as it (probably) mimics the behavior of real Tibia's NPCs the most.
  17. -- However, you are strongly recommended to test some (or all) other settings as well as it might suit you better.
  18. -- Also note that not much difference can be seen with the different settings unless you have a npc with a quite heavy
  19. -- nestled keyword hierarchy.
  20. -- Note: BEHAVIOR_SIMPLE should not be used unless you have any special reason to do so as it forces you to keep track of talkStates etc.
  21. -- This was pretty much the method used in the 2.0x versions of this system. It is here mainly for compability issues.
  22. KEYWORD_BEHAVIOR = BEHAVIOR_NORMAL_EXTENDED
  23.  
  24.  
  25. KeywordNode = {
  26. keywords = nil,
  27. callback = nil,
  28. parameters = nil,
  29. children = nil,
  30. parent = nil
  31. }
  32.  
  33. -- Created a new keywordnode with the given keywords, callback function and parameters and without any childNodes.
  34. function KeywordNode:new(keys, func, param)
  35. local obj = {}
  36. obj.keywords = keys
  37. obj.callback = func
  38. obj.parameters = param
  39. obj.children = {}
  40. setmetatable(obj, self)
  41. self.__index = self
  42. return obj
  43. end
  44.  
  45. -- Calls the underlying callback function if it is not nil.
  46. function KeywordNode:processMessage(cid, message)
  47. return (self.callback == nil or self.callback(cid, message, self.keywords, self.parameters, self))
  48. end
  49.  
  50. -- Returns true if message contains all patterns/strings found in keywords.
  51. function KeywordNode:checkMessage(message)
  52. local ret = true
  53. if(self.keywords.callback ~= nil) then
  54. return self.keywords.callback(self.keywords, message)
  55. end
  56. for i,v in ipairs(self.keywords) do
  57. if(type(v) == 'string') then
  58. local a, b = string.find(message, v)
  59. if(a == nil or b == nil) then
  60. ret = false
  61. break
  62. end
  63. end
  64. end
  65. return ret
  66. end
  67.  
  68. -- Returns the parent of this node or nil if no such node exists.
  69. function KeywordNode:getParent()
  70. return self.parent
  71. end
  72.  
  73. -- Returns an array of the callback function parameters assosiated with this node.
  74. function KeywordNode:getParameters()
  75. return self.parameters
  76. end
  77.  
  78. -- Returns an array of the triggering keywords assosiated with this node.
  79. function KeywordNode:getKeywords()
  80. return self.keywords
  81. end
  82.  
  83. -- Adds a childNode to this node. Creates the childNode based on the parameters (k = keywords, c = callback, p = parameters)
  84. function KeywordNode:addChildKeyword(keywords, callback, parameters)
  85. local new = KeywordNode:new(keywords, callback, parameters)
  86. return self:addChildKeywordNode(new)
  87. end
  88.  
  89. -- Adds a pre-created childNode to this node. Should be used for example if several nodes should have a common child.
  90. function KeywordNode:addChildKeywordNode(childNode)
  91. table.insert(self.children, childNode)
  92. childNode.parent = self
  93. return childNode
  94. end
  95.  
  96.  
  97.  
  98.  
  99. KeywordHandler = {
  100. root = nil,
  101. lastNode = nil
  102. }
  103.  
  104. -- Creates a new keywordhandler with an empty rootnode.
  105. function KeywordHandler:new()
  106. local obj = {}
  107. obj.root = KeywordNode:new(nil, nil, nil)
  108. setmetatable(obj, self)
  109. self.__index = self
  110. return obj
  111. end
  112.  
  113. -- Resets the lastNode field, and this resetting the current position in the node hierarchy to root.
  114. function KeywordHandler:reset()
  115. self.lastNode = nil
  116. end
  117.  
  118.  
  119. -- Makes sure the correct childNode of lastNode gets a chance to process the message.
  120. -- The behavior of this function depends much on the KEYWORD_BEHAVIOR.
  121. function KeywordHandler:processMessage(cid, message)
  122. local node = self:getLastNode()
  123. if(node == nil) then
  124. error('No root node found.')
  125. return false
  126. end
  127. if(KEYWORD_BEHAVIOR == BEHAVIOR_SIMPLE) then
  128. local ret = self:processNodeMessage(node, cid, message)
  129. if(ret) then
  130. return true
  131. end
  132. elseif(KEYWORD_BEHAVIOR == BEHAVIOR_NORMAL or KEYWORD_BEHAVIOR == BEHAVIOR_NORMAL_EXTENDED) then
  133. local ret = self:processNodeMessage(node, cid, message)
  134. if(ret) then
  135. return true
  136. end
  137. if(KEYWORD_BEHAVIOR == BEHAVIOR_NORMAL_EXTENDED and node:getParent()) then
  138. node = node:getParent() -- Search through the parent.
  139. local ret = self:processNodeMessage(node, cid, message)
  140. if(ret) then
  141. return true
  142. end
  143. end
  144. if(node ~= self:getRoot()) then
  145. node = self:getRoot() -- Search through the root.
  146. local ret = self:processNodeMessage(node, cid, message)
  147. if(ret) then
  148. return true
  149. end
  150. end
  151. elseif(KEYWORD_BEHAVIOR == BEHAVIOR_COMPLEX) then
  152. while true do
  153.  
  154. local ret = self:processNodeMessage(node, cid, message)
  155. if(ret) then
  156. return true
  157. end
  158.  
  159. if(node:getParent() ~= nil) then
  160. node = node:getParent() -- Move one step upwards in the hierarchy.
  161. else
  162. break
  163. end
  164. end
  165. else
  166. error('Unknown keyword behavior.')
  167. end
  168. return false
  169. end
  170.  
  171. -- Tries to process the given message using the node parameter's children and calls the node's callback function if found.
  172. -- Returns the childNode which processed the message or nil if no such node was found.
  173. function KeywordHandler:processNodeMessage(node, cid, message)
  174. local messageLower = string.lower(message)
  175. for i, childNode in pairs(node.children) do
  176. if(childNode:checkMessage(messageLower)) then
  177. local oldLast = self.lastNode
  178. self.lastNode = childNode
  179. childNode.parent = node -- Make sure node is the parent of childNode (as one node can be parent to several nodes).
  180. if(childNode:processMessage(cid, message)) then
  181. return true
  182. else
  183. self.lastNode = oldLast
  184. end
  185. end
  186. end
  187. return false
  188. end
  189.  
  190. -- Returns the root keywordnode
  191. function KeywordHandler:getRoot()
  192. return self.root
  193. end
  194.  
  195. -- Returns the last processed keywordnode or root if no last node is found.
  196. function KeywordHandler:getLastNode()
  197. if(KEYWORD_BEHAVIOR == BEHAVIOR_SIMPLE) then
  198. return self:getRoot()
  199. else
  200. return self.lastNode or self:getRoot()
  201. end
  202. end
  203.  
  204. -- Adds a new keyword to the root keywordnode. Returns the new node.
  205. function KeywordHandler:addKeyword(keys, callback, parameters)
  206. return self:getRoot():addChildKeyword(keys, callback, parameters)
  207. end
  208.  
  209. -- Moves the current position in the keyword hierarchy count steps upwards. Count defalut value = 1.
  210. -- This function MIGHT not work properly yet. Use at your own risk.
  211. function KeywordHandler:moveUp(count)
  212. local steps = count
  213. if(steps == nil) then
  214. steps = 1
  215. end
  216. for i=1,steps,1 do
  217. if(self.lastNode == nil) then
  218. break
  219. else
  220. self.lastNode = self.lastNode:getParent() or self:getRoot()
  221. end
  222. end
  223. return self.lastNode
  224. end
  225.  
  226.  
  227. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement