Guest User

Untitled

a guest
Jun 2nd, 2020
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.58 KB | None | 0 0
  1. -- Advanced NPC System by Jiddo
  2.  
  3. if KeywordHandler == nil then
  4.  
  5. KeywordNode = {
  6. keywords = nil,
  7. callback = nil,
  8. parameters = nil,
  9. children = nil,
  10. parent = nil,
  11. condition = nil,
  12. action = nil
  13. }
  14.  
  15. -- Created a new keywordnode with the given keywords, callback function and parameters and without any childNodes.
  16. function KeywordNode:new(keys, func, param, condition, action)
  17. local obj = {}
  18. obj.keywords = keys
  19. obj.callback = func
  20. obj.parameters = param
  21. obj.children = {}
  22. obj.condition = condition
  23. obj.action = action
  24. setmetatable(obj, self)
  25. self.__index = self
  26. return obj
  27. end
  28.  
  29. -- Calls the underlying callback function if it is not nil.
  30. function KeywordNode:processMessage(cid, message)
  31. return (not self.callback or self.callback(cid, message, self.keywords, self.parameters, self))
  32. end
  33.  
  34. function KeywordNode:processAction(cid)
  35. if not self.action then
  36. return
  37. end
  38.  
  39. local player = Player(cid)
  40. if not player then
  41. return
  42. end
  43.  
  44. self.action(player, self.parameters.npcHandler)
  45. end
  46.  
  47. -- Returns true if message contains all patterns/strings found in keywords.
  48. -- Returns true if message contains all patterns/strings found in keywords.
  49. function KeywordNode:checkMessage(cid, message)
  50. if self.keywords.callback then
  51. local ret, data = self.keywords.callback(self.keywords, message)
  52. if not ret then
  53. return false
  54. end
  55.  
  56. if self.condition and not self.condition(Player(cid), data) then
  57. return false
  58. end
  59. return true
  60. end
  61.  
  62. local data = {}
  63. local last = 0
  64. for _, keyword in ipairs(self.keywords) do
  65. if type(keyword) == 'string' then
  66. local a, b = string.find(message, keyword)
  67. if a == nil or b == nil or a < last then
  68. return false
  69. end
  70. if keyword:sub(1, 1) == '%' then
  71. data[#data + 1] = tonumber(message:sub(a, b)) or nil
  72. end
  73. last = a
  74. end
  75. end
  76.  
  77. if self.condition and not self.condition(Player(cid), data) then
  78. return false
  79. end
  80. return true
  81. end
  82.  
  83. -- Returns the parent of this node or nil if no such node exists.
  84. function KeywordNode:getParent()
  85. return self.parent
  86. end
  87.  
  88. -- Returns an array of the callback function parameters assosiated with this node.
  89. function KeywordNode:getParameters()
  90. return self.parameters
  91. end
  92.  
  93. -- Returns an array of the triggering keywords assosiated with this node.
  94. function KeywordNode:getKeywords()
  95. return self.keywords
  96. end
  97.  
  98. -- Adds a childNode to this node. Creates the childNode based on the parameters (k = keywords, c = callback, p = parameters)
  99. function KeywordNode:addChildKeyword(keywords, callback, parameters, condition, action)
  100. local new = KeywordNode:new(keywords, callback, parameters, condition, action)
  101. return self:addChildKeywordNode(new)
  102. end
  103.  
  104. function KeywordNode:addAliasKeyword(keywords)
  105. if #self.children == 0 then
  106. print('KeywordNode:addAliasKeyword no previous node found')
  107. return false
  108. end
  109.  
  110. local prevNode = self.children[#self.children]
  111. local new = KeywordNode:new(keywords, prevNode.callback, prevNode.parameters, prevNode.condition, prevNode.action)
  112. for i = 1, #prevNode.children do
  113. new:addChildKeywordNode(prevNode.children[i])
  114. end
  115. return self:addChildKeywordNode(new)
  116. end
  117.  
  118. -- Adds a pre-created childNode to this node. Should be used for example if several nodes should have a common child.
  119. function KeywordNode:addChildKeywordNode(childNode)
  120. self.children[#self.children + 1] = childNode
  121. childNode.parent = self
  122. return childNode
  123. end
  124.  
  125. KeywordHandler = {
  126. root = nil,
  127. lastNode = nil
  128. }
  129.  
  130. -- Creates a new keywordhandler with an empty rootnode.
  131. function KeywordHandler:new()
  132. local obj = {}
  133. obj.root = KeywordNode:new(nil, nil, nil)
  134. obj.lastNode = {}
  135. setmetatable(obj, self)
  136. self.__index = self
  137. return obj
  138. end
  139.  
  140. -- Resets the lastNode field, and this resetting the current position in the node hierarchy to root.
  141. function KeywordHandler:reset(cid)
  142. if self.lastNode[cid] then
  143. self.lastNode[cid] = nil
  144. end
  145. end
  146.  
  147. -- Makes sure the correct childNode of lastNode gets a chance to process the message.
  148. function KeywordHandler:processMessage(cid, message)
  149. local node = self:getLastNode(cid)
  150. if not node then
  151. error('No root node found.')
  152. return false
  153. end
  154.  
  155. local ret = self:processNodeMessage(node, cid, message)
  156. if ret then
  157. return true
  158. end
  159.  
  160. if node:getParent() then
  161. node = node:getParent() -- Search through the parent.
  162. local ret = self:processNodeMessage(node, cid, message)
  163. if ret then
  164. return true
  165. end
  166. end
  167.  
  168. if node ~= self:getRoot() then
  169. node = self:getRoot() -- Search through the root.
  170. local ret = self:processNodeMessage(node, cid, message)
  171. if ret then
  172. return true
  173. end
  174. end
  175. return false
  176. end
  177.  
  178. -- Tries to process the given message using the node parameter's children and calls the node's callback function if found.
  179. -- Returns the childNode which processed the message or nil if no such node was found.
  180. function KeywordHandler:processNodeMessage(node, cid, message)
  181. local messageLower = string.lower(message)
  182. for i, childNode in pairs(node.children) do
  183. if childNode:checkMessage(cid, messageLower) then
  184. local oldLast = self.lastNode[cid]
  185. self.lastNode[cid] = childNode
  186. childNode.parent = node -- Make sure node is the parent of childNode (as one node can be parent to several nodes).
  187. if childNode:processMessage(cid, message) then
  188. childNode:processAction(cid)
  189. return true
  190. end
  191. self.lastNode[cid] = oldLast
  192. end
  193. end
  194. return false
  195. end
  196.  
  197. -- Returns the root keywordnode
  198. function KeywordHandler:getRoot()
  199. return self.root
  200. end
  201.  
  202. -- Returns the last processed keywordnode or root if no last node is found.
  203. function KeywordHandler:getLastNode(cid)
  204. return self.lastNode[cid] or self:getRoot()
  205. end
  206.  
  207. -- Adds a new keyword to the root keywordnode. Returns the new node.
  208. function KeywordHandler:addKeyword(keys, callback, parameters, condition, action)
  209. return self:getRoot():addChildKeyword(keys, callback, parameters, condition, action)
  210. end
  211.  
  212. function KeywordHandler:addAliasKeyword(keys)
  213. return self:getRoot():addAliasKeyword(keys)
  214. end
  215.  
  216. -- Moves the current position in the keyword hierarchy steps upwards. Steps defalut value = 1.
  217. function KeywordHandler:moveUp(cid, steps)
  218. if not steps or type(steps) ~= "number" then
  219. steps = 1
  220. end
  221.  
  222. for i = 1, steps do
  223. if not self.lastNode[cid] then
  224. return nil
  225. end
  226. self.lastNode[cid] = self.lastNode[cid]:getParent() or self:getRoot()
  227. end
  228. return self.lastNode[cid]
  229. end
  230. end
Add Comment
Please, Sign In to add comment