1
0
mirror of https://github.com/TerryCavanagh/VVVVVV.git synced 2024-06-26 06:28:30 +02:00
Commit Graph

2443 Commits

Author SHA1 Message Date
Misa
8e3ec9aeef Use enums for time trial indexes
This adds an anonymous enum for time trial indexes (e.g. the bestrank,
bestlives, etc. arrays and timetriallevel), and replaces all integer
literals with them.

Just like the unlock arrays, these are indexes to an array in XML save
files, so the numbers matter, and therefore should not use strict
typechecking.
2023-06-05 17:57:23 -07:00
Misa
e931f2a4a1 Use enums for unlock, unlocknotify, unlocknum
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.
2023-06-05 17:57:23 -07:00
Misa
14d034e4c6 Use enums for swngame
This replaces the swngame int variable with a named enum and enforces
strict typechecking on it.

Strict typechecking is okay here as the swngame variable is not part of
the API surface of the game in any way and is completely internal.

And just to make things clear, I've added a SWN_NONE enum to use for
initialization, because previously it was being initialized to 0, even
though 0 was the Gravitron.
2023-06-05 17:57:23 -07:00
Misa
414b0647aa Correct orientation of Game Saved clock in Flip Mode
The clock on the Game Saved quicksave screen has always been upside-down
in Flip Mode. And technically, the trinket was too, but this was
unnoticeable because the default trinket sprite is symmetrical.

To fix this, draw flipsprites.png if these sprites are being drawn in
Flip Mode instead of sprites.png.
2023-06-05 17:57:23 -07:00
Misa
4ea26617b8 Initialize currentsong to -1
There's not any ill effects of it being initialized to 0 that I am aware
of (because in most cases, it either gets overwritten anyways or there
isn't a track playing in the first place), but it shouldn't be 0,
because that's Path Complete, so fixing this just in case.
2023-06-05 17:57:23 -07:00
Misa
4058975ce9 Use enums for sound effects
This adds an anonymous enum for sound effects and replaces all calls to
music.playef that use integer literals.

This is not a named enum (that can be used for strict typechecking)
because sound effect IDs are essentially part of the API of the game -
many custom levels use these numbers. This is just to make the source
code more readable without needing a comment to denote what number is
what sound.
2023-06-05 17:57:23 -07:00
Misa
cdeca65be7 Use enums for music tracks
This adds an anonymous enum for music tracks and replaces all calls to
music.play and music.niceplay that use integer literals. Additionally,
this is also done for integer literals for cl.levmusic (except 0) and
music.currentsong where appropriate, but _not_ the music areamap because
that would not make it look very aesthetically pleasing in the code.

This is not a named enum (that can be used for strict typechecking)
because music track IDs are essentially part of the API of the game -
almost every custom level uses these numbers. This is just to make the
source code more readable without needing a comment to denote what
number is what track.
2023-06-05 17:57:23 -07:00
Misa
e9eeaa4186 Remove unneeded play()s in intermission menu
For some reason these were here, but they don't do anything, because the
music here should be playing Presenting VVVVVV already.
2023-06-05 17:57:23 -07:00
Misa
ef46dadb68 Show skip prompt during credits and ending picture
This adds a "- Press {button} to skip -" prompt to both the credits and
ending picture sequences.

It was always possible to skip them by pressing Enter, but not many
people knew this. In fact, even I didn't know this until I saw Elomavi
do it a year or so ago. So it's not really intuitive that this is
possible.

The prompt only shows up if you've completed the game before, and
disappears after two seconds similar to the "[Press {button} to return
to editor]" text.

Unfortunately, given how the game works, game completion is detected
based on if you have unlocked Flip Mode or not. At this point, the
unlock for the game being completed (unlock 5) will already be set to
true no matter what during the Plenary fanfare, but the Flip Mode unlock
(unlock 18) won't be until the player hits "play" on the main menu. As a
special case, the prompt will always show up in M&P (because Flip Mode
is always unlocked in M&P).
2023-06-05 17:57:23 -07:00
Misa
d841612be2 Prevent deleting saves in special or customs
This prevents deleting telesaves and quicksaves in special modes and
custom levels.

Otherwise, rolling credits in a custom level would still delete the main
game quicksave.
2023-06-05 17:57:23 -07:00
Misa
41126c2097 Fix bug: Unable to skip credits in certain cases
If you had the map button held before the game transitioned to the
credits and ending picture sequences, then you wouldn't be able to skip
them, because those gamemodes don't have logic to detect when you've
released the map button.

To fix this, just implement the map button release logic.

We do need a better input system soon...
2023-06-05 17:57:23 -07:00
Dav999
6148550472 Fix setactivityposition still taking two arguments
This command was changed from setactivityposition(x,y) to
setactivityposition(y), but there's a small problem here:

```diff
             else if (words[0] == "setactivityposition")
             {
-                obj.customactivitypositionx = ss_toi(words[1]);
                 obj.customactivitypositiony = ss_toi(words[2]);
             }
```

This meant that the function still took two arguments, the first of
which was unused and the second of which was the Y position of the
activity zone. This is now fixed.
2023-06-04 08:59:40 -07:00
Misa
d09b0d6d84 Fix bug: Playing music during Game Over screen
This fixes a long-standing bug where it's possible to play music during
the Game Over screen in No Death Mode. All you have to do is die while
music is fading out from one area to the next.

The easiest way to do this is in the entrance to Space Station 2, since
there's a music change to Passion for Exploring in Outer Hull (you will
need to go into the zone far enough to activate Pushing Onwards first),
which also contains spikes to die on.

Basically, it's a simple oversight because the nicefade system relies on
music fading out to start playing the next track, but in this case, No
Death Mode fades the music out without accounting for that. It's best to
just disable nicefade entirely when dying in No Death Mode.

Thanks to KSS for reporting this bug.
2023-05-21 23:31:18 -07:00
Misa
7ff4949066 Call savestatsandsettings after unlocking MotU
This calls Game::savestatsandsettings() after unlocking Master of the
Universe (the achievement for completing No Death Mode), instead of
before.

This is not a big deal since Game::savestatsandsettings() is called
anyway whenever the game is gracefully closed since 2.3, but it helps to
make sure people won't lose their achievement data.
2023-05-21 23:08:09 -07:00
Misa
25b4361563 Allow quitting to menu if gamestate is EDITORMODE
Otherwise you wouldn't be able to quit from the editor normally.
2023-05-20 15:22:08 -07:00
Misa
24ef59c65e Prevent other cases of losing unsaved levels by returning to menu
2.3 already made it so that if you ran the `rollcredits` command during
in-editor playtesting, you wouldn't be returned to the title screen
while losing unsaved level changes. But there are plenty of other ways
to go back to the title screen from in-editor playtesting too. Namely,
gamestate 1015 (the gamestate after completing a level) and 82 (time
trial complete).

So just add the appropriate checks to those gamestates, and add a
catch-all check in Game::quittomenu(). Additionally,
Game::updatecustomlevelstats() should not update custom level stats
during in-editor playtesting (otherwise it would still happen even if
the game didn't bring you back to the title screen).

Editor notes will also be shown if the game prevents you from going to
the title screen.

Also, just to make things clear, I also added a level note for when the
level is completed during in-editor playtesting. This is just to make it
clear in cases where it might not be obvious that the game returned you
to the editor for this reason. E.g. you have a terminal that calls
gamestate(1013) in a level with 0 custom crewmates, but when you
activate it, it looks like the terminal didn't work for some reason and
just brought you back to the editor. But that's just only because you
literally just completed the level.
2023-05-18 20:01:03 -07:00
Misa
dea77e98fa Defer hardreset to end of frame in quittomenu
This fixes a bug where the wrong music can play on the title screen, as
reported by AllyTally on Discord.

The bug can be triggered by triggering a room transition right as
game.quittomenu() is called (which is easiest to achieve by placing the
player on an oscillating/"out of bounds" room border in a custom level
so they go back and forth between two rooms every frame, and triggering
gamestate 1013, which starts a fadeout to menu if all custom crewmates
are rescued).

When this happens, game.quittomenu() calls script.hardreset(), but the
rest of the frame still executes, even though we set game.gamestate to
TITLEMODE too (because game.quittomenu() was called by
game.updatestate() which was called by gamelogic(), and game.gamestate
is only checked at the start of the frame). This ends up triggering a
room transition, and since map.custommode is guaranteed to now be off
(because of script.hardreset()), the main game music area code kicks in,
and plays something that isn't Presenting VVVVVV.

The bug here is that we're resetting too early when we still have the
rest of an in-game frame to execute. So, instead, we should only reset
at the end of the frame, and this can be achieved with a defer callback.
2023-05-18 19:11:04 -07:00
Misa
474cdc092e Use levelDirError for graphics errors too
This will actually do several things:

(1) Make the tile size checks apply to the appropriate graphics files
    once again.
(2) Make the game print a fallback error message if the error message
    hasn't been set on the levelDirError error screen.
(3) Use levelDirError for graphics errors too.
(4) Make the error message for tile size checks failing specify both
    width and height, not just a square dimension.
(5) Make the error messages mentioned above translatable.

It turns out that (1) didn't happen after #923 was merged, since #923
removed needing to process a tilesheet into a vector of surfaces for all
graphics files except sprites.png and flipsprites.png. Thus, the game
ended up only checking the correct tile sizes for those files only.

In the process of fixing this, I also got rid of the PROCESS_TILESHEET
macros and turned them into two different functions: One to make the
array, and one to check the tile size of the tilesheet.

I also did (2) just in case FILESYSTEM_levelDirHasError() returns false
even though we know we have an error.

And (3) is needed so things are unified and we have one user-facing
error message system when users load levels. To facilitate this, I
removed the title string, since it's really not needed.

Unfortunately, (1) doesn't apply to font.png again, but that's because
of the new font stuff and I'm not sure what Dav999 has in store for
error checking. But that's also why I did (4), because it looks like
tile sizes in font.png files can be different (i.e. non-square).
2023-05-17 17:11:26 -07:00
Misa
68199396bd Set custommode and custommodeforreal before loading level
This fixes a bug where if a level errors upon loading, it wouldn't take
you back to the levels list.
2023-05-17 12:12:36 -07:00
Misa
28ef3dd7bf Use quittomenu in gotoerrorloadinglevel
game.quittomenu() correctly resets state, as it's the function that's
always used when quitting to menu. This fixes a bug where if a level
with assets failed to load, it wouldn't unload the assets.
2023-05-17 11:45:21 -07:00
Misa
9387186083 Use setLevelDirError for level not found & parse errors
This exports the previously-internal setLevelDirError function in
FileSystemUtils and uses it for if a level is not found or there was a
parsing error. Previously, if a level failed to load in these ways, it
would take you to the error screen with no error, while printing it to
the console. But this makes it more user-friendly.

As a bonus, the text is localizable, just like the existing usage of
FILESYSTEM_setLevelDirError for if a path couldn't be mounted.
2023-05-17 10:09:59 -07:00
Misa
a5eb361448 Set TITLEMODE if loading level results in error
After the scriptclass::startgamemode refactor, a lot of common code is
still being executed even if the level loading failed. This sets the
game-gamestate to TITLEMODE in gotoerrorloadinglevel(), and also returns
early just in case.

Fixes #975.
2023-05-17 08:42:50 -07:00
Misa
27aa10a18c Fix regression: Editing script disables mute buttons
This is quite a simple bug: If you edit a script, then close it, you
will no longer be able to use the mute buttons (N and M).

The problem here is that in 2.3, key.disabletextentry() was called when
closing a script. However, #944 removed the call. Therefore, a
regression.
2023-05-15 18:25:43 -07:00
Misa
ec587fc37e Remove bogus warning if CLI playtesting zip level
If you used command-line playtesting to load a level in a zip, the game
would print a warning saying the level wasn't found. This is because the
warning is printed when it tries to load a level before it loads zips,
inside the metadata load function itself.

To fix this, just move the responsibility for printing the error outside
the function, and put it on the caller.
2023-05-15 18:12:28 -07:00
Misa
0f45e0c52e Print binary blob check fails and remove EOF check
This prints all binary blob check fails. It's an error if the game
rejects the header and will refuse to load it at all, and a warning if
the game continues on.

This also removes the EOF check (`offset + header->size > size`) as a
fatal error. It will only print a warning now. If the last header goes
past the end of file, it will be handled gracefully by PhysFS, which is
the same case in VVVVVV 2.2. This actually fixes a regression from 2.3
where certain custom level tracks that were working perfectly fine in
2.2 (e.g. Summer Spooktacular's track 15) refused to play since 2.3.
2023-05-15 18:04:37 -07:00
Misa
8036471e76 Handle cases where less bytes are read than expected
This checks the return value of PHYSFS_readBytes() in all cases, and
uses a wrapper to not duplicate common logic. If the read fails, then it
will vlog an error, else if the amount of bytes read was less than
expected, it will vlog a warning.

Additionally, the space allocated for a file in
FILESYSTEM_loadFileToMemory is SDL_calloc()ed instead of SDL_malloc()ed
so if there are less bytes than expected, the memory will at least be
zeroed. This also means we don't have to do the null termination,
because the last byte will already be zeroed.

The return value of PHYSFS_readBytes() when reading the headers of
binary blobs now assigns to `header->size`, so the call has been placed
after the increment to `offset` because `offset` needs the correct (i.e.
intended) size of the header.
2023-05-15 17:37:07 -07:00
Misa
90c1a39231 Remove UTF8-CPP from non-bundled dependencies
UTF8-CPP was removed but Dav forgot to also remove it from dependencies
if BUNDLE_DEPENDENCIES was disabled.
2023-05-15 16:26:31 -07:00
Reese Rivers
6158c27205 Update Esperanto language files for new strings 2023-05-08 12:59:16 -07:00
Dav999
d072998995 Add section on editing existing strings to README-programmers.txt
In the past I was thinking we could use some kind of feature in VVVVVV
to track outdated strings across language files. But as it turns out, a
manual solution is actually *perfect* (in combination with automatic
syncing): duplicating strings and marking the old one as outdated. We
started doing it in recent PRs, so let's make it official by adding it
to the readme.
2023-05-08 12:59:16 -07:00
Dav999
bfe068096f Update Dutch language files for new strings
These are strings for #944 and #963.
2023-05-08 12:59:16 -07:00
Dav999
943362559c Adapt font size as needed for "Credits" title in rolling credits
In Italian, "Credits" is "Riconoscimenti", which runs offscreen with
the 3x font size that this title uses in the rolling credits at the end
of the game. I'm not sure if the translators saw that specific
instance, or thought the limit complaint was about the main menu button
all along (which is more prominent and *does* stick out far enough that
the complaint could plausibly have been about that, from a translator's
perspective!)

Either way, it's solved now: this string's width is now checked, and if
it will run offscreen at 3x size, it will now be displayed at 2x size
instead. The limit has been increased from 13 to 20 in the language
files accordingly.
2023-05-08 12:59:16 -07:00
Dav999
3b9d3a687b Add |upper to Italian number strings
The translators indicated that they wanted to use |upper here but it
didn't seem to work, therefore they left it as-is because it was minor.
2023-05-08 12:59:16 -07:00
Dav999
4aa576cd66 Update Italian language files
These updates were delivered 14 Apr, with further updates on 18 Apr.
2023-05-08 12:59:16 -07:00
Dav999
78a3dc23d4 Update Portuguese (BR) language files
This already happened on 2023-03-16, but I held off on updating the
repo's version a bit long: I wanted to wait a little to batch it up
with the next update, but the next update only arrived today, so...
2023-05-08 12:59:16 -07:00
AllyTally
6abb76238d Add textboxtimer command 2023-05-08 12:49:05 -07:00
Misa
fb38668182 Fix regression with controller binds on first launch
I noticed that in 2.3, the game would launch with default controller
binds upon first launch (e.g. no pre-existing unlock.vvv or
settings.vvv), but in 2.4, this wasn't the case, and the default binds
would only be set the next time the game was launched. This would result
in you being essentially unable to use the controller on first launch
save for the analogue stick and D-pad to move between menu selections
and move the player.

Bisecting pointed to commit 3ef5248db9 as
the cause of the regression. It turns out returning early upon error or
a file not existing didn't set the default controller binds, because
they were done at the end of Game::deserializesettings(). But the binds
would be set on the next launch because if the file didn't exist, a new
file would be written, not with the default binds, but then the next
launch would read the file, see there were no binds, and then set the
default binds accordingly.

To fix this, I made it so that the default controller binds are set when
Game is initialized. That way, it covers all cases where the game can't
read a settings file.
2023-04-15 11:20:48 -07:00
Dav999-v
4f2fe163bc Fix rebinding "menu" (esc) bindings to different actions
Ever since 2.3, if you bind a controller button to the "menu" action
(i.e. back/escape) you won't be able to change that button to any other
action, because pressing it anywhere in the binding menu will exit to
the previous menu, without applying the binding.

I know action sets will overhaul everything, but 2.4 may (probably
"should") come out before we have action sets. This part is very
broken, and the fix is very easy: just move the bind-assigning code to
above the menu-return-on-esc code, and add a return.
2023-04-15 10:58:57 -07:00
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