1
0
Fork 0
mirror of https://github.com/TerryCavanagh/VVVVVV.git synced 2024-12-23 01:59:43 +01:00
Commit graph

2606 commits

Author SHA1 Message Date
AllyTally
c6ebf5aeda Disable more flashing elements if a11y is on
For some reason, the accessibility option that was meant to disable
flashes doesn't disable ALL flashes, only screen flashes and screen
shaking. This commit disables a lot more, most importantly randomness
in colors, the player flashing on death/respawn, and teleporters
flashing.
2023-04-05 20:02:29 -07:00
Misa
73aee381ad Update lerp positions during VVVVVV-Man transforms
This updates the interpolation positions of the player when transforming
into and out of VVVVVV-Man.

Otherwise, it can be seen that the player "zips" quickly during these
transformations if the Secret Lab entrance cutscene is played with
screen effects off.
2023-04-05 19:51:58 -07:00
Misa
5fbdf2b663 Fix regression with music fade transitions not working
Unfortunately, 1de459d9b4 caused a
regression where musicclass::niceplay() didn't work, because fading out
the music would cause haltdasmusik() to be called, which would reset the
fade variables.

To fix this, haltdasmusik() will now only reset the fade variables if
it's not called from a fade, which is signaled with a function
parameter.
2023-04-05 19:32:42 -07:00
Misa
c88f249f48 Sync language files after merging #963
This syncs the language files to include the new string about changing
platform speed.
2023-04-02 23:50:11 -07:00
AllyTally
f3cf771cc8 CTRL+, and CTRL+. to modify platv
`platv` is a room property that controls platform speed, and it has
always worked (other than some weird storage issues due to a bug).
However, the editor has no way to edit it currently, so people had to
resort to editing the level file by hand, or with a third-party tool.
This commit simply adds an easy way to modify platform speed.
2023-04-02 23:48:09 -07:00
AllyTally
d328be2a03 Add fill bucket subtool
VED has a fill bucket subtool for tiles and backgrounds, which is
really useful when creating rooms. This commit adds a fill bucket as
well, with an adaptive tool highlight, unlike VED.
2023-04-02 23:48:09 -07:00
Misa
1de459d9b4 Fix nice fade variables persisting when they shouldn't
This fixes a regression from 2.3 where the very beginning of A New
Dimension isn't silent.

A New Dimension's level music is set to Predestined Fate, but there is a
script box the player touches right upon spawning that stops playing
music. Then after the player ascends upwards, they touch a script box
that plays Predestined Fate. But in 2.2 and before, the very beginning
is silent due to the script box that stops music.

However in 2.3, due to the changes made to playing music during a fade,
the initial level music trying to play Predestined Fate during a music
fadeout from the main menu resulted in Predestined Fate being stored in
the nice fade variables, which kicked in after halting the music since
halting didn't reset those variables.

This resets those variables whenever music is halted, and now the
beginning of A New Dimension is back to how it was in 2.2 and before.
2023-03-31 21:39:29 -07:00
Misa
8f23261134 Whiten texture only after loading surface
This fixes a regression where the red channel 0 glitch didn't work,
because the surface was always whitened, because LoadSprites would
whiten the image before converting it to surface.

This regression happened because of #923.

Fixes #962.
2023-03-30 19:54:46 -07:00
Dav999-v
78128222e9 Make textbuttons() work for transparent text boxes
Misa asked me if this should only work for non-transparent textboxes,
and it shouldn't - that was kind of an oversight.

To make it work for transparent textboxes as well, I made a little
restructuring to avoid duplicating the code - fill_buttons() is now
called textbox_line(), and it replaces the direct accessing of the
textbox lines in the printing loops. The code that checks the width
of the textbox does not need to be copied, since the text box is
naturally not drawn for transparent text boxes.
2023-03-30 00:44:33 -07:00
Misa
71dbe95dcb Separate CustomEntity global positions internally
This makes it so that `CustomEntity`s, at least internally, do not use
global tile position. Instead, they will use room-x and room-y
coordinates, which will be separate from their x- and y- positions.

This makes it much easier to deal with `CustomEntity`s, because you
don't have to divide and modulo everywhere to use them.

Since editorclass::add_entity and editorclass::get_entity_at expect
global tile position in their arguments, I've added room-x and room-y
arguments to these functions too.

Of course, due to compatibility reasons, the XML files will still have
to use global tile position. For the same reason, warp token
destinations are still using global tile position too.
2023-03-29 13:49:08 -07:00
Misa
98feeade02 Fix gray entities applying in main game
As reported by Lilithtreasure on the VVVVVV Discord server, it is
possible to get gray moving platforms and enemies in the main game.

This happens if you play the main game after loading a custom level with
a room that is gray at the same coordinates. E.g. if you play a custom
level with a gray room at (12, 4), then exit and go to Gantry and Dolly
in the main game which is also at (12, 4), then the platforms there
would be gray too.

This is because there is a missing map.custommode check.
2023-03-29 13:49:08 -07:00
Misa
09c07d8ad4 Copy rest of music code to OGG sound effects
The missing piece from sound effects was handling what to do when the
buffer ran out. Which seems to happen often when decoding from OGG,
unlike WAV. This handling involves callbacks to functions named
refillReserve and swapBuffers.

Without this code,some sound effects would be cut off early, as
documented in #953. This might also explain the division by 20 - which
I've copied too, just in case.

Now OGG sound effect tracks should be identical to music tracks (except
I've stripped the looping code out).

Fixes #953.
2023-03-29 13:49:08 -07:00
Misa
c36655d5c7 Don't use FAudioVoice_GetVoiceDetails
We were using this function to check if the format of the existing voice
is different from the format of the voice we intended to play. However,
whereas the format we use is the FAudioWaveFormatEx struct, the only
details we get from FAudioVoice_GetVoiceDetails is the
FAudioVoiceDetails struct, which has much less details and is missing
important things like whether the format is 8-bit or 16-bit or something
else.

And of course, if we don't check that the number of bits matches, then
it still leads to playback issues as described in #953.

There are no other functions in FAudio that operate on
FAudioWaveFormatEx structs. So instead, we'll just have to do it
ourselves, and store the format of the existing voice alongside the
format of the intended voice. And then use SDL_memcmp to make sure the
formats are the same before playing, and if not, then destroy and
re-create the voice.

Fixes #953.
2023-03-29 13:49:08 -07:00
AllyTally
07e48565ed Reset textbox colors properly 2023-03-29 13:48:44 -07:00
AllyTally
efa1bad449 Unhardcode textbox colors in textbox arguments
There's a few places where textboxes are constructed through code, but
they pass in the color's RGB values in manually. This commit
unhardcodes most of them them, replacing them with a color lookup.

The ones that weren't changed are special cases, like `175, 174, 174`.
2023-03-29 13:48:44 -07:00
AllyTally
bd34af32de Remove hardcoded textbox colours
We have a custom textbox colour system, why not use it? This also moves
the map of colours from CustomLevels to Script.
2023-03-29 13:48:44 -07:00
Dav999-v
c3e251fea9 Show correct button glyph for interact if Enter/E are not split
I thought 2.2 already had separate map and interact gamepad bindings,
and they simply got neglected and broken with 2.3's split Enter/E key
option. But actually, the new split Enter/E option also applied to
gamepad buttons, and a separate interact binding was added, without
really indicating anything if Enter and E are not split. And I guess
using the same button for map and interact by default also makes sense
for simplicity...

This commit makes sure the button glyph displayed in-game is at least
the correct button. The gamepad bindings menu is also slightly modified
to darken the interact option - the button glyphs code now
automatically causes them to show equal buttons anyway, so it wasn't
too big of a change to also darken the line and disable the binding
option. To me this says: "the interact key is fixed to be the same as
enter right now, but there is a way to change it."

It's still not ideal of course, and I know a similar change to the
gamepad menu to hide the interact option was rejected a year ago
because action sets would already fix it, but it's a year later now,
and showing misleading button glyphs should be fixed in 2.4, whether it
will already have action sets or not (And at this point I think the
plan already is to keep the existing input system for 2.4)

And it's a 3 line diff to darken and disable the option, compared to
fully hiding the option.
2023-03-26 17:56:10 -07:00
Dav999-v
a2c3f47748 Add button glyphs support to selection hint on language screen
The language screen has a "Press Space, Z, or V to select" hint, which
I forgot to update for supporting button glyphs in #943, so this commit
does.

    <action_hint>Press Space, Z, or V to select</action_hint>
    <gamepad_hint>Press {button} to select</gamepad_hint>
2023-03-26 17:54:47 -07:00
Dav999-v
0984e06546 CI: Include CMakeLists.txt in the cache
> CMake is re-running because D:/a/VVVVVV/VVVVVV/desktop_version
> /build_default/CMakeFiles/generate.stamp is out-of-date.
>   the file 'D:/a/VVVVVV/VVVVVV/desktop_version/CMakeLists.txt'
>   is newer than 'D:/a/VVVVVV/VVVVVV/desktop_version/build_default
>   /CMakeFiles/generate.stamp.depend'
>   result='-1'

"newer" probably means "the last edit date is newer because it was just
cloned", so let's see if including it in the cache means the last edit
date will be kept the same too... We can freely do this, as the cache
key includes the hash of the file itself.
2023-03-24 16:56:26 -07:00
Dav999-v
78c3696651 CI: Cache build folder on Windows
Since the initial `cmake -G "Visual Studio 17 2022" ..` seems to be a
real bottleneck on the Windows CI (sometimes taking multiple minutes
for seemingly no reason), cache the build folder based on the hash
of CMakeLists.txt. It should be possible to reuse the build folder if
CMakeLists hasn't changed, and if it does change (because someone adds
a source file or library or something), we'll just do that initial
cmake with -G once, and cache that version as well.

https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows
2023-03-24 16:56:26 -07:00
Dav999-v
62449dfa9a CI: Skip "Download SDL" step instead of using Test-Path, use cache@v3
For some reason, this test takes a dozen seconds or more. Maybe because
it needs to boot up powershell or something like that? No idea, but
it's just sitting there. The cache action has a return value that
indicates whether there was a cache hit, so there's no need to use
Test-Path, saving CI time.

EDIT: Maybe the SDL cache hasn't ever been working. It seems to cache
30 bytes (huh?) and the folder it caches is C:\SDL, not C:\SDL2-2.24.0
as the folder would look like. So it was probably downloading SDL every
time anyway?

Also, I upgraded the cache@v2 action to cache@v3. I added a cache@v3
myself and noticed this was still using cache@v2, so I figured, why not
future-proof it? And that's when I notice this warning: "Node.js 12
actions are deprecated. Please update the following actions to use
Node.js 16: actions/cache@v2." So it's pretty good timing.
2023-03-24 16:56:26 -07:00
AllyTally
0961084ff9 Fix missing leftbutton check 2023-03-24 11:13:16 -07:00
Dav999-v
5d2e477f06 Add /MP to CMakeLists for Windows
This should make compilation on Windows faster because it uses multiple
processors. The Windows CI is the slowest, so let's make it faster.
From my experimentation, adding this flag does seem to reduce compile
times, especially after the first build (default version) is done.

https://learn.microsoft.com/en-us/cpp/build/reference/mp-build-with-multiple-processes?view=msvc-170
2023-03-22 17:52:40 -07:00
Dav999-v
65d9d9a0d8 Make Violet's button dialogue work in cutscene test
This was easier than I expected - just add an optional buttons="1"
attribute to cutscenes.xml. It's treated like the speaker attribute -
it's only there as context for the translator, and for the cutscene
test.
2023-03-22 16:20:44 -07:00
Dav999-v
bc156137d8 Sync language files for button glyphs changes
Due to rebasing messiness and diff noise, it's probably best if pull
requests either don't sync all the language files at all (and only
modify the English ones) OR only do it as a final commit. It's still
something we need to figure out, lol.
2023-03-21 19:59:48 -07:00
Dav999-v
01200b5e64 Switch between controller glyphs and keyboard keys automatically
If a controller button is pressed, a controller is connected (even at
startup!) or an axis is moved, the game will switch to displaying
controller glyphs. If a keyboard key is pressed or the last controller
is removed, the game will switch to displaying keyboard keys.
2023-03-21 19:59:48 -07:00
Dav999-v
e55e9efd9b Add controller button layout mappings
This adds mappings from SDL's Xbox-based SDL_GameControllerButton
constants, to glyphs for the following layouts:

- LAYOUT_NINTENDO_SWITCH_PRO,
- LAYOUT_NINTENDO_SWITCH_JOYCON_L,
- LAYOUT_NINTENDO_SWITCH_JOYCON_R,
- LAYOUT_DECK,
- LAYOUT_PLAYSTATION,
- LAYOUT_XBOX,
- LAYOUT_GENERIC,

There may still be errors in these, but they should be mostly correct.
I'm leaving it up to Ethan to make it show the correct button glyphs
for the correct controllers being connected (and possibly to fix these
mappings where needed).
2023-03-21 19:59:48 -07:00
Dav999-v
09365347b6 Replace ACTION in texts by {button} placeholders
Gamepads and the Steam Deck need "ACTION" to be replaced by a
controller glyph, so that's now possible.
2023-03-21 19:59:48 -07:00
Dav999-v
620365614d Add textbuttons() script command, make Violet's ENTER dialogue dynamic
Violet's dialogue now looks like this:

squeak(purple)
text(purple,0,0,2)
Remember that you can press {b_map}
to check where you are on the map!
position(purple,above)
textbuttons()
speak_active

The new textbuttons() command sets the next textbox to replace {b_map}
with the map button, and {b_int} with the interact button. The
remaining keys would be added as soon as they need to be added to
ActionSets.h as well.
2023-03-21 19:59:48 -07:00
Dav999-v
3354a1a352 Add support for button glyph display
This adds a function that converts an action (such as interacting
in-game) to the corresponding button text ("ENTER", "E") or button
glyph (PlayStation triangle, Steam Deck Y, etc). This function
currently only gives the existing ENTERs or Es, because I don't know
how best to detect controller usage, or whether the game is running on
a Steam Deck, or what buttons need to be displayed there. Still, it
should now be really easy to adapt the rendering of keyboard keys to
consoles, controllers, or rebound keys.

To identify the actions that currently need to be displayed, this
commit also adds the initial enums for action sets as described by
Ethan in a comment in #834 (Jan 18, 2022).
2023-03-21 19:59:48 -07:00
Misa
5180e430a2 Sync language files after #944 merged
This syncs language files after the merge of PR #944, since that PR
obsoleted English strings, but didn't sync them.
2023-03-21 18:46:41 -07:00
Ally
0edbf6398a Add suggestions from style pass
Co-authored-by: Misa Elizabeth Kai <infoteddy@infoteddy.info>
2023-03-21 15:41:49 -07:00
AllyTally
234776bbec Fix macOS build errors/warnings 2023-03-21 15:41:49 -07:00
AllyTally
045ce3a0fc Allow placing warp token destination in walls
Staying consistent with how entities can now be placed in walls, the
warp token destination should follow this as well.
2023-03-21 15:41:49 -07:00
AllyTally
08084e5a97 Add edge-guides for horizontal gravity lines
These visualize the horizontal gravity line kludge for rooms beside
eachother. When you enter another room, gravity lines which look like
they're connected between the rooms try to have the same activated
state.

Basically, if you're in room (1,4) and you go into (2,4), if a
gravity line in (1,4) is activated (gray, on cooldown) and it's
touching the gravity line in (2,4), that gravity line will also be
activated.
2023-03-21 15:41:49 -07:00
AllyTally
d152730510 Add interpolation to tile tools
This uses DDA (https://w.wiki/6RSQ) to draw a line between the previous
frame's mouse position, and the current frame's mouse position. This
means that there will no longer be gaps in lines of tiles if you move
your mouse fast enough (which is actually rather slow, so it gets
annoying quickly).

The editor's timestep is no longer hardcoded to 24, as I assume that
was only done so there would be less gaps in lines of tiles drawn.
With interpolation, that is no longer an issue, so I've removed the
editor's special case for the timestep.
2023-03-21 15:41:49 -07:00
AllyTally
6cae666c76 Clean up scripts in the editor
Scripts used a weird "hook" system, where script names were extracted
into their own list. This was completely unneeded, so it has been
replaced with using the script.customscripts vector directly.

The script editor has been cleaned up, so the cursor's Y position is
relative to the entire script, rather than what's just displaying on
the screen currently. This simplifies a lot of code, and I don't know
why it was done the other way in the first place.

The script selector and script editor cursors have been sped up, since
both lists can be massive, and waiting 6 frames per line is extremely
slow and boring. This is still slow and boring, but we don't have
proper input repetition yet.
2023-03-21 15:41:49 -07:00
AllyTally
9c26f51931 Update English language file
The English language file should always be in sync with the code.
2023-03-21 15:41:49 -07:00
AllyTally
7ac405c831 Move everything to the editor state system
This commit moves everything left out of the previous commit to the
state system. This means a bunch of new functions were added as well,
to avoid the code in each function becoming too huge. A lot of cleanup
was done as well, simplifying logic, merging duplicated code, etc.

This commit does NOT touch "script hooks", script editor logic and
autotiling, as those seem to be their own separate beasts.
2023-03-21 15:41:49 -07:00
AllyTally
7b5ef40926 Fix gravity/warp lines being modified during draw
While warp lines were being drawn, they also got resized to
automatically fit between collision. In renderfixed, gravity lines are
resized the same way. Doing logic while drawing is very poor practice,
so resizing of these has been moved into logic, and merged together.

Aside from some more cleanup, this commit also removes the very poorly
done right click emulation, when you hold CTRL and click. It never
worked well in the past, and even requires a right click to use, so
there's not really any point to keeping it around.
2023-03-21 15:41:49 -07:00
AllyTally
84c6d44c52 Clean code for direct mode drawer
The drawer could definitely be improved further, however I cleaned up a
little bit of the code duplication. I'll have to take a closer look
some other time, but I'm pretty sure that the duplicated code at the
bottom can be removed with a few tweaks, but I'll do that carefully
in a different commit.
2023-03-21 15:41:49 -07:00
AllyTally
34cc15505b Cleanup tools & main rendering
Tools were a mess, spread all over the code with hundreds of `else-if`
statements. Instead of magic numbers denoting tools, an enum has been
created, and logic has been extracted into simple switch/cases, shared
logic being deduplicated.

The base of a state system for the editor has been created as well,
laying a good path for further organization improvements. Because of
this, the entire editor no longer gets drawn underneath the menus,
except for a few pieces which I haven't extracted yet. Either way,
this should be good for performance, if that was a concern.
2023-03-21 15:41:49 -07:00
Misa
e3612afbd3 Store display index of window to settings
I have this annoying issue where the game will open on the wrong monitor
in fullscreen mode, because that monitor is considered to be display 0,
whereas the primary monitor I want is display 1.

To mitigate this somewhat, the game now stores the display index that it
was closed on, and will save it to settings. Then the next time the game
opens, it will open on that display index. This should work pretty well
as long as you aren't changing your monitor setup constantly.

Of course, none of this applies if your window manager is busted. For
example, on GNOME Wayland, which is what I use, in windowed mode the
game will always open on the monitor the cursor is on, and it won't even
be centered in the monitor. But it works fine if I use XWayland via
SDL_VIDEODRIVER=x11.
2023-03-21 00:23:42 -07:00
Misa
54990638fd Persist windowed mode size through fullscreen mode
Previously, the game would not store the size of the window itself, and
would always call SDL_GetRendererOutputSize() (via
Screen::GetWindowSize()) to figure out the size of the window. The only
problem is, this would return the size of the whole monitor if the game
was in fullscreen mode. And the only place where the original windowed
mode size was stored would be in SDL itself, but that wouldn't persist
after the game was closed.

So, if you exited the game while in fullscreen mode, then your window
size would get set to the size of your monitor (1920 by 1080 in my
case). Then when you opened the game and toggled fullscreen off, it
would go back to the default window size, which is 640 by 480.

This is made worse, however, if you were in forced fullscreen mode when
you previously exited the game in windowed mode. In that case, the game
saves the size of 1920 by 1080, but doesn't save that you were in
fullscreen mode, so opening the game not in forced fullscreen mode would
result in you having a 1920 by 1080 window, but in windowed mode.
Meaning that not even fullscreening and unfullscreening would put the
game window back to normal size.

The solution, of course, is to just store the window size ourselves,
like any other screen setting, and only use GetWindowSize() if needed.
And just to make things clear, I've also renamed the GetWindowSize()
function to GetScreenSize(), because if it was named "window" it could
lead one to think that it would always return the size of the screen in
windowed mode, when in fact it returns the size of the screen whatever
mode it is in - fullscreen size if in fullscreen mode and window size if
in windowed mode.

And doing this also fixes the FIXME above Screen::isForcedFullscreen().
2023-03-20 20:59:37 -07:00
Misa
e1e9e47d95 Always update scaling before rendering
This fixes the following bug that only occurs on Wayland: If the game is
configured to be fullscreened and in stretch mode, on startup, it won't
be in stretch mode. It will appear to be in letterbox mode, but the game
still thinks it's in stretch mode.

This is because during the ResizeScreen() call on startup, for whatever
reason, the window size will be reported to be the default size (640 by
480) instead of the screen resolution of the monitor, as one would
expect from being in fullscreen. It seems like when the game queries the
window size, the window isn't actually in fullscreen at that time, even
though this is after fullscreen has been set to true.

To fix this, I decided to always update the logical size before
SDL_RenderPresent() is called. To make this neater, I put the scaling
code in its own function named UpdateScaling().

This bug has existed since 2.3 and does not occur on X11. I tested this
on GNOME Wayland, and for testing it on X11, I used Openbox in a Xephyr
session while running VVVVVV with SDL_VIDEODRIVER=x11.
2023-03-20 20:56:15 -07:00
Misa
64874065eb Rename menuoffTexture to tempShakeTexture
It turns out this texture is only used as a temporary texture to draw
the screen with an offset before rendering it to the output target.

I thought it was used for drawing the map menu animation, but that was
only true of `tempBuffer`, and is no longer true of the new render
system.
2023-03-20 17:05:57 -07:00
AllyTally
371404f393 Fix textboxes fully fading out during blackout
When `blackout` is active, the screen (to simplify) stops getting drawn
to. The excecption is textboxes, which draw anyway. But since the
screen isn't being cleared, removed textboxes stay on screen, since
that texture isn't being cleared. In the SDL_Renderer PR, I
accidentally broke this behavior, so this commit fixes it.

Fixes #951.
2023-03-19 15:15:52 -07:00
Misa
397d7f21b4 Add length check to OGG check
Dav999 pointed out this potential issue on Discord.

While basically all memcmp implementations will terminate early here if
there's a null byte (because it's mismatched), it doesn't hurt to add
the check here.
2023-03-19 14:05:51 -07:00
Misa
2dc7f0b5e8 Remove dialogue and cutscene bars if disabling completestop
This fixes a bug where the trinket collection text boxes, along with the
cutscene bars, would stay on-screen if the player warped to the ship
while they were up.

This only happens during the gamestate 0 anti-softlock checks, and only
if completestop is active in the first place, so text boxes aren't
cleared if the player is doing something that wouldn't lead to a
softlock otherise.

Fixes #921.
2023-03-19 13:48:01 -07:00
Misa
88d49547d4 Evaluate flipping eligibility per-entity
This fixes a regression where the behavior of duplicate player entities
is different, causing a gameplay section in Vespera Scientifica to be
impossible, as described in #903.

In the level, you are allowed to flip in mid-air. Vespera accomplishes
this by having two duplicate player entities stuck in a platform. One of
them is responsible for letting the player flip in one direction, and
one of them is responsible for letting them flip in the other.

In 2.3, this works because in order for a player entity to flip,
`game.jumppressed` is checked, and the entity will flip if
`game.jumppressed` is greater than 0, then `game.jumppressed` will be
set to 0. In this way, whenever a player entity flips, it will set
`game.jumppressed` to 0, so whenever the next player entity is
evaluated, `game.jumppressed` is 0 and thus _that_ entity will not flip.

This is because the for-loop surrounds both the `game.jumppressed` check
and flipping the entity. In 2.4 after #609 and subsequent patches,
however, this is not the case. Here, the for-loop only surrounds
flipping the entity. Therefore, the `game.jumppressed` check is
evaluated only once. So, it will end up flipping every player entity if
the entities are eligible. In this case, one of them is eligible twice,
resulting in the game flipping gravitycontrol four times, which is
essentially the same as not flipping at all (except for all the sound
effects).

Hence, the fix here is to make it so the for-loop surrounds the
`game.jumppressed` check.

Now, this doesn't mean that the intent of #609 - that duplicate player
entities have the same initial velocity applied to them when flipping -
has to be removed. We can just put the for-loops back in. But I
carefully implemented them in such a way that the overall function is
not quadratic, i.e. O(n²). Instead, there's a pass done over the
`obj.entities` vector beforehand to store all indexes of a player entity
in a temporary vector, and then that vector is used to update all the
player entities. In this manner, the function is still linear - O(n) -
over the number of entities in the room.

I tested this to make sure that no previous regressions popped up again,
including #839, #855, and #887. And #484 is still resolved.

Fixes #903.
2023-03-18 21:30:23 -07:00