This requires some look-ahead, so quantize_lasers will now compute all
samples ahead of time before starting to build segments. The samples are
held in a global dynamic array to minimize reallocations.
Not included by default, intended for custom distributions (for DoKomi
in particular)
Also improve the upgrade mechanism by ignoring settings that were not
changed in the config being parsed.
The framedump mode captures every frame and saves it as a .png image.
This can be useful for rendering videos.
To activate, set the `TAISEI_FRAMEDUMP` environment variable to a
prefix. A 8-digit frame number followed by ".png" will be appended to
this string to form the filename of each frame.
Example:
$ mkdir /var/tmp/taisei
$ export TAISEI_FRAMEDUMP="/var/tmp/taisei/frame-"
$ taisei -f1 -r /foo/some-replay.tsr
$ ls /var/tmp/taisei
frame-00000000.png frame-00000001.png frame-00000002.png
...
`TAISEI_FRAMEDUMP_SOURCE` can be set to either "screen" or "viewport".
The default is "screen", which records the whole game screen as it
appears (minus the letterboxing borders). "viewport" makes it record the
stage viewport only. The image is taken directly from the viewport
framebuffer, so elements that are drawn over the viewport will be
missing, such as the dialogue or the pause menu.
`TAISEI_FRAMEDUMP_COMPRESSION` can be set to change the quality of zlib
compression of the png images, ranging from 0 to 9. The default is 1.
Additionally, it's now possible to take screenshots of the game viewport
by pressing Alt+P (by default). This works on the same principle as
`TAISEI_FRAMEDUMP_SOURCE=viewport`, so the same caveats apply. This can
be used to take a clean screenshot of the viewport while the game is
paused.
There were two distinct things going on here:
1. If we receive multiple buffered TE_GAME_PAUSE events in the same
frame, we'd process all of them and create a pause menu for each.
This could theoretically overflow the evloop stack and crash the
game.
2. The `stage_comain` task starts before scheduling the stage main
loop via `eventloop_enter`. It initializes systems that depend on
tasks, and then immediatelly enters its per-frame async loop,
finishing its first iteration before yielding back to `_stage_enter`
and thus allowing `eventloop_enter` to be finally called. If there is
a TE_GAME_PAUSE event in the queue at this point, it would be handled
right there, and a pause menu would be created before the stage main
loop is scheduled. This messes things up quite a bit, leaking a
"zombie" pause menu into the evloop stack. After the stage is
destroyed, the evloop would try to switch to the frame created for
this menu. The menu's draw function would then attempt to reference
free'd resources of the destroyed stage, crashing the game. This
crash has actually been observed and reported (thanks @0kalekale)
To fix #1, the stage now tracks its paused state and refuses to open a
pause menu if one already exists.
To fix #2, `stage_comain` now yields before starting its async loop, to
let the stage set up its main loop early.
Note that because the stage main loop runs all coroutine tasks before
incrementing the frame counter, `stage_comain`'s per-frame logic would
execute twice on frame 0. This is obviously wrong, but this behavior
must be preserved to maintain compatibility with v1.4 replays. For that
reason, the `stage_comain` loop now skips its first YIELD. This hack can
be removed once v1.4 compat is no longer a concern.
Like ENT_ARRAY_ADD, but tries to scan the array for dead slots first. If
it finds one, it will put the new entity into that slot instead of
adding a new one. Returns the index. The regular ENT_ARRAY_ADD() now
also returns the index as well.