1
0
mirror of https://github.com/TerryCavanagh/VVVVVV.git synced 2024-07-01 00:48:30 +02:00
Commit Graph

496 Commits

Author SHA1 Message Date
Misa
aed7b220c7 Remove now-unused function mapclass::fillcontent()
Previously, it was used to parse 30 strings whenever loading a room. But
now it's no longer used since we just assign the tilemap to the vector
directly.
2020-05-17 22:03:29 -04:00
Misa
ec72031cfd Refactor Otherlevel.cpp to not use strings for tilemaps
Instead, they're all held in a constant int array instead.
2020-05-17 22:03:29 -04:00
Misa
8a573af273 Refactor Spacestation2.cpp to not use strings for tilemaps
They are now stored in const int arrays instead. Except for the Prize
for the Reckless room, which I made sure had its spikes removed in No
Death Mode and the Time Trial.
2020-05-17 22:03:29 -04:00
Misa
781aa38e1f Refactor Finalclass.cpp to not use strings for tilemaps
Instead, they're all stored in a constant int array.

I made sure The Gravitron still has 30 rows just like Outer Space,
though I don't think it matters.
2020-05-17 22:03:29 -04:00
Misa
5126c4dbc4 Refactor WarpClass.cpp to not use strings for tilemaps
They now use a constant int array instead.
2020-05-17 22:03:29 -04:00
Misa
cc0d5d1d79 Refactor Labclass.cpp to not use strings for tilemaps
They now use a const int array instead.
2020-05-17 22:03:29 -04:00
Misa
f617b6d695 Fix FILESYSTEM_openDirectory command used on Haiku and *BSD
Previously:
 - Linux: xdg-open
 - Everything else: open

Now:
 - macOS and Haiku: open
 - Everything else: xdg-open

This is all according to a comment by leo60228 in PR #203.
2020-05-14 17:18:47 -04:00
Misa
e69cc964ab Don't duplicate activity zone handling code in playtesting
This change makes it so that in in-editor playtesting, the code to
handle pressing ENTER on activity zones is the same code to handle
pressing ENTER on activity zones in custommodeforreal.

This removes the need to copy-paste code and adapt it to in-editor
playtesting. And thus, this fixes an editor artifact where you can press
ENTER on activity zones while doing the death animation, even though you
can't do that when you're playing custom levels normally.
2020-05-14 16:15:07 -04:00
Misa
610768658e Remove graphics.drawgui() from maprender()
Since this is at the start of maprender(), the text boxes drawn by this
function will get hidden behind everything else being drawn on top of
it. Thus, it'll only result in a glitchy rendering where the text boxes
at the very top of the screen will be rendered in the roomname space of
the map screen.

To fix this rendering glitch, just remove the drawgui(). It's useless
anyway since it's being drawn behind everything else, so no need to have
it here.
2020-05-14 14:40:27 -04:00
Misa
be2d2e1e2a Fix 1x1 quicksand collision optimization not working
We need to replace an "or" with an "and".

My best guess for this oversight happening was because of the weird
ordering. The code originally did "temp < 30" first and "temp > -30"
second instead of the other way around. With the weird ordering, it
becomes more natural to insert an "or" instead of an "and". So I swapped
around the ordering just for good measure.

This is also fixed in the mobile version.
2020-05-13 08:16:34 -04:00
Misa
2d07090a6b Move returning to editor to end of frame
This fixes horizontal and vertical warp backgrounds not resetting, and
also a bunch of other 1-frame glitches, most noticeably cutscene bars
and fadeouts.

This adds a new variable shouldreturntoeditor to Game to signal whether
or not it should return to editor at the end of the frame.
2020-05-09 16:40:01 -04:00
Misa
51971fa84c Abstract returning-to-editor code to Game::returntoeditor()
This way I can easily move it around without moving around a bunch of
lines of code.
2020-05-09 16:40:01 -04:00
Misa
915100b370 Reset vvvvvvman size in mapclass::resetplayer()
It's a bit annoying how vvvvvvman status is preserved between in-game
sessions, and the only thing reset is the color. This is annoying
because it means you have to close the game to reset vvvvvvman.

But now it'll be reset properly. I chose to put this reset code in
mapclass::resetplayer() instead of scriptclass::hardreset() because it
seemed like the more appropriate place. It's where all other properties
of the player are reset, after all.
2020-05-09 15:16:11 -04:00
Misa
269ad18b86 Call game.savestats() when setting new Super Gravitron record
This is to be extra safe and ensure that your hard-earned record isn't
lost at all.

In 2.2, the game didn't save your Super Gravitron record at all. It only
saved it if you closed the game by quitting to the title screen and
pressing ACTION on "quit game". You couldn't press Alt+F4, and you
couldn't press X, you had to do it that way, otherwise your record would
be lost.

In 2.3 right now, the game WILL save your unlock.vvv when you close the
game gracefully by any means, but this still means that if it doesn't
otherwise close gracefully (like, say, a crash), it won't save your
record. It feels like we shouldn't rely on this catch-all saving to save
Super Gravitron records.
2020-05-09 15:07:41 -04:00
Misa
f585d53955 Fix flag 67 turning on too early
Flag 67 seems to be a general-purpose Game Complete flag. It's used to
replace the CREW option with the SHIP option on the pause screen.

Unfortunately, it gets turned on too early during Game Complete. Right
when Viridian starts to teleport, you can bring up the pause screen and
select the SHIP option.

It will teleport you to the ship coordinates, but still keep you in
finalmode, and since the ship coordinates are at 102,111 (finalmode is
only around 46,54), you'll still be stuck in Outside Dimension VVVVVV,
and you've interrupted the Game Complete gamestate by switching to the
teleporting gamestate. Oh, and your checkpoint is set, too, so you can't
even press R. Oh and since there's no teleporter, and checkpoint setting
doesn't check the sentinel value, this results in Undefined Behavior,
too.

So this results in an in-game softlock. The only option you can do is
quit the game at this point.

To fix this issue, just move turning on flag 67 before the savetele() in
gamecompletelogic2().
2020-05-09 14:55:24 -04:00
Misa
65341a8d1c Unindent block that previously had the fademode check
From the previous commit. It makes the diffs easier to read if I do the
unindent in a separate commit.
2020-05-08 08:34:46 -04:00
Misa
c61025c172 Remove fademode check from quitting to menu
This means you're allowed to quit to the menu even if you're faded-out,
because it's weird if you can close the menu but not be able to quit.
2020-05-08 08:34:46 -04:00
Misa
82d19145ae Only draw fading-in and fading-out animations in MAPMODE
This makes it so if you bring up the quit screen during a faded-out
screen, you will at least see the screen and won't see black. And also
the fade-in and fade-out animations will still work on the quit screen.
And more importantly, I tested and there's no 1-frame flicker or
anything.
2020-05-08 08:34:46 -04:00
Misa
3235b64d19 Remove reliance on fademode to return to menu
This was used by the old system, which also had an over-reliance on
Terry's State Machine. And due to the fact that it relied on fademode,
it also meant that bringing up the pause screen while faded-out would
result in the player getting sent back to the menu, so one accidental
Esc press during a cutscene could mean countless hours of progress lost
(especially in custom levels).
2020-05-08 08:34:46 -04:00
Misa
656680b49c Fix returning to editor when game is faded-out
This would cause the editor to think that it itself is in the middle of
fading to the menu, and so then will fade to the menu, thus losing any
unsaved work without warning.
2020-05-08 08:34:46 -04:00
Misa
b83cab8577 Directly do returntolab code instead of relying on a script
Having to rely on a script means the fade out wouldn't be self-contained
in MAPMODE, which could cause a small issue where you could die during
the return to the lab. But that issue is now fixed. There's no need to
use the script, and anyway the endcutscene() and untilbars() in said
script don't do anything because there are no cutscene bars in the first
place, so no need to worry about those.
2020-05-08 08:34:46 -04:00
Misa
fc2f269548 Move returning to lab to separate variables
Again, what I've done here is removed the over-reliance on Terry's State
Machine to return to the lab, and just moved it into separate variables
instead. This means that returning to the lab is ALMOST entirely
self-contained in MAPMODE, except there's a quick jaunt over to GAMEMODE
to run a script because you can only run scripts in GAMEMODE.
2020-05-08 08:34:46 -04:00
Misa
17e7c6983b Move fading to menu to separate variables
Alright, so what I've done here is made exiting to the menu entirely
separate from Terry's State Machine, and thus it can now take place
entirely within MAPMODE instead of having to go back to GAMEMODE. Also,
it's faster by 15 frames since we don't need to wait for the map screen
to go back down.
2020-05-08 08:34:46 -04:00
Misa
69aeac2410 Move return to lab code to Game::returntolab()
Again, I'll keep gamestate 96 and 97 for compatibility reasons, but
ultimately we shouldn't be using gamestates to return to the lab.
2020-05-08 08:34:46 -04:00
Misa
b59e5a8346 Move script.hardreset() to after quit to menu
This cleans up a whole lot of kludge variables, because this aggressive
hardreset() right as ACTION is pressed doesn't do anyone any favors.

This aggressive hardreset() was probably here because of the whole fact
that exiting to the menu uses Terry's State Machine, to minimize the
chances of interruption, but it actually causes more issues and allows
towers to interrupt the fadeout. And we should fix the root cause (the
usage of the state machine) instead of patching together some kludge.
2020-05-08 08:34:46 -04:00
Misa
6ac41e112c Move quit to menu to Game::quittomenu()
I don't want the quit code to only be in the state machine, but I'll
keep the gamestate around for compatibility reasons (there are custom
levels that directly use gamestate 80 to quit to the menu).
2020-05-08 08:34:46 -04:00
Misa
0787475e63 Remove unused variable 'pause' from Game
Looks like this variable is never used anywhere.
2020-05-08 08:34:46 -04:00
Misa
38a25b985e Fix a copy-paste error in getLevelMetaData()
Whoops.
2020-05-08 08:14:55 -04:00
Misa
29ff773cc4 Rename "start" option to "new game"
By popular request. Aizu said that "start" looks ugly since it's too
short compared to the rest of the menu options.
2020-05-06 20:52:47 -04:00
Misa
80db2f1d15 Add out-of-bounds puts() to updateentitylogic and entitymapcollision
Due to the previous commit, these will no longer be regularly taking in
out-of-bounds entity indices. Or at least they shouldn't, so I'm putting
in these print statements here on the off-chance that they do.
2020-05-05 17:22:47 -04:00
Misa
ce1e212317 Prevent updating an entity if updateentities() removed it
Otherwise, this would result in the game updating an entity twice, which
isn't good. This is most noticeable in the Gravitron, where many
Gravitron squares are created and destroyed at a time, and it's
especially noticeable during the part near the end of the Gravitron
where the pattern is two Gravitron squares, one at the top and bottom,
and then two Gravitron squares in the middle afterwards. The timing is
just right such that the top one of the two middle ones would be
misaligned with the bottom one of the two when a Gravitron square gets
outside the screen.

To do this, I changed entityclass::updateentities() into a bool, and
made every single caller check its return value. I only needed to do
this for the ones preceding updateentitylogic() and
entitymapcollision(), but I wanted to play it safe and be defensive, so
I did it for the disappearing platform kludge, as well as the
updateentities() within the updateentities() function.
2020-05-05 17:22:47 -04:00
Misa
3c80d136e4 Add towermode checks to minitowermode screen transitions
Apparently, the game just leaves minitowermode on, which can cause
issues if you're in a horizontal warping room (and not any other room
type, due to how frame ordering works). This would manifest itself as a
wrong warp to (20,20) because the game is trying to apply the hardcoded
minitower screen transitions when it shouldn't be.
2020-05-05 14:39:02 -04:00
Misa
27a5d1fa4f Add puts()es to functions unlikely to receive OoB indices
This is every function in Entity.cpp except for updateentitylogic() and
entitymapcollision().
2020-05-05 13:49:47 -04:00
Misa
8a78318990 Add bounds checks to functions taking in entity/blocks/linecross indices
The main ones to beware of here are entityclass::updateentities(),
entityclass::updateentitylogic(), and entityclass::entitymapcollision().
They would index out-of-bounds and thus commit Undefined Behavior if the
entity was removed in entityclass::updateentities(). And it would've
been fine enough if I only added bounds checks to those functions.

However, I decided to be a bit more defensive and play it safe, and
added bounds checks to ALL functions taking in not only an entity
indice, but also blocks and linecrosskludge indices.
2020-05-05 13:49:47 -04:00
Misa
c8d50d3067 Re-draw tower background when dying in No Death Mode
Otherwise, if you died after entering a room with a horizontal or
vertical warp background (but not the all-sides warp background), the
warp background would be the first thing you see when going to the Game
Over screen, and would then start scrolling downwards with the proper
tower background coming in from the top.

This oversight seems to have always been in the game.

Was No Death Mode actually tested? Like, did anyone ever play through
the entire game without dying in the Warp Zone, or even AFTER completing
the Warp Zone, like, ever?
2020-05-04 23:33:37 -04:00
Misa
dc19a51d38 Fix copy-paste bug in command-line playtesting code
Found this because when I compiled with Clang, -Wself-assign-field was
enabled.
2020-05-04 14:58:52 -04:00
Misa
f78603ef87 Fix menu that you land on when you complete game or custom level
When you complete the game, you're now redirected to the play menu. This
is because your quicksave will have been deleted so you can't go back to
the summary menu.

When you complete a custom level, you'll go back to the levels list, in
case you started the level from a quicksave.
2020-05-02 23:47:37 -04:00
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
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
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