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

480 commits

Author SHA1 Message Date
Misa
b53d2ae53f Remove i/j/k attributes from classes that don't need them
The only class that actually needs its i/j/k kept is scriptclass,
because some custom levels rely on it for creating custom activity
zones. So I haven't touched that.

Other than that, there's no chance that anything important relies on
i/j/k in any other class. For that to be the case, it would have to use
i/j/k without initializing it beforehand, and that can simply be
detected by removing the attribute from the header file and seeing where
the compiler complains. And the compiler complains only about cases
where it's initialized first. (Note that due to this check, I *haven't*
removed Graphics's `m` as it precisely does exactly this, using it
without initializing it first.)

Interestingly enough, otherlevelclass and towerclass have unused i/k
variables for whatever reason.
2020-06-14 14:37:29 -04:00
Misa
1f360620cf Add inspecial() checks to savetele() and savequick()
This prevents the game from being saved if you manage to trigger a
savetele() during a "special" gamemode (like if you use the Gravitron
out-of-bounds glitch when replaying Intermission 2, then go to Game
Complete that way).
2020-06-14 07:24:28 -04:00
Misa
fdce412680 Guard all cases obj.getcompanion() is used unchecked
And this the function with the least amount of cases where its sentinel
value is used unchecked. Thankfully. obj.getplayer() was a bit of a slug
to get through.
2020-06-12 23:55:48 -04:00
Misa
beab344267 Guard all cases obj.getplayer() is used unchecked
obj.getplayer() can return -1, which can cause out-of-bounds indexing of
obj.entities, which is really bad. This was by far the most changes, as
obj.getplayer() is the most used entity-getting function that returns
-1, as well as the most-used function whose sentinel value goes
unchecked.

To deal with the usage of obj.getplayer() in mapclass::warpto(), I just
added general bounds checks inside that function instead of changing all
the callers.
2020-06-12 23:55:48 -04:00
Misa
08e47e839f Guard all cases obj.getteleporter() is used unchecked
obj.getteleporter() is able to return -1. If there's no check on it, it
will end up indexing out-of-bounds, which is Undefined Behavior.
2020-06-12 23:55:48 -04:00
AllyTally
d740205138 Don't initialize game.gametimer in the header file
That's a C++ thing apparently.
2020-06-12 19:11:48 -04:00
AllyTally
eb52657c23 Add a player trail to the editor (ghosts)
A few months ago, I added ghosts to the VVVVVV: Community Edition editor. I was told recently I should think
about upstreaming it, and with Terry saying go ahead I finally ported them into VVVVVV. There's one slight
difference however--you can choose whether you have them or not in the editor's settings menu. They're off by
default, and this is saved to the save file.
Anyway, when you're playtesting, the game saves the players position, color, room coordinates and sprite every 3
frames. The max is 100, where if it tries to add more, the oldest one gets removed.
When you exit playtesting, the saved positions appear one at a time, and you can use the Z key to speed it up.

[Here's a video of them in action.](https://o.lol-sa.me/4H21zCv.mp4)
2020-06-12 19:11:48 -04:00
Misa
3f4df82583 Remove TinyXML-1
This removes the TinyXML source files, removes it from CMakeLists.txt,
removes all the includes, and removes the functions
FILESYSTEM_saveTiXmlDocument() and FILESYSTEM_loadTiXmlDocument() (use
FILESYSTEM_saveTiXml2Document() and FILESYSTEM_loadTiXml2Document()
instead).

Additionally I've cleaned up the tinyxml2.h include in FileSystemUtils.h
so that it doesn't actually include tinyxml2.h unnecessarily, meaning a
change to TinyXML2 shouldn't rebuild all files that include
FileSystemUtils.h.
2020-06-12 15:08:29 -04:00
Misa
c397c898fc Convert Game::loadcustomlevelstats() to TinyXML2 2020-06-12 15:08:29 -04:00
Misa
683dc1f97d Convert Game::savecustomlevelstats() to TinyXML2 2020-06-12 15:08:29 -04:00
Misa
142241fd74 Convert Game::Game() to TinyXML2 2020-06-12 15:08:29 -04:00
Misa
45e864315e Convert Game::loadsummary() to TinyXML2 2020-06-12 15:08:29 -04:00
Misa
677dd424ec Convert Game::customsavequick() to TinyXML2
At this point I stopped actually doing a quick test, and just went off
of "if it compiles, it works".
2020-06-12 15:08:29 -04:00
Misa
c03fdc6c01 Convert Game::customloadquick() to TinyXML2
Ok, who's even reading these commit messages at this point?
2020-06-12 15:08:29 -04:00
Misa
c62bfad19d Convert Game::savequick() to TinyXML2
Same steps as converting all other XML-saving functions.
2020-06-12 15:08:29 -04:00
Misa
3419f9fa15 Convert Game::loadquick() to TinyXML2
Same changes as all other XML-loading functions.
2020-06-12 15:08:29 -04:00
Misa
6706197741 Convert Game::savetele() to TinyXML2
I just had to find-and-replace all `new TiXmlDocument` to
`doc.NewDocument` and `new TiXmlText` to `doc.NewText`, along some other
stuff.
2020-06-12 15:08:29 -04:00
Misa
9348bf5b24 Convert Game::loadtele() to TinyXML2
Again, the only thing that needs to be changed is just the code at the
top of the function.
2020-06-12 15:08:29 -04:00
Misa
6274707777 Convert Game::savestats() to TinyXML2
Ok, so it was a bit of a struggle at first figuring out the new API, but
honestly it wasn't so bad in the end.

I made a copy of my old unlock.vvv before testing this, and checking
with `diff` the only difference is the new `encoding="UTF-8"` in the XML
declaration, which isn't a bad thing.
2020-06-12 15:08:29 -04:00
Misa
f2709731e2 Convert Game::loadstats() to TinyXML2
Surprisingly, I only had to change some names and stuff around at the
top of the function. The rest of the function could be left untouched
and it worked fine.
2020-06-12 15:08:29 -04:00
Misa
c561cd9740 Fix custom assets being unmounted in scriptclass::hardreset()
This resulted in two bugs:
 1. Custom assets would not be unmounted when quitting to the menu.
 2. Custom assets would be unmounted when playtesting a level.

The solution is to unmount assets in Game::quittomenu() instead.
2020-06-03 21:44:56 -04:00
Fussmatte
58df371c3e Changed my name from Stelpjo to my current name, Fußmatte
I also left a note for the in-game credits list to change the "ss" to an eszett when the Unicode font is implemented.
2020-05-31 20:38:06 -04:00
Matt Penny
50798d5add Fix build with CUSTOM_LEVEL_SUPPORT=disabled 2020-05-30 16:33:17 -04:00
Misa
6913abb171 Refactor superpatrons/patrons/githubfriends to not push_back(string)
It's a bit bad for the compiler if you have lots of function calls with
hardcoded strings in them, because every time the compiler encounters
one, it has to go out of its way to find a dedicated storage location
for the string, which is really inefficient. And it does this
inefficient thing every single time.

There's not much of an impact compiling these lists, but I at least want
to encourage this sort of code style, instead of the push_back(string)
style, in case we ever need a hardcoded array of things later.
2020-05-21 09:12:34 -04:00
Misa
4034c22833 Add bounds checks to roomdeaths and roomdeathsfinal
This fixes being able to trigger Undefined Behavior by pressing R when
not in-bounds in the Outside Dimension VVVVVV map, usually when you're
falling upwards towards Game Complete.

I also put bounds checks on normal roomdeaths for good measure. You'll
never know when you need it.
2020-05-19 20:43:02 -04:00
Misa
14af88695f Select "continue" if returning from new game when having had a save
If you started a new game while having had a save (meaning you selectedd
"new game" while it wasn't in the same position as "continue"), then
saved and quit, your cursor will now end up at "continue" instead of
"new game". (If you didn't save, then your cursor would be out-of-bounds
and end up at position 0 anyway.)
2020-05-18 21:01:07 -04:00
Misa
a33c460d40 Re-create menu if returntomenu() is given current menu
This fixes a bug where if you had the play menu in a state where the
first option was "new game", then kept playing up until a quicksave or
telesave was created, then quit to the menu, the menu wouldn't update.
Thanks to KSSBrawl for reporting this bug to me:
https://cdn.discordapp.com/attachments/708567577978470410/712060797924147240/untitled.webm
2020-05-18 21:01:07 -04:00
Misa
72ddd9bdb4 Fix <hardestroom> having atoi() called on it when loading quicksave
For some reason (probably a copy-paste error), this XML tag gets atoi()
called on it before being assigned to Game::hardestroom. And only when
loading a quicksave, at that.

This would result in Game::hardestroom being set to an empty string,
which if you kept until Game Complete, would end up rendering as a
single null byte (if you even have a font face for said null byte).

I'm not sure how this error compiles in the first place, but whatever.
2020-05-18 17:43:04 -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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
Misa
119d2ad25f Condense indentation levels of else-if chain in "play" menu
Previously, the code looked something like:

    else { if (...) {...} else { if (...) {...} else { etc. } }

And kept indenting every time there was an else-if.

This commit puts all else-ifs on the same indentation level, so it
doesn't slowly push the code to the right.
2020-04-17 15:41:48 -04:00
Misa
fe178f817b Remove outdated commented-out graphics options code
If we need it (which I don't think we will be anytime soon) we can
always just get it back through source control. Otherwise, it simply
gets in the way.
2020-04-17 15:41:48 -04:00
Misa
511de0c5c1 Refactor menu creation code
Firstly, menu options are no longer ad-hoc objects, and are added by
using Game::option() (this is the biggest change). This removes the
vector Game::menuoptionsactive, and Game::menuoptions is now a vector of
MenuOption instead of std::string.

Secondly, the manual tracker variable of the amount of menu options,
Game::nummenuoptions, has been removed, in favor of using vectors
properly and using Game::menuoptions::size().

As a result, a lot of copy-pasted code has been removed from
Game::createmenu(), mostly due to having to have different versions of
menus depending on whether or not we have certain defines, or having an
mmmmmm.vvv file inside the VVVVVV directory. In the old days, you
couldn't just add or remove a menu option conveniently, you had to
shuffle around the position of every other menu option too, which
resulted in lots of copy-pasted code. But now this copy-pasted code has
been de-duplicated, at least in Game::createmenu().
2020-04-17 15:41:48 -04:00
Misa
d63ba761d5 Remove map.numteleporters
This removes the separate length-tracking variable map.numteleporters,
in favor of using map.teleporters.size().
2020-04-14 22:54:16 -04:00
Misa
d4034661e2 Don't use std::count() in Game::crewmates()
The less STL usage, the better.
2020-04-09 19:20:31 -04:00
Misa
3774ec390c Don't use std::count() in Game::trinkets()
The less STL, the better.
2020-04-09 19:20:31 -04:00
Misa
45e7a9db3e Use for-loop in Game::crewrescued()
It's better to not use an STL function here.
2020-04-09 19:20:31 -04:00
Misa
17a64aee7a Make obj.customcollect a vector of bools
It's already treated as a vector of bools, so might as well formally
declare it as that.
2020-04-09 19:20:31 -04:00
Misa
8507bdc65d Change obj.collect into a vector of bools
It's already treated like a bunch of bools anyway, so might as well just
formalize it.
2020-04-09 19:20:31 -04:00
Misa
2ba9a0e67b Don't use obj.changeflag() to set flags
The way I see it, that function is basically an unnecessary middleman.
2020-04-09 19:20:31 -04:00
Misa
abfae6b4d7 Declare obj.flags a vector of bools instead of ints
It's treated like a bool anyway, so might as well make it one.

This also necessitates updating every single instance where it or an
element inside it is used, too.
2020-04-09 19:20:31 -04:00
Misa
2f1c400c9a Remove temporary UtilityClass from Game::savestats()
Looks like it was here from that arg passing stuff from earlier, as a
workaround to not pass args around. Well, there's no need to create an
extra UtilityClass now either, just use the one in the global namespace.
2020-04-09 19:20:31 -04:00
Misa
699af342e8 Refactor Game::crewrescued() to use std::count() instead
Makes the code less hardcoded, take up less lines, and is way easier to
read.
2020-04-09 19:20:31 -04:00
Misa
588a49dbc8 Remove useless variable game.timerStartTime
It sometimes gets set to SDL_GetTicks(), but without being checked or
actually used, it's useless and does nothing.
2020-04-09 19:20:31 -04:00
Misa
317eece28d Remove useless variable game.coins
It kept getting set to 0 and getting incremented sometimes, but without
it ever actually getting checked, it's a useless variable.
2020-04-09 19:20:31 -04:00
Misa
89b6b67a77 Don't use separate variable for number of crewmates in level
Same as previous commit, this time for crewmates.
2020-04-09 19:20:31 -04:00
Misa
0047dc8d81 Don't use separate variable for number of trinkets in level
Same principle as removing the separate variable to track number of
collected trinkets. This means it's less error-prone as we're no longer
tracking number of trinkets separately.

In the function that counts the number of trinkets, I would've liked to
have used std::count_if(). However, the most optimal way would require
using a lambda, and lambdas are too new for the C++ standard we're
using. So I just bit the bullet and counted them manually.
2020-04-09 19:20:31 -04:00
Misa
5661f46a52 Remove unnecessary int casts relating to custom crewmate numbers
I don't know why these are here, but there's never a point where these
integers were at any risk of no longer being integers.
2020-04-09 19:20:31 -04:00
Misa
6b317c5ab9 Remove map.customcrewmates
Same as the previous commit, except for the amount of custom crewmates.
2020-04-09 19:20:31 -04:00
Misa
85bd7d9a2d Remove map.customtrinkets
This variable's sole purpose is to copy ed.numtrinkets, even though ed
has always been a name that's been accessible globally. So let's not
dupe cope.
2020-04-09 19:20:31 -04:00
Misa
c077e51fb4 Don't use separate variable for number of collected crewmates
Same as previous commit, except for crewmates in custom levels instead.
2020-04-09 19:20:31 -04:00
Misa
9510c3c871 Don't use separate variable for number of collected trinkets
game.trinkets is supposed to be correlated with obj.collect, however why
not just count obj.collect directly?

This turns game.trinkets into a function, game.trinkets(), which will
directly count the number of collected trinkets and return it. This will
fix a few corner cases where the number of trinkets can desync with the
actual collection statuses of trinkets.

In order to keep save compatibility with previous versions of VVVVVV,
the game will still write the <trinkets> variable. However, it will not
read the <trinkets> variable from a save file.
2020-04-09 19:20:31 -04:00
leo60228
94b2ebd55c
Implement command-line playtesting (#163) 2020-04-09 15:03:24 -04:00
Misa
b1b1474b7b Refactor entities and linecrosskludge to not use the 'active' system
This removes the variables obj.nentity and obj.nlinecrosskludge, as well
as removing the 'active' attribute from the entity class object. Now
every entity you access is guaranteed to be real and you don't have to
check the 'active' variable.

The biggest part of this is changing createentity() to modify a
newly-created entity object and push it back instead of already
modifying an indice in obj.entities.

As well, removing an entity now uses the new obj.removeentity() function
and removeentity_iter() macro.
2020-04-03 23:28:47 -04:00
Misa
134510d26a Remove remnants of screen recording stuff
Most of the code was already commented out, and those comments were
removed in earlier commits, but this removes all recording variables
from Game and simplifies the game-gamestate handling in main.cpp a
little bit.
2020-04-03 10:40:50 -04:00
Misa
b061051297 Remove outdated comments from Game.cpp
Most of this is telecookie/quickcookie stuff, which was used in the
Flash version, but there's no longer any such thing as a save cookie.

Also one TODO that says to make a function that's now been made.
2020-04-03 10:40:50 -04:00
Misa
f7ff076074 Move tempstring off of Graphics, Game, and UtilityClass
Unlike, say, the scriptclass i/j/k stuff, these tempstrings are only
purely visual, and there's no known glitches to manipulate them anyway.
Thus I think it's safe to make this cleanup.
2020-04-03 10:40:50 -04:00
Misa
ff449a2c3a Remove game.test and game.teststring
It looks like this may have been used earlier in development, judging
from the name, obviously, but right now it seems like it's used as an
error message if a main game level is asked for an invalid room (well,
only two of them - the Lab and Warp Zone). It should probably be
formalized into an error system, if we want to keep teststring, and also
people would never see it anyway because I don't think there's a
reliable and consistent way to trigger loading a non-existent room.

I have seen someone manage to load a non-existent Warp Zone room only
one time, but even then this teststring didn't pop up. So this
teststring doesn't even trigger in the right circumstances.

Also, when it does pop up, as far as I can tell it will stay onscreen,
which is kinda annoying. So I'm just removing this ancient relic from
the code.
2020-04-03 10:40:50 -04:00
Misa
88c16cdae8 Fix mixed indentation in Game.cpp and Game.h
This removes all indentation that suddenly switches in the middle of a
function. Most particularly egregious offenses are the ones made by the
person who has 2-wide tabs, but keeps tabbing up to make each
indentation level match up with the 4-wide spaces, so to them (and only
them) it will look just fine, but since by default tabstop is 8-wide,
their lines are pushed off all the way to the right.
2020-04-03 10:40:50 -04:00
Misa
12d5433efc Remove trailing whitespace from all files
Surprisingly, there's not a lot of it. There is, however, a lot of mixed
indentation in this project.
2020-04-03 10:40:50 -04:00
Misa
6c6b6c68ff Change all UtilityClass::something to help.something
This changes something like UtilityClass::String to help.String,
basically. It takes less typing this way, and is a neat effect of having
global args actually be global variables.
2020-04-03 10:40:50 -04:00
Misa
16c3966ace Remove unused argument from musicclass::playef()
Apparently the 'offset' argument did something in the 1.x Flash
versions, but now it does nothing.
2020-04-03 10:40:50 -04:00
Misa
606c740b4f Remove useless variable Game::quickcookieexists
Even though it keeps getting set to true and false everywhere, it never
once gets checked. So it's a variable that does nothing.
2020-04-03 10:40:50 -04:00
Misa
340f57762d Remove useless variable Game::telecookieexists
Although it keeps getting set to true and false in various places, it
never once gets checked, essentially deeming it a variable that's used
but does nothing.
2020-04-03 10:40:50 -04:00
Misa
9cec63bcf7 Remove unused variable Game::sfpsmode
This variable does absolutely nothing, so I'm removing it.
2020-04-03 10:40:50 -04:00
Misa
7abf40881a Remove unused argument of entityclass::getcompanion()
The argument provided to entityclass::getcompanion() does absolutely
nothing. Remove it, and update all callers.
2020-04-03 10:40:50 -04:00
Misa
0e561f23f8 Remove global args from Game
I've decided to call dwgfx/game/map/obj/key/help/music the "global args".
Because they're essentially global variables that are being passed
around in args.

This commit removes global args from all functions on the Game class,
and deals with updating the callsites of said functions accordingly. It
also renames all usages of 'dwgfx' in Game.cpp to 'graphics', since the
global variable is called 'graphics' now.

Interesting to note, I was removing the class defines from Game.h, but
it turns out that Graphics.h depends on the mapclass and entityclass
defines from Game.h. And also Graphics.h spelled mapclass wrong (it
forgot the "class") so I just decided to use that existing line instead.
This is only temporary and after all is said and done, at the end of
this pull request those class defines will be gone.
2020-04-03 10:40:50 -04:00
Misa
cfd355bf4d Don't let custom levels tamper with main game save data
Someone being mean could've overwritten the telesaves of unsuspecting
players, or unlocked a bunch of stuff which they shouldn't have for
those players, using things like the telesave() command and gamestates.
To prevent this, return early in Game::savequick(), Game::savetele(),
and Game::unlocknum() if we are in custommode.
2020-03-15 12:29:26 -04:00
AlexApps99
aff0c06458 Fixes #112: Backbuffer is always 32bpp 2020-03-12 10:06:23 -04:00
Misa
1b04cb5dd6 Fix crewmate-found text boxes overlapping in flip mode
The problem was that the code seemed to be wrongly copy-pasted from the
code for generating the trinket-found text boxes (to the point where
even the comment for the crewmate-found text boxes didn't get changed
from "//Found a trinket!").

For the trinket-found text boxes, they use y-positions 85 and 135 if not
in flip mode, and y-positions 105 and 65 if the game IS in flip mode.
These text boxes are positioned correctly in flip mode.

However, for the crewmate-found text boxes, they use y-positions 85 and
135 if not in flip mode, as usual, but they use y-positions 105 and 135
if the game IS in flip mode. Looks like someone forgot to change the
second y-position when copy-pasting code around.

Which is actually a bit funny, because I can conclude from this that it
seems like the code to position these text boxes in flip mode was
bolted-on AFTER the initial code of these text boxes was written.

I can also conclude (hot take incoming) that basically no one actually
ever tested this game in flip mode (but that was already evident, given
TerryCavanagh/VVVVVV#140, less strongly TerryCavanagh/VVVVVV#141, and
TerryCavanagh/VVVVVV#142 is another flip-mode-related bug which I guess
sorta kinda doesn't really count since text outline wasn't enabled until
2.3?).

So I fixed the second y-position to be 65, just like the y-position the
trinket text boxes use. I even took the opportunity to fix the comment
to say "//Found a crewmate!" instead of "//Found a trinket!".
2020-02-16 09:30:00 -05:00
Matt Penny
df1c1303bf
Use dynamic credits lists for main menu credits screens (and add GitHub contributors) (#160)
Also added GitHub contributors to the credits on the main menu
(previously they were only present in the credits at the end of the
game)
2020-02-11 23:45:58 -05:00
Matt Penny
1b00d12600 Add option to allow custom levels when the editor is disabled 2020-02-09 23:31:44 -05:00
Matt Penny
7d35c5ce4e Add option to compile without the level editor 2020-02-09 23:31:44 -05:00
Matt Penny
dd7170dc59
Add -basedir option to specify base user directory (#154)
Useful for maintaining multiple save files or for debugging
2020-02-08 18:49:03 -05:00
AllyTally
19de5ec59d Add self to CONTRIBTORS.txt and githubfriends 2020-02-07 23:30:49 -05:00
Info Teddy
8ead9db39f Make hardest room "Dimension VVVVVV" if it has no room name
The only places where you can die in a room without a room name is the
Overworld, and I feel that calling it Dimension VVVVVV is appropriate.

You can't naturally die in The Ship nor the Secret Lab, and you can only
do it by pressing R, so I didn't feel it appropriate to add checks to
make the hardest room be "The Ship" or "The Secret Lab" if you managed
to get your hardest room to be a room in either of those areas.
2020-02-03 19:27:49 -08:00
Info Teddy
5a316d65e6 Allow using help/graphics/music/game/key/map/obj everywhere
This commit makes `help`, `graphics`, `music`, `game`, `key`, `map`, and
`obj` essentially static global objects that can be used everywhere.
This is useful in case we ever need to add a new function in the future,
so we don't have to bother with passing a new argument in which means we
have to pass a new argument in to the function that calls that function
which means having to pass a new argument into the function that calls
THAT function, etc. which is a real headache when working on fan mods of
the source code.

Note that this changes NONE of the existing function signatures, it
merely just makes those variables accessible everywhere in the same way
`script` and `ed` are.

Also note that some classes had to be initialized after the filesystem
was initialized, but C++ would keep initializing them before the
filesystem got initialized, because I *had* to put them at the top of
`main.cpp`, or else they wouldn't be global variables.

The only way to work around this was to use entityclass's initialization
style (which I'm pretty sure entityclass of all things doesn't need to
be initialized this way), where you actually initialize the class in an
`init()` function, and so then you do `graphics.init()` after the
filesystem initialization, AFTER doing `Graphics graphics` up at the
top.

I've had to do this for `graphics` (but only because its child
GraphicsResources `grphx` needs to be initialized this way), `music`,
and `game`. I don't think this will affect anything. Other than that,
`help`, `key`, and `map` are still using the C++-intended method of
having ClassName::ClassName() functions.
2020-01-29 07:58:23 -05:00
Allison Fleischer
03a4c3362a Add graphics option to toggle mouse cursor
Adds an option to show or hide the system mouse cursor over the game window.
2020-01-29 07:55:50 -05:00
Info Teddy
df83c2d494 Add an accessibility option to be able to see through the roomname
This is the variable dwgfx.translucentroomname and <translucentroomname>
in unlock.vvv.

This lets you see through the black background of the roomname at the
bottom of the screen, i.e. it makes the roomname background translucent.
So you can see if someone decides to hide pesky spikes there.
2020-01-25 23:29:37 -05:00
Ethan Lee
6e9712f113 Add text outline as an accessibility option 2020-01-17 12:37:53 -05:00
Ethan Lee
2aa4aa5f8a Integrate dynamic list sizes for credited patrons, add CONTRIBUTORS to credits
(Also added myself to the credits, only took 6 years to not be lazy about it)
2020-01-16 20:14:56 -05:00
Info Teddy
fa075010c8 Fix being able to set lower custom level score
For reference, here is the list of scores for a custom level:
 0 - not played
 1 - finished
 2 - all trinkets
 3 - finished, all trinkets

Previously, you could've played a level and finished it and set a score
of 3. Then you could re-play the entire level, but manage to only get a
score of 1, i.e. only finished but not with all trinkets. Then your
score for that level would get set back to 1, which basically nullifies
the time you spent playing that level and getting all of the trinkets.

This commit makes it so your new score will get set only if it is higher
than the previous one.
2020-01-13 21:02:40 -05:00
Info Teddy
c2ac1dc7d2 Add an accessibility option to toggle the fake loading screen (#63) 2020-01-12 20:45:44 -05:00
Dav999-v
facc34d86c Replace 2 remaining TinyXml LoadFile()s by FILESYSTEM_loadTiXmlDocument 2020-01-12 10:44:11 -05:00
Dav999-v
b884b7e4e9 Replace TiXmlDocument load and save functions by PHYSFS
The TinyXml functions to load and save files don't properly support
unicode file paths on Windows, so in order to support that properly, I
saw no other option than to do the actual loading and saving via PHYSFS
(or to use the Windows API on Windows and retain doc.LoadFile and
doc.SaveFile on other OSes, but that'd be more complicated and
unnecessary, we already have PHYSFS, right?).

There are two new functions in FileSystemUtils:
bool FILESYSTEM_saveTiXmlDocument(const char *name, TiXmlDocument *doc)
bool FILESYSTEM_loadTiXmlDocument(const char *name, TiXmlDocument *doc)

Any instances of doc.SaveFile(<FULL_PATH>) have been replaced by
FILESYSTEM_saveTiXmlDocument(<VVVVVV_FOLDER_PATH>, &doc), where
<FULL_PATH> included the full path to the saves or levels directory,
and <VVVVVV_FOLDER_PATH> only includes the path relative to the VVVVVV
directory.
When loading a document, a TiXmlDocument used to be created with a full
path in its constructor and doc.LoadFile() would then be called, now a
TiXmlDocument is constructed with no path name and
FILESYSTEM_loadTiXmlDocument(<VVVVVV_FOLDER_PATH>, &doc) is called.
2020-01-12 10:44:11 -05:00
Marvin Scholz
64fd50be6f Simplify std::vector initializations
Resizing the vector does the same thing that the loops did, it changes
the size for the vector and initializes it with default-constructed
elements (or 0 or its equivalent for POD types).

Where a specific value is needed, it is set with the second
parameter of resize().
2020-01-12 10:29:17 -05:00
Ethan Lee
f7c0321b71 Hello WWWWWWorld! 2020-01-08 10:37:50 -05:00