1
0
Fork 0
mirror of https://github.com/TerryCavanagh/VVVVVV.git synced 2024-11-14 06:59:42 +01:00
Commit graph

500 commits

Author SHA1 Message Date
Misa
85074c1402 Prevent spawning crewmates/activity zones in custommode
Looks like there wasn't a custommode check for the spawning of crewmates
based on which crewmates were rescued, but now there is.

This has gone undiscovered for a long time, mostly because people don't
use the rescued() internal command.
2020-04-30 05:05:04 -04:00
Misa
192b2f2dba Don't re-draw credits scroll background every frame
While I was working on my over-30-FPS patch, I found out that the tower
background in the credits scroll was being completely re-drawn every
single frame, which was a bit wasteful and expensive. It's also harder
to interpolate for my over-30-FPS patch. I'm guessing this constant
re-draw was done because the math to get the surface scroll properly
working is a bit subtle, but I've figured the precise math out!

The first changes of this patch is just removing the unconditional
`map.tdrawback = true;`, and having to set `map.scrolldir` everywhere to
get the credits scrolling in the right direction but make sure the title
screen doesn't start scrolling like a descending tower, too.

After that, the first problem is that it looks like the ACTION press to
speed up the credits scrolling doesn't speed up the background, too. No
problem, just shove a `!game.press_action` check in
`gamecompletelogic()`.

However, this introduces a mini-problem, which is that NOW when you hold
down ACTION, the background appears to be slowly getting out of sync
with the credits text by a one-pixel-per-second difference. This is
actually due to the fact that, as a result of me adding the conditional,
`map.bscroll` is no longer always unconditionally getting set to 1,
while `game.creditposition` IS always unconditionally getting
decremented by 1. And when you hold down ACTION, `game.creditposition`
gets decremented by 6.

Thus, I need to set `map.bscroll` when holding down ACTION to be 7,
which is 6 plus 1.

Then we have another problem, which is that the incoming textures desync
when you press ACTION, and when you release ACTION. They desync by
precisely 6 pixels, which should be a familiar number. I (eventually)
tracked this down to `map.bypos` being updated at the same time
`map.bscroll` is, even though `map.bypos` should be updated a frame
later AFTER updating `map.bscroll`.

So I had to change the `map.bypos` update in `gamecompleteinput()` and
`gamecompletelogic()` to be `map.bypos += map.bscroll;` and then place
it before any `map.bscroll` update, thus ensuring that `map.bscroll`
updates exactly one frame before `map.ypos` does. I had to move the
`map.bypos += map.bscroll;` to be in `gamecompleteinput()`, because
`gamecompleteinput()` comes first before `gamecompletelogic()` in the
`main.cpp` game loop, otherwise the `map.bypos` update won't be delayed
by one frame for when you press ACTION to make it go faster, and thus
cause a desync when you press ACTION.

Oh and then after that, I had to make the descending tower background
draw a THIRD row of incoming tiles, otherwise you could see some black
flickering at the bottom of the screen when you held down ACTION.

All of this took me way too long to figure out, but now the credits
scroll works perfectly while being more optimized.
2020-04-30 05:04:13 -04:00
Misa
1fd20e5e99 Render screen effects in maprender()
I had forgotten that the game flashed and did screen-shaking when you
pressed ACTION to quicksave.

While testing for my over-30-FPS patch I stumbled across this.
2020-04-29 19:35:00 -04:00
Misa
28db7038fc Merge drawtowerbackgroundsolo() into drawtowerbackground()
It's less code being copied and pasted, especially since for my
over-30-FPS patch I would have to make a separate function for each if
both of them were still there, but if they're unified into one then I
will only have to make one more function.

And since map.scrolldir is now used outside of GAMEMODE, we'll need to
reset it in hardreset() and when exiting playtesting.
2020-04-29 18:08:13 -04:00
Misa
e9dd38ee35 Fix descending tower BG redraw
Due to the previous commit, the descending tower background now has to
account for map.bscroll, or else it will be off by one pixel from the
incoming textures. But ascending tower backgrounds work fine, so no need
to do anything with those.
2020-04-29 18:08:13 -04:00
Misa
b50ca5b9e6 Don't redraw tower background in descending towers
Looks like this was done as a quick fix instead of taking the time to
figure out the math needed to actually draw the incoming textures, which
is fair enough - it only makes one room, Panic Room, slightly laggier.

While I was working on my over-30-FPS patch, though, I came across the
fact that this background kept getting entirely redrawn every frame, and
it seems like it would be easier to interpolate descending tower
backgrounds if we scrolled what was already there instead.

Here, we have to draw two rows of incoming textures, otherwise the
scrolling surface will produce black lines.
2020-04-29 18:08:13 -04:00
Misa
f33cbfbe62 Fix editor menu being drawn on top of editor with BGs disabled
Previously, if you had backgrounds disabled in accessibility options,
and went to the editor and opened up the editor menu, it would be drawn
straight on top of what was already there in the editor instead of being
drawn on top of black. So now it's drawn on top of black.
2020-04-29 14:25:39 -04:00
Misa
e92a21cf8a Fix exiting No Death Mode being one menu too far back
I want exiting No Death Mode to go back to the "play modes" menu, not to
the "start game" menu, because it's too far back. Also do the same if
you either die or complete No Death Mode.

Also I initialized Game::wasinintermission, probably a good thing to
initialize variables.
2020-04-27 15:41:07 -04:00
Misa
585ff51ec6 Call hardreset() when returning to menu from editor
During testing, I made a cursed level that set the flash timer to
precisely 1,000,000 frames. It turns out that if I activated the timer
in playtesting, exited playtesting, and exited the editor without ever
re-entering playtesting, the timer still kept going. So to prevent being
able to do that, we should hardreset() when exiting the editor.
2020-04-27 15:07:58 -04:00
Misa
edb930344a Reset screen effects timers in hardreset()
That way a gigantic timer from one in-game jaunt doesn't carry over to
the next.
2020-04-27 15:07:58 -04:00
Misa
94edfcf87e Only render screen effects on the title screen and in-game
In-game because that's where screen effects are used the most. But on
the title screen, screen effects are used when you press ACTION to start
the game, and when you enable screen effects, too.

Otherwise, we don't need screen effects for any other game-gamestate.
2020-04-27 15:07:58 -04:00
Misa
857937326e Put screen effects render handling inside a function
This de-duplicates the screen effects rendering code by putting it
inside a function, Graphics::renderwithscreeneffects(), and using that
instead of copy-pasted code.
2020-04-27 15:07:58 -04:00
Misa
0e082551b1 De-duplicate screen effects timer decrementing
The code to decrement the timers for flashing and shaking is now handled
outside the game-gamestate case-switch, instead of having to be
duplicated inside each render function.

As a bonus, I made it so the timer decrements even if screen effects are
disabled. This is to prevent any theoretical situation where the timer
can "pile up" due to disabled screen effects not letting it tick down.
2020-04-27 15:07:58 -04:00
Misa
b26e94b919 Simplify GAMEMODE loop
Now that towers no longer use separate functions, we can remove the
map.towermode conditional.
2020-04-26 19:07:40 -04:00
Misa
53bad3bcaf Merge towerrender() into gamerender()
This removes a lot of duplicate code, which towerrender() mostly
consisted of, even though the only difference is that it draws a
separate map and screen edge spikes are drawn.
2020-04-26 19:07:40 -04:00
Misa
660f752bae Merge drawtowerentities() into drawentities()
This removes lots of duplicated code that drawtowerentities() did,
because all that really changed was accounting for map.ypos (which can
be done conditionally) and where and when the room wrapped (which can
also be done conditionally).
2020-04-26 19:07:40 -04:00
Misa
b5e813dbbb Make Graphics::drawentities() use a case-switch instead of an else-if
Makes it easier to read and doesn't require copy-pasting or re-typing
'obj.entities[i].size =='.
2020-04-26 19:07:40 -04:00
Misa
02dc1084e7 Fix offscreen teleporter rendering
This fixes an oddity that's only visual, which could only happen in
custom levels by using the createentity() internal command.

For the same reason that the second through fourth tiles of moving
platforms on the top and left was buggily rendered, SDL_BlitSurface()
strikes again to mutate the SDL_Rect we pass it and render the next
SDL_BlitSurface() call inbounds, even though we don't need it to.
2020-04-26 19:07:40 -04:00
Misa
4c45a8ac47 Prevent double-rendering of warping sprites on left and top of screen
Previously, the game could end up rendering a warping sprite twice due
to the fact that it could run "if entity is on the right side of the
screen" right after "if entity is on the left side of the screen" (but
not the other way around). This is most noticeable if you have a custom
player sprite with translucent pixels and stand on the left side of a
warping screen, but the code suggests it happens when warping through
the top of the screen, too.
2020-04-26 19:07:40 -04:00
Misa
276daa11bb Invert entity invis check to reduce indentation level
Instead of doing

    if (!obj.entities[i].invis)
    {
        ...
    }

It's better to do

    if (obj.entities[i].invis)
    {
        continue;
    }

    ...

It reduces the indentation by one level, which is always a good thing.
2020-04-26 19:07:40 -04:00
Misa
3f46a0a2e9 Remove temporary indents from the last commit
In the last commit, I removed having the flip mode conditional directly
inside the sprite-drawing code for each size type, which would reduce
the indentation one level. However, I opted to hold off un-indenting
until this commit, otherwise it would've produced too much noise.
2020-04-26 19:07:40 -04:00
Misa
8536185661 De-duplicate flip mode conditional code in Graphics::drawentities()
The game uses flipsprites.png instead of sprites.png when in flip mode,
mostly to add exceptions for sprites that SHOULDN'T be flipped in flip
mode.

Looks like to achieve this, the routines for sprite drawing got
copy-and-pasted every single time flipsprites.png needed to be
conditionally used, resulting in large amounts of copy-pasted code. And
this copy-pasted code resulted in copy-paste errors, with relating to
VVVVVV-Man, because apparently due to two copy-pasting errors, the
combined giant crewmate in the epilogue uses flipsprites.png even if you
aren't in flip mode, and it also uses the width instead of the height of
sprites_rect when in flip mode (although, this doesn't end up mattering,
but still).

The solution here is to simply change the referenced sprites vector to a
pointer that can conditionally change based on the game being in flip
mode or not.
2020-04-26 19:07:40 -04:00
Misa
c040ceda29 Merge towerlogic() into gamelogic()
This doesn't change anything functionality-wise, but it does remove a
lot of duplicate code, which makes it easier to work on.
2020-04-26 19:07:40 -04:00
Misa
841bfb7eae Fix music not being silent during trinket/crewmate collect
Looks like I forgot to test that my music silencing patch didn't break
the music being silent during the "You have found a shiny trinket" and
"You have found a shiny crewmate" text boxes. So I've added a check for
game.completestop in the music handling in main.cpp.

Found this bug while I was testing my towerlogic/gamelogic merge patch.
2020-04-26 19:07:40 -04:00
Misa
197c7caf08 Add and use Game::save_exists()
This is simply a shorthand for telesummary != "" || quicksummary != "",
to make it easier and less error-prone to negate. This improves
readability.
2020-04-26 17:20:16 -04:00
Misa
7df42242e7 Actually delete saves/unlock.vvv in deletestats()
Having to blank everything out in the stats file is very kludge-y.
2020-04-26 17:20:16 -04:00
Misa
2076898020 Fix deletequick() and deletetele() not deleting their files
The problem here is that we're directly using the C stdio library,
instead of using PHYSFS's stuff. So I've added a function
FILESYSTEM_delete() that does exactly that.
2020-04-26 17:20:16 -04:00
Misa
842eb669b7 Make deletequick() and deletetele() error messages less vague
Now it clearly specifies exactly which file failed to be deleted.
2020-04-26 17:20:16 -04:00
Misa
4f3df23e02 Don't clear telesummary/quicksummary if delete unsuccessful
Otherwise the game will think the saves are gone even though they still
exist.
2020-04-26 17:20:16 -04:00
Misa
047d71840b Remove unnecessary 'game.' qualifiers in Game.cpp
No need to refer to the class global name if we're already in the class
itself.
2020-04-26 17:20:16 -04:00
Misa
85f851bc17 Make "start game" goto play menu if any unlocks, even if saves deleted
This commit fixes a slightly frustrating thing where if you start a new
game, and then exit before saving, "start game" will always take you to
a new game, even though you have unlocked things like the Secret Lab or
Time Trials.

Now, if you select "new game" (only possible if you have something
unlocked), then quit before saving, "start game" will still take you to
the play menu, but "continue" is replaced with "start" and "new game" is
gone.
2020-04-26 17:20:16 -04:00
Misa
833bbdbbef Add function Game::anything_unlocked()
This will be a useful shorthand to ask "do we have the Secret Lab, or
any Time Trial, or Intermission replays, or No Death Mode, or Flip Mode
unlocked?"
2020-04-26 17:20:16 -04:00
Misa
dc2adea8ee Improve ed_settings Esc press handling
This fixes being able to rack up a large amount of stack frames by
pressing Esc repeatedly in the editor, which would be a problem if you
were to then return to the main menu afterwards.

Instead, if Menu::ed_settings is already in the stack, the game will
simply return to that menu instead of creating it. Else, it will just
create the menu.

Also, as extra attention to detail, I made sure that the menu create or
return only happens if Esc opens the settings menu, and not when Esc is
closes it.
2020-04-26 08:15:30 -04:00
Misa
98e33fca9e Fix editor menu options going back to editor not using returnmenu()
Instead of directly using Game::createmenu(Menu::ed_settings), we should
be using Game::returnmenu() here, so the stack frames don't keep piling
up.
2020-04-26 08:15:30 -04:00
Misa
9fca3e111f Improve quit-to-menu menu handling
This stabilizes the code that handles the menu that you land on if you
press Esc and quit to the menu.

Instead of using Game::returnmenu(), we now use the new function
Game::returntomenu() to clearly express intent that we want to return to
a specific menu. So I've added another kludge variable
Game::wasinintermission for the was-in-intermission case.

Also, I made it so that if you didn't have a main game telesave or
quicksave, you just get brought back to the main menu. Because you
shouldn't be able to go to the play menu without a quicksave or
telesave.
2020-04-26 08:15:30 -04:00
Misa
536184f394 Add function Game::returntomenu()
When exiting from a game-gamestate which may have been entered through a
varying amount of menus, the solution is to not use Game::returnmenu(),
and to instead have a way to go back to a certain given menu.
2020-04-26 08:15:30 -04:00
Misa
a60cdb3ab7 Fix the 2nd to 4th tiles of moving plats rendering offset from 1st tile
This commit fixes a bug where the second, third, and fourth tiles of
moving platforms would render offset from the first tile if the moving
platform hit the top or left edge of the screen.

This is due to the fact that SDL_BlitSurface() will end up changing the
coordinates of the rectangle we pass to it to be 0 if they're negative,
but only after it's already been drawn. Previously, we kept re-using the
same rectangle each time we drew each segment of the moving platform,
but since it only changes the draw rectangle after it's already been
drawn, the first tile shows up fine, but not the rest of the tiles,
hence resulting in an offset.

To fix this, we do the same thing as we did for drawing the "really big
sprite" (size-type 9): just reset the rectangle we use every time we
draw a segment of the moving platform.
2020-04-25 18:20:33 -04:00
Misa
da612de1f4 De-duplicate size-type 2/8 drawing by putting them together
They're literally the exact same thing, except one is 4 and the other
has an 8. No need to have all that copy-pasted code.

Actually, the only other difference was that size-type 8 set the
drawRect to sprites_rect instead of tiles_rect for some reason? Even
though it doesn't matter, anyway, because SDL_BlitSurface() only cares
about the X and Y you pass it, not the width and height, which is the
only difference between tiles_rect and sprites_rect.

To make sure that people wouldn't wonder where size-type 8 went if they
saw a blank space between size-type 7 and size-type 9, I kept the
size-type 8 conditional, but inside it is just a comment telling you to
go to size-type 2.
2020-04-25 18:20:33 -04:00
Misa
2f180bb6df De-duplicate repeated size-type 2/8 tile drawing with a for-loop
For some reason, previously it looked like this was a for-loop that was
manually unrolled (or never rolled up in the first place).
2020-04-25 18:20:33 -04:00
Misa
a6c1d13603 De-duplicate map.custommode check when drawing size-type 2/8 entities
Instead of copy-pasting all the BlitSurfaceStandard()s all over again,
just make the referenced vector a pointer that changes depending on
map.custommode.
2020-04-25 18:20:33 -04:00
Misa
6e0b267aac Draw first-pass of H/V warp BGs 3 pixels to the left
There's a noticeable seam in the horizontal and warp backgrounds
whenever you enter a new room. Entering a new room triggers the game to
re-draw the entire warp background instead of simply scrolling what it
already has. This seam is the result of the initial background draw
being misaligned with the rest of the scrolling.

If you get out your measuring tools, you'll see that it's misaligned by
exactly 3 pixels (this applies to both horizontal and vertical warping).
If you look at the part of the code where the game draws fresh warping
textures after scrolling the existing ones offscreen, you'll see it
starts with an offset of 317, which is exactly 320 minus 3. And for
vertical, it uses 237, which is exactly 240 minus 3.

This is where the misalignment comes from. Since the incoming textures
are drawn 3 pixels to the left, but the initial draw isn't, this results
in a misalignment and causes the seam.

To fix this, draw the initial draw of the horizontal and vertical warp
backgrounds 3 pixels to the left.
2020-04-25 15:50:09 -04:00
Pierre-Alain TORET
7328508436 Fix build on DragonFlyBSD 2020-04-23 23:35:33 -04:00
Ethan Lee
ac7ee0e959 Check for GCC7 for implicit-fallthrough support 2020-04-23 15:32:34 -04:00
Misa
58e512d001 Fix weird bracketing in game.gamestate switch-case
It looks like one bracket got out-of-place for whatever reason. This
doesn't affect the case-switch at all, due to how case-switches work,
but it's still weird to look at.

Indentation has been updated accordingly.
2020-04-19 20:51:35 -04:00
Misa
4bea40fc22 Pause all audio output when the game is unfocused
Some custom levels have their own custom music and sync that music to
scripted cutscenes, which is actually pretty impressive. However,
they've always run into a small thorn, which is that you can easily
desync the music by unfocusing the game, because the audio will keep
playing when the game is unfocused.

This should remove that thorn by pausing the audio on unfocus, and
resuming when focused, so that the music can no longer desync, but you
can still pause the game by unfocusing it.

This is yet another feature in VCE that hasn't been upstreamed until
now.
2020-04-19 20:51:35 -04:00
Misa
2016ee1b60 Use an 'else' instead of re-checking 'game.muted' again
Makes the code easier to read and parse.
2020-04-19 20:51:35 -04:00
Misa
9db96f004b Remove Game::globalsound
It looks like this variable was originally intended to keep track of th
volume of the game, but then it was used as a boolean in main.cpp to
make sure the game didn't call Mix_Volume() and Mix_VolumeMusic() every
frame.

However, it is now a problem, because I put the music mute handling code
in the very branch that game.globalsound protects against, but since
game.globalsound is here, if I mute the music, then mute the whole game,
then unmute the music, and then unmute the whole game, sound effects
will no longer be muted but the music will still be muted, until I mute
and unmute the whole game again. This is annoying and inconsistent, so
I'm removing this check from the 'if (!game.muted)' branch.

Plus, given that the Mix_VolumeMusic() and Mix_Volume() calls happen
every frame if the game is muted anyways, it doesn't seem to be a
problem to call these every frame.
2020-04-19 20:51:35 -04:00
Misa
c176127529 Remove useless attributes m_globalVol, set/getGlobalSound from Game
These do basically nothing. The only time they're used is
getGlobalSound() in an if-statement in main.cpp, but all that
if-conditional does is call setGlobalSound() anyway, which is something
that doesn't really have any side effects. So I'm removing these vars to
simplify the code.
2020-04-19 20:51:35 -04:00
Misa
aacd39f5c6 Add "Press N to mute music only" to "Game paused" screen
Because there's a "Press M to mute in game" hint, I'll add a "Press N to
mute music only" hint as well to be consistent.
2020-04-19 20:51:35 -04:00
Misa
43b1b71da1 Add being able to mute the music by pressing N
This is for people who want to use their own soundtrack while playing
the game, but who don't want to mute the sound effects as well.

This feature was added to VCE, but it was added in the strangest way. It
was made an option in "game options" instead of being a keybind, and I
don't know why.
2020-04-19 20:51:35 -04:00
Ethan Lee
68bb84f90b Bools are hard... 2020-04-18 11:38:27 -04:00
Ethan Lee
6f26443783 Pull openDirectoryEnabled out of the openDirectory ifdefness 2020-04-18 11:37:28 -04:00
Misa
ca0e9ec963 Disable "open level folder" in Steam Big Picture mode
The environment variable SteamTenfoot corresponds with the game running
in Steam Big Picture mode or SteamOS if it is defined. There's a
certification process for both full controller support and Big Picture
mode, and being able to launch a file window in Big Picture mode is an
instant cert failure.
2020-04-18 11:32:06 -04:00
Misa
bc9013c228 Add "open level folder" option to playerworlds menu
This simply adds another menu option utilizing what I added in the
previous commit.
2020-04-18 11:32:06 -04:00
Misa
6847eb3a87 Add FILESYSTEM_openDirectory() and _openDirectoryEnabled()
Have to add some includes and put these behind some ifdefs, of course.

I'm pretty sure FreeBSD and OpenBSD and Haiku are POSIX enough that the
"open" command will work on them, too.

I would've loved to make FILESYSTEM_openDirectoryEnabled a simple bool
instead of a function, but I ran into issues with putting it in the
FileSystemUtils header file, so I'll just make it a function and call it
a day.
2020-04-18 11:32:06 -04:00
Misa
ec3f937f93 Handle errors from PHYSFS_readBytes()
This fixes a bug where levels in the levels list duplicate if there's an
invalid file (such as a folder) in the levels directory.

It looks like it happens because we don't free the memory if
PHYSFS_readBytes() encounters an error, even though we should. Then we
get into Undefined Behavior territory and end up reusing memory, and
here it just happens that previously, parsing the entire XML document
for each level file was enough to make the loaded file pointer point to
garbage that would fail the metadata check, but if we optimize it so we
don't parse the entire XML document, it starts reusing memory instead.
2020-04-17 19:14:44 -04:00
Misa
9c4c76f609 Optimize editorclass::getLevelMetaData()
Now whenever it looks at a level file, it NOT parse the entire XML
document, which is a huge slowdown. Loading levels should be really
quick now.
2020-04-17 19:14:44 -04:00
Misa
9aeb9ad739 Add tag finder functions
To find each individual tag quickly, to optimize levels list loading.

I opted to not read the tags <Created>, <Modified>, and <Modifiers> as
they're actually pretty useless.

Also I've added a tag finder for <MetaData> but it's not meant to be
used directly, it's only used to check that the tag exists.
2020-04-17 19:14:44 -04:00
Misa
b4f56d39d7 Add find_tag()
This simply finds a given tag in a buffer and returns what's inside that
tag, making sure to parse XML entities and such.
2020-04-17 19:14:44 -04:00
Misa
9b4975e396 Add is_positive_num() to UtilityClass.cpp
This is a convenience function to tell if a string is not only a number
(and can thus be passed into atoi()), but is also positive in
particular.
2020-04-17 19:14:44 -04:00
Misa
a28f68968c Add replace_all()
This is just a function that will be used in the optimized tag-finding
function.
2020-04-17 19:14:44 -04:00
Misa
ae6c4223e2 Don't add -Werror=implicit-fallthrough for MSVC
MSVC doesn't have a neat equivalent, but most development happens on
Linux anyway with Clang/GCC, so it's fine to leave this error out for
MSVC.
2020-04-17 15:41:48 -04:00
Misa
57f027e478 Add -Werror=implicit-fallthrough to CMakeLists.txt
This turns the implicit-fallthrough warning into a full compile-time
error.

Implicit fallthrough is when you forget a break statement in a
case-switch, thus letting one case fall through into the next case and
causing debugging headaches.

This is different from the good type of fallthrough that you use to have
one case with multiple different names, like so:

    case 0:
    case 1:
    case 2:

In that case, it's obvious that you want to have fallthrough there.
2020-04-17 15:41:48 -04:00
Misa
8796f2c9e0 Fix Menu::quickloadlevel not using returnmenu()
Whoops, almost forgot this one.

Now if you hit "back to levels", your position will still be kept on the
selected level.
2020-04-17 15:41:48 -04:00
Misa
b02c4aac78 Fix going to wrong menu upon quit
The problem was, if you were in a time trial and quit, it wouldn't go
back to selecting your current time trial. But also if you were in a
custom level and quit, you would still be on the playerworlds menu.

The problem was twofold: first, I simply wasn't doing the custommode
check. But secondly, I couldn't use map.custommode directly, because
whenever you quit the game aggressively hardreset()s everything
immediately when you press ACTION.

There's probably a good reason for that aggressive hardreset(), so I
won't touch that hardreset() in any way. Instead, I had to introduce two
kludge variables wasintimetrial and wasincustommode to Game, and use
those to do the check proper.
2020-04-17 15:41:48 -04:00
Misa
995dc3940a Add a "previous page" option to the credits menu
The credits aren't super-long, but it's still nice to have this menu
option.

If it's the first page, "previous page" will be "last page" instead.
2020-04-17 15:41:48 -04:00
Misa
85b16b969a Add a "previous page" option to the levels list
This makes it more convenient if you have a large levels directory, as
some people in the VVVVVV custom levels community do.

On the first page, this option will change to be "last page" instead.

Since the addition of another menu option pushes up the list of levels
too close to the selected level data itself, I've had to move the list
of levels down by 4 pixels (but "next page"/"previous page"/"return to
menu" are still in their same position).

This feature was already added to VCE but hasn't been upstreamed until
now.
2020-04-17 15:41:48 -04:00
Misa
e909515f3d Don't go to main menu when exiting to menu
This also replaces some createmenu()s with returnmenu()s as needed even
when said createmenu()s already didn't go to the main menu.

Now when you exit the level editor, you'll be selecting the "level
editor" option in "play levels", and if you exit from a level you'll
still be selecting that level in the levels list.

Furthermore, regardless of what you're exiting, your cursor position
will be remembered.
2020-04-17 15:41:48 -04:00
Misa
4d9c834a13 Change gamestate ints to their enum names
This is to make it easier to read, so I don't have to reference Enums.h
if I want to know what they are referring to.
2020-04-17 15:41:48 -04:00
Misa
637a9d5665 Remove now-unused variable Game::previousmenuname
This used to be used for Menu::youwannaquit, but now it uses the same
stack frame system as everything else, so it's gone unused now.
2020-04-17 15:41:48 -04:00
Misa
2bb64198fe Use game.returnmenu() for all "return" menu options
This is to not reset your cursor position every time you return on
something. It's also to automatically keep track of which menu was the
previous menu instead of manually hardcoding said previous menu.
2020-04-17 15:41:48 -04:00
Misa
224585d774 Fix being able to mismatch summary and menu color
You were able to mismatch the color of the quicksave/telesave summary
and the text/background by pressing Esc when in the "continue" menu,
then pressing ACTION on "no, return".

This commit fixes that bug by putting the map.settowercolour(3) inside
the Menu::continuemenu creation code itself. However, since the
Menu::youwannaquit code does map.nexttowercolour() right after it does
the game.createmenu(), we also need to put the map.nexttowercolour()
before the game.createmenu() beforehand so it doesn't mess up the cyan
color that Menu::continuemenu sets.

Additionally, I removed the map.settowercolour() from the input handling
of Menu::play, as it's superfluous.
2020-04-17 15:41:48 -04:00
Misa
250be2dbb7 Mark same menus in levels list, credits, and unlock menus
This marks pressing ACTION on "next page" in the levels list, credits,
pressing ACTION on "continue" in "You have unlocked" menus, and pressing
ACTION on an unlock option in the unlock menu and time trial unlock menu
as being the same menu.

This is to prevent creating unnecessary stack frames when using said
menu options in those menus.
2020-04-17 15:41:48 -04:00
Misa
80ae625585 Remove unnecessary createmenu(Menu::graphicoptions) calls
These aren't necessary, the menu will update regardless. There isn't
even such a call for the mouse cursor toggle option, that's how
unnecessary it is.
2020-04-17 15:41:48 -04:00
Misa
bf4427c75a Add function Game::returnmenu()
It simply goes to the previous menu stack frame.
2020-04-17 15:41:48 -04:00
Misa
de0205e09b Push a stack frame when Game::createmenu() is called
Unless it's the main menu, or unless it's not the same menu. Whether or
not the menu is the same is left up to the caller, because some menus
could be the same but use different names, so we can't simply
automatically check that the names are different and assume that they
aren't the same menu.
2020-04-17 15:41:48 -04:00
Misa
58b9941d73 Add vector of MenuStackFrame menustack to Game
We need a stack to put our stack frames inside.
2020-04-17 15:41:48 -04:00
Misa
13d2d6b623 Add struct MenuStackFrame
This will be pushed onto a stack when going to a different menu so the
game can dynamically keep track of which menu option got you to which
menu.
2020-04-17 15:41:48 -04:00
Misa
503b3f1692 Move temp int off of Game
This temp variable isn't used anywhere else, and even if it was it's set
to something every time it's used, so there's no risk of this commit
breaking any backwards compatibility.
2020-04-17 15:41:48 -04:00
Misa
56a168eed6 Remove ABCDEFG comment
I assume it was so a dev could mark the spot where they needed to put in
the analogue toggle, and they found a unique yet easy to remember
sequence of characters to Ctrl+F as a marker.
2020-04-17 15:41:48 -04:00
Misa
7b233a0e69 Rename Menu::setslowdown2 to Menu::setslowdown
Now that setslowdown1 has been removed it's no longer necessary to have
a 2 on the end of setslowdown2.
2020-04-17 15:41:48 -04:00
Misa
1c2cee48a7 Remove unused menu setslowdown1
Looks like it was a remnant from the Flash days, and the "delete your
saves if you want to use slowdown" was a bit too mean so it stopped
being a thing in the C++ version.
2020-04-17 15:41:48 -04:00
Misa
9e99246e02 Turn game.currentmenuname "else-if"s into case-switches
Much more stylistic, you don't need to repeat "game.currentmenuname" for
each case, and you don't need to deal with the dangling first "if" that
doesn't have an "else".
2020-04-17 15:41:48 -04:00
Misa
ceb8d3f3d8 Remove unused variable Game::menuselection
I presume it was meant to have the text of the currently-selected menu
option inside it, before the code switched over to using the indice of
the currently-selected menu instead? Would've been more error-prone to
use the text name directly.
2020-04-17 15:41:48 -04:00
Misa
e8a07f9c3d Convert menu names to be an enum instead of being stringly-typed
Stringly-typed things are bad, because if you make a typo when typing
out a string, it's not caught at compile-time. And in the case of this
menu system, you'd have to do an excessive amount of testing to uncover
any bugs caused by a typo. Why do that when you can just use an enum and
catch compile-time errors instead?

Also, you can't use switch-case statements on stringly-typed variables.

So every menu name is now in the enum Menu::MenuName, but you can simply
refer to a menu name by just prefixing it with Menu::.

Unfortunately, I've had to change the "continue" menu name to be
"continuemenu", because "continue" is a keyword in C and C++. Also, it
looks like "timetrialcomplete4" is an unused menu name, even though it
was referenced in Render.cpp.
2020-04-17 15:41:48 -04:00
Misa
83ca75a831 Change "else if"-chain in editormenuactionpress to case-switch
It makes it better so you don't have to deal with that dangling first
"if" that doesn't have an 'else'.
2020-04-17 15:41:48 -04:00
Misa
78169cdc1c Move editor menu option rendering to separate function
Just like before, it makes editorrender() easier to read and reduces the
indentation level of the option rendering by one level.
2020-04-17 15:41:48 -04:00
Misa
0b5d7b1fef Move editor menu ACTION press handling to separate function
This removes a whopping four indentation levels from the ACTION
handling, and makes editorinput() easier to read.
2020-04-17 15:41:48 -04:00
Misa
d6d9b505a2 Capitalize "No Death Mode" in "not available" message
It's fully capitalized everywhere else, so why not here?
2020-04-17 15:41:48 -04:00
Misa
256ead4799 Bump version number in bottom-right to 2.3
I think it's about time that this number be updated, yeah? This isn't to
say that 2.3 is finished or almost finished or anything, this is just to
clearly differentiate that this isn't 2.2.
2020-04-17 15:41:48 -04:00
Misa
cbd7ef94ba Gray out play modes if disabled due to enabled accessibility options
If you have invincibility mode or slowdown enabled, the game will not
let you select the Secret Lab, Time Trials, or No Death Mode. To make
this clearer, this commit grays out said options if they are disabled
for that reason.
2020-04-17 15:41:48 -04:00
Misa
38d749f536 Prevent selecting Secret Lab if game isn't at full speed
The game won't let you select the Secret Lab if you're in invincibility
mode, probably so you can't set illegitimate Super Gravitron records
just by standing there and doing nothing.

However, for some reason, it'll still let you select the Secret Lab even
if you've slowed down the game. For consistency, let's prevent selecting
the Secret Lab if the game isn't running at fullspeed, too.
2020-04-17 15:41:48 -04:00
Misa
d9d0748ce3 Use case-switch for menu options where possible
I've converted every "else if"-chain in menu render/input code to be a
case-switch, except for the levels list, the "game options" menu
(because it has the MMMMMM menu option which isn't a compile-time
constant), and the "play" menu (because it has the Secret Lab menu
option which also isn't a compile-time option).

I also did NOT convert some case-switches relating to unlocks in
Input.cpp, mostly because they use a system where the "if we have this
unlocked" conditional is a part of the "if this is the current menu
option" conditional, and they use the 'else' branch to play a sad sound
if that "if we have this unlocked" conditional fails.

I've also converted the game.gameframerate and game.crewrescued() "else
if"-chains to be case-switches instead.
2020-04-17 15:41:48 -04:00
Misa
46d0b3a4e9 Fix indentation of "graphicoptions" in Render.cpp
There was one level that was indented with 2 spaces instead of 4, which
made everything else look weird. Then some lines were randomly indented
further for no reason.

Doing this before the next commit is done so as to not make the next
commit noisier.
2020-04-17 15:41:48 -04:00
Misa
678ade88b9 De-duplicate "secret lab" menu option in "play" menu
Instead of creating an entirely new menu for it, just dynamically add
the Secret Lab menu option as needed.
2020-04-17 15:41:48 -04:00
Misa
4f6835c485 De-duplicate copy-pasted input/render code in menus
This removes duplicate code that came about as a result of various
possible permutations of menu options, depending on being M&P, having no
custom level support, having no editor support, and having MMMMMM.

The menus with such permutations are the following:

- main menu
  - "start game" is gone in MAKEANDPLAY
  - "player levels" is gone in NO_CUSTOM_LEVELS
  - "view credits" is gone in MAKEANDPLAY

- "game options"
  - "unlock play data" is gone in MAKEANDPLAY
  - "soundtrack" is gone if you don't have an mmmmmm.vvv file

- "player levels"
  - "level editor" is gone in NO_EDITOR

I achieve this de-duplication by clever use of calculating offsets,
which I feel is the best way to de-duplicate the code with the least
amount of work, if a little brittle.

The other options are to (1) put function pointers on each MenuOption
object, which is pretty verbose and would inflate Game::createmenu() by
a lot, (2) switch all game.currentmenuoption checks to instead check for
the text of the currently-selected menu option, which is very
error-prone because if you make a typo it won't be caught at
compile-time, (3) add a unique ID to each MenuOption object that
represents a text but will error at compile-time if you make a typo,
however this just duplicates all the menu option text, which is more
code than was duplicated previously.

So I just went with this one.
2020-04-17 15:41:48 -04:00
Misa
bf62233b60 Fix compile failure if both MAKEANDPLAY and NO_CUSTOM_LEVELS are defined
I don't know why you would have to have both defined simultaneously, but
now you can.

The compile fail was caused by the fact that if both were defined, then
there would be an expression like this in Map.cpp:

    switch (t)
    {
    case 0:
    }

which is an invalid expression.

The solution is to put 'case 0:' into the MAKEANDPLAY ifdef-guard as
well.
2020-04-17 15:41:48 -04:00
Misa
4ace8d15be Fix NO_CUSTOM_LEVELS builds breaking after command-line playtesting 2020-04-17 15:41:48 -04:00
Misa
b835ce3927 Move menu rendering to separate function
Just like I moved the menu ACTION press handler, I'm doing this as well.
It only removes one level of indentation, but it makes titlerender()
easier to understand.

Just like before, I have to put the separate function first, else
titlerender() won't know what it is.
2020-04-17 15:41:48 -04:00
Misa
1e3879b8fe De-duplicate "You have unlocked" menu input and options
They all have the same input handling and menu options, so condense them
into one block instead of duplicating the same block of code multiple
times.
2020-04-17 15:41:48 -04:00