Fixes#1242.
Turns out it was a really simple fix - the X positions were good, but
the Y positions were always at the top of the screen regardless of the
height of the textbox. Now they're vertically centered respective to
the speaker.
This fixes our problem with Valgrind reporting a jump based on an
uninitialized value; see https://github.com/Tehreer/SheenBidi/issues/19
Just to be sure nothing unexpected happens, I tested that this doesn't
cause any changes in behavior by outputting bidi-transformed versions
of all strings in strings.xml to a file for both our Arabic and Persian
localizations before and after the update, and confirming that the
files are the same.
This includes translations that were missing translations, with varying
extent between different languages, for the following things:
- "X mode is enabled" in-game warnings
- "Press {button} to freeze/unfreeze gameplay" for the level debugger
- Some credits strings for the post-2.4.0 extra Spanish options, the
PT_BR proofread, and Persian
- The recent gamepad menu changes (#1229)
Furthermore:
- "TAB" (used in the level debugger string) is now a separate string
instead of being hardcoded, because some languages needed it
translated
- Added missing arrows to Arabic/Persian font (needed for the gamepad
menu, and also a translator menu actually)
Seems like the build root can change and CMake rightfully gets confused at the conflicting paths, so let's just use the minutes to do this from scratch.
- Update actions/checkout to v4
- Add build caching for macOS and Linux jobs
- Implement concurrency control to cancel redundant runs
- Restrict GITHUB_TOKEN permissions for security
These changes improve CI performance, stability, and security.
When writing the initial stretch mode code, the existence of HiDPI
displays completely slipped my mind -- or at least I didn't realize
that they'd be a problem.
We implement scaling modes ourselves, so transforming the mouse
coordinates to our 320x240 viewport is done manually. Unfortunately,
that code did not take into account HiDPI scaling whatsoever, meaning
that all of the math which assumes the window size and the renderer
size is wrong.
To fix this, we use `SDL_GetWindowSizeInPixels` and `SDL_GetWindow` to
find the scaling factor, and then apply that to the mouse coordinates
to get the mouse coordinates in the pixel-space instead, and then we do
all of our normal logic after.
Due to our usage of `SDL_GetWindowSizeInPixels`, this bumps the minimum
SDL version to 2.26.0.
Closes#1235.
A SDL_GameControllerButton below 0 is out of array bounds, so that
should trip the assert and return GLYPH_UNKNOWN just like when the
value is too high.
This makes the following improvements to the gamepad bindings menu:
- The menu now shows a hint that you can press a button while any of
the bind options are selected (or that you can navigate away from
those options)
- Instead of button presses immediately setting a binding, they now
ask for confirmation: press the same button a second time to confirm
- You can now remove a binding, the same way you add it (this has the
same type of confirmation)
- This menu used to be inconsistent with pretty much every other menu
in the game by showing a permanent title and description for the menu
itself ("Game Pad", "Change controller options.") rather than showing
a title and description for the currently selected option.
This inconsistency is now fixed.
The Persian localizers noticed an issue where the translation for
"Dimension VVVVVV, 12:34:56" would become "VVVVVV, 12:34:56 noisnemiD",
rather than "12:34:56 ,VVVVVV noisnemiD" as expected. This was fixed
for Persian but the same issue also affected Arabic, so I added a
RIGHT-TO-LEFT MARK (U+200F) to fix it there as well.
This adds "Persian" to all the languages, and brings the Persian files
up-to-date (mainly removing outdated strings and adding some late 2.4
stuff that we'll contact all translators for soon)
Every now and then, the game crashes for me because of a division by
zero, due to the rect returned by `Graphics::get_stretch_info`. I don't
fully know how the width and height get set to 0, but this should
protect against it.
As I always use integer scaling, my guess is that
`Screen::GetScreenSize` (which later calls `SDL_GetRendererOutputSize`)
returns 0 sometimes, and the code trusts that -- but I know that
windows and things can be finicky, so the clamp is probably a good
idea.
When `SDL_RenderReadPixels` fails for some reason, the game tries to
free the temporary source surface it creates. Unfortunately, it never
sets it to `NULL` after, so the next time the game tries to render the
filter, it'll try to work with a memory region that was already freed.
To fix this, I just replaced `SDL_FreeSurface(*src);` with
`VVV_freefunc(SDL_FreeSurface, *src);` which is a helper macro which
sets the pointer to NULL after freeing.
Now, there's a new issue -- since the temporary buffer is now NULL,
next frame we'll try to remake it! So I've introduced a static bool
which disables the filter entirely if `SDL_RenderReadPixels` fails.
Without this, it'd create and destroy a surface every frame, which
could lead to slowdown. (Not as slow as the filter when it DOES work,
but still...)
I also added a line which frees the second temporary surface... it's
weird that was missing in the first place, but I think reimplementing
analogue mode was one of the last things I did for the renderer
rewrite anyways.
Resolves#1223.
PR #1226 tweaks both the crew and the stats screens. When there's no
trinkets in the level, it removes the trinket count from the STATS
screen in the menu. This, however, is missing a `custommode` check,
meaning that the main game is ALSO missing the trinket count.
This PR fixes that oversight.
There's a problem in #1224 where it breaks spawning custom activity
zones. After a bit of confusion after this was reported, I realized
that I removed the fallback from `getcrewman` and changed the return
value to `-1` if the entity isn't found, to avoid returning the wrong
entity (entity 0, aka probably the player).
Unfortunately, it seems like a ton of levels (including my older ones)
rely on this behavior.
Creating custom activity zones is a long process which uses a bunch of
unintended behaviour, which includes targeting a crewmate with color
35. With the change I mentioned earlier, the `getcrewman` function
would return `-1` instead, which was out of bounds of the entity array,
so the game avoided spawning the activity zone at all. The prior
behaviour of falling back to entity 0 (most likely the player) would
spawn the activity zone around the player instead.
Nowadays, I try to spawn a crewmate with color 35 anyways so I can
control where the box spawns (instead of on the player always), however
most people don't (and haven't) so reverting this change seems best for
now.
If we wanted to reintroduce the `-1` fallback in the future, things
that call `getcrewman` would have to check for `-1` and use `0`
instead, but that would require a lot more testing and studying where
it's used, and I'd rather squash this bug quickly and worry about
cleanliness later.
Entity colors are just integers. Their colour ID gets passed through a
big switch, returning different RGB values depending on the colour ID
(and can also get affected by randomness or other game state.)
But because of this, there's a bunch of random numbers floating around,
with no actual description on what they are other than comments which,
while most of the time are accurate, only exist in the switch.
To fix this, this commit adds a new enum which labels every colour.
While we can't use it as a type (as we need to allow colours outside of
what are defined, in case people want a "pure white", and scripting can
set any colour ID they want), colours have to stay as `int`.
This PR adds a new XML property for the player's colour. It is 0 by
default, but you can change it to any colour ID. For example, making
the player use the trinket color is `<PlayerColour>3</PlayerColour>`.
This is mostly a quality-of-life addition, as the player's colour is
always 0 unless changed by scripts. A lot of levels which use different
player colours use an intro script which both changes the player's
colour and sets their respawn colour, which works great for finished,
completed levels, but makes playtesting a little more annoying as they
will spawn in as the wrong colour. Adding a level property for the
default player colour fixes this annoyance.
Additionally, this changes the behavior of `restoreplayercolour`. This
command used to set the player's colour to 0 (ignoring the respawn
colour, so when Viridian would die, they would revert to the respawn
colour). Now, it sets both Viridian's colour AND the respawn colour to
what was present in the level file. This way, you can temporarily
change the player colour using the script commands, and then use
`restoreplayercolour` to revert back to what the player colour
normally is.
The start point colour has also changed, to show the player colour
instead of always colour 0.
Like most changes like this, a way to change this in-editor does not
yet exist, but is planned for the future.
Turns out there was a little miscommunication with the translator -
they said the option needed to say "Ślōnsko" but were only talking
about correcting the first word, where I thought the whole thing needed
to be replaced.
If you push a button to set a controller binding, you may either hear
one Viridian squeak, two Viridian squeaks (a louder one), or Viridian
doesn't stop squeaking until you let go of the button. While you hear
the continuous squeaking, your save file is also repeatedly saved.
There are two small bugs at play here:
- the squeak is actually played in two different places at the same
time (both in titleinput() whenever a button is pressed, and in
updatebuttonmappings() when a mapping is succesfully changed)
- titleinput() doesn't register that a button is held down and applies
the button (and saves to file) every frame for as long as the button
is held
This commit fixes both these issues. Now a single button press always
causes one squeak, and only if the bindings actually changed. Your save
file is also no longer saved repeatedly from holding down the button.
In an effort to remove magic numbers, I've given every entity type a
name. Hopefully I didn't miss anywhere.
Also, add `createentity` case 100 for backwards compatibility.
Co-authored-by: NyakoFox <nyakowofox@gmail.com>
Co-authored-by: Dav999 <dav999.tolp@gmail.com>
This argument forces the textbox position, meaning it won't be moved
to be inside of the bounds of the screen (nor have the 10 pixel padding
on each side.)