A major ink update, including lots of improvements and fixes under the hood!
ink language changes
-
"Loose end" detection is now far more robust. Previously it wouldn't detect loose ends in even in simple choices, only in a sequence of "flat" content. (#416)
-
White-space handling is a bit different since handling was re-written in the engine (see below). Most obvious difference the following: previously it would be one line, whereas now there will be a newline inserted:
Hello {true: ...world. }
-
Temporary values may not be accesssed by stitches from their parent knot, or across stitches. For example, this used to be possible, but is no longer allowed:
== knot == ~ temp x = 5 -> stitch = stitch {x} -> END
-
Writing
not A ? B
will show a warning, since you almost certainly wantnot (A ? B)
rather than(not A) ? B
, but order of operations makes that impossible. -
Using the increment and decrement operators (
x++
andx--
) is now much stricter - you're only allowed to use them on their own, and not inline, so only~ x++
is allowed.
And, as always, there's a smattering of bug fixes and smaller improvements!
Game- and engine-side major changes
- Big improvements in how ink can cope with saving/loading a save state when the ink story has been changed. It will never be possible to make this perfect, so you should always exercise caution, especially when editing content for a game that's in production. But it shouldn't be quite so fragile anymore! (#195)
- If a variable is added, it will no longer crash when it accesses the value from a save state. It will try to use the original declared value. If you try to access a temporary variable that doesn't exist (yet) it will return the default value of
0
(false
). - If you try to call
ChoosePathString
on a path that doesn't precisely exist, or make a choice that diverts to a target that no longer exists in a new version of the ink content, the engine will do its best to work its way up the path and find content that does exist. If it has to do this, it will create a runtime warning (see next point).
- If a variable is added, it will no longer crash when it accesses the value from a save state. It will try to use the original declared value. If you try to access a temporary variable that doesn't exist (yet) it will return the default value of
Story
objects now have acurrentWarnings
list as well ascurrentErrors
. It's very important that you pay attention to (logging) both of these lists whenever you callContinue
, or you could be missing out on vital debugging information.story.ContinueAsync(millisecs)
- major game-side feature. New version ofContinue()
that allows you to specify a budget of a maximum amount of time you want to allow the engine to execute for before it pauses and allows you to finish another time. Great if your story sometimes goes into some complex logic, and you only want to allow it to execute for a few milliseconds per game frame. You can use thestory.asyncContinueComplete
property to detect when it's finished. Obviously this feature needs to be used with caution, since the story will be in an unpredictable state in the middle of execution. Although we have tried to guard against certain operations, it may still possible to accidentally get into sticky situations if you're not careful!- The compiler has now been moved out into a separate DLL (ink_compiler.dll), making inklecate a very lightweight wrapper around it. This should make it much easier for you to compile ink scripts from your own C# code (e.g. for game modding.)
story.ChoosePathString
now takes aresetCallstack
parameter that defaults to true. This means that if you were in a tunnel (or multiple) when callingChoosePathString
, then by default it'll take you back out again. If you passfalse
toresetCallstack
then it'll preserve the state of the tunnel(s). It defaults totrue
since the assumption is that usually you useChoosePathString
to entirely change scene / go to an entirely new section.- Re-write the way
EvaluateFunction
calls from game code work in the engine to be more robust, and allow them to make multiple nested calls from Game -> ink -> game -> ink for very complex logic! - Re-write the way that whitespace is handled - see ink language changes above for an example of how this has subtly affected the language. Previously the compiler inserted "single-direction implicit glue" at the start and end of anything enclosed in
{
and}
(inline logic). This wasn't robust since it was possible to divert out of the logic, which would "leak glue" since the left/right portions didn't match. Instead, newlines are now automatically consumed at the start of function calls, which makes the story lighter weight, and the whole system more robust. - Optimisation to the way the engine steps through the content.