I'm trying to implement a simple scripting system for game enemies using coroutines as behavior scripts. As many average C++ coders, I'm having hard time wading through convoluted std::coroutine stuff but I managed to patch up something that works. My scripts now looks like this, where R and A are return and awaiter types pasted from one of coroutine tutorials:
R script(){
command_moveTo(10, 10);
co_await A;
command_idle(3);
co_await A;
command_moveTo(20, 20)
co_await A;
// etc..
}
This does the job but I'd like to eliminate the need to constantly write co_await after each command_*() call, so the scripts look tidy like this:
R script(){
command_moveTo(10, 10);
command_idle(3);
command_moveTo(20, 20)
// etc..
}
Is there a way to somehow suspend the coroutine from within command_*() functions. The complexity of sdt::coroutine is often justified by saying it facilitates making any kind of coroutine system. Can this rather typical use be implemented?
The only thing I could come up with is using macros for command_*() functions that simply sneak in co_await into coroutine's source code. Is there a better way?
A coroutine can only suspend itself by using
co_awaitor similar syntax. Nothing outside a coroutine, even a function it calls, can force it to suspend.If all of these
command_functions are intended to be followed by aco_awaitcall, then you should have them return the awaitable. This means you invokeco_await command_*. And set the functions to be[[nodiscard]], so users can't call them without doing something with the return value.This also allows the command to have a say in when it is finished and the next command should be executed. You could even make the awaitable something you can chain, so that you can have multiple commands that will be considered finished when all of them are finished.