In the example I gave this would work to some degree, since I could use connections like MoveToFinished.
However it wouldn’t hold up with more complex NPC commands. Assume for example, we couldn’t use the MoveToFinished event and had to check for ourselves in a step function whether or not our NPC has reached its destination.
Haven’t touched the pathfinding in a while, so a bit of a disclaimer if I’m overlooking something here.
The pathfinding route would’ve finished if the NPC has reached all the waypoints, you can simply do a check for how many waypoints are left per NPC surely? I remember doing something similar and printing “finished” before.
Another option would be to store the destination location from the pathfinding and do a check if the character is within (x) radius of there.
What you’re saying definitely works, and if we put it all into a step/update method it would certainly do the job of getting to the destination and jumping. But what comes next, is trying to program a framework that lets the command be interrupted/canceled. Or a command being inputted, overwriting another command that is running.
More specifically, I’m trying to find different ways to structure an NPC command system like that without using coroutines.
I suppose if we are doing a for loop going through the waypoints (or similar), you can just break out of that if you get a command to interrupt it, and then set a new “thing” if something is overwriting it.
You could have a value wherever your doing this that is “cancel” or similar, you then could every iteration in the for loop, check to see if cancel is still false. If it turns true, you can break the loop.
There are many other ways I suppose it could be done. Optimisations can always come later if it’s a performance issue, as long as functionality is there, we can optimise it later, surely?
Someone else reading this thread may have a better idea how this could be achieved, and if so feel free to drop it in a reply here.
--//Variables
local my_npc = {}
my_npc.__index = my_npc
--//Functions
function my_npc.new(plyr)
if not (plyr and plyr.Character) then return end
local self = setmetatable({}, my_npc)
self.Commands = deepcopy(my_npc.Commands) --deepcopy function just clones table 1:1
self.CurrentCommand = nil
return self
end
function my_npc:Step()
if self.CurrentCommand then
self.CurrentCommand:Step()
end
end
--//Commands
my_npc.Commands = {}
function my_npc:IssueCommand(cmd, ...)
if self.Commands[cmd] then
if self.CurrentCommand then
self.CurrentCommand:Cleanup()
end
self.Commands[cmd]:Issue(...)
self.CurrentCommand = self.Commands[cmd]
end
end
function my_npc:StopCommand()
if self.CurrentCommand then
self.CurrentCommand:Cleanup()
self.CurrentCommand = nil
end
end
--first command from hypothetical
my_npc.Commands.WalkToJump= {}
function my_npc.Commands.WalkToJump:Issue(...)
--set temporary data passed from original object (to avoid cyclic tables)
end
function my_npc.Commands.WalkToJump:Step()
--if destination reached then
-- jump
--end
end
function my_npc.Commands.WalkToJump:Cleanup()
--code that fires if command is interrupted/cancelled
end
return my_npc
The use case for this would be:
customNpc:IssueCommand("WalkToJump")
--wait! maybe I want to cancel it instead!
customNpc:StopCommand()
I can’t shake the feeling that there is a better solution (;⌣̀_⌣́). So if anyone spots something that could be improved on let me know!