For localization, the "Thanks for playing!" text was split into two
lines, when it was originally one line. Unfortunately, it was not
updated to account for Flip Mode, so in Flip Mode, it looked like
"playing! Thanks for".
This has been fixed.
These weren't getting updated when cycling language with CTRL+F8. This
is because they would be already baked. Luckily, at least the bool
keeping track of whether or not to translate them in the first place
already exists, so we can just rely on that.
This allows switching languages while a text box is on screen by saving
the necessary state for a text box to be retranslated when the language
is switched.
This saves the state of the position and direction of the crewmate that
the text box position is based off of (if applicable), and the text
case of the text box, the script name of the script, and the original
(English) lines of the text box. I did not explicitly label the original
lines as English lines except in a main game context, because
technically, custom levels could have original lines in a different
language.
Unfortunately, this doesn't work for every text box in the game.
Notably, the Level Complete, Game Complete, number of crewmates
remaining, trinket collection, Intermission 1 guides, etc. text boxes
are special and require further fixes, but that will be coming in later
commits.
This makes it so that the boolean to draw mode indicator text is false
if there aren't any modes active.
Otherwise, when loading in, the in-game timer would only come in after a
few seconds instead of appearing when the fade-in finishes.
I forgot that the position of the activity zone can vary based on
setactivityposition() in custom levels. So account for that.
Additionally, if the activity zone prompt is far down enough, then we
don't need to move the mode text at all.
This makes the mode indicator text be visible even if there is an
activity zone prompt on screen, by making it so that it gets moved if an
activity prompt is being rendered.
This is to make sure that it's visible no matter what, even if e.g. a
custom level starts the player on an activity zone.
Trophy text can overlap with the timer. How bad it is depends on the
localization but in English some text definitely overlaps.
Simple fix is to disable rendering the timer if we are rendering any
trophy text.
This is mostly so people making levels in an RTL language have a more
pleasant and logical experience. If roomtext is placed in a level set
to RTL, it will get p1=1, which makes that roomtext right-aligned.
Because, imagine for English you click to place roomtext, and the text
runs left of where you clicked, which wouldn't be logical.
Since it's an entity-bound property, switching RTL on and off either in
the editor or via a script does not affect existing entities.
If you load in to gameplay with invincibility mode, glitchrunner mode,
Flip Mode, or slowdown enabled, then there will be text displayed on
screen for a few seconds that says so.
This is to serve as a useful reminder. A common pitfall with using
invincibility is forgetting to turn it off when you don't want it
anymore. What usually happens is that players forget that they have it
on until they encounter a hazard. Now, they can realize it as soon as
they load in.
See #1091.
This has a lot of reading-orientation stuff on it like "Key: value",
so easiest is to just flip the whole design of the screen rather than
trying to flip individual strings.
Okay, the "Font:" thing needed some local code after all, because both
the interface font as well as the level font are used there. But it's
good enough - all the other places can just use the flag.
Notably, I also used this for the menus, since the existing ones are
kinda LTR-oriented, and it's something that we don't *really* have to
do, but I think it shows we care!
Again, the RTL property controls whether textboxes will be
right-aligned, and that kind of stuff. It can't be font-bound, since
Space Station supports Hebrew characters and we want to be able to
support, say, a Hebrew translation or Hebrew levels in the future
without having to make a dedicated (or duplicated) font for it.
Therefore it's a property of both the language pack as well as custom
levels - like custom levels already had a <font> tag, they now also
have an <rtl> tag that sets this property.
Right now, we'll have to hardcode it so the menu option for the Arabic
font sets the <rtl> property to 1, and all the other options set it to
0. But it's future-proof in that we can later decide to split the
option for Space Station into an LTR option and an RTL option (so both
"english/..." and "עברית" would select Space Station, but one sets the
RTL property to 0 and the other sets it to 1).
There is a clash between the timer text and the "Survive for 60
seconds!" text. It's minor in English but it can be worse in other
languages (e.g. Polish).
So make the timer go away when that text is onscreen.
The "[Press {button} to return to editor]" and the "TIME:" text
overlapped, which resulted in an ugly clash.
To fix this, make the return editor text take priority over the timer
text. This involves a minor refactor to first calculate whether or not
we should draw the return editor text before we check if we should draw
the timer text.
The new localization-related credits are placed 5 characters from
the left border in the rolling credits (at x=40), which means the
limit was 35 8x8 characters. Which was broken by several languages.
So instead, move the string leftward a bit if it would run offscreen
otherwise.
The header "Translators", as well as the language names, were using
PR_FONT_8X8, even though it was translatable text. This is now fixed.
(Also, the CJK spacing for the language names is now higher because
that looked nicer)
This commit adds translation credits to the game's end credits
screen. Note that this is not implemented into the menu credits
screen yet. The translator name list is subject to tweaks, and
additionally some localised strings ("Localisation Project Led by"
and "Pan-European Font Design by") run off the screen in some
languages (Catalan, Spanish, Irish, Italian, Dutch, European
Portuguese and Ukrainian) and will need to be addressed later.
The level debugger is toggleable in playtesting mode by pressing Y.
You can toggle whether or not the game is paused inside of the debugger
by pressing TAB. The debugger screen allows you to see entity and block
properties, and allows you to move them around.
This ensures loading a 2.4 save in the English-only 2.3 or earlier
doesn't result in missing characters because a translated area name
appears in the save file. We are not reading from <summary> anymore
in 2.4.
The way this is done is by not translating the area names inside
mapclass::currentarea(), but at the callsites other than the one which
saves the <summary>.
For both `tele` and `quick`, I removed these attributes of class Game:
- std::string *_gametime
- int *_trinkets
- std::string *_currentarea
- bool *_crewstats[numcrew]
All this info can now be gotten from members of Game::last_telesave and
Game::last_telesave. I've also cleaned up the continue menu to not have
all the display code appear twice (once for telesave and once for
quicksave).
RIP "Error! Error!" though lol
This is what got saved to the area part of the <summary> tags, and it
was specifically set upon pressing ACTION to save in the map menu.
Which meant tsave.vvv may not get an accurate area name (notably
"nowhere" if you hadn't quicksaved before in that session) even though
it's not displayed anywhere so it didn't really matter. But this
variable can be removed - there's only one place where <summary> is
written for both quicksaves and telesaves, so that now gets the area
at saving time.
Fun fact: custom level quicksaves also have a <summary> tag, and it's
even less functional than the one in tsave.vvv, because it stores
whatever main-game area name applies to your current coordinates.
So I simply filled in the level's name instead (just like what the
actual save box says).
Game::telesummary and Game::quicksummary stored the summary string for
the save files - which is the <summary> tag that says something like
"Space Station, 10:30:59". The game only ever displays the quicksave
variant of these two, for "Last Save:" on the map menu's SAVE tab.
So the telesave has a <summary> too, but it's never displayed anywhere.
(In fact, the area is often set to "nowhere"...)
However, the summary strings have another function: detect that both
the telesave and quicksave exist. If a summary string for a save is
empty, then that save is considered not to exist.
I'm refactoring the summary string system, by making the new variables
Game::last_telesave and Game::last_quicksave of type struct
Game::Summary. This struct should have all data necessary to display
the summary string at runtime, and thus translate it at runtime (so
we don't store a summary in a certain language and then display it in
the wrong font later - the summary can always be in the current
language). It also has an `exists` member, to replace the need to
check for empty strings.
The <summary> tag is now completely unused, but is still written to
for older versions of the game to read.
(This commit does not add the new string to the language files, since
Terry now added it separately in his own branch)
It'll start working in the next commit... See the description there.
(This commit does not add the new strings to the language files, since
Terry now added them separately in his own branch)
Since VVVVVV 2.3, time trial best times are stored not just with the
number of seconds, but also the number of frames. However, there was
no room to display it with the old design of the time trials screen.
Now there is, so it can easily be displayed now with a small change!
Unset frames are stored as -1, which fits perfectly into the frames
argument of help.format_time(), because in that case the amount of
centiseconds is not shown.
It should be noted that opening VVVVVV 2.2 will instantly wipe your
frames records, as described by #1030. But many people will likely
never open 2.2 anymore.
I really thought I was going to need to block changing the language
in-game altogether, but activity zone prompts are now fixed and the
only obvious problem I can think of right now is having a dialogue
open, so I just disable the language option if a textbox is displayed.
(like how the map menu only has the save option if a script is running)
The translations for the prompts used to be looked up at creation time
(when the room is loaded or the activity zone is otherwise spawned),
which meant they would persist through changing the language while
in-game. This would look especially weird when the languages you switch
between use different fonts, as the prompt would show up in the old
language in the new language's font.
This problem is now fixed by letting the activity zone block keep
around the English prompt instead of the translated prompt, and letting
the prompt be translated at display time. This fixes a big part of the
reason I was going to disable changing the language while in-game; I
might only need to do it while textboxes are active now! :)
If someone makes a build of the game without copying the correct
folders, their version will have no translations, and display some text
wrong (like credits or button glyphs, or any custom levels that rely on
characters in the fonts being there). So I added a message in the
bottom left corner of the title screen to warn for that.
Showing the option on the "play a level" option feels to me as though
inexperienced players would think they're not supposed to open the
player levels, because the message says editor levels are unsupported,
right? But the message is only referring to the level editor, so in my
opinion, it's clearer to only show it there.
This commit removes the `NO_EDITOR` and `NO_CUSTOM_LEVELS` defines,
which cleans up the code a lot, and they weren't really needed anyways.
This commit also disables the editor on the Steam Deck, and adds a
program argument to re-enable the editor, `-enable-editor`.
If this text on the time trial results screen would overlap with the
time value, all rank labels will be displayed on the header line
instead ("TIME TAKEN:" etc). This works because the overlap with the
time most likely only happens with CJK fonts (where the time will be
very wide because of the font size) while strings like "TIME TAKEN"
take up very little space due to only needing 4 characters or so for
the same information.
- ERROR/WARNING screen title was overlapping with message
- Crewmate screen names and rescued statuses were overlapping with each
other
- Textboxes on Level Complete screen were overlapping with each other
and the crewmate was not vertically centered in the box
- Some strings were running into each other in flip mode, instead of
being moved out of each other (PR_CJK_HIGH and PR_CJK_LOW worked the
wrong way around because of FLIP macros being applied to Y coords)
- In-game esc menu was "bouncy" with selected menu options because of a
hardcoded 16 pixel offset
- Bindings in the gamepad menu were overlapping with each other
- Some Super Gravitron "Best Time" labels and values were a little too
close
Turns out `graphics.drawrect` exists. Well, not anymore!
This was another function from before the renderer rewrite which tried
to draw a rectangle by using four filled rectangles. We can draw
outline rectangles properly now, so let's make sure everywhere does it!
This adds an anonymous enum for the unlock and unlocknotify arrays and
unlocknum function, and replaces all integer literals with them.
This is not named and thus cannot be used for strict typechecking
because these are actually indexes into an array in XML save files, so
the numbers themselves matter a lot.