waypoints.lua

main 755 lines · 25.1 KB Raw
Alex Alex Commit Client Upload Part 2 19/10/2026 00:06
1local context = G.botContext
2local Panels = context.Panels
3
4Panels.Waypoints = function(parent)
5 local ui = context.setupUI([[
6Panel
7 id: waypoints
8 height: 206
9
10 BotLabel
11 anchors.top: parent.top
12 anchors.left: parent.left
13 anchors.right: parent.right
14 text: Waypoints
15
16 ComboBox
17 id: config
18 anchors.top: prev.bottom
19 anchors.left: parent.left
20 margin-top: 5
21 text-offset: 3 0
22 width: 130
23
24 Button
25 id: enableButton
26 anchors.top: prev.top
27 anchors.left: prev.right
28 anchors.right: parent.right
29 margin-left: 5
30
31 Button
32 margin-top: 1
33 id: add
34 anchors.top: prev.bottom
35 anchors.left: parent.left
36 text: Add
37 width: 60
38 height: 17
39
40 Button
41 id: edit
42 anchors.top: prev.top
43 anchors.horizontalCenter: parent.horizontalCenter
44 text: Edit
45 width: 60
46 height: 17
47
48 Button
49 id: remove
50 anchors.top: prev.top
51 anchors.right: parent.right
52 text: Remove
53 width: 60
54 height: 17
55
56 TextList
57 id: list
58 anchors.top: prev.bottom
59 anchors.left: parent.left
60 anchors.right: parent.right
61 vertical-scrollbar: listScrollbar
62 margin-right: 15
63 margin-top: 2
64 height: 60
65 focusable: false
66 auto-focus: first
67
68 VerticalScrollBar
69 id: listScrollbar
70 anchors.top: prev.top
71 anchors.bottom: prev.bottom
72 anchors.right: parent.right
73 pixels-scroll: true
74 step: 5
75
76 Label
77 id: pos
78 anchors.top: prev.bottom
79 anchors.left: parent.left
80 anchors.right: parent.right
81 text-align: center
82 margin-top: 2
83
84 Button
85 id: wGoto
86 anchors.top: prev.bottom
87 anchors.left: parent.left
88 text: Goto
89 width: 61
90 margin-top: 1
91 height: 17
92
93 Button
94 id: wUse
95 anchors.top: prev.top
96 anchors.left: prev.right
97 text: Use
98 width: 61
99 height: 17
100
101 Button
102 id: wUseWith
103 anchors.top: prev.top
104 anchors.left: prev.right
105 text: UseWith
106 width: 61
107 height: 17
108
109 Button
110 id: wWait
111 anchors.top: prev.bottom
112 anchors.left: parent.left
113 text: Wait
114 width: 61
115 margin-top: 1
116 height: 17
117
118 Button
119 id: wSay
120 anchors.top: prev.top
121 anchors.left: prev.right
122 text: Say
123 width: 61
124 height: 17
125
126 Button
127 id: wNpc
128 anchors.top: prev.top
129 anchors.left: prev.right
130 text: Say NPC
131 width: 61
132 height: 17
133
134 Button
135 id: wLabel
136 anchors.top: prev.bottom
137 anchors.left: parent.left
138 text: Label
139 width: 61
140 margin-top: 1
141 height: 17
142
143 Button
144 id: wFollow
145 anchors.top: prev.top
146 anchors.left: prev.right
147 text: Follow
148 width: 61
149 height: 17
150
151 Button
152 id: wFunction
153 anchors.top: prev.top
154 anchors.left: prev.right
155 text: Function
156 width: 61
157 height: 17
158
159 BotSwitch
160 id: recording
161 anchors.top: prev.bottom
162 anchors.left: parent.left
163 anchors.right: parent.right
164 text: Auto Recording
165 height: 17
166
167]], parent)
168
169 if type(context.storage.cavebot) ~= "table" then
170 context.storage.cavebot = {}
171 end
172 if type(context.storage.cavebot.configs) ~= "table" then
173 context.storage.cavebot.configs = {}
174 end
175
176 local getConfigName = function(config)
177 local matches = regexMatch(config, [[name:\s*([^\n]*)$]])
178 if matches[1] and matches[1][2] then
179 return matches[1][2]:trim()
180 end
181 return nil
182 end
183
184 local isValidCommand = function(command)
185 if command == "goto" then
186 return true
187 elseif command == "use" then
188 return true
189 elseif command == "usewith" then
190 return true
191 elseif command == "wait" then
192 return true
193 elseif command == "say" then
194 return true
195 elseif command == "npc" then
196 return true
197 elseif command == "follow" then
198 return true
199 elseif command == "label" then
200 return true
201 elseif command == "gotolabel" then
202 return true
203 elseif command == "comment" then
204 return true
205 elseif command == "function" then
206 return true
207 end
208 return false
209 end
210
211 local commands = {}
212 local waitTo = 0
213 local autoRecording = false
214
215 local parseConfig = function(config)
216 commands = {}
217 local matches = regexMatch(config, [[([^:^\n^\s]+)(:?)([^\n]*)]])
218 for i=1,#matches do
219 local command = matches[i][2]
220 local validation = (matches[i][3] == ":")
221 if not validation or isValidCommand(command) then
222 local text = matches[i][4]
223 if validation then
224 table.insert(commands, {command=command:lower(), text=text})
225 elseif #commands > 0 then
226 commands[#commands].text = commands[#commands].text .. "\n" .. matches[i][1]
227 end
228 end
229 end
230
231 for i=1,#commands do
232 local label = g_ui.createWidget("CaveBotLabel", ui.list)
233 label:setText(commands[i].command .. ":" .. commands[i].text)
234 if commands[i].command == "goto" then
235 label:setColor("green")
236 elseif commands[i].command == "label" then
237 label:setColor("yellow")
238 elseif commands[i].command == "comment" then
239 label:setText(commands[i].text)
240 label:setColor("white")
241 elseif commands[i].command == "use" or commands[i].command == "usewith" then
242 label:setColor("orange")
243 elseif commands[i].command == "gotolabel" then
244 label:setColor("red")
245 end
246 end
247 end
248
249 local ignoreOnOptionChange = true
250 local refreshConfig = function(scrollDown)
251 ignoreOnOptionChange = true
252 if context.storage.cavebot.enabled then
253 autoRecording = false
254 ui.recording:setOn(false)
255 ui.enableButton:setText("On")
256 ui.enableButton:setColor('#00AA00FF')
257 else
258 ui.enableButton:setText("Off")
259 ui.enableButton:setColor('#FF0000FF')
260 ui.recording:setOn(autoRecording)
261 end
262
263 ui.config:clear()
264 for i, config in ipairs(context.storage.cavebot.configs) do
265 local name = getConfigName(config)
266 if not name then
267 name = "Unnamed config"
268 end
269 ui.config:addOption(name)
270 end
271
272 if (not context.storage.cavebot.activeConfig or context.storage.cavebot.activeConfig == 0) and #context.storage.cavebot.configs > 0 then
273 context.storage.cavebot.activeConfig = 1
274 end
275
276 ui.list:destroyChildren()
277
278 if context.storage.cavebot.activeConfig and context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
279 ui.config:setCurrentIndex(context.storage.cavebot.activeConfig)
280 parseConfig(context.storage.cavebot.configs[context.storage.cavebot.activeConfig])
281 end
282
283 context.saveConfig()
284 if scrollDown and ui.list:getLastChild() then
285 ui.list:focusChild(ui.list:getLastChild())
286 end
287
288 waitTo = 0
289 ignoreOnOptionChange = false
290 end
291
292
293 ui.config.onOptionChange = function(widget)
294 if not ignoreOnOptionChange then
295 context.storage.cavebot.activeConfig = widget.currentIndex
296 refreshConfig()
297 end
298 end
299 ui.enableButton.onClick = function()
300 if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
301 return
302 end
303 context.storage.cavebot.enabled = not context.storage.cavebot.enabled
304 if autoRecording then
305 refreshConfig()
306 elseif context.storage.cavebot.enabled then
307 ui.enableButton:setText("On")
308 ui.enableButton:setColor('#00AA00FF')
309 else
310 ui.enableButton:setText("Off")
311 ui.enableButton:setColor('#FF0000FF')
312 end
313 end
314 ui.add.onClick = function()
315 modules.client_textedit.multilineEditor("Waypoints editor", "name:Config name\nlabel:start\n", function(newText)
316 table.insert(context.storage.cavebot.configs, newText)
317 context.storage.cavebot.activeConfig = #context.storage.cavebot.configs
318 refreshConfig()
319 end)
320 end
321 ui.edit.onClick = function()
322 if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
323 return
324 end
325 modules.client_textedit.multilineEditor("Waypoints editor", context.storage.cavebot.configs[context.storage.cavebot.activeConfig], function(newText)
326 context.storage.cavebot.configs[context.storage.cavebot.activeConfig] = newText
327 refreshConfig()
328 end)
329 end
330 ui.remove.onClick = function()
331 if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
332 return
333 end
334 local questionWindow = nil
335 local closeWindow = function()
336 questionWindow:destroy()
337 end
338 local removeConfig = function()
339 closeWindow()
340 if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
341 return
342 end
343 context.storage.cavebot.enabled = false
344 table.remove(context.storage.cavebot.configs, context.storage.cavebot.activeConfig)
345 context.storage.cavebot.activeConfig = 0
346 refreshConfig()
347 end
348 questionWindow = context.displayGeneralBox(tr('Remove config'), tr('Do you want to remove current waypoints config?'), {
349 { text=tr('Yes'), callback=removeConfig },
350 { text=tr('No'), callback=closeWindow },
351 anchor=AnchorHorizontalCenter}, removeConfig, closeWindow)
352 end
353
354 -- waypoint editor
355 -- auto recording
356 local stepsSincleLastPos = 0
357
358 context.onPlayerPositionChange(function(newPos, oldPos)
359 ui.pos:setText("Position: " .. newPos.x .. ", " .. newPos.y .. ", " .. newPos.z)
360 if not autoRecording then
361 return
362 end
363 if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
364 return
365 end
366 local newText = ""
367 if newPos.z ~= oldPos.z then
368 newText = "goto:" .. oldPos.x .. "," .. oldPos.y .. "," .. oldPos.z
369 newText = newText .. "\ngoto:" .. newPos.x .. "," .. newPos.y .. "," .. newPos.z
370 stepsSincleLastPos = 0
371 else
372 stepsSincleLastPos = stepsSincleLastPos + 1
373 if stepsSincleLastPos > 10 then
374 newText = "goto:" .. oldPos.x .. "," .. oldPos.y .. "," .. oldPos.z
375 stepsSincleLastPos = 0
376 end
377 end
378
379 if newText:len() > 0 then
380 context.storage.cavebot.configs[context.storage.cavebot.activeConfig] = context.storage.cavebot.configs[context.storage.cavebot.activeConfig] .. "\n" .. newText
381 refreshConfig(true)
382 end
383 end)
384
385 context.onUse(function(pos, itemId, stackPos, subType)
386 if not autoRecording then
387 return
388 end
389 if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
390 return
391 end
392 if pos.x == 0xFFFF then
393 return
394 end
395 stepsSincleLastPos = 0
396 local playerPos = context.player:getPosition()
397 newText = "goto:" .. playerPos.x .. "," .. playerPos.y .. "," .. playerPos.z .. "\nuse:" .. pos.x .. "," .. pos.y .. "," .. pos.z
398 context.storage.cavebot.configs[context.storage.cavebot.activeConfig] = context.storage.cavebot.configs[context.storage.cavebot.activeConfig] .. "\n" .. newText
399 refreshConfig(true)
400 end)
401 context.onUseWith(function(pos, itemId, target, subType)
402 if not autoRecording then
403 return
404 end
405 if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
406 return
407 end
408 if not target:isItem() then
409 return
410 end
411 local targetPos = target:getPosition()
412 if targetPos.x == 0xFFFF then
413 return
414 end
415 stepsSincleLastPos = 0
416 local playerPos = context.player:getPosition()
417 newText = "goto:" .. playerPos.x .. "," .. playerPos.y .. "," .. playerPos.z .. "\nusewith:" .. itemId .. "," .. targetPos.x .. "," .. targetPos.y .. "," .. targetPos.z
418 context.storage.cavebot.configs[context.storage.cavebot.activeConfig] = context.storage.cavebot.configs[context.storage.cavebot.activeConfig] .. "\n" .. newText
419 refreshConfig(true)
420 end)
421
422 -- ui
423 local pos = context.player:getPosition()
424 ui.pos:setText("Position: " .. pos.x .. ", " .. pos.y .. ", " .. pos.z)
425
426 ui.wGoto.onClick = function()
427 if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
428 return
429 end
430 local pos = context.player:getPosition()
431 modules.client_textedit.singlelineEditor("" .. pos.x .. "," .. pos.y .. "," .. pos.z, function(newText)
432 context.storage.cavebot.configs[context.storage.cavebot.activeConfig] = context.storage.cavebot.configs[context.storage.cavebot.activeConfig] .. "\ngoto:" .. newText
433 refreshConfig(true)
434 end)
435 end
436
437 ui.wUse.onClick = function()
438 if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
439 return
440 end
441 local pos = context.player:getPosition()
442 modules.client_textedit.singlelineEditor("" .. pos.x .. "," .. pos.y .. "," .. pos.z, function(newText)
443 context.storage.cavebot.configs[context.storage.cavebot.activeConfig] = context.storage.cavebot.configs[context.storage.cavebot.activeConfig] .. "\nuse:" .. newText
444 refreshConfig(true)
445 end)
446 end
447
448 ui.wUseWith.onClick = function()
449 if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
450 return
451 end
452 local pos = context.player:getPosition()
453 modules.client_textedit.singlelineEditor("ITEMID," .. pos.x .. "," .. pos.y .. "," .. pos.z, function(newText)
454 context.storage.cavebot.configs[context.storage.cavebot.activeConfig] = context.storage.cavebot.configs[context.storage.cavebot.activeConfig] .. "\nusewith:" .. newText
455 refreshConfig(true)
456 end)
457 end
458
459 ui.wWait.onClick = function()
460 if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
461 return
462 end
463 modules.client_textedit.singlelineEditor("1000", function(newText)
464 context.storage.cavebot.configs[context.storage.cavebot.activeConfig] = context.storage.cavebot.configs[context.storage.cavebot.activeConfig] .. "\nwait:" .. newText
465 refreshConfig(true)
466 end)
467 end
468
469 ui.wSay.onClick = function()
470 if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
471 return
472 end
473 modules.client_textedit.singlelineEditor("text", function(newText)
474 context.storage.cavebot.configs[context.storage.cavebot.activeConfig] = context.storage.cavebot.configs[context.storage.cavebot.activeConfig] .. "\nsay:" .. newText
475 refreshConfig(true)
476 end)
477 end
478
479 ui.wNpc.onClick = function()
480 if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
481 return
482 end
483 modules.client_textedit.singlelineEditor("text", function(newText)
484 context.storage.cavebot.configs[context.storage.cavebot.activeConfig] = context.storage.cavebot.configs[context.storage.cavebot.activeConfig] .. "\nnpc:" .. newText
485 refreshConfig(true)
486 end)
487 end
488
489 ui.wLabel.onClick = function()
490 if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
491 return
492 end
493 modules.client_textedit.singlelineEditor("label name", function(newText)
494 context.storage.cavebot.configs[context.storage.cavebot.activeConfig] = context.storage.cavebot.configs[context.storage.cavebot.activeConfig] .. "\nlabel:" .. newText
495 refreshConfig(true)
496 end)
497 end
498
499 ui.wFollow.onClick = function()
500 if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
501 return
502 end
503 modules.client_textedit.singlelineEditor("creature name", function(newText)
504 context.storage.cavebot.configs[context.storage.cavebot.activeConfig] = context.storage.cavebot.configs[context.storage.cavebot.activeConfig] .. "\nfollow:" .. newText
505 refreshConfig(true)
506 end)
507 end
508
509 ui.wFunction.onClick = function()
510 if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
511 return
512 end
513 modules.client_textedit.multilineEditor("Add function", "function(waypoints)\n -- your lua code, function is executed if previous goto was successful or is just after label\n\n -- must return true to execute next command, otherwise will run in loop till correct return\n return true\nend", function(newText)
514 context.storage.cavebot.configs[context.storage.cavebot.activeConfig] = context.storage.cavebot.configs[context.storage.cavebot.activeConfig] .. "\nfunction:" .. newText
515 refreshConfig(true)
516 end)
517 end
518
519 ui.recording.onClick = function()
520 if not context.storage.cavebot.activeConfig or not context.storage.cavebot.configs[context.storage.cavebot.activeConfig] then
521 return
522 end
523 autoRecording = not autoRecording
524 if autoRecording then
525 context.storage.cavebot.enabled = false
526 stepsSincleLastPos = 10
527 end
528 refreshConfig(true)
529 end
530
531 refreshConfig()
532
533 local usedGotoLabel = false
534 local executeNextMacroCall = false
535 local commandExecutionNo = 0
536 local lastGotoSuccesful = true
537 local lastOpenedContainer = 0
538
539 local functions = {
540 enable = function()
541 context.storage.cavebot.enabled = true
542 refreshConfig()
543 end,
544 disable = function()
545 context.storage.cavebot.enabled = false
546 refreshConfig()
547 end,
548 refresh = function()
549 refreshConfig()
550 end,
551 wait = function(peroid)
552 waitTo = context.now + peroid
553 end,
554 waitTo = function(timepoint)
555 waitTo = timepoint
556 end,
557 gotoLabel = function(name)
558 for i=1,ui.list:getChildCount() do
559 local command = commands[i]
560 if command and command.command == "label" and command.text == name then
561 ui.list:focusChild(ui.list:getChildByIndex(i))
562 usedGotoLabel = true
563 lastGotoSuccesful = true
564 return true
565 end
566 end
567 end
568 }
569
570 context.onContainerOpen(function(container)
571 if container:getItemsCount() > 0 then
572 lastOpenedContainer = context.now + container:getItemsCount() * 100
573 end
574 end)
575
576
577 context.macro(250, function()
578 if not context.storage.cavebot.enabled then
579 return
580 end
581
582 if modules.game_walking.lastManualWalk + 500 > context.now then
583 return
584 end
585
586 -- wait if walked or opened container recently
587 if context.player:isWalking() or lastOpenedContainer + 1000 > context.now then
588 executeNextMacroCall = false
589 return
590 end
591
592 -- wait if attacking/following creature
593 local attacking = g_game.getAttackingCreature()
594 local following = g_game.getFollowingCreature()
595 if (attacking and context.getCreatureById(attacking:getId()) and not attacking.ignoreByWaypoints) or (following and context.getCreatureById(following:getId())) then
596 executeNextMacroCall = false
597 return
598 end
599
600 if not executeNextMacroCall then
601 executeNextMacroCall = true
602 return
603 end
604 executeNextMacroCall = false
605
606 local commandWidget = ui.list:getFocusedChild()
607 if not commandWidget then
608 if ui.list:getFirstChild() then
609 ui.list:focusChild(ui.list:getFirstChild())
610 end
611 return
612 end
613
614 local commandIndex = ui.list:getChildIndex(commandWidget)
615 local command = commands[commandIndex]
616 if not command then
617 if ui.list:getFirstChild() then
618 ui.list:focusChild(ui.list:getFirstChild())
619 end
620 return
621 end
622
623 if commandIndex == 1 then
624 lastGotoSuccesful = true
625 end
626
627 if command.command == "goto" or command.command == "follow" then
628 local matches = regexMatch(command.text, [[([0-9]+)[^0-9]+([0-9]+)[^0-9]+([0-9]+)]])
629 if (#matches == 1 and #matches[1] == 4) or command.command == "follow" then
630 local position = nil
631 if command.command == "follow" then
632 local creature = context.getCreatureByName(command.text)
633 if creature then
634 position = creature:getPosition()
635 end
636 else
637 position = {x=tonumber(matches[1][2]), y=tonumber(matches[1][3]), z=tonumber(matches[1][4])}
638 end
639 local distance = 0
640 if position then
641 distance = context.getDistanceBetween(position, context.player:getPosition())
642 end
643 if distance > 100 or not position or position.z ~= context.player:getPosition().z then
644 lastGotoSuccesful = false
645 elseif distance > 0 then
646 if not context.findPath(context.player:getPosition(), position, 100, { ignoreNonPathable = true, precision = 1, ignoreCreatures = true }) then
647 lastGotoSuccesful = false
648 executeNextMacroCall = true
649 else
650 commandExecutionNo = commandExecutionNo + 1
651 lastGotoSuccesful = false
652 if commandExecutionNo <= 3 then -- try max 3 times
653 if not context.autoWalk(position, distance * 2, { ignoreNonPathable = false }) then
654 if commandExecutionNo > 1 then
655 if context.autoWalk(position, distance * 2, { ignoreNonPathable = true, precision = 1 }) then
656 context.delay(500)
657 end
658 end
659 return
660 end
661 return
662 elseif commandExecutionNo == 4 then -- try last time, location close to destination
663 if context.autoWalk(position, distance * 2, { ignoreNonPathable = true, ignoreLastCreature = true, precision = 2, allowUnseen = true }) then
664 context.delay(500)
665 return
666 end
667 elseif distance <= 2 then
668 lastGotoSuccesful = true
669 executeNextMacroCall = true
670 end
671 end
672 else
673 lastGotoSuccesful = true
674 executeNextMacroCall = true
675 end
676 else
677 context.error("Waypoints: invalid use of goto function")
678 end
679 elseif command.command == "use" then
680 local matches = regexMatch(command.text, [[([0-9]+)[^0-9]+([0-9]+)[^0-9]+([0-9]+)]])
681 if #matches == 1 and #matches[1] == 4 then
682 local position = {x=tonumber(matches[1][2]), y=tonumber(matches[1][3]), z=tonumber(matches[1][4])}
683 if context.player:getPosition().z == position.z then
684 local tile = g_map.getTile(position)
685 if tile then
686 local topThing = tile:getTopUseThing()
687 if topThing then
688 g_game.use(topThing)
689 context.delay(500)
690 end
691 end
692 end
693 else
694 context.error("Waypoints: invalid use of use function")
695 end
696 elseif command.command == "usewith" then
697 local matches = regexMatch(command.text, [[([0-9]+)[^0-9]+([0-9]+)[^0-9]+([0-9]+)[^0-9]+([0-9]+)]])
698 if #matches == 1 and #matches[1] == 5 then
699 local itemId = tonumber(matches[1][2])
700 local position = {x=tonumber(matches[1][3]), y=tonumber(matches[1][4]), z=tonumber(matches[1][5])}
701 if context.player:getPosition().z == position.z then
702 local tile = g_map.getTile(position)
703 if tile then
704 local topThing = tile:getTopUseThing()
705 if topThing then
706 context.useWith(itemId, topThing)
707 context.delay(500)
708 end
709 end
710 end
711 else
712 context.error("Waypoints: invalid use of usewith function")
713 end
714 elseif command.command == "wait" and lastGotoSuccesful then
715 if not waitTo or waitTo == 0 then
716 waitTo = context.now + tonumber(command.text)
717 end
718 if context.now < waitTo then
719 return
720 end
721 waitTo = 0
722 elseif command.command == "say" and lastGotoSuccesful then
723 context.say(command.text)
724 elseif command.command == "npc" and lastGotoSuccesful then
725 context.sayNpc(command.text)
726 elseif command.command == "function" and lastGotoSuccesful then
727 usedGotoLabel = false
728 local status, result = pcall(function()
729 return assert(load("return " .. command.text, nil, nil, context))()(functions)
730 end)
731 if not status then
732 context.error("Waypoints function execution error:\n" .. result)
733 context.delay(2500)
734 end
735 if not result or usedGotoLabel then
736 return
737 end
738 elseif command.command == "gotolabel" then
739 if functions.gotoLabel(command.text) then
740 return
741 end
742 end
743
744 local nextIndex = 1 + commandIndex % #commands
745 local nextChild = ui.list:getChildByIndex(nextIndex)
746 if nextChild then
747 ui.list:focusChild(nextChild)
748 commandExecutionNo = 0
749 end
750 end)
751
752 return functions
753end
754
755
Top