2020-07-19 21:03:16 +02:00
|
|
|
#include <tinyxml2.h>
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-07-19 21:43:29 +02:00
|
|
|
#include "Credits.h"
|
2020-07-19 21:05:41 +02:00
|
|
|
#include "editor.h"
|
|
|
|
#include "Entity.h"
|
|
|
|
#include "Enums.h"
|
2020-07-19 21:43:29 +02:00
|
|
|
#include "FileSystemUtils.h"
|
2020-07-19 21:05:41 +02:00
|
|
|
#include "Game.h"
|
|
|
|
#include "Graphics.h"
|
|
|
|
#include "KeyPoll.h"
|
2020-07-19 21:43:29 +02:00
|
|
|
#include "MakeAndPlay.h"
|
2020-07-19 21:05:41 +02:00
|
|
|
#include "Map.h"
|
|
|
|
#include "Music.h"
|
2020-11-08 00:47:49 +01:00
|
|
|
#include "RenderFixed.h"
|
2020-07-19 21:43:29 +02:00
|
|
|
#include "Script.h"
|
Use explicit INBOUNDS_VEC() instead of checking sentinel -1
It's better to do INBOUNDS_VEC(i, obj.entities) instead of 'i > -1'.
'i > -1' is used in cases like obj.getplayer(), which COULD return a
sentinel value of -1 and so correct code will have to check that value.
However, I am now of the opinion that INBOUNDS_VEC() should be used and
isn't unnecessary.
Consider the case of the face() script command: it's not enough to check
i > -1, you should read the routine carefully. Because if you look
closely, you'll see that it's not guaranteed that 'i' will be initialized
at all in that command. Indeed, if you call face() with invalid
arguments, it won't be. And so, 'i' could be something like 215, and
that would index out-of-bounds, and that wouldn't be good. Therefore,
it's better to have the full bounds check instead of checking only one
bounds. Many commands are like this, after some searching I can also
name position(), changemood(), changetile(), changegravity(), etc.
It also makes the code more explicit. Now you don't have to wonder what
-1 means or why it's being checked, you can just read the 'INBOUNDS' and
go "oh, that checks if it's actually inbounds or not".
2020-09-09 13:15:14 +02:00
|
|
|
#include "UtilityClass.h"
|
2020-07-19 21:05:41 +02:00
|
|
|
|
2021-01-10 18:14:37 +01:00
|
|
|
static void updatebuttonmappings(int bind)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-04-02 23:06:56 +02:00
|
|
|
for (
|
|
|
|
SDL_GameControllerButton i = SDL_CONTROLLER_BUTTON_A;
|
|
|
|
i < SDL_CONTROLLER_BUTTON_DPAD_UP;
|
|
|
|
i = (SDL_GameControllerButton) (i + 1)
|
|
|
|
) {
|
|
|
|
if (key.isDown(i))
|
|
|
|
{
|
|
|
|
bool dupe = false;
|
|
|
|
if (bind == 1)
|
|
|
|
{
|
|
|
|
for (size_t j = 0; j < game.controllerButton_flip.size(); j += 1)
|
|
|
|
{
|
|
|
|
if (i == game.controllerButton_flip[j])
|
|
|
|
{
|
|
|
|
dupe = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!dupe)
|
|
|
|
{
|
|
|
|
game.controllerButton_flip.push_back(i);
|
|
|
|
music.playef(11);
|
|
|
|
}
|
|
|
|
for (size_t j = 0; j < game.controllerButton_map.size(); j += 1)
|
|
|
|
{
|
|
|
|
if (i == game.controllerButton_map[j])
|
|
|
|
{
|
|
|
|
game.controllerButton_map.erase(game.controllerButton_map.begin() + j);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (size_t j = 0; j < game.controllerButton_esc.size(); j += 1)
|
|
|
|
{
|
|
|
|
if (i == game.controllerButton_esc[j])
|
|
|
|
{
|
|
|
|
game.controllerButton_esc.erase(game.controllerButton_esc.begin() + j);
|
|
|
|
}
|
|
|
|
}
|
2020-08-09 00:41:59 +02:00
|
|
|
for (size_t j = 0; j < game.controllerButton_restart.size(); j += 1)
|
|
|
|
{
|
|
|
|
if (i == game.controllerButton_restart[j])
|
|
|
|
{
|
|
|
|
game.controllerButton_restart.erase(game.controllerButton_restart.begin() + j);
|
|
|
|
}
|
|
|
|
}
|
2020-04-02 23:06:56 +02:00
|
|
|
}
|
|
|
|
if (bind == 2)
|
|
|
|
{
|
|
|
|
for (size_t j = 0; j < game.controllerButton_map.size(); j += 1)
|
|
|
|
{
|
|
|
|
if (i == game.controllerButton_map[j])
|
|
|
|
{
|
|
|
|
dupe = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!dupe)
|
|
|
|
{
|
|
|
|
game.controllerButton_map.push_back(i);
|
|
|
|
music.playef(11);
|
|
|
|
}
|
|
|
|
for (size_t j = 0; j < game.controllerButton_flip.size(); j += 1)
|
|
|
|
{
|
|
|
|
if (i == game.controllerButton_flip[j])
|
|
|
|
{
|
|
|
|
game.controllerButton_flip.erase(game.controllerButton_flip.begin() + j);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (size_t j = 0; j < game.controllerButton_esc.size(); j += 1)
|
|
|
|
{
|
|
|
|
if (i == game.controllerButton_esc[j])
|
|
|
|
{
|
|
|
|
game.controllerButton_esc.erase(game.controllerButton_esc.begin() + j);
|
|
|
|
}
|
|
|
|
}
|
2020-08-09 00:41:59 +02:00
|
|
|
for (size_t j = 0; j < game.controllerButton_restart.size(); j += 1)
|
|
|
|
{
|
|
|
|
if (i == game.controllerButton_restart[j])
|
|
|
|
{
|
|
|
|
game.controllerButton_restart.erase(game.controllerButton_restart.begin() + j);
|
|
|
|
}
|
|
|
|
}
|
2020-04-02 23:06:56 +02:00
|
|
|
}
|
|
|
|
if (bind == 3)
|
|
|
|
{
|
|
|
|
for (size_t j = 0; j < game.controllerButton_esc.size(); j += 1)
|
|
|
|
{
|
|
|
|
if (i == game.controllerButton_esc[j])
|
|
|
|
{
|
|
|
|
dupe = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!dupe)
|
|
|
|
{
|
|
|
|
game.controllerButton_esc.push_back(i);
|
|
|
|
music.playef(11);
|
|
|
|
}
|
|
|
|
for (size_t j = 0; j < game.controllerButton_flip.size(); j += 1)
|
|
|
|
{
|
|
|
|
if (i == game.controllerButton_flip[j])
|
|
|
|
{
|
|
|
|
game.controllerButton_flip.erase(game.controllerButton_flip.begin() + j);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (size_t j = 0; j < game.controllerButton_map.size(); j += 1)
|
|
|
|
{
|
|
|
|
if (i == game.controllerButton_map[j])
|
|
|
|
{
|
|
|
|
game.controllerButton_map.erase(game.controllerButton_map.begin() + j);
|
|
|
|
}
|
|
|
|
}
|
2020-08-09 00:41:59 +02:00
|
|
|
for (size_t j = 0; j < game.controllerButton_restart.size(); j += 1)
|
|
|
|
{
|
|
|
|
if (i == game.controllerButton_restart[j])
|
|
|
|
{
|
|
|
|
game.controllerButton_restart.erase(game.controllerButton_restart.begin() + j);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (bind == 4)
|
|
|
|
{
|
|
|
|
for (size_t j = 0; j < game.controllerButton_restart.size(); j += 1)
|
|
|
|
{
|
|
|
|
if (i == game.controllerButton_restart[j])
|
|
|
|
{
|
|
|
|
dupe = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!dupe)
|
|
|
|
{
|
|
|
|
game.controllerButton_restart.push_back(i);
|
|
|
|
music.playef(11);
|
|
|
|
}
|
|
|
|
for (size_t j = 0; j < game.controllerButton_flip.size(); j += 1)
|
|
|
|
{
|
|
|
|
if (i == game.controllerButton_flip[j])
|
|
|
|
{
|
|
|
|
game.controllerButton_flip.erase(game.controllerButton_flip.begin() + j);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (size_t j = 0; j < game.controllerButton_map.size(); j += 1)
|
|
|
|
{
|
|
|
|
if (i == game.controllerButton_map[j])
|
|
|
|
{
|
|
|
|
game.controllerButton_map.erase(game.controllerButton_map.begin() + j);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (size_t j = 0; j < game.controllerButton_esc.size(); j += 1)
|
|
|
|
{
|
|
|
|
if (i == game.controllerButton_esc[j])
|
|
|
|
{
|
|
|
|
game.controllerButton_esc.erase(game.controllerButton_esc.begin() + j);
|
|
|
|
}
|
|
|
|
}
|
2020-04-02 23:06:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
2021-01-10 18:14:37 +01:00
|
|
|
static void menuactionpress()
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-04-17 00:19:17 +02:00
|
|
|
switch (game.currentmenuname)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-04-17 00:19:17 +02:00
|
|
|
case Menu::mainmenu:
|
2020-04-15 19:14:42 +02:00
|
|
|
#if defined(MAKEANDPLAY)
|
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-16 02:59:03 +02:00
|
|
|
#define MPOFFSET -1
|
|
|
|
#else
|
|
|
|
#define MPOFFSET 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(NO_CUSTOM_LEVELS)
|
|
|
|
#define NOCUSTOMSOFFSET -1
|
|
|
|
#else
|
|
|
|
#define NOCUSTOMSOFFSET 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define OFFSET (MPOFFSET+NOCUSTOMSOFFSET)
|
|
|
|
|
2020-04-16 05:10:11 +02:00
|
|
|
switch (game.currentmenuoption)
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
2020-04-16 05:10:11 +02:00
|
|
|
#if !defined(MAKEANDPLAY)
|
|
|
|
case 0:
|
2020-04-15 19:14:42 +02:00
|
|
|
//Play
|
2020-04-26 22:41:35 +02:00
|
|
|
if (!game.save_exists() && !game.anything_unlocked())
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-04-15 19:14:42 +02:00
|
|
|
//No saves exist, just start a new game
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 0;
|
|
|
|
graphics.fademode = 2;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-04-15 19:14:42 +02:00
|
|
|
//Bring you to the normal playmenu
|
|
|
|
music.playef(11);
|
2020-04-16 06:53:36 +02:00
|
|
|
game.createmenu(Menu::play);
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
|
|
|
}
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
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-16 02:59:03 +02:00
|
|
|
#endif
|
|
|
|
#if !defined(NO_CUSTOM_LEVELS)
|
2020-04-16 05:10:11 +02:00
|
|
|
case OFFSET+1:
|
2020-04-15 19:14:42 +02:00
|
|
|
//Bring you to the normal playmenu
|
|
|
|
music.playef(11);
|
2020-04-16 06:53:36 +02:00
|
|
|
game.createmenu(Menu::playerworlds);
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
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-16 02:59:03 +02:00
|
|
|
#endif
|
2020-04-16 05:10:11 +02:00
|
|
|
case OFFSET+2:
|
2020-04-15 19:14:42 +02:00
|
|
|
//Options
|
|
|
|
music.playef(11);
|
2020-04-16 06:53:36 +02:00
|
|
|
game.createmenu(Menu::graphicoptions);
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case OFFSET+3:
|
2020-04-15 19:14:42 +02:00
|
|
|
//Options
|
|
|
|
music.playef(11);
|
2020-04-16 06:53:36 +02:00
|
|
|
game.createmenu(Menu::options);
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
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-16 02:59:03 +02:00
|
|
|
#if !defined(MAKEANDPLAY)
|
2020-04-16 05:10:11 +02:00
|
|
|
case OFFSET+4:
|
2020-04-15 19:14:42 +02:00
|
|
|
//Credits
|
|
|
|
music.playef(11);
|
2020-04-16 06:53:36 +02:00
|
|
|
game.createmenu(Menu::credits);
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
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-16 02:59:03 +02:00
|
|
|
#else
|
|
|
|
#undef MPOFFSET
|
|
|
|
#define MPOFFSET -2
|
|
|
|
#endif
|
2020-04-16 05:10:11 +02:00
|
|
|
case OFFSET+5:
|
2020-04-15 19:14:42 +02:00
|
|
|
//bye!
|
|
|
|
music.playef(2);
|
|
|
|
game.mainmenu = 100;
|
|
|
|
graphics.fademode = 2;
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
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-16 02:59:03 +02:00
|
|
|
#undef OFFSET
|
|
|
|
#undef NOCUSTOMSOFFSET
|
|
|
|
#undef MPOFFSET
|
2020-04-16 05:10:11 +02:00
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
2020-04-02 23:06:56 +02:00
|
|
|
#if !defined(NO_CUSTOM_LEVELS)
|
2020-04-17 00:19:17 +02:00
|
|
|
case Menu::levellist:
|
2020-04-15 19:14:42 +02:00
|
|
|
if(game.currentmenuoption==(int)game.menuoptions.size()-1){
|
|
|
|
//go back to menu
|
|
|
|
music.playef(11);
|
2020-04-17 05:05:01 +02:00
|
|
|
game.returnmenu();
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
|
|
|
}else if(game.currentmenuoption==(int)game.menuoptions.size()-2){
|
2020-04-17 08:05:49 +02:00
|
|
|
//previous page
|
|
|
|
music.playef(11);
|
|
|
|
if(game.levelpage==0){
|
|
|
|
game.levelpage=(ed.ListOfMetaData.size()-1)/8;
|
|
|
|
}else{
|
|
|
|
game.levelpage--;
|
|
|
|
}
|
|
|
|
game.createmenu(Menu::levellist, true);
|
|
|
|
game.currentmenuoption=game.menuoptions.size()-2;
|
|
|
|
map.nexttowercolour();
|
|
|
|
}else if(game.currentmenuoption==(int)game.menuoptions.size()-3){
|
2020-04-15 19:14:42 +02:00
|
|
|
//next page
|
|
|
|
music.playef(11);
|
|
|
|
if((size_t) ((game.levelpage*8)+8) >= ed.ListOfMetaData.size()){
|
|
|
|
game.levelpage=0;
|
|
|
|
}else{
|
|
|
|
game.levelpage++;
|
|
|
|
}
|
2020-04-17 04:26:49 +02:00
|
|
|
game.createmenu(Menu::levellist, true);
|
2020-04-17 08:05:49 +02:00
|
|
|
game.currentmenuoption=game.menuoptions.size()-3;
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
|
|
|
}else{
|
|
|
|
//Ok, launch the level!
|
|
|
|
//PLAY CUSTOM LEVEL HOOK
|
|
|
|
music.playef(11);
|
|
|
|
game.playcustomlevel=(game.levelpage*8)+game.currentmenuoption;
|
|
|
|
game.customleveltitle=ed.ListOfMetaData[game.playcustomlevel].title;
|
|
|
|
game.customlevelfilename=ed.ListOfMetaData[game.playcustomlevel].filename;
|
2020-04-02 23:06:56 +02:00
|
|
|
|
2020-04-15 19:14:42 +02:00
|
|
|
std::string name = "saves/" + ed.ListOfMetaData[game.playcustomlevel].filename.substr(7) + ".vvv";
|
2020-06-04 02:39:21 +02:00
|
|
|
tinyxml2::XMLDocument doc;
|
|
|
|
if (!FILESYSTEM_loadTiXml2Document(name.c_str(), doc)){
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 22;
|
|
|
|
graphics.fademode = 2;
|
|
|
|
}else{
|
2020-04-16 06:53:36 +02:00
|
|
|
game.createmenu(Menu::quickloadlevel);
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
|
|
|
}
|
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
2020-04-02 23:06:56 +02:00
|
|
|
#endif
|
2020-04-17 00:19:17 +02:00
|
|
|
case Menu::quickloadlevel:
|
2020-04-16 05:10:11 +02:00
|
|
|
switch (game.currentmenuoption)
|
|
|
|
{
|
|
|
|
case 0: //continue save
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 23;
|
|
|
|
graphics.fademode = 2;
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 1:
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 22;
|
|
|
|
graphics.fademode = 2;
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 2:
|
2020-04-15 19:14:42 +02:00
|
|
|
music.playef(11);
|
2020-04-17 21:10:07 +02:00
|
|
|
game.returnmenu();
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
2020-04-02 23:06:56 +02:00
|
|
|
#if !defined(NO_CUSTOM_LEVELS)
|
2020-04-17 00:19:17 +02:00
|
|
|
case Menu::playerworlds:
|
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-16 02:59:03 +02:00
|
|
|
#if defined(NO_EDITOR)
|
|
|
|
#define OFFSET -1
|
|
|
|
#else
|
|
|
|
#define OFFSET 0
|
|
|
|
#endif
|
2020-04-16 05:10:11 +02:00
|
|
|
switch (game.currentmenuoption)
|
|
|
|
{
|
|
|
|
case 0:
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-04-15 19:14:42 +02:00
|
|
|
music.playef(11);
|
|
|
|
game.levelpage=0;
|
|
|
|
ed.getDirectoryData();
|
|
|
|
game.loadcustomlevelstats(); //Should only load a file if it's needed
|
2020-04-16 06:53:36 +02:00
|
|
|
game.createmenu(Menu::levellist);
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
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-16 02:59:03 +02:00
|
|
|
#if !defined(NO_EDITOR)
|
2020-04-16 05:10:11 +02:00
|
|
|
case 1:
|
2020-04-15 19:14:42 +02:00
|
|
|
//LEVEL EDITOR HOOK
|
|
|
|
music.playef(11);
|
|
|
|
game.mainmenu = 20;
|
|
|
|
graphics.fademode = 2;
|
|
|
|
ed.filename="";
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
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-16 02:59:03 +02:00
|
|
|
#endif
|
2020-04-16 05:10:11 +02:00
|
|
|
case OFFSET+2:
|
2020-04-18 03:50:10 +02:00
|
|
|
//"OPENFOLDERHOOK"
|
2020-04-18 17:06:06 +02:00
|
|
|
if (FILESYSTEM_openDirectoryEnabled()
|
|
|
|
&& FILESYSTEM_openDirectory(FILESYSTEM_getUserLevelDirectory()))
|
2020-04-18 03:50:10 +02:00
|
|
|
{
|
|
|
|
music.playef(11);
|
|
|
|
SDL_MinimizeWindow(graphics.screenbuffer->m_window);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
music.playef(2);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OFFSET+3:
|
2020-04-15 19:14:42 +02:00
|
|
|
//back
|
|
|
|
music.playef(11);
|
2020-04-17 05:05:01 +02:00
|
|
|
game.returnmenu();
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
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-16 02:59:03 +02:00
|
|
|
#undef OFFSET
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
2020-04-02 23:06:56 +02:00
|
|
|
#endif
|
2020-04-17 00:19:17 +02:00
|
|
|
case Menu::errornostart:
|
2020-04-15 19:14:42 +02:00
|
|
|
music.playef(11);
|
2020-04-16 06:53:36 +02:00
|
|
|
game.createmenu(Menu::mainmenu);
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
|
|
|
case Menu::graphicoptions:
|
2020-04-16 05:10:11 +02:00
|
|
|
switch (game.currentmenuoption)
|
|
|
|
{
|
|
|
|
case 0:
|
2020-04-15 19:14:42 +02:00
|
|
|
music.playef(11);
|
|
|
|
graphics.screenbuffer->toggleFullScreen();
|
Add "resize to nearest" graphics option
If you want your game window to simply be exactly 320x240, or 640x480,
or 960x720 etc. then it's really annoying that there's no easy way to do
this (to clarify, this is different from integer mode, which controls
the size of the game INSIDE the window). The easiest way would be having
to close the game, go into unlock.vvv, and edit the window size
manually. VCE has a 1x/2x/3x/4x graphics option to solve this, although
it does not account for actual monitor size (those 1x/2x/3x/4x modes are
all you get, whether or not you have a monitor too small for some of
them or too big for any of them to be what you want).
I discussed this with flibit, and he said that VCE's approach (if it
accounted for monitor size) wouldn't work on high-retina displays or
high DPIs, because getting the actual multiplier to account for those
monitors is kind of a pain. So the next best thing would be to add an
option that resizes to the nearest perfect multiple of 320x240. That way
you could simply resize the window and let the game correct any
imperfect dimensions automatically.
2020-06-30 07:02:21 +02:00
|
|
|
|
|
|
|
// Recreate menu to update "resize to nearest"
|
|
|
|
game.createmenu(game.currentmenuname, true);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.currentmenuoption = 0;
|
2020-11-22 03:10:26 +01:00
|
|
|
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 1:
|
2020-04-15 19:14:42 +02:00
|
|
|
music.playef(11);
|
|
|
|
graphics.screenbuffer->toggleStretchMode();
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 2:
|
2020-06-30 22:30:59 +02:00
|
|
|
// resize to nearest multiple
|
|
|
|
if (graphics.screenbuffer->isWindowed)
|
|
|
|
{
|
|
|
|
music.playef(11);
|
|
|
|
graphics.screenbuffer->ResizeToNearestMultiple();
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-06-30 22:30:59 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
music.playef(2);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 3:
|
2020-04-15 19:14:42 +02:00
|
|
|
music.playef(11);
|
|
|
|
graphics.screenbuffer->toggleLinearFilter();
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
2020-06-30 22:30:59 +02:00
|
|
|
case 4:
|
2020-04-15 19:14:42 +02:00
|
|
|
//change smoothing
|
|
|
|
music.playef(11);
|
|
|
|
graphics.screenbuffer->badSignalEffect= !graphics.screenbuffer->badSignalEffect;
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
2020-06-30 22:30:59 +02:00
|
|
|
case 5:
|
2020-05-04 21:52:57 +02:00
|
|
|
//toggle 30+ fps
|
|
|
|
music.playef(11);
|
|
|
|
game.over30mode = !game.over30mode;
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-05-04 21:52:57 +02:00
|
|
|
break;
|
2020-06-30 22:30:59 +02:00
|
|
|
case 6:
|
2020-05-04 22:19:47 +02:00
|
|
|
//toggle vsync
|
|
|
|
music.playef(11);
|
2020-07-08 20:43:04 +02:00
|
|
|
#ifndef __HAIKU__ // FIXME: Remove after SDL VSync bug is fixed! -flibit
|
2020-07-02 06:19:40 +02:00
|
|
|
graphics.screenbuffer->vsync = !graphics.screenbuffer->vsync;
|
|
|
|
graphics.screenbuffer->resetRendererWorkaround();
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-07-08 20:38:55 +02:00
|
|
|
#endif
|
2020-07-08 20:43:04 +02:00
|
|
|
break;
|
2020-04-16 05:10:11 +02:00
|
|
|
default:
|
2020-04-15 19:14:42 +02:00
|
|
|
//back
|
|
|
|
music.playef(11);
|
2020-06-23 01:51:16 +02:00
|
|
|
if (game.ingame_titlemode)
|
|
|
|
{
|
2020-06-23 02:26:45 +02:00
|
|
|
game.returntopausemenu();
|
2020-06-23 01:51:16 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-06-23 02:23:56 +02:00
|
|
|
game.returnmenu();
|
2020-06-23 01:51:16 +02:00
|
|
|
map.nexttowercolour();
|
|
|
|
}
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
|
|
|
case Menu::youwannaquit:
|
2020-04-16 05:10:11 +02:00
|
|
|
switch (game.currentmenuoption)
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
2020-04-16 05:10:11 +02:00
|
|
|
case 0:
|
2020-04-15 19:14:42 +02:00
|
|
|
//bye!
|
|
|
|
music.playef(2);
|
|
|
|
game.mainmenu = 100;
|
|
|
|
graphics.fademode = 2;
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
default:
|
2020-04-15 19:14:42 +02:00
|
|
|
music.playef(11);
|
2020-04-17 04:52:39 +02:00
|
|
|
map.nexttowercolour(); //This goes first, otherwise mismatching continuemenu color is possible
|
2020-04-17 05:05:01 +02:00
|
|
|
game.returnmenu();
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
|
|
|
case Menu::setinvincibility:
|
2020-04-16 05:10:11 +02:00
|
|
|
switch (game.currentmenuoption)
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
2020-04-16 05:10:11 +02:00
|
|
|
case 0:
|
2020-04-15 19:14:42 +02:00
|
|
|
//back
|
|
|
|
music.playef(11);
|
2020-04-17 05:05:01 +02:00
|
|
|
game.returnmenu();
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
default:
|
2020-04-15 19:14:42 +02:00
|
|
|
map.invincibility = !map.invincibility;
|
|
|
|
music.playef(11);
|
2020-04-17 05:05:01 +02:00
|
|
|
game.returnmenu();
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
2020-04-17 01:02:01 +02:00
|
|
|
case Menu::setslowdown:
|
2020-04-16 05:10:11 +02:00
|
|
|
switch (game.currentmenuoption)
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
2020-04-16 05:10:11 +02:00
|
|
|
case 0:
|
2020-04-15 19:14:42 +02:00
|
|
|
//back
|
|
|
|
game.slowdown = 30;
|
|
|
|
music.playef(11);
|
2020-04-17 05:05:01 +02:00
|
|
|
game.returnmenu();
|
2020-04-15 19:14:42 +02:00
|
|
|
game.currentmenuoption = 4;
|
|
|
|
map.nexttowercolour();
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 1:
|
2020-04-15 19:14:42 +02:00
|
|
|
game.slowdown = 24;
|
|
|
|
music.playef(11);
|
2020-04-17 05:05:01 +02:00
|
|
|
game.returnmenu();
|
2020-04-15 19:14:42 +02:00
|
|
|
game.currentmenuoption = 4;
|
|
|
|
map.nexttowercolour();
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 2:
|
2020-04-15 19:14:42 +02:00
|
|
|
game.slowdown = 18;
|
|
|
|
music.playef(11);
|
2020-04-17 05:05:01 +02:00
|
|
|
game.returnmenu();
|
2020-04-15 19:14:42 +02:00
|
|
|
game.currentmenuoption = 4;
|
|
|
|
map.nexttowercolour();
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 3:
|
2020-04-15 19:14:42 +02:00
|
|
|
game.slowdown = 12;
|
|
|
|
music.playef(11);
|
2020-04-17 05:05:01 +02:00
|
|
|
game.returnmenu();
|
2020-04-15 19:14:42 +02:00
|
|
|
game.currentmenuoption = 4;
|
|
|
|
map.nexttowercolour();
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
2020-06-30 22:06:19 +02:00
|
|
|
case Menu::advancedoptions:
|
|
|
|
switch (game.currentmenuoption)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
//toggle mouse cursor
|
|
|
|
music.playef(11);
|
|
|
|
if (graphics.showmousecursor == true) {
|
|
|
|
SDL_ShowCursor(SDL_DISABLE);
|
|
|
|
graphics.showmousecursor = false;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
SDL_ShowCursor(SDL_ENABLE);
|
|
|
|
graphics.showmousecursor = true;
|
|
|
|
}
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-06-30 22:06:19 +02:00
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
// toggle unfocus pause
|
|
|
|
game.disablepause = !game.disablepause;
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-06-30 22:06:19 +02:00
|
|
|
music.playef(11);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
// toggle fake load screen
|
|
|
|
game.skipfakeload = !game.skipfakeload;
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-06-30 22:06:19 +02:00
|
|
|
music.playef(11);
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
// toggle translucent roomname BG
|
|
|
|
graphics.translucentroomname = !graphics.translucentroomname;
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-06-30 22:06:19 +02:00
|
|
|
music.playef(11);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
// Glitchrunner mode
|
|
|
|
music.playef(11);
|
|
|
|
game.glitchrunnermode = !game.glitchrunnermode;
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-06-30 22:06:19 +02:00
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
//back
|
|
|
|
music.playef(11);
|
|
|
|
game.returnmenu();
|
|
|
|
map.nexttowercolour();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
2020-04-17 00:19:17 +02:00
|
|
|
case Menu::accessibility:
|
2020-04-16 05:10:11 +02:00
|
|
|
switch (game.currentmenuoption)
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
2020-04-16 05:10:11 +02:00
|
|
|
case 0:
|
2020-04-15 19:14:42 +02:00
|
|
|
//disable animated backgrounds
|
|
|
|
game.colourblindmode = !game.colourblindmode;
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-11-03 00:05:24 +01:00
|
|
|
graphics.towerbg.tdrawback = true;
|
2020-11-03 00:23:53 +01:00
|
|
|
graphics.titlebg.tdrawback = true;
|
2020-04-15 19:14:42 +02:00
|
|
|
music.playef(11);
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 1:
|
2020-04-15 19:14:42 +02:00
|
|
|
//disable screeneffects
|
|
|
|
game.noflashingmode = !game.noflashingmode;
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-04-15 19:14:42 +02:00
|
|
|
if (!game.noflashingmode)
|
|
|
|
{
|
|
|
|
music.playef(18);
|
|
|
|
game.screenshake = 10;
|
|
|
|
game.flashlight = 5;
|
|
|
|
}else{
|
|
|
|
music.playef(11);
|
|
|
|
}
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 2:
|
2020-04-15 19:14:42 +02:00
|
|
|
//disable text outline
|
|
|
|
graphics.notextoutline = !graphics.notextoutline;
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-04-15 19:14:42 +02:00
|
|
|
music.playef(11);
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 3:
|
2020-04-15 19:14:42 +02:00
|
|
|
//invincibility
|
2020-06-23 07:55:59 +02:00
|
|
|
if (!game.ingame_titlemode || (!game.insecretlab && !game.intimetrial && !game.nodeathmode))
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
2020-06-23 02:37:53 +02:00
|
|
|
if (!map.invincibility)
|
|
|
|
{
|
|
|
|
game.createmenu(Menu::setinvincibility);
|
|
|
|
map.nexttowercolour();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
map.invincibility = !map.invincibility;
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-06-23 02:37:53 +02:00
|
|
|
}
|
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-06-23 02:37:53 +02:00
|
|
|
music.playef(2);
|
|
|
|
map.invincibility = false;
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 4:
|
2020-04-15 19:14:42 +02:00
|
|
|
//change game speed
|
2020-06-23 07:56:40 +02:00
|
|
|
if (!game.ingame_titlemode || (!game.insecretlab && !game.intimetrial && !game.nodeathmode))
|
2020-06-23 02:37:53 +02:00
|
|
|
{
|
|
|
|
game.createmenu(Menu::setslowdown);
|
|
|
|
map.nexttowercolour();
|
|
|
|
music.playef(11);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
music.playef(2);
|
2020-11-13 02:05:18 +01:00
|
|
|
game.slowdown = 30;
|
2020-06-23 02:37:53 +02:00
|
|
|
}
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 5:
|
2020-04-15 19:14:42 +02:00
|
|
|
//back
|
|
|
|
music.playef(11);
|
2020-04-17 05:05:01 +02:00
|
|
|
game.returnmenu();
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
default:
|
2020-04-15 19:14:42 +02:00
|
|
|
//Can't do yet! play sad sound
|
|
|
|
music.playef(2);
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
|
|
|
case Menu::options:
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
|
|
|
#if defined(MAKEANDPLAY)
|
2020-06-30 05:45:57 +02:00
|
|
|
int flipmode_offset = 0;
|
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-16 02:59:03 +02:00
|
|
|
#else
|
2020-06-30 05:45:57 +02:00
|
|
|
int flipmode_offset = game.ingame_titlemode && game.unlock[18] ? 0 : -1;
|
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-16 02:59:03 +02:00
|
|
|
#endif
|
2020-04-15 19:14:42 +02:00
|
|
|
|
2020-06-30 05:45:57 +02:00
|
|
|
#if defined(MAKEANDPLAY)
|
|
|
|
int unlockmode_offset = -1;
|
|
|
|
#else
|
|
|
|
int unlockmode_offset = 0;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int mmmmmm_offset = music.mmmmmm ? 0 : -1;
|
|
|
|
|
|
|
|
int offset = 0;
|
|
|
|
|
2020-04-16 05:10:11 +02:00
|
|
|
switch (game.currentmenuoption)
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
2020-04-16 05:10:11 +02:00
|
|
|
case 0:
|
2020-04-15 19:14:42 +02:00
|
|
|
//accessibility options
|
|
|
|
music.playef(11);
|
2020-04-16 06:53:36 +02:00
|
|
|
game.createmenu(Menu::accessibility);
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 1:
|
2020-06-30 22:06:19 +02:00
|
|
|
//advanced options
|
2020-06-25 23:31:37 +02:00
|
|
|
music.playef(11);
|
2020-06-30 22:06:19 +02:00
|
|
|
game.createmenu(Menu::advancedoptions);
|
|
|
|
map.nexttowercolour();
|
2020-06-25 23:31:37 +02:00
|
|
|
break;
|
|
|
|
case 2:
|
2020-06-30 05:45:57 +02:00
|
|
|
#if !defined(MAKEANDPLAY)
|
|
|
|
if (game.ingame_titlemode && game.unlock[18])
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
// toggle Flip Mode
|
|
|
|
graphics.setflipmode = !graphics.setflipmode;
|
2021-01-11 04:39:19 +01:00
|
|
|
game.savestatsandsettings();
|
2020-06-30 05:45:57 +02:00
|
|
|
if (graphics.setflipmode)
|
|
|
|
{
|
|
|
|
music.playef(18);
|
|
|
|
game.screenshake = 10;
|
|
|
|
game.flashlight = 5;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
music.playef(11);
|
|
|
|
}
|
2020-07-11 01:55:56 +02:00
|
|
|
// Fix wrong area music in Tower (Positive Force vs. ecroF evitisoP)
|
|
|
|
if (map.custommode)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
int area = map.area(game.roomx, game.roomy);
|
|
|
|
if (area == 3 || area == 11)
|
|
|
|
{
|
|
|
|
if (graphics.setflipmode)
|
|
|
|
{
|
|
|
|
music.play(9); // ecroF evitisoP
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
music.play(2); // Positive Force
|
|
|
|
}
|
|
|
|
}
|
2020-06-30 05:45:57 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
offset += flipmode_offset;
|
|
|
|
|
|
|
|
#if !defined(MAKEANDPLAY)
|
|
|
|
if (game.currentmenuoption == 3+offset)
|
|
|
|
{
|
2020-04-15 19:14:42 +02:00
|
|
|
//unlock play options
|
|
|
|
music.playef(11);
|
2020-04-16 06:53:36 +02:00
|
|
|
game.createmenu(Menu::unlockmenu);
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-06-30 05:45:57 +02:00
|
|
|
}
|
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-16 02:59:03 +02:00
|
|
|
#endif
|
2020-06-30 05:45:57 +02:00
|
|
|
|
|
|
|
offset += unlockmode_offset;
|
|
|
|
|
|
|
|
if (game.currentmenuoption == 4+offset)
|
|
|
|
{
|
2020-04-15 19:14:42 +02:00
|
|
|
//clear data menu
|
|
|
|
music.playef(11);
|
2020-04-16 06:53:36 +02:00
|
|
|
game.createmenu(Menu::controller);
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
2020-06-30 05:45:57 +02:00
|
|
|
}
|
|
|
|
else if (game.currentmenuoption == 5+offset)
|
|
|
|
{
|
2020-04-15 19:14:42 +02:00
|
|
|
//clear data menu
|
|
|
|
music.playef(11);
|
2020-04-16 06:53:36 +02:00
|
|
|
game.createmenu(Menu::cleardatamenu);
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
|
|
|
}
|
2020-06-30 05:45:57 +02:00
|
|
|
else if (game.currentmenuoption == 6+offset && music.mmmmmm)
|
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-16 02:59:03 +02:00
|
|
|
{
|
|
|
|
//**** TOGGLE MMMMMM
|
|
|
|
music.usingmmmmmm = !music.usingmmmmmm;
|
|
|
|
music.playef(11);
|
2020-06-23 02:44:03 +02:00
|
|
|
music.play(music.currentsong);
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings();
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
2020-06-30 05:45:57 +02:00
|
|
|
|
|
|
|
offset += mmmmmm_offset;
|
|
|
|
|
|
|
|
if (game.currentmenuoption == 7+offset)
|
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-16 02:59:03 +02:00
|
|
|
{
|
|
|
|
//back
|
|
|
|
music.playef(11);
|
2020-06-23 01:51:16 +02:00
|
|
|
if (game.ingame_titlemode)
|
|
|
|
{
|
2020-06-23 02:26:45 +02:00
|
|
|
game.returntopausemenu();
|
2020-06-23 01:51:16 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-06-23 02:23:56 +02:00
|
|
|
game.returnmenu();
|
2020-06-23 01:51:16 +02:00
|
|
|
map.nexttowercolour();
|
|
|
|
}
|
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-16 02:59:03 +02:00
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
case Menu::unlockmenutrials:
|
2020-04-16 05:10:11 +02:00
|
|
|
switch (game.currentmenuoption)
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
2020-04-16 05:10:11 +02:00
|
|
|
case 0: //unlock 1
|
2020-04-15 19:14:42 +02:00
|
|
|
game.unlock[9] = true;
|
|
|
|
game.unlocknotify[9] = true;
|
|
|
|
music.playef(11);
|
2020-04-17 04:26:49 +02:00
|
|
|
game.createmenu(Menu::unlockmenutrials, true);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.currentmenuoption = 0;
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 1: //unlock 2
|
2020-04-15 19:14:42 +02:00
|
|
|
game.unlock[10] = true;
|
|
|
|
game.unlocknotify[10] = true;
|
|
|
|
music.playef(11);
|
2020-04-17 04:26:49 +02:00
|
|
|
game.createmenu(Menu::unlockmenutrials, true);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.currentmenuoption = 1;
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 2: //unlock 3
|
2020-04-15 19:14:42 +02:00
|
|
|
game.unlock[11] = true;
|
|
|
|
game.unlocknotify[11] = true;
|
|
|
|
music.playef(11);
|
2020-04-17 04:26:49 +02:00
|
|
|
game.createmenu(Menu::unlockmenutrials, true);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.currentmenuoption = 2;
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 3: //unlock 4
|
2020-04-15 19:14:42 +02:00
|
|
|
game.unlock[12] = true;
|
|
|
|
game.unlocknotify[12] = true;
|
|
|
|
music.playef(11);
|
2020-04-17 04:26:49 +02:00
|
|
|
game.createmenu(Menu::unlockmenutrials, true);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.currentmenuoption = 3;
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 4: //unlock 5
|
2020-04-15 19:14:42 +02:00
|
|
|
game.unlock[13] = true;
|
|
|
|
game.unlocknotify[13] = true;
|
|
|
|
music.playef(11);
|
2020-04-17 04:26:49 +02:00
|
|
|
game.createmenu(Menu::unlockmenutrials, true);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.currentmenuoption = 4;
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 5: //unlock 6
|
2020-04-15 19:14:42 +02:00
|
|
|
game.unlock[14] = true;
|
|
|
|
game.unlocknotify[14] = true;
|
|
|
|
music.playef(11);
|
2020-04-17 04:26:49 +02:00
|
|
|
game.createmenu(Menu::unlockmenutrials, true);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.currentmenuoption = 5;
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 6: //back
|
2020-04-15 19:14:42 +02:00
|
|
|
//back
|
|
|
|
music.playef(11);
|
2020-04-17 05:05:01 +02:00
|
|
|
game.returnmenu();
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
|
|
|
case Menu::unlockmenu:
|
2020-04-16 05:10:11 +02:00
|
|
|
switch (game.currentmenuoption)
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
2020-04-16 05:10:11 +02:00
|
|
|
case 0:
|
2020-04-15 19:14:42 +02:00
|
|
|
//unlock time trials separately...
|
|
|
|
music.playef(11);
|
2020-04-16 06:53:36 +02:00
|
|
|
game.createmenu(Menu::unlockmenutrials);
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 1:
|
2020-04-15 19:14:42 +02:00
|
|
|
//unlock intermissions
|
|
|
|
music.playef(11);
|
|
|
|
game.unlock[16] = true;
|
|
|
|
game.unlocknotify[16] = true;
|
|
|
|
game.unlock[6] = true;
|
|
|
|
game.unlock[7] = true;
|
2020-04-17 04:26:49 +02:00
|
|
|
game.createmenu(Menu::unlockmenu, true);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.currentmenuoption = 1;
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 2:
|
2020-04-15 19:14:42 +02:00
|
|
|
//unlock no death mode
|
|
|
|
music.playef(11);
|
|
|
|
game.unlock[17] = true;
|
|
|
|
game.unlocknotify[17] = true;
|
2020-04-17 04:26:49 +02:00
|
|
|
game.createmenu(Menu::unlockmenu, true);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.currentmenuoption = 2;
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 3:
|
2020-04-15 19:14:42 +02:00
|
|
|
//unlock flip mode
|
|
|
|
music.playef(11);
|
|
|
|
game.unlock[18] = true;
|
|
|
|
game.unlocknotify[18] = true;
|
2020-04-17 04:26:49 +02:00
|
|
|
game.createmenu(Menu::unlockmenu, true);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.currentmenuoption = 3;
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 4:
|
2020-04-15 19:14:42 +02:00
|
|
|
//unlock jukebox
|
|
|
|
music.playef(11);
|
|
|
|
game.stat_trinkets = 20;
|
2020-04-17 04:26:49 +02:00
|
|
|
game.createmenu(Menu::unlockmenu, true);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.currentmenuoption = 4;
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 5:
|
2020-04-15 19:14:42 +02:00
|
|
|
//unlock secret lab
|
|
|
|
music.playef(11);
|
|
|
|
game.unlock[8] = true;
|
|
|
|
game.unlocknotify[8] = true;
|
2020-04-17 04:26:49 +02:00
|
|
|
game.createmenu(Menu::unlockmenu, true);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.currentmenuoption = 5;
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
default:
|
2020-04-15 19:14:42 +02:00
|
|
|
//back
|
|
|
|
music.playef(11);
|
2020-04-17 05:05:01 +02:00
|
|
|
game.returnmenu();
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
|
|
|
case Menu::credits:
|
2020-04-16 05:10:11 +02:00
|
|
|
switch (game.currentmenuoption)
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
2020-04-16 05:10:11 +02:00
|
|
|
case 0:
|
2020-04-15 19:14:42 +02:00
|
|
|
//next page
|
|
|
|
music.playef(11);
|
2020-04-17 04:26:49 +02:00
|
|
|
game.createmenu(Menu::credits2, true);
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
2020-04-17 08:37:49 +02:00
|
|
|
case 1:
|
|
|
|
//last page
|
|
|
|
music.playef(11);
|
|
|
|
game.createmenu(Menu::credits6, true);
|
|
|
|
game.currentmenuoption = 1;
|
|
|
|
map.nexttowercolour();
|
|
|
|
break;
|
2020-04-16 05:10:11 +02:00
|
|
|
default:
|
2020-04-15 19:14:42 +02:00
|
|
|
//back
|
|
|
|
music.playef(11);
|
2020-04-17 05:05:01 +02:00
|
|
|
game.returnmenu();
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
|
|
|
case Menu::credits2:
|
2020-04-16 05:10:11 +02:00
|
|
|
switch (game.currentmenuoption)
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
2020-04-16 05:10:11 +02:00
|
|
|
case 0:
|
2020-04-15 19:14:42 +02:00
|
|
|
//next page
|
|
|
|
music.playef(11);
|
2020-04-17 04:26:49 +02:00
|
|
|
game.createmenu(Menu::credits25, true);
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 1:
|
2020-04-17 08:37:49 +02:00
|
|
|
//previous page
|
|
|
|
music.playef(11);
|
|
|
|
game.createmenu(Menu::credits, true);
|
|
|
|
game.currentmenuoption = 1;
|
|
|
|
map.nexttowercolour();
|
|
|
|
break;
|
|
|
|
case 2:
|
2020-04-15 19:14:42 +02:00
|
|
|
//back
|
|
|
|
music.playef(11);
|
2020-04-17 05:05:01 +02:00
|
|
|
game.returnmenu();
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
|
|
|
case Menu::credits25:
|
2020-04-16 05:10:11 +02:00
|
|
|
switch (game.currentmenuoption)
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
2020-04-16 05:10:11 +02:00
|
|
|
case 0:
|
2020-04-15 19:14:42 +02:00
|
|
|
//next page
|
|
|
|
music.playef(11);
|
2020-04-17 04:26:49 +02:00
|
|
|
game.createmenu(Menu::credits3, true);
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
2020-04-17 08:37:49 +02:00
|
|
|
case 1:
|
|
|
|
//previous page
|
|
|
|
music.playef(11);
|
|
|
|
game.createmenu(Menu::credits2, true);
|
|
|
|
game.currentmenuoption = 1;
|
|
|
|
map.nexttowercolour();
|
|
|
|
break;
|
2020-04-16 05:10:11 +02:00
|
|
|
default:
|
2020-04-15 19:14:42 +02:00
|
|
|
//back
|
|
|
|
music.playef(11);
|
2020-04-17 05:05:01 +02:00
|
|
|
game.returnmenu();
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
|
|
|
case Menu::credits3:
|
2020-04-16 05:10:11 +02:00
|
|
|
switch (game.currentmenuoption)
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
2020-04-16 05:10:11 +02:00
|
|
|
case 0:
|
2020-04-15 19:14:42 +02:00
|
|
|
//next page
|
|
|
|
music.playef(11);
|
|
|
|
game.current_credits_list_index += 9;
|
|
|
|
|
Turn (super)patrons/githubfriends into arrays & move them to new file
So, originally, I wanted to keep them on Game, but it turns out that if
I initialize it in Game.cpp, the compiler will complain that other files
won't know what's actually inside the array. To do that, I'd have to
initialize it in Game.h. But I don't want to initialize it in Game.h
because that'd mean recompiling a lot of unnecessary files whenever
someone gets added to the credits.
So, I moved all the patrons, superpatrons, and GitHub contributors to a
new file, Credits.h, which only contains the list (and the credits max
position calculation). That way, whenever someone gets added, only the
minimal amount of files need to be recompiled.
2020-07-03 12:13:15 +02:00
|
|
|
if (game.current_credits_list_index >= (int)SDL_arraysize(Credits::superpatrons))
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
|
|
|
// No more super patrons. Move to the next credits section
|
|
|
|
game.current_credits_list_index = 0;
|
2020-04-17 04:26:49 +02:00
|
|
|
game.createmenu(Menu::credits4, true);
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// There are more super patrons. Refresh the menu with the next ones
|
2020-04-17 04:26:49 +02:00
|
|
|
game.createmenu(Menu::credits3, true);
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
|
|
|
|
2020-04-17 08:37:49 +02:00
|
|
|
map.nexttowercolour();
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
//previous page
|
|
|
|
music.playef(11);
|
|
|
|
game.current_credits_list_index -= 9;
|
|
|
|
|
|
|
|
if (game.current_credits_list_index < 0)
|
|
|
|
{
|
|
|
|
//No more super patrons. Move to the previous credits section
|
|
|
|
game.current_credits_list_index = 0;
|
|
|
|
game.createmenu(Menu::credits25, true);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//There are more super patrons. Refresh the menu with the next ones
|
|
|
|
game.createmenu(Menu::credits3, true);
|
|
|
|
}
|
|
|
|
game.currentmenuoption = 1;
|
|
|
|
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
default:
|
2020-04-15 19:14:42 +02:00
|
|
|
//back
|
|
|
|
music.playef(11);
|
|
|
|
game.current_credits_list_index = 0;
|
2020-04-17 05:05:01 +02:00
|
|
|
game.returnmenu();
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
|
|
|
case Menu::credits4:
|
2020-04-16 05:10:11 +02:00
|
|
|
switch (game.currentmenuoption)
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
2020-04-16 05:10:11 +02:00
|
|
|
case 0:
|
2020-04-15 19:14:42 +02:00
|
|
|
//next page
|
|
|
|
music.playef(11);
|
|
|
|
game.current_credits_list_index += 14;
|
|
|
|
|
Turn (super)patrons/githubfriends into arrays & move them to new file
So, originally, I wanted to keep them on Game, but it turns out that if
I initialize it in Game.cpp, the compiler will complain that other files
won't know what's actually inside the array. To do that, I'd have to
initialize it in Game.h. But I don't want to initialize it in Game.h
because that'd mean recompiling a lot of unnecessary files whenever
someone gets added to the credits.
So, I moved all the patrons, superpatrons, and GitHub contributors to a
new file, Credits.h, which only contains the list (and the credits max
position calculation). That way, whenever someone gets added, only the
minimal amount of files need to be recompiled.
2020-07-03 12:13:15 +02:00
|
|
|
if (game.current_credits_list_index >= (int)SDL_arraysize(Credits::patrons))
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
|
|
|
// No more patrons. Move to the next credits section
|
|
|
|
game.current_credits_list_index = 0;
|
2020-04-17 04:26:49 +02:00
|
|
|
game.createmenu(Menu::credits5, true);
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// There are more patrons. Refresh the menu with the next ones
|
2020-04-17 04:26:49 +02:00
|
|
|
game.createmenu(Menu::credits4, true);
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
|
|
|
|
2020-04-17 08:37:49 +02:00
|
|
|
map.nexttowercolour();
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
//previous page
|
|
|
|
music.playef(11);
|
|
|
|
game.current_credits_list_index -= 14;
|
|
|
|
|
|
|
|
if (game.current_credits_list_index < 0)
|
|
|
|
{
|
|
|
|
//No more patrons. Move to the previous credits section
|
Turn (super)patrons/githubfriends into arrays & move them to new file
So, originally, I wanted to keep them on Game, but it turns out that if
I initialize it in Game.cpp, the compiler will complain that other files
won't know what's actually inside the array. To do that, I'd have to
initialize it in Game.h. But I don't want to initialize it in Game.h
because that'd mean recompiling a lot of unnecessary files whenever
someone gets added to the credits.
So, I moved all the patrons, superpatrons, and GitHub contributors to a
new file, Credits.h, which only contains the list (and the credits max
position calculation). That way, whenever someone gets added, only the
minimal amount of files need to be recompiled.
2020-07-03 12:13:15 +02:00
|
|
|
game.current_credits_list_index = SDL_arraysize(Credits::superpatrons) - 1 - (SDL_arraysize(Credits::superpatrons)-1)%9;
|
2020-04-17 08:37:49 +02:00
|
|
|
game.createmenu(Menu::credits3, true);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//There are more patrons. Refresh the menu with the next ones
|
|
|
|
game.createmenu(Menu::credits4, true);
|
|
|
|
}
|
|
|
|
game.currentmenuoption = 1;
|
|
|
|
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
default:
|
2020-04-15 19:14:42 +02:00
|
|
|
//back
|
|
|
|
music.playef(11);
|
|
|
|
game.current_credits_list_index = 0;
|
2020-04-17 05:05:01 +02:00
|
|
|
game.returnmenu();
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
|
|
|
case Menu::credits5:
|
2020-04-16 05:10:11 +02:00
|
|
|
switch (game.currentmenuoption)
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
2020-04-16 05:10:11 +02:00
|
|
|
case 0:
|
2020-04-15 19:14:42 +02:00
|
|
|
//next page
|
|
|
|
music.playef(11);
|
|
|
|
game.current_credits_list_index += 9;
|
|
|
|
|
Turn (super)patrons/githubfriends into arrays & move them to new file
So, originally, I wanted to keep them on Game, but it turns out that if
I initialize it in Game.cpp, the compiler will complain that other files
won't know what's actually inside the array. To do that, I'd have to
initialize it in Game.h. But I don't want to initialize it in Game.h
because that'd mean recompiling a lot of unnecessary files whenever
someone gets added to the credits.
So, I moved all the patrons, superpatrons, and GitHub contributors to a
new file, Credits.h, which only contains the list (and the credits max
position calculation). That way, whenever someone gets added, only the
minimal amount of files need to be recompiled.
2020-07-03 12:13:15 +02:00
|
|
|
if (game.current_credits_list_index >= (int)SDL_arraysize(Credits::githubfriends))
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
|
|
|
// No more GitHub contributors. Move to the next credits section
|
|
|
|
game.current_credits_list_index = 0;
|
2020-04-17 04:26:49 +02:00
|
|
|
game.createmenu(Menu::credits6, true);
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// There are more GitHub contributors. Refresh the menu with the next ones
|
2020-04-17 04:26:49 +02:00
|
|
|
game.createmenu(Menu::credits5, true);
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
|
|
|
|
2020-04-17 08:37:49 +02:00
|
|
|
map.nexttowercolour();
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
//previous page
|
|
|
|
music.playef(11);
|
|
|
|
game.current_credits_list_index -= 9;
|
|
|
|
|
|
|
|
if (game.current_credits_list_index < 0)
|
|
|
|
{
|
|
|
|
//No more GitHub contributors. Move to the previous credits section
|
Turn (super)patrons/githubfriends into arrays & move them to new file
So, originally, I wanted to keep them on Game, but it turns out that if
I initialize it in Game.cpp, the compiler will complain that other files
won't know what's actually inside the array. To do that, I'd have to
initialize it in Game.h. But I don't want to initialize it in Game.h
because that'd mean recompiling a lot of unnecessary files whenever
someone gets added to the credits.
So, I moved all the patrons, superpatrons, and GitHub contributors to a
new file, Credits.h, which only contains the list (and the credits max
position calculation). That way, whenever someone gets added, only the
minimal amount of files need to be recompiled.
2020-07-03 12:13:15 +02:00
|
|
|
game.current_credits_list_index = SDL_arraysize(Credits::patrons) - 1 - (SDL_arraysize(Credits::patrons)-1)%14;
|
2020-04-17 08:37:49 +02:00
|
|
|
game.createmenu(Menu::credits4, true);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//There are more GitHub contributors. Refresh the menu with the next ones
|
|
|
|
game.createmenu(Menu::credits5, true);
|
|
|
|
}
|
|
|
|
game.currentmenuoption = 1;
|
|
|
|
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
default:
|
2020-04-15 19:14:42 +02:00
|
|
|
//back
|
|
|
|
music.playef(11);
|
|
|
|
game.current_credits_list_index = 0;
|
2020-04-17 05:05:01 +02:00
|
|
|
game.returnmenu();
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
|
|
|
case Menu::credits6:
|
2020-04-16 05:10:11 +02:00
|
|
|
switch (game.currentmenuoption)
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
2020-04-16 05:10:11 +02:00
|
|
|
case 0:
|
2020-04-15 19:14:42 +02:00
|
|
|
//first page
|
|
|
|
music.playef(11);
|
2020-04-17 04:26:49 +02:00
|
|
|
game.createmenu(Menu::credits, true);
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
2020-04-17 08:37:49 +02:00
|
|
|
case 1:
|
|
|
|
//previous page
|
|
|
|
music.playef(11);
|
Turn (super)patrons/githubfriends into arrays & move them to new file
So, originally, I wanted to keep them on Game, but it turns out that if
I initialize it in Game.cpp, the compiler will complain that other files
won't know what's actually inside the array. To do that, I'd have to
initialize it in Game.h. But I don't want to initialize it in Game.h
because that'd mean recompiling a lot of unnecessary files whenever
someone gets added to the credits.
So, I moved all the patrons, superpatrons, and GitHub contributors to a
new file, Credits.h, which only contains the list (and the credits max
position calculation). That way, whenever someone gets added, only the
minimal amount of files need to be recompiled.
2020-07-03 12:13:15 +02:00
|
|
|
game.current_credits_list_index = SDL_arraysize(Credits::githubfriends) - 1 - (SDL_arraysize(Credits::githubfriends)-1)%9;
|
2020-04-17 08:37:49 +02:00
|
|
|
game.createmenu(Menu::credits5, true);
|
|
|
|
game.currentmenuoption = 1;
|
|
|
|
map.nexttowercolour();
|
|
|
|
break;
|
2020-04-16 05:10:11 +02:00
|
|
|
default:
|
2020-04-15 19:14:42 +02:00
|
|
|
//back
|
|
|
|
music.playef(11);
|
2020-04-17 05:05:01 +02:00
|
|
|
game.returnmenu();
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
|
|
|
music.niceplay(6);
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
|
|
|
case Menu::play:
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
2020-04-16 04:38:42 +02:00
|
|
|
//Do we have the Secret Lab option?
|
2020-04-26 22:09:56 +02:00
|
|
|
int sloffset = game.unlock[8] ? 0 : -1;
|
|
|
|
//Do we have a telesave or quicksave?
|
2020-04-26 22:41:35 +02:00
|
|
|
int ngoffset = game.save_exists() ? 0 : -1;
|
2020-04-15 19:14:42 +02:00
|
|
|
if (game.currentmenuoption == 0)
|
|
|
|
{
|
|
|
|
//continue
|
|
|
|
//right, this depends on what saves you've got
|
2020-04-26 22:41:35 +02:00
|
|
|
if (!game.save_exists())
|
2020-04-26 22:09:56 +02:00
|
|
|
{
|
|
|
|
//You have no saves but have something unlocked, or you couldn't have gotten here
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-26 22:09:56 +02:00
|
|
|
game.mainmenu = 0;
|
|
|
|
graphics.fademode = 2;
|
|
|
|
}
|
|
|
|
else if (game.telesummary == "")
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
|
|
|
//You at least have a quicksave, or you couldn't have gotten here
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 2;
|
|
|
|
graphics.fademode = 2;
|
|
|
|
}
|
|
|
|
else if (game.quicksummary == "")
|
|
|
|
{
|
|
|
|
//You at least have a telesave, or you couldn't have gotten here
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 1;
|
|
|
|
graphics.fademode = 2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//go to a menu!
|
|
|
|
music.playef(11);
|
|
|
|
game.loadsummary(); //Prepare save slots to display
|
2020-04-16 06:53:36 +02:00
|
|
|
game.createmenu(Menu::continuemenu);
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
|
|
|
}
|
2020-04-16 04:38:42 +02:00
|
|
|
else if (game.currentmenuoption == 1 && game.unlock[8])
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
2020-04-16 05:17:36 +02:00
|
|
|
if(!map.invincibility && game.slowdown == 30){
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 11;
|
|
|
|
graphics.fademode = 2;
|
|
|
|
}else{
|
|
|
|
//Can't do yet! play sad sound
|
|
|
|
music.playef(2);
|
|
|
|
}
|
|
|
|
}
|
2020-04-26 22:09:56 +02:00
|
|
|
else if (game.currentmenuoption == sloffset+2)
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
|
|
|
//play modes
|
|
|
|
music.playef(11);
|
2020-04-16 06:53:36 +02:00
|
|
|
game.createmenu(Menu::playmodes);
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
|
|
|
}
|
2020-04-26 22:41:35 +02:00
|
|
|
else if (game.currentmenuoption == sloffset+3 && game.save_exists())
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
|
|
|
//newgame
|
|
|
|
music.playef(11);
|
2020-04-16 06:53:36 +02:00
|
|
|
game.createmenu(Menu::newgamewarning);
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
|
|
|
}
|
2020-04-26 22:09:56 +02:00
|
|
|
else if (game.currentmenuoption == sloffset+ngoffset+4)
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
|
|
|
//back
|
|
|
|
music.playef(11);
|
2020-04-17 05:05:01 +02:00
|
|
|
game.returnmenu();
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
case Menu::newgamewarning:
|
2020-04-16 05:10:11 +02:00
|
|
|
switch (game.currentmenuoption)
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
2020-04-16 05:10:11 +02:00
|
|
|
case 0:
|
2020-04-15 19:14:42 +02:00
|
|
|
//yep
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 0;
|
|
|
|
graphics.fademode = 2;
|
|
|
|
game.deletequick();
|
|
|
|
game.deletetele();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
default:
|
2020-04-15 19:14:42 +02:00
|
|
|
//back
|
|
|
|
music.playef(11);
|
2020-04-17 05:05:01 +02:00
|
|
|
game.returnmenu();
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
2020-04-15 19:14:42 +02:00
|
|
|
|
2020-04-17 00:19:17 +02:00
|
|
|
case Menu::controller:
|
2020-04-16 05:10:11 +02:00
|
|
|
switch (game.currentmenuoption)
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
2020-04-16 05:10:11 +02:00
|
|
|
case 0:
|
2020-11-13 02:16:18 +01:00
|
|
|
key.sensitivity++;
|
2020-04-15 19:14:42 +02:00
|
|
|
music.playef(11);
|
2020-11-13 02:16:18 +01:00
|
|
|
if(key.sensitivity > 4)
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
2020-11-13 02:16:18 +01:00
|
|
|
key.sensitivity = 0;
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
Refactor Game::savestats() to not use a default argument
In order to be able to fix the bug #556, I'm planning on adding
ScreenSettings* to the settings.vvv write function. However, that
entails adding another argument to Game::savesettings(), which is going
to be really messy given the default argument of Game::savestats().
That, combined with the fact that the code comment at the site of the
implementation of Game::savestats() being wrong (!!!), leads me to
believe that using default function arguments here isn't worth it.
Instead, what I've done is made it so callers are explicit about whether
or not they're calling savestats(), savesettings(), or both at the same
time. If they are calling both at the same time, then they will be using
a new function named savestatsandsettings().
In short, these are the interface changes:
* bool Game::savestats(bool) has been removed
* bool Game::savestatsandsettings() has been added
* void Game::savestats_menu() has been renamed to
void Game::savestatsandsettings_menu()
* All previous callers of bool Game::savestats() are now using bool
Game::savestatsandsettings()
* The one caller of bool Game::savestats(bool) is now using bool
Game::savestats()
2020-12-22 01:03:19 +01:00
|
|
|
game.savestatsandsettings_menu();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
2020-04-15 19:14:42 +02:00
|
|
|
|
2020-08-09 00:41:59 +02:00
|
|
|
case 5:
|
2020-04-15 19:14:42 +02:00
|
|
|
music.playef(11);
|
2020-04-17 05:05:01 +02:00
|
|
|
game.returnmenu();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
|
|
|
case Menu::cleardatamenu:
|
2020-04-16 05:10:11 +02:00
|
|
|
switch (game.currentmenuoption)
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
2020-04-16 05:10:11 +02:00
|
|
|
case 0:
|
2020-04-15 19:14:42 +02:00
|
|
|
//back
|
|
|
|
music.playef(11);
|
2020-04-17 05:05:01 +02:00
|
|
|
game.returnmenu();
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
default:
|
2020-04-15 19:14:42 +02:00
|
|
|
//yep
|
|
|
|
music.playef(23);
|
|
|
|
game.deletequick();
|
|
|
|
game.deletetele();
|
|
|
|
game.deletestats();
|
Move all settings to settings.vvv
The game previously did this dumb thing where it lumped in all its
settings with its file that tracked your records and unlocks,
`unlock.vvv`. It wasn't really an issue, until 2.3 came along and added
a few settings, suddenly making a problem where 2.3 settings would be
reset by chance if you decided to touch 2.2.
The solution to this is to move all settings to a new file,
`settings.vvv`. However, for compatibility with 2.2, settings will still
be written to `unlock.vvv`.
The game will prioritize reading from `settings.vvv` instead of
`unlock.vvv`, so if there's a setting that's missing from `unlock.vvv`,
no worries there. But if `settings.vvv` is missing, then it'll read
settings from `unlock.vvv`. As well, if `unlock.vvv` is missing, then
`settings.vvv` will be read from instead (I explicitly tested for this,
and found that I had to write special code to handle this case,
otherwise the game would overwrite the existing `settings.vvv` before
reading from it; kids, make sure to always test your code!).
Closes #373 fully.
2020-11-04 08:11:21 +01:00
|
|
|
game.deletesettings();
|
2020-04-15 19:14:42 +02:00
|
|
|
game.flashlight = 5;
|
|
|
|
game.screenshake = 15;
|
2020-04-16 06:53:36 +02:00
|
|
|
game.createmenu(Menu::mainmenu);
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
|
|
|
case Menu::playmodes:
|
2020-04-16 05:10:11 +02:00
|
|
|
if (game.currentmenuoption == 0 && game.slowdown == 30 && !map.invincibility) //go to the time trial menu
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
|
|
|
music.playef(11);
|
2020-04-16 06:53:36 +02:00
|
|
|
game.createmenu(Menu::timetrials);
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
|
|
|
}
|
|
|
|
else if (game.currentmenuoption == 1 && game.unlock[16])
|
|
|
|
{
|
|
|
|
//intermission mode menu
|
|
|
|
music.playef(11);
|
2020-04-16 06:53:36 +02:00
|
|
|
game.createmenu(Menu::intermissionmenu);
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
|
|
|
}
|
|
|
|
else if (game.currentmenuoption == 2 && game.unlock[17] && game.slowdown == 30 && !map.invincibility) //start a game in no death mode
|
|
|
|
{
|
|
|
|
music.playef(11);
|
2020-04-16 06:53:36 +02:00
|
|
|
game.createmenu(Menu::startnodeathmode);
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
|
|
|
}
|
|
|
|
else if (game.currentmenuoption == 3 && game.unlock[18]) //enable/disable flip mode
|
|
|
|
{
|
2020-06-30 05:45:57 +02:00
|
|
|
// WARNING: Partially duplicated in Menu::options
|
2020-04-15 19:14:42 +02:00
|
|
|
graphics.setflipmode = !graphics.setflipmode;
|
2021-01-11 04:39:19 +01:00
|
|
|
game.savestatsandsettings();
|
2020-05-19 03:09:12 +02:00
|
|
|
if (graphics.setflipmode)
|
|
|
|
{
|
|
|
|
music.playef(18);
|
|
|
|
game.screenshake = 10;
|
|
|
|
game.flashlight = 5;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
music.playef(11);
|
|
|
|
}
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
|
|
|
else if (game.currentmenuoption == 4)
|
|
|
|
{
|
|
|
|
//back
|
|
|
|
music.playef(11);
|
2020-04-17 05:05:01 +02:00
|
|
|
game.returnmenu();
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//Can't do yet! play sad sound
|
|
|
|
music.playef(2);
|
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
|
|
|
case Menu::startnodeathmode:
|
2020-04-16 05:10:11 +02:00
|
|
|
switch (game.currentmenuoption)
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
2020-04-16 05:10:11 +02:00
|
|
|
case 0: //start no death mode, disabling cutscenes
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 10;
|
|
|
|
graphics.fademode = 2;
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 1:
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 9;
|
|
|
|
graphics.fademode = 2;
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 2:
|
2020-04-15 19:14:42 +02:00
|
|
|
//back
|
|
|
|
music.playef(11);
|
2020-04-17 05:05:01 +02:00
|
|
|
game.returnmenu();
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
|
|
|
case Menu::continuemenu:
|
2020-04-16 05:10:11 +02:00
|
|
|
switch (game.currentmenuoption)
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
2020-04-16 05:10:11 +02:00
|
|
|
case 0:
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 1;
|
|
|
|
graphics.fademode = 2;
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 1:
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 2;
|
|
|
|
graphics.fademode = 2;
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 2:
|
2020-04-15 19:14:42 +02:00
|
|
|
//back
|
|
|
|
music.playef(11);
|
2020-04-17 05:05:01 +02:00
|
|
|
game.returnmenu();
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
|
|
|
case Menu::intermissionmenu:
|
2020-04-16 05:10:11 +02:00
|
|
|
switch (game.currentmenuoption)
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
2020-04-16 05:10:11 +02:00
|
|
|
case 0:
|
2020-04-15 19:14:42 +02:00
|
|
|
music.playef(11);
|
|
|
|
music.play(6);
|
2020-04-16 06:53:36 +02:00
|
|
|
game.createmenu(Menu::playint1);
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 1:
|
2020-04-15 19:14:42 +02:00
|
|
|
music.playef(11);
|
|
|
|
music.play(6);
|
2020-04-16 06:53:36 +02:00
|
|
|
game.createmenu(Menu::playint2);
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 2:
|
2020-04-15 19:14:42 +02:00
|
|
|
//back
|
|
|
|
music.playef(11);
|
2020-04-17 05:05:01 +02:00
|
|
|
game.returnmenu();
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
|
|
|
case Menu::playint1:
|
2020-04-16 05:10:11 +02:00
|
|
|
switch (game.currentmenuoption)
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
2020-04-16 05:10:11 +02:00
|
|
|
case 0:
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 12;
|
|
|
|
graphics.fademode = 2;
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 1:
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 13;
|
|
|
|
graphics.fademode = 2;
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 2:
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 14;
|
|
|
|
graphics.fademode = 2;
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 3:
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 15;
|
|
|
|
graphics.fademode = 2;
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 4:
|
2020-04-15 19:14:42 +02:00
|
|
|
//back
|
|
|
|
music.playef(11);
|
2020-04-17 05:05:01 +02:00
|
|
|
game.returnmenu();
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
|
|
|
case Menu::playint2:
|
2020-04-16 05:10:11 +02:00
|
|
|
switch (game.currentmenuoption)
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
2020-04-16 05:10:11 +02:00
|
|
|
case 0:
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 16;
|
|
|
|
graphics.fademode = 2;
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 1:
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 17;
|
|
|
|
graphics.fademode = 2;
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 2:
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 18;
|
|
|
|
graphics.fademode = 2;
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 3:
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 19;
|
|
|
|
graphics.fademode = 2;
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 4:
|
2020-04-15 19:14:42 +02:00
|
|
|
//back
|
|
|
|
music.playef(11);
|
2020-04-17 05:05:01 +02:00
|
|
|
game.returnmenu();
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
|
|
|
case Menu::gameover2:
|
2020-04-15 19:14:42 +02:00
|
|
|
//back
|
|
|
|
music.playef(11);
|
|
|
|
music.play(6);
|
2020-04-27 21:27:12 +02:00
|
|
|
game.returntomenu(Menu::playmodes);
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
|
|
|
case Menu::unlocktimetrials:
|
|
|
|
case Menu::unlocktimetrial:
|
|
|
|
case Menu::unlocknodeathmode:
|
|
|
|
case Menu::unlockintermission:
|
|
|
|
case Menu::unlockflipmode:
|
2020-04-15 19:14:42 +02:00
|
|
|
//back
|
|
|
|
music.playef(11);
|
2020-04-17 04:26:49 +02:00
|
|
|
game.createmenu(Menu::play, true);
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
|
|
|
case Menu::timetrials:
|
2020-04-15 19:14:42 +02:00
|
|
|
if (game.currentmenuoption == 0 && game.unlock[9]) //space station 1
|
|
|
|
{
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 3;
|
|
|
|
graphics.fademode = 2;
|
|
|
|
}
|
|
|
|
else if (game.currentmenuoption == 1 && game.unlock[10]) //lab
|
|
|
|
{
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 4;
|
|
|
|
graphics.fademode = 2;
|
|
|
|
}
|
|
|
|
else if (game.currentmenuoption == 2 && game.unlock[11]) //tower
|
|
|
|
{
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 5;
|
|
|
|
graphics.fademode = 2;
|
|
|
|
}
|
|
|
|
else if (game.currentmenuoption == 3 && game.unlock[12]) //station 2
|
|
|
|
{
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 6;
|
|
|
|
graphics.fademode = 2;
|
|
|
|
}
|
|
|
|
else if (game.currentmenuoption == 4 && game.unlock[13]) //warp
|
|
|
|
{
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 7;
|
|
|
|
graphics.fademode = 2;
|
|
|
|
}
|
|
|
|
else if (game.currentmenuoption == 5 && game.unlock[14]) //final
|
|
|
|
{
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 8;
|
|
|
|
graphics.fademode = 2;
|
|
|
|
}
|
|
|
|
else if (game.currentmenuoption == 6) //go to the time trial menu
|
|
|
|
{
|
|
|
|
//back
|
|
|
|
music.playef(11);
|
2020-04-17 05:05:01 +02:00
|
|
|
game.returnmenu();
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//Can't do yet! play sad sound
|
|
|
|
music.playef(2);
|
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
|
|
|
case Menu::timetrialcomplete3:
|
2020-04-16 05:10:11 +02:00
|
|
|
switch (game.currentmenuoption)
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
2020-04-16 05:10:11 +02:00
|
|
|
case 0:
|
2020-04-15 19:14:42 +02:00
|
|
|
//back
|
|
|
|
music.playef(11);
|
|
|
|
music.play(6);
|
2020-06-26 01:22:58 +02:00
|
|
|
game.returntomenu(Menu::timetrials);
|
2020-04-15 19:14:42 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
|
|
|
case 1:
|
2020-04-17 06:25:30 +02:00
|
|
|
//Ok but first quickly remove the last stack frame to prevent piling up timetrialcomplete stack frames
|
|
|
|
if (game.menustack.empty())
|
|
|
|
{
|
|
|
|
puts("Error: menu stack is empty!");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
game.menustack.pop_back();
|
|
|
|
}
|
2020-04-15 19:14:42 +02:00
|
|
|
//duplicate the above based on given time trial level!
|
|
|
|
if (game.timetriallevel == 0) //space station 1
|
|
|
|
{
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 3;
|
|
|
|
graphics.fademode = 2;
|
|
|
|
}
|
|
|
|
else if (game.timetriallevel == 1) //lab
|
|
|
|
{
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 4;
|
|
|
|
graphics.fademode = 2;
|
|
|
|
}
|
|
|
|
else if (game.timetriallevel == 2) //tower
|
|
|
|
{
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 5;
|
|
|
|
graphics.fademode = 2;
|
|
|
|
}
|
|
|
|
else if (game.timetriallevel == 3) //station 2
|
|
|
|
{
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 6;
|
|
|
|
graphics.fademode = 2;
|
|
|
|
}
|
|
|
|
else if (game.timetriallevel == 4) //warp
|
|
|
|
{
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 7;
|
|
|
|
graphics.fademode = 2;
|
|
|
|
}
|
|
|
|
else if (game.timetriallevel == 5) //final
|
|
|
|
{
|
2020-05-19 03:03:18 +02:00
|
|
|
music.playef(11);
|
2020-04-15 19:14:42 +02:00
|
|
|
game.mainmenu = 8;
|
|
|
|
graphics.fademode = 2;
|
|
|
|
}
|
2020-04-16 05:10:11 +02:00
|
|
|
break;
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
|
|
|
case Menu::gamecompletecontinue:
|
|
|
|
case Menu::nodeathmodecomplete2:
|
2020-04-16 05:10:11 +02:00
|
|
|
music.play(6);
|
|
|
|
music.playef(11);
|
2020-04-17 06:25:30 +02:00
|
|
|
game.returnmenu();
|
2020-04-16 05:10:11 +02:00
|
|
|
map.nexttowercolour();
|
2020-04-17 00:19:17 +02:00
|
|
|
break;
|
2020-11-22 03:10:26 +01:00
|
|
|
case Menu::errorsavingsettings:
|
|
|
|
if (game.currentmenuoption == 1)
|
|
|
|
{
|
|
|
|
game.silence_settings_error = true;
|
|
|
|
}
|
|
|
|
music.playef(11);
|
|
|
|
game.returnmenu();
|
|
|
|
map.nexttowercolour();
|
|
|
|
break;
|
2020-04-17 00:19:17 +02:00
|
|
|
default:
|
|
|
|
break;
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
|
|
|
}
|
2020-02-12 05:45:58 +01:00
|
|
|
|
2020-04-15 19:14:42 +02:00
|
|
|
void titleinput()
|
|
|
|
{
|
|
|
|
//game.mx = (mouseX / 4);
|
|
|
|
//game.my = (mouseY / 4);
|
2020-02-12 05:45:58 +01:00
|
|
|
|
2020-04-15 19:14:42 +02:00
|
|
|
game.press_left = false;
|
|
|
|
game.press_right = false;
|
|
|
|
game.press_action = false;
|
|
|
|
game.press_map = false;
|
2020-02-12 05:45:58 +01:00
|
|
|
|
2020-04-15 19:14:42 +02:00
|
|
|
if (graphics.flipmode)
|
|
|
|
{
|
|
|
|
if (key.isDown(KEYBOARD_LEFT) || key.isDown(KEYBOARD_DOWN) || key.isDown(KEYBOARD_a) || key.isDown(KEYBOARD_s) || key.controllerWantsRight(true)) game.press_left = true;
|
|
|
|
if (key.isDown(KEYBOARD_RIGHT) || key.isDown(KEYBOARD_UP) || key.isDown(KEYBOARD_d) || key.isDown(KEYBOARD_w) || key.controllerWantsLeft(true)) game.press_right = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (key.isDown(KEYBOARD_LEFT) || key.isDown(KEYBOARD_UP) || key.isDown(KEYBOARD_a) || key.isDown(KEYBOARD_w) || key.controllerWantsLeft(true))
|
|
|
|
{
|
|
|
|
game.press_left = true;
|
|
|
|
}
|
|
|
|
if (key.isDown(KEYBOARD_RIGHT) || key.isDown(KEYBOARD_DOWN) || key.isDown(KEYBOARD_d) || key.isDown(KEYBOARD_s) || key.controllerWantsRight(true))
|
|
|
|
{
|
|
|
|
game.press_right = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (key.isDown(KEYBOARD_z) || key.isDown(KEYBOARD_SPACE) || key.isDown(KEYBOARD_v) || key.isDown(game.controllerButton_flip)) game.press_action = true;
|
|
|
|
//|| key.isDown(KEYBOARD_UP) || key.isDown(KEYBOARD_DOWN)) game.press_action = true; //on menus, up and down don't work as action
|
|
|
|
if (key.isDown(KEYBOARD_ENTER)) game.press_map = true;
|
2020-02-12 05:45:58 +01:00
|
|
|
|
2020-04-15 19:14:42 +02:00
|
|
|
//In the menu system, all keypresses are single taps rather than holds. Therefore this test has to be done for all presses
|
|
|
|
if (!game.press_action && !game.press_left && !game.press_right) game.jumpheld = false;
|
|
|
|
if (!game.press_map) game.mapheld = false;
|
2020-02-12 05:45:58 +01:00
|
|
|
|
2020-04-15 19:14:42 +02:00
|
|
|
if (!game.jumpheld && graphics.fademode==0)
|
|
|
|
{
|
|
|
|
if (game.press_action || game.press_left || game.press_right || game.press_map)
|
|
|
|
{
|
|
|
|
game.jumpheld = true;
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-04-16 06:53:36 +02:00
|
|
|
if (key.isDown(27) && game.currentmenuname != Menu::youwannaquit && game.menustart)
|
2020-04-15 19:14:42 +02:00
|
|
|
{
|
|
|
|
music.playef(11);
|
2020-06-23 02:29:30 +02:00
|
|
|
if (game.ingame_titlemode)
|
|
|
|
{
|
|
|
|
game.returntopausemenu();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
game.createmenu(Menu::youwannaquit);
|
|
|
|
map.nexttowercolour();
|
|
|
|
}
|
2020-04-15 19:14:42 +02:00
|
|
|
}
|
2020-04-02 23:06:56 +02:00
|
|
|
|
2020-04-15 19:14:42 +02:00
|
|
|
if(game.menustart)
|
|
|
|
{
|
|
|
|
if (game.press_left)
|
|
|
|
{
|
|
|
|
game.currentmenuoption--;
|
|
|
|
}
|
|
|
|
else if (game.press_right)
|
|
|
|
{
|
|
|
|
game.currentmenuoption++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (game.currentmenuoption < 0) game.currentmenuoption = game.menuoptions.size()-1;
|
|
|
|
if (game.currentmenuoption >= (int) game.menuoptions.size() ) game.currentmenuoption = 0;
|
|
|
|
|
|
|
|
if (game.press_action)
|
|
|
|
{
|
|
|
|
if (!game.menustart)
|
|
|
|
{
|
|
|
|
game.menustart = true;
|
|
|
|
music.play(6);
|
|
|
|
music.playef(18);
|
|
|
|
game.screenshake = 10;
|
|
|
|
game.flashlight = 5;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
menuactionpress();
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
}
|
2020-04-16 06:53:36 +02:00
|
|
|
if ( game.currentmenuname == Menu::controller &&
|
2020-01-01 21:29:24 +01:00
|
|
|
game.currentmenuoption > 0 &&
|
2020-08-09 00:41:59 +02:00
|
|
|
game.currentmenuoption < 5 &&
|
2020-01-01 21:29:24 +01:00
|
|
|
key.controllerButtonDown() )
|
|
|
|
{
|
2020-04-01 23:52:45 +02:00
|
|
|
updatebuttonmappings(game.currentmenuoption);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-04-01 23:52:45 +02:00
|
|
|
if (graphics.fademode == 1)
|
2020-03-31 21:38:52 +02:00
|
|
|
script.startgamemode(game.mainmenu);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
2020-04-01 23:52:45 +02:00
|
|
|
void gameinput()
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
//TODO mouse input
|
|
|
|
//game.mx = (mouseX / 2);
|
|
|
|
//game.my = (mouseY / 2);
|
|
|
|
|
|
|
|
if(!script.running)
|
|
|
|
{
|
|
|
|
game.press_left = false;
|
|
|
|
game.press_right = false;
|
|
|
|
game.press_action = false;
|
|
|
|
|
2020-04-03 02:59:08 +02:00
|
|
|
if (key.isDown(KEYBOARD_LEFT) || key.isDown(KEYBOARD_a) || key.controllerWantsLeft(false))
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-04-03 02:59:08 +02:00
|
|
|
game.press_left = true;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
2020-04-03 02:59:08 +02:00
|
|
|
if (key.isDown(KEYBOARD_RIGHT) || key.isDown(KEYBOARD_d) || key.controllerWantsRight(false))
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-04-03 02:59:08 +02:00
|
|
|
game.press_right = true;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
2020-04-03 02:59:08 +02:00
|
|
|
if (key.isDown(KEYBOARD_z) || key.isDown(KEYBOARD_SPACE) || key.isDown(KEYBOARD_v)
|
|
|
|
|| key.isDown(KEYBOARD_UP) || key.isDown(KEYBOARD_DOWN) || key.isDown(KEYBOARD_w) || key.isDown(KEYBOARD_s)|| key.isDown(game.controllerButton_flip))
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-04-03 02:59:08 +02:00
|
|
|
game.press_action = true;
|
|
|
|
};
|
2020-09-06 13:49:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
game.press_map = false;
|
|
|
|
if (key.isDown(KEYBOARD_ENTER) || key.isDown(SDLK_KP_ENTER) || key.isDown(game.controllerButton_map) )
|
|
|
|
{
|
|
|
|
game.press_map = true;
|
2020-04-03 02:59:08 +02:00
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
if (game.advancetext)
|
|
|
|
{
|
|
|
|
if (game.pausescript)
|
|
|
|
{
|
|
|
|
game.press_action = false;
|
|
|
|
if (key.isDown(KEYBOARD_z) || key.isDown(KEYBOARD_SPACE) || key.isDown(KEYBOARD_v)
|
|
|
|
|| key.isDown(KEYBOARD_UP) || key.isDown(KEYBOARD_DOWN) || key.isDown(KEYBOARD_w) || key.isDown(KEYBOARD_s) || key.isDown(game.controllerButton_flip)) game.press_action = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (game.press_action && !game.jumpheld)
|
|
|
|
{
|
|
|
|
if (game.pausescript)
|
|
|
|
{
|
|
|
|
game.pausescript = false;
|
|
|
|
game.hascontrol = true;
|
|
|
|
game.jumpheld = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-06-25 23:34:22 +02:00
|
|
|
if(game.glitchrunnermode || !game.glitchrunkludge) game.state++;
|
2020-04-02 23:06:56 +02:00
|
|
|
game.jumpheld = true;
|
|
|
|
game.glitchrunkludge=true;
|
|
|
|
//Bug fix! You should only be able to do this ONCE.
|
2020-06-25 23:34:22 +02:00
|
|
|
//...Unless you're in glitchrunner mode
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Fix bringing up map menu during gamemode(teleporter)
When gamemode(teleporter) gets run in a script, it brings up a read-only
version of the teleporter screen, intended only for displaying rooms on
the minimap.
However, ever since 2.3 allowed bringing up the map screen during
cutscenes (in order to prevent softlocks), bringing up the map screen
during this mode would (1) do an unnecessary animation of suddenly
switching back to the game and bringing up the menu screen again (even
though the menu screen has already been brought up), and (2) would let
you close the menu entirely and go back to GAMEMODE, thus
unintentionally closing the teleporter screen and kind of ruining the
cutscene.
To fix this, when you bring up the map screen, it will instead instantly
transition to the map screen. And when you bring it down, it will also
instantly transition back to the teleporter screen.
But that's not all. The previous behavior was actually kind of a nice
failsafe, in that if you somehow got stuck in a state where a script ran
gamemode(teleporter), but stopped running before it could take you out
of that mode by running gamemode(game), then you could return to
GAMEMODE yourself by bringing up the map screen and then bringing it
back down. So I've made sure to keep that failsafe behavior, only as
long as there isn't a script running.
2020-12-29 00:36:32 +01:00
|
|
|
if (!game.press_map
|
|
|
|
//Extra conditionals as a kludge fix so if you open the quit menu during
|
|
|
|
//the script command gamemode(teleporter) and close it with Esc, it won't
|
|
|
|
//immediately open again
|
|
|
|
//We really need a better input system soon...
|
|
|
|
&& !key.isDown(27)
|
|
|
|
&& !key.isDown(game.controllerButton_esc))
|
|
|
|
{
|
|
|
|
game.mapheld = false;
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-04-01 23:52:45 +02:00
|
|
|
if (game.intimetrial && graphics.fademode == 1 && game.quickrestartkludge)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
//restart the time trial
|
|
|
|
game.quickrestartkludge = false;
|
2020-03-31 21:38:52 +02:00
|
|
|
script.startgamemode(game.timetriallevel + 3);
|
2020-01-01 21:29:24 +01:00
|
|
|
game.deathseq = -1;
|
|
|
|
game.completestop = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Returning to editor mode must always be possible
|
2020-02-10 03:21:19 +01:00
|
|
|
#if !defined(NO_CUSTOM_LEVELS)
|
2020-01-01 21:29:24 +01:00
|
|
|
if(map.custommode && !map.custommodeforreal){
|
2020-04-04 01:34:20 +02:00
|
|
|
if ((game.press_map || key.isDown(27)) && !game.mapheld){
|
|
|
|
//Return to level editor
|
Use explicit INBOUNDS_VEC() instead of checking sentinel -1
It's better to do INBOUNDS_VEC(i, obj.entities) instead of 'i > -1'.
'i > -1' is used in cases like obj.getplayer(), which COULD return a
sentinel value of -1 and so correct code will have to check that value.
However, I am now of the opinion that INBOUNDS_VEC() should be used and
isn't unnecessary.
Consider the case of the face() script command: it's not enough to check
i > -1, you should read the routine carefully. Because if you look
closely, you'll see that it's not guaranteed that 'i' will be initialized
at all in that command. Indeed, if you call face() with invalid
arguments, it won't be. And so, 'i' could be something like 215, and
that would index out-of-bounds, and that wouldn't be good. Therefore,
it's better to have the full bounds check instead of checking only one
bounds. Many commands are like this, after some searching I can also
name position(), changemood(), changetile(), changegravity(), etc.
It also makes the code more explicit. Now you don't have to wonder what
-1 means or why it's being checked, you can just read the 'INBOUNDS' and
go "oh, that checks if it's actually inbounds or not".
2020-09-09 13:15:14 +02:00
|
|
|
if (INBOUNDS_VEC(game.activeactivity, obj.blocks) && game.press_map){
|
2020-05-14 21:39:29 +02:00
|
|
|
//pass, let code block below handle it
|
2020-07-11 09:15:06 +02:00
|
|
|
}else if(game.activetele && game.readytotele > 20 && game.press_map){
|
|
|
|
//pass, let code block below handle it
|
2020-04-04 01:34:20 +02:00
|
|
|
}else{
|
2020-05-09 21:52:58 +02:00
|
|
|
game.shouldreturntoeditor = true;
|
2020-05-14 21:39:29 +02:00
|
|
|
game.mapheld = true;
|
2020-01-31 04:06:16 +01:00
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
}
|
2020-02-10 01:53:01 +01:00
|
|
|
#endif
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
//Entity type 0 is player controled
|
2020-09-06 13:28:09 +02:00
|
|
|
bool has_control = false;
|
|
|
|
bool enter_pressed = game.press_map && !game.mapheld;
|
|
|
|
bool enter_already_processed = false;
|
2020-04-03 22:50:16 +02:00
|
|
|
for (size_t ie = 0; ie < obj.entities.size(); ++ie)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
if (obj.entities[ie].rule == 0)
|
|
|
|
{
|
|
|
|
if (game.hascontrol && game.deathseq == -1 && game.lifeseq <= 5)
|
|
|
|
{
|
2020-09-06 13:28:09 +02:00
|
|
|
has_control = true;
|
|
|
|
if (enter_pressed)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
game.mapheld = true;
|
|
|
|
|
|
|
|
if (game.activetele && game.readytotele > 20 && !game.intimetrial)
|
|
|
|
{
|
2020-09-06 13:28:09 +02:00
|
|
|
enter_already_processed = true;
|
2021-01-02 03:38:55 +01:00
|
|
|
if(int(SDL_fabsf(obj.entities[ie].vx))<=1 && int(obj.entities[ie].vy)==0)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
//wait! space station 2 debug thingy
|
|
|
|
if (game.teleportscript != "")
|
|
|
|
{
|
|
|
|
|
|
|
|
//trace(game.recordstring);
|
|
|
|
//We're teleporting! Yey!
|
|
|
|
game.activetele = false;
|
|
|
|
game.hascontrol = false;
|
2020-04-03 02:59:08 +02:00
|
|
|
music.fadeout();
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
int player = obj.getplayer();
|
Use explicit INBOUNDS_VEC() instead of checking sentinel -1
It's better to do INBOUNDS_VEC(i, obj.entities) instead of 'i > -1'.
'i > -1' is used in cases like obj.getplayer(), which COULD return a
sentinel value of -1 and so correct code will have to check that value.
However, I am now of the opinion that INBOUNDS_VEC() should be used and
isn't unnecessary.
Consider the case of the face() script command: it's not enough to check
i > -1, you should read the routine carefully. Because if you look
closely, you'll see that it's not guaranteed that 'i' will be initialized
at all in that command. Indeed, if you call face() with invalid
arguments, it won't be. And so, 'i' could be something like 215, and
that would index out-of-bounds, and that wouldn't be good. Therefore,
it's better to have the full bounds check instead of checking only one
bounds. Many commands are like this, after some searching I can also
name position(), changemood(), changetile(), changegravity(), etc.
It also makes the code more explicit. Now you don't have to wonder what
-1 means or why it's being checked, you can just read the 'INBOUNDS' and
go "oh, that checks if it's actually inbounds or not".
2020-09-09 13:15:14 +02:00
|
|
|
if (INBOUNDS_VEC(player, obj.entities))
|
2020-06-13 05:36:08 +02:00
|
|
|
{
|
|
|
|
obj.entities[player].colour = 102;
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
int teleporter = obj.getteleporter();
|
Use explicit INBOUNDS_VEC() instead of checking sentinel -1
It's better to do INBOUNDS_VEC(i, obj.entities) instead of 'i > -1'.
'i > -1' is used in cases like obj.getplayer(), which COULD return a
sentinel value of -1 and so correct code will have to check that value.
However, I am now of the opinion that INBOUNDS_VEC() should be used and
isn't unnecessary.
Consider the case of the face() script command: it's not enough to check
i > -1, you should read the routine carefully. Because if you look
closely, you'll see that it's not guaranteed that 'i' will be initialized
at all in that command. Indeed, if you call face() with invalid
arguments, it won't be. And so, 'i' could be something like 215, and
that would index out-of-bounds, and that wouldn't be good. Therefore,
it's better to have the full bounds check instead of checking only one
bounds. Many commands are like this, after some searching I can also
name position(), changemood(), changetile(), changegravity(), etc.
It also makes the code more explicit. Now you don't have to wonder what
-1 means or why it's being checked, you can just read the 'INBOUNDS' and
go "oh, that checks if it's actually inbounds or not".
2020-09-09 13:15:14 +02:00
|
|
|
if (INBOUNDS_VEC(teleporter, obj.entities))
|
2020-06-13 04:31:08 +02:00
|
|
|
{
|
|
|
|
obj.entities[teleporter].tile = 6;
|
|
|
|
obj.entities[teleporter].colour = 102;
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
//which teleporter script do we use? it depends on the companion!
|
|
|
|
game.state = 4000;
|
|
|
|
game.statedelay = 0;
|
|
|
|
}
|
|
|
|
else if (game.companion == 0)
|
|
|
|
{
|
|
|
|
//Alright, normal teleporting
|
De-duplicate menu animation code when bringing up map screen
When bringing up the map screen, the game does a small menu animation
where the menu comes in from the bottom. The code to calculate the menu
offset is copy-pasted everywhere, so I thought I'd de-duplicate it to
make my life easier when working with it. I also included the
game.gamestate assignment in the de-duplicated function, so it would be
easier for a future bugfix.
At the same time, I'm also removing all the BlitSurfaceStandard()s that
copied menubuffer to backBuffer. The red flag is that this blit happened
for every single entry point to MAPMODE and TELEPORTERMODE, except for
the script command gamemode(teleporter). Pressing Enter to bring up the
map screen, pressing Enter to quit the Super Gravitron, pressing Esc to
bring up the pause screen, and pressing Enter to bring up the teleporter
screen all do this blit, so if this blit was there to fix a bug, then
there's a bug with using the script command gamemode(teleporter)... but,
as far as I can tell, there isn't.
That's because the blit basically does nothing. All the blit does is
copy menubuffer onto backBuffer. Then the next thing that happens is
that either maprender() or teleporterrender() will be called, and the
first thing that those functions will always do is fill backBuffer with
solid black, completely overriding the previous blit. So that's why
removing this blit won't have any effect, and it can be safely removed
for code clarity.
2020-12-28 23:23:35 +01:00
|
|
|
game.mapmenuchange(TELEPORTERMODE);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
game.useteleporter = true;
|
2020-03-31 02:16:02 +02:00
|
|
|
game.initteleportermode();
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//We're teleporting! Yey!
|
|
|
|
game.activetele = false;
|
|
|
|
game.hascontrol = false;
|
2020-04-03 02:59:08 +02:00
|
|
|
music.fadeout();
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
int player = obj.getplayer();
|
Use explicit INBOUNDS_VEC() instead of checking sentinel -1
It's better to do INBOUNDS_VEC(i, obj.entities) instead of 'i > -1'.
'i > -1' is used in cases like obj.getplayer(), which COULD return a
sentinel value of -1 and so correct code will have to check that value.
However, I am now of the opinion that INBOUNDS_VEC() should be used and
isn't unnecessary.
Consider the case of the face() script command: it's not enough to check
i > -1, you should read the routine carefully. Because if you look
closely, you'll see that it's not guaranteed that 'i' will be initialized
at all in that command. Indeed, if you call face() with invalid
arguments, it won't be. And so, 'i' could be something like 215, and
that would index out-of-bounds, and that wouldn't be good. Therefore,
it's better to have the full bounds check instead of checking only one
bounds. Many commands are like this, after some searching I can also
name position(), changemood(), changetile(), changegravity(), etc.
It also makes the code more explicit. Now you don't have to wonder what
-1 means or why it's being checked, you can just read the 'INBOUNDS' and
go "oh, that checks if it's actually inbounds or not".
2020-09-09 13:15:14 +02:00
|
|
|
if (INBOUNDS_VEC(player, obj.entities))
|
2020-06-13 05:36:08 +02:00
|
|
|
{
|
|
|
|
obj.entities[player].colour = 102;
|
|
|
|
}
|
2020-04-02 00:32:21 +02:00
|
|
|
int companion = obj.getcompanion();
|
Use explicit INBOUNDS_VEC() instead of checking sentinel -1
It's better to do INBOUNDS_VEC(i, obj.entities) instead of 'i > -1'.
'i > -1' is used in cases like obj.getplayer(), which COULD return a
sentinel value of -1 and so correct code will have to check that value.
However, I am now of the opinion that INBOUNDS_VEC() should be used and
isn't unnecessary.
Consider the case of the face() script command: it's not enough to check
i > -1, you should read the routine carefully. Because if you look
closely, you'll see that it's not guaranteed that 'i' will be initialized
at all in that command. Indeed, if you call face() with invalid
arguments, it won't be. And so, 'i' could be something like 215, and
that would index out-of-bounds, and that wouldn't be good. Therefore,
it's better to have the full bounds check instead of checking only one
bounds. Many commands are like this, after some searching I can also
name position(), changemood(), changetile(), changegravity(), etc.
It also makes the code more explicit. Now you don't have to wonder what
-1 means or why it's being checked, you can just read the 'INBOUNDS' and
go "oh, that checks if it's actually inbounds or not".
2020-09-09 13:15:14 +02:00
|
|
|
if(INBOUNDS_VEC(companion, obj.entities)) obj.entities[companion].colour = 102;
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
int teleporter = obj.getteleporter();
|
Use explicit INBOUNDS_VEC() instead of checking sentinel -1
It's better to do INBOUNDS_VEC(i, obj.entities) instead of 'i > -1'.
'i > -1' is used in cases like obj.getplayer(), which COULD return a
sentinel value of -1 and so correct code will have to check that value.
However, I am now of the opinion that INBOUNDS_VEC() should be used and
isn't unnecessary.
Consider the case of the face() script command: it's not enough to check
i > -1, you should read the routine carefully. Because if you look
closely, you'll see that it's not guaranteed that 'i' will be initialized
at all in that command. Indeed, if you call face() with invalid
arguments, it won't be. And so, 'i' could be something like 215, and
that would index out-of-bounds, and that wouldn't be good. Therefore,
it's better to have the full bounds check instead of checking only one
bounds. Many commands are like this, after some searching I can also
name position(), changemood(), changetile(), changegravity(), etc.
It also makes the code more explicit. Now you don't have to wonder what
-1 means or why it's being checked, you can just read the 'INBOUNDS' and
go "oh, that checks if it's actually inbounds or not".
2020-09-09 13:15:14 +02:00
|
|
|
if (INBOUNDS_VEC(teleporter, obj.entities))
|
2020-06-13 04:31:08 +02:00
|
|
|
{
|
|
|
|
obj.entities[teleporter].tile = 6;
|
|
|
|
obj.entities[teleporter].colour = 102;
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
//which teleporter script do we use? it depends on the companion!
|
|
|
|
game.state = 3000;
|
|
|
|
game.statedelay = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
Use explicit INBOUNDS_VEC() instead of checking sentinel -1
It's better to do INBOUNDS_VEC(i, obj.entities) instead of 'i > -1'.
'i > -1' is used in cases like obj.getplayer(), which COULD return a
sentinel value of -1 and so correct code will have to check that value.
However, I am now of the opinion that INBOUNDS_VEC() should be used and
isn't unnecessary.
Consider the case of the face() script command: it's not enough to check
i > -1, you should read the routine carefully. Because if you look
closely, you'll see that it's not guaranteed that 'i' will be initialized
at all in that command. Indeed, if you call face() with invalid
arguments, it won't be. And so, 'i' could be something like 215, and
that would index out-of-bounds, and that wouldn't be good. Therefore,
it's better to have the full bounds check instead of checking only one
bounds. Many commands are like this, after some searching I can also
name position(), changemood(), changetile(), changegravity(), etc.
It also makes the code more explicit. Now you don't have to wonder what
-1 means or why it's being checked, you can just read the 'INBOUNDS' and
go "oh, that checks if it's actually inbounds or not".
2020-09-09 13:15:14 +02:00
|
|
|
else if (INBOUNDS_VEC(game.activeactivity, obj.blocks))
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-09-06 13:28:09 +02:00
|
|
|
enter_already_processed = true;
|
2021-01-02 03:38:55 +01:00
|
|
|
if((int(SDL_fabsf(obj.entities[ie].vx))<=1) && (int(obj.entities[ie].vy) == 0) )
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
script.load(obj.blocks[game.activeactivity].script);
|
|
|
|
obj.removeblock(game.activeactivity);
|
2020-04-04 01:28:50 +02:00
|
|
|
game.activeactivity = -1;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (game.press_left)
|
|
|
|
{
|
|
|
|
game.tapleft++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (game.tapleft <= 4 && game.tapleft > 0)
|
|
|
|
{
|
|
|
|
if (obj.entities[ie].vx < 0.0f)
|
|
|
|
{
|
|
|
|
obj.entities[ie].vx = 0.0f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
game.tapleft = 0;
|
|
|
|
}
|
|
|
|
if (game.press_right)
|
|
|
|
{
|
|
|
|
game.tapright++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (game.tapright <= 4 && game.tapright > 0)
|
|
|
|
{
|
|
|
|
if (obj.entities[ie].vx > 0.0f)
|
|
|
|
{
|
|
|
|
obj.entities[ie].vx = 0.0f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
game.tapright = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(game.press_left)
|
|
|
|
{
|
|
|
|
obj.entities[ie].ax = -3;
|
|
|
|
obj.entities[ie].dir = 0;
|
|
|
|
}
|
|
|
|
else if (game.press_right)
|
|
|
|
{
|
|
|
|
obj.entities[ie].ax = 3;
|
|
|
|
obj.entities[ie].dir = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!game.press_action)
|
|
|
|
{
|
|
|
|
game.jumppressed = 0;
|
|
|
|
game.jumpheld = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (game.press_action && !game.jumpheld)
|
|
|
|
{
|
|
|
|
game.jumppressed = 5;
|
|
|
|
game.jumpheld = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (game.jumppressed > 0)
|
|
|
|
{
|
|
|
|
game.jumppressed--;
|
|
|
|
if (obj.entities[ie].onground>0 && game.gravitycontrol == 0)
|
|
|
|
{
|
|
|
|
game.gravitycontrol = 1;
|
|
|
|
obj.entities[ie].vy = -4;
|
|
|
|
obj.entities[ie].ay = -3;
|
2020-04-02 01:36:35 +02:00
|
|
|
music.playef(0);
|
2020-01-01 21:29:24 +01:00
|
|
|
game.jumppressed = 0;
|
|
|
|
game.totalflips++;
|
|
|
|
}
|
|
|
|
if (obj.entities[ie].onroof>0 && game.gravitycontrol == 1)
|
|
|
|
{
|
|
|
|
game.gravitycontrol = 0;
|
|
|
|
obj.entities[ie].vy = 4;
|
|
|
|
obj.entities[ie].ay = 3;
|
2020-04-02 01:36:35 +02:00
|
|
|
music.playef(1);
|
2020-01-01 21:29:24 +01:00
|
|
|
game.jumppressed = 0;
|
|
|
|
game.totalflips++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-09-06 13:28:09 +02:00
|
|
|
}
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-09-06 13:28:09 +02:00
|
|
|
if (!has_control)
|
|
|
|
{
|
|
|
|
//Simple detection of keypresses outside player control, will probably scrap this (expand on
|
|
|
|
//advance text function)
|
|
|
|
if (!game.press_action)
|
|
|
|
{
|
|
|
|
game.jumppressed = 0;
|
|
|
|
game.jumpheld = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (game.press_action && !game.jumpheld)
|
|
|
|
{
|
|
|
|
game.jumppressed = 5;
|
|
|
|
game.jumpheld = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Continuation of Enter processing. The rest of the if-tree runs only if
|
|
|
|
// enter_pressed && !enter_already_pressed
|
|
|
|
if (!enter_pressed || enter_already_processed)
|
|
|
|
{
|
|
|
|
// Do nothing
|
|
|
|
}
|
|
|
|
else if (game.swnmode == 1 && game.swngame == 1)
|
|
|
|
{
|
|
|
|
//quitting the super gravitron
|
|
|
|
game.mapheld = true;
|
|
|
|
//Quit menu, same conditions as in game menu
|
De-duplicate menu animation code when bringing up map screen
When bringing up the map screen, the game does a small menu animation
where the menu comes in from the bottom. The code to calculate the menu
offset is copy-pasted everywhere, so I thought I'd de-duplicate it to
make my life easier when working with it. I also included the
game.gamestate assignment in the de-duplicated function, so it would be
easier for a future bugfix.
At the same time, I'm also removing all the BlitSurfaceStandard()s that
copied menubuffer to backBuffer. The red flag is that this blit happened
for every single entry point to MAPMODE and TELEPORTERMODE, except for
the script command gamemode(teleporter). Pressing Enter to bring up the
map screen, pressing Enter to quit the Super Gravitron, pressing Esc to
bring up the pause screen, and pressing Enter to bring up the teleporter
screen all do this blit, so if this blit was there to fix a bug, then
there's a bug with using the script command gamemode(teleporter)... but,
as far as I can tell, there isn't.
That's because the blit basically does nothing. All the blit does is
copy menubuffer onto backBuffer. Then the next thing that happens is
that either maprender() or teleporterrender() will be called, and the
first thing that those functions will always do is fill backBuffer with
solid black, completely overriding the previous blit. So that's why
removing this blit won't have any effect, and it can be safely removed
for code clarity.
2020-12-28 23:23:35 +01:00
|
|
|
game.mapmenuchange(MAPMODE);
|
2020-09-06 13:28:09 +02:00
|
|
|
game.gamesaved = false;
|
2020-11-04 03:45:33 +01:00
|
|
|
game.gamesavefailed = false;
|
2020-09-06 13:28:09 +02:00
|
|
|
game.menupage = 20; // The Map Page
|
|
|
|
}
|
2020-09-06 13:28:18 +02:00
|
|
|
else if (game.intimetrial && graphics.fademode == 0)
|
2020-09-06 13:28:09 +02:00
|
|
|
{
|
|
|
|
//Quick restart of time trial
|
|
|
|
graphics.fademode = 2;
|
|
|
|
game.completestop = true;
|
|
|
|
music.fadeout();
|
|
|
|
game.quickrestartkludge = true;
|
|
|
|
}
|
2020-09-06 13:28:18 +02:00
|
|
|
else if (game.intimetrial)
|
|
|
|
{
|
|
|
|
//Do nothing if we're in a Time Trial but a fade animation is playing
|
|
|
|
}
|
|
|
|
else
|
2020-09-06 13:28:09 +02:00
|
|
|
{
|
|
|
|
//Normal map screen, do transition later
|
De-duplicate menu animation code when bringing up map screen
When bringing up the map screen, the game does a small menu animation
where the menu comes in from the bottom. The code to calculate the menu
offset is copy-pasted everywhere, so I thought I'd de-duplicate it to
make my life easier when working with it. I also included the
game.gamestate assignment in the de-duplicated function, so it would be
easier for a future bugfix.
At the same time, I'm also removing all the BlitSurfaceStandard()s that
copied menubuffer to backBuffer. The red flag is that this blit happened
for every single entry point to MAPMODE and TELEPORTERMODE, except for
the script command gamemode(teleporter). Pressing Enter to bring up the
map screen, pressing Enter to quit the Super Gravitron, pressing Esc to
bring up the pause screen, and pressing Enter to bring up the teleporter
screen all do this blit, so if this blit was there to fix a bug, then
there's a bug with using the script command gamemode(teleporter)... but,
as far as I can tell, there isn't.
That's because the blit basically does nothing. All the blit does is
copy menubuffer onto backBuffer. Then the next thing that happens is
that either maprender() or teleporterrender() will be called, and the
first thing that those functions will always do is fill backBuffer with
solid black, completely overriding the previous blit. So that's why
removing this blit won't have any effect, and it can be safely removed
for code clarity.
2020-12-28 23:23:35 +01:00
|
|
|
game.mapmenuchange(MAPMODE);
|
2020-09-06 13:28:09 +02:00
|
|
|
map.cursordelay = 0;
|
|
|
|
map.cursorstate = 0;
|
|
|
|
game.gamesaved = false;
|
2020-11-04 03:45:33 +01:00
|
|
|
game.gamesavefailed = false;
|
2020-11-16 00:32:44 +01:00
|
|
|
if (script.running)
|
|
|
|
{
|
|
|
|
game.menupage = 3; // Only allow saving
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
game.menupage = 0; // The Map Page
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
2020-09-06 13:28:09 +02:00
|
|
|
|
Fix bringing up map menu during gamemode(teleporter)
When gamemode(teleporter) gets run in a script, it brings up a read-only
version of the teleporter screen, intended only for displaying rooms on
the minimap.
However, ever since 2.3 allowed bringing up the map screen during
cutscenes (in order to prevent softlocks), bringing up the map screen
during this mode would (1) do an unnecessary animation of suddenly
switching back to the game and bringing up the menu screen again (even
though the menu screen has already been brought up), and (2) would let
you close the menu entirely and go back to GAMEMODE, thus
unintentionally closing the teleporter screen and kind of ruining the
cutscene.
To fix this, when you bring up the map screen, it will instead instantly
transition to the map screen. And when you bring it down, it will also
instantly transition back to the teleporter screen.
But that's not all. The previous behavior was actually kind of a nice
failsafe, in that if you somehow got stuck in a state where a script ran
gamemode(teleporter), but stopped running before it could take you out
of that mode by running gamemode(game), then you could return to
GAMEMODE yourself by bringing up the map screen and then bringing it
back down. So I've made sure to keep that failsafe behavior, only as
long as there isn't a script running.
2020-12-29 00:36:32 +01:00
|
|
|
if (!game.mapheld
|
|
|
|
&& (key.isDown(27) || key.isDown(game.controllerButton_esc))
|
|
|
|
&& (!map.custommode || map.custommodeforreal))
|
2020-09-06 13:28:09 +02:00
|
|
|
{
|
|
|
|
game.mapheld = true;
|
|
|
|
//Quit menu, same conditions as in game menu
|
De-duplicate menu animation code when bringing up map screen
When bringing up the map screen, the game does a small menu animation
where the menu comes in from the bottom. The code to calculate the menu
offset is copy-pasted everywhere, so I thought I'd de-duplicate it to
make my life easier when working with it. I also included the
game.gamestate assignment in the de-duplicated function, so it would be
easier for a future bugfix.
At the same time, I'm also removing all the BlitSurfaceStandard()s that
copied menubuffer to backBuffer. The red flag is that this blit happened
for every single entry point to MAPMODE and TELEPORTERMODE, except for
the script command gamemode(teleporter). Pressing Enter to bring up the
map screen, pressing Enter to quit the Super Gravitron, pressing Esc to
bring up the pause screen, and pressing Enter to bring up the teleporter
screen all do this blit, so if this blit was there to fix a bug, then
there's a bug with using the script command gamemode(teleporter)... but,
as far as I can tell, there isn't.
That's because the blit basically does nothing. All the blit does is
copy menubuffer onto backBuffer. Then the next thing that happens is
that either maprender() or teleporterrender() will be called, and the
first thing that those functions will always do is fill backBuffer with
solid black, completely overriding the previous blit. So that's why
removing this blit won't have any effect, and it can be safely removed
for code clarity.
2020-12-28 23:23:35 +01:00
|
|
|
game.mapmenuchange(MAPMODE);
|
2020-09-06 13:28:09 +02:00
|
|
|
game.gamesaved = false;
|
2020-11-04 03:45:33 +01:00
|
|
|
game.gamesavefailed = false;
|
2020-09-06 13:28:09 +02:00
|
|
|
game.menupage = 30; // Pause screen
|
|
|
|
}
|
|
|
|
|
|
|
|
if (game.deathseq == -1 && (key.isDown(SDLK_r) || key.isDown(game.controllerButton_restart)) && !game.nodeathmode)// && map.custommode) //Have fun glitchrunners!
|
|
|
|
{
|
|
|
|
game.deathseq = 30;
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
2021-01-10 18:14:37 +01:00
|
|
|
static void mapmenuactionpress();
|
2020-06-23 00:30:10 +02:00
|
|
|
|
2020-04-01 23:52:45 +02:00
|
|
|
void mapinput()
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
//TODO Mouse Input!
|
|
|
|
//game.mx = (mouseX / 2);
|
|
|
|
//game.my = (mouseY / 2);
|
|
|
|
|
|
|
|
game.press_left = false;
|
|
|
|
game.press_right = false;
|
|
|
|
game.press_action = false;
|
|
|
|
game.press_map = false;
|
|
|
|
|
2020-06-25 23:41:44 +02:00
|
|
|
if (game.glitchrunnermode && graphics.fademode == 1 && graphics.menuoffset == 0)
|
|
|
|
{
|
|
|
|
// Deliberate re-addition of the glitchy gamestate-based fadeout!
|
|
|
|
|
|
|
|
// First of all, detecting a black screen means if the glitchy fadeout
|
|
|
|
// gets interrupted but you're still on a black screen, opening a menu
|
|
|
|
// immediately quits you to the title. This has the side effect that if
|
|
|
|
// you accidentally press Esc during a cutscene when it's black, you'll
|
|
|
|
// immediately be quit and lose all your progress, but that's fair in
|
|
|
|
// glitchrunner mode.
|
|
|
|
// Also have to check graphics.menuoffset so this doesn't run every frame
|
|
|
|
|
2020-08-03 06:43:55 +02:00
|
|
|
// Have to close the menu in order to run gamestates
|
2020-06-25 23:41:44 +02:00
|
|
|
graphics.resumegamemode = true;
|
2020-08-03 06:43:55 +02:00
|
|
|
// Remove half-second delay
|
|
|
|
graphics.menuoffset = 250;
|
2020-06-25 23:41:44 +02:00
|
|
|
|
|
|
|
// Technically this was in <=2.2 as well
|
|
|
|
obj.removeallblocks();
|
|
|
|
|
|
|
|
if (game.menupage >= 20 && game.menupage <= 21)
|
|
|
|
{
|
|
|
|
game.state = 96;
|
|
|
|
game.statedelay = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Produces more glitchiness! Necessary for credits warp to work.
|
Fix aggressive glitchrunner hardreset causing issues quitting to menu
This fixes the bug where in glitchrunner mode, quitting to the menu
would always put you back at the play menu on the first option, instead
of the menu you entered the game from.
The problem is the script.hardreset() that gets called before the game
actually quits to the menu, so when Game::quittomenu() gets called to
quit to the menu, all the variables that keep track of whether you're in
a certain gamemode, such as game.insecretlab and map.custommode, all get
prematurely reset before that function can read them and put you back to
the correct menu.
The solution here is to simply reset only what's needed when quitting to
the menu. Specifically, in order for credits warp to work,
script.running needs to be set to false and all the text boxes need to
be removed. Text boxes need to be gone so the "- Press ACTION to advance
text -" prompt will stay up without a text box, enabling the player to
increment the gamestate at will by pressing ACTION, and the script needs
to stop running so further text boxes don't spawn in.
Fixes #389.
2020-08-14 04:26:52 +02:00
|
|
|
script.running = false;
|
|
|
|
graphics.textbox.clear();
|
2020-06-25 23:41:44 +02:00
|
|
|
|
|
|
|
game.state = 80;
|
|
|
|
game.statedelay = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (game.fadetomenu && !game.glitchrunnermode)
|
2020-05-08 00:23:55 +02:00
|
|
|
{
|
|
|
|
if (game.fadetomenudelay > 0)
|
|
|
|
{
|
|
|
|
game.fadetomenudelay--;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
game.quittomenu();
|
|
|
|
game.fadetomenu = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-25 23:41:44 +02:00
|
|
|
if (game.fadetolab && !game.glitchrunnermode)
|
2020-05-08 00:30:26 +02:00
|
|
|
{
|
|
|
|
if (game.fadetolabdelay > 0)
|
|
|
|
{
|
|
|
|
game.fadetolabdelay--;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
game.returntolab();
|
|
|
|
game.fadetolab = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-25 23:41:44 +02:00
|
|
|
if(graphics.menuoffset==0
|
Fix ACTION press processing on same frame as fade ticks to 0
Here's what causes #401: After the fade to menu delay ticks down to 0,
the game calls game.quittomenu(), but the rest of mapinput() still
executes. This means that the block that detects your ACTION press gets
executed, because there's a check that fadetomenudelay is less than or
equal to 0, and, well, it is.
So if you've pressed ACTION on the exact frame that it counts down to 0,
then the game detects your ACTION press, then processes it accordingly,
and then sets the fadetomenudelay, which means it'll get reactivated the
next time you open the map screen. But at this point, you get sent to
TITLEMODE, because game.quittomenu() set game.gamestate accordingly.
(This is why resetting game.fadetomenu or game.fadetomenudelay in
game.quittomenu() or script.hardreset() won't fix this bug.)
The solution here is to add a game.fadetomenu check to the ACTION press
processing.
Same-frame state transition logic is hard... actually, any sort of thing
where two things happen on the same frame is really annoying.
This also applies to fadetolab and fadetolabdelay, too.
Fixes #401.
2020-11-06 10:03:47 +01:00
|
|
|
&& ((!game.glitchrunnermode && !game.fadetomenu && game.fadetomenudelay <= 0 && !game.fadetolab && game.fadetolabdelay <= 0)
|
2020-07-17 00:11:54 +02:00
|
|
|
|| graphics.fademode == 0))
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-04-01 23:52:45 +02:00
|
|
|
if (graphics.flipmode)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-08-08 22:00:46 +02:00
|
|
|
if (key.isDown(KEYBOARD_LEFT) || key.isDown(KEYBOARD_DOWN) || key.isDown(KEYBOARD_a) || key.isDown(KEYBOARD_s) || key.controllerWantsLeft(true) ) game.press_left = true;
|
|
|
|
if (key.isDown(KEYBOARD_RIGHT) || key.isDown(KEYBOARD_UP) || key.isDown(KEYBOARD_d) || key.isDown(KEYBOARD_w) || key.controllerWantsRight(true)) game.press_right = true;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-08-08 22:00:46 +02:00
|
|
|
if (key.isDown(KEYBOARD_LEFT) || key.isDown(KEYBOARD_UP) || key.isDown(KEYBOARD_a) || key.isDown(KEYBOARD_w)|| key.controllerWantsLeft(true))
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
game.press_left = true;
|
|
|
|
}
|
2020-08-08 22:00:46 +02:00
|
|
|
if (key.isDown(KEYBOARD_RIGHT) || key.isDown(KEYBOARD_DOWN) || key.isDown(KEYBOARD_d) || key.isDown(KEYBOARD_s)|| key.controllerWantsRight(true))
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
game.press_right = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (key.isDown(KEYBOARD_z) || key.isDown(KEYBOARD_SPACE) || key.isDown(KEYBOARD_v) || key.isDown(game.controllerButton_flip))
|
|
|
|
{
|
|
|
|
game.press_action = true;
|
|
|
|
}
|
2020-06-23 06:36:50 +02:00
|
|
|
if (game.menupage < 12 || (game.menupage >= 30 && game.menupage <= 33))
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
if (key.isDown(KEYBOARD_ENTER) || key.isDown(game.controllerButton_map) ) game.press_map = true;
|
2020-06-23 06:36:50 +02:00
|
|
|
if (key.isDown(27) && !game.mapheld)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
game.mapheld = true;
|
2020-06-23 06:20:05 +02:00
|
|
|
if (game.menupage < 9)
|
|
|
|
{
|
|
|
|
game.menupage = 30;
|
|
|
|
}
|
2020-06-23 06:36:50 +02:00
|
|
|
else if (game.menupage < 12)
|
2020-06-23 06:20:05 +02:00
|
|
|
{
|
|
|
|
game.menupage = 31;
|
|
|
|
}
|
2020-06-23 06:36:50 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
graphics.resumegamemode = true;
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (key.isDown(KEYBOARD_ENTER) || key.isDown(27)|| key.isDown(game.controllerButton_map) ) game.press_map = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//In the menu system, all keypresses are single taps rather than holds. Therefore this test has to be done for all presses
|
|
|
|
if (!game.press_action && !game.press_left && !game.press_right)
|
|
|
|
{
|
|
|
|
game.jumpheld = false;
|
|
|
|
}
|
|
|
|
if (!game.press_map && !key.isDown(27))
|
|
|
|
{
|
|
|
|
game.mapheld = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
game.mapheld = true;
|
|
|
|
game.jumpheld = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!game.mapheld)
|
|
|
|
{
|
|
|
|
if(game.press_map && game.menupage < 10)
|
|
|
|
{
|
|
|
|
//Normal map screen, do transition later
|
2020-04-01 23:52:45 +02:00
|
|
|
graphics.resumegamemode = true;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!game.jumpheld)
|
|
|
|
{
|
|
|
|
if (game.press_action || game.press_left || game.press_right || game.press_map)
|
|
|
|
{
|
|
|
|
game.jumpheld = true;
|
|
|
|
}
|
|
|
|
|
2020-11-16 00:32:44 +01:00
|
|
|
if (script.running && game.menupage == 3)
|
|
|
|
{
|
|
|
|
// Force the player to stay in the SAVE tab while in a cutscene
|
|
|
|
}
|
|
|
|
else if (game.press_left)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
game.menupage--;
|
|
|
|
}
|
|
|
|
else if (game.press_right)
|
|
|
|
{
|
|
|
|
game.menupage++;
|
|
|
|
}
|
|
|
|
|
2020-06-23 00:32:21 +02:00
|
|
|
if (game.press_action)
|
|
|
|
{
|
|
|
|
mapmenuactionpress();
|
|
|
|
}
|
2020-06-23 00:30:10 +02:00
|
|
|
|
|
|
|
if (game.menupage < 0) game.menupage = 3;
|
|
|
|
if (game.menupage > 3 && game.menupage < 9) game.menupage = 0;
|
|
|
|
|
|
|
|
if (game.menupage == 9) game.menupage = 11;
|
|
|
|
if (game.menupage == 12) game.menupage = 10;
|
|
|
|
|
|
|
|
if (game.menupage == 19) game.menupage = 21;
|
|
|
|
if (game.menupage == 22) game.menupage = 20;
|
|
|
|
|
|
|
|
if (game.menupage == 29) game.menupage = 33;
|
|
|
|
if (game.menupage == 34) game.menupage = 30;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-10 18:14:37 +01:00
|
|
|
static void mapmenuactionpress()
|
2020-06-23 00:30:10 +02:00
|
|
|
{
|
2020-06-23 00:35:26 +02:00
|
|
|
switch (game.menupage)
|
|
|
|
{
|
|
|
|
case 1:
|
2020-06-23 00:37:19 +02:00
|
|
|
if (obj.flags[67] && !game.inspecial() && !map.custommode)
|
2020-06-23 00:31:14 +02:00
|
|
|
{
|
|
|
|
//Warp back to the ship
|
|
|
|
graphics.resumegamemode = true;
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-06-23 00:31:14 +02:00
|
|
|
game.teleport_to_x = 2;
|
|
|
|
game.teleport_to_y = 11;
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-06-23 00:31:14 +02:00
|
|
|
//trace(game.recordstring);
|
|
|
|
//We're teleporting! Yey!
|
|
|
|
game.activetele = false;
|
|
|
|
game.hascontrol = false;
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-06-23 00:31:14 +02:00
|
|
|
int i = obj.getplayer();
|
Use explicit INBOUNDS_VEC() instead of checking sentinel -1
It's better to do INBOUNDS_VEC(i, obj.entities) instead of 'i > -1'.
'i > -1' is used in cases like obj.getplayer(), which COULD return a
sentinel value of -1 and so correct code will have to check that value.
However, I am now of the opinion that INBOUNDS_VEC() should be used and
isn't unnecessary.
Consider the case of the face() script command: it's not enough to check
i > -1, you should read the routine carefully. Because if you look
closely, you'll see that it's not guaranteed that 'i' will be initialized
at all in that command. Indeed, if you call face() with invalid
arguments, it won't be. And so, 'i' could be something like 215, and
that would index out-of-bounds, and that wouldn't be good. Therefore,
it's better to have the full bounds check instead of checking only one
bounds. Many commands are like this, after some searching I can also
name position(), changemood(), changetile(), changegravity(), etc.
It also makes the code more explicit. Now you don't have to wonder what
-1 means or why it's being checked, you can just read the 'INBOUNDS' and
go "oh, that checks if it's actually inbounds or not".
2020-09-09 13:15:14 +02:00
|
|
|
if (INBOUNDS_VEC(i, obj.entities))
|
2020-06-23 00:31:14 +02:00
|
|
|
{
|
|
|
|
obj.entities[i].colour = 102;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
2020-06-23 00:31:14 +02:00
|
|
|
//which teleporter script do we use? it depends on the companion!
|
|
|
|
game.state = 4000;
|
|
|
|
game.statedelay = 0;
|
|
|
|
}
|
2020-06-23 00:35:26 +02:00
|
|
|
break;
|
|
|
|
case 3:
|
2020-11-04 03:45:33 +01:00
|
|
|
if (!game.gamesaved && !game.gamesavefailed && !game.inspecial())
|
2020-06-23 00:31:14 +02:00
|
|
|
{
|
|
|
|
game.flashlight = 5;
|
|
|
|
game.screenshake = 10;
|
|
|
|
music.playef(18);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-06-23 00:31:14 +02:00
|
|
|
game.savetime = game.timestring();
|
|
|
|
game.savearea = map.currentarea(map.area(game.roomx, game.roomy));
|
|
|
|
game.savetrinkets = game.trinkets();
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-06-23 00:31:14 +02:00
|
|
|
if (game.roomx >= 102 && game.roomx <= 104 && game.roomy >= 110 && game.roomy <= 111) game.savearea = "The Ship";
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-11-04 03:45:33 +01:00
|
|
|
bool success;
|
2020-04-02 23:06:56 +02:00
|
|
|
#if !defined(NO_CUSTOM_LEVELS)
|
2020-06-23 00:31:14 +02:00
|
|
|
if(map.custommodeforreal)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-11-04 03:45:33 +01:00
|
|
|
success = game.customsavequick(ed.ListOfMetaData[game.playcustomlevel].filename);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
2020-06-23 00:31:14 +02:00
|
|
|
else
|
|
|
|
#endif
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-11-04 03:45:33 +01:00
|
|
|
success = game.savequick();
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
2020-11-04 03:45:33 +01:00
|
|
|
game.gamesaved = success;
|
|
|
|
game.gamesavefailed = !success;
|
2020-06-23 00:31:14 +02:00
|
|
|
}
|
2020-06-23 00:35:26 +02:00
|
|
|
break;
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-06-23 00:35:26 +02:00
|
|
|
case 10:
|
2020-06-23 05:58:09 +02:00
|
|
|
//return to pause menu
|
|
|
|
music.playef(11);
|
|
|
|
game.menupage = 31;
|
2020-06-23 00:35:26 +02:00
|
|
|
break;
|
|
|
|
case 11:
|
2020-06-23 00:31:14 +02:00
|
|
|
//quit to menu
|
|
|
|
|
|
|
|
//Kill contents of offset render buffer, since we do that for some reason.
|
|
|
|
//This fixes an apparent frame flicker.
|
|
|
|
FillRect(graphics.tempBuffer, 0x000000);
|
|
|
|
graphics.fademode = 2;
|
2021-01-04 07:17:31 +01:00
|
|
|
music.fadeout();
|
2020-06-23 00:31:14 +02:00
|
|
|
map.nexttowercolour();
|
2020-06-25 23:41:44 +02:00
|
|
|
if (!game.glitchrunnermode)
|
|
|
|
{
|
|
|
|
game.fadetomenu = true;
|
|
|
|
game.fadetomenudelay = 16;
|
|
|
|
}
|
2020-06-23 00:35:26 +02:00
|
|
|
break;
|
2020-06-23 00:31:14 +02:00
|
|
|
|
2020-06-23 00:35:26 +02:00
|
|
|
case 20:
|
2020-06-23 00:31:14 +02:00
|
|
|
//return to game
|
|
|
|
graphics.resumegamemode = true;
|
2020-06-23 00:35:26 +02:00
|
|
|
break;
|
|
|
|
case 21:
|
2020-06-23 00:31:14 +02:00
|
|
|
//quit to menu
|
|
|
|
game.swnmode = false;
|
|
|
|
graphics.fademode = 2;
|
|
|
|
music.fadeout();
|
2020-07-17 00:11:54 +02:00
|
|
|
if (!game.glitchrunnermode)
|
|
|
|
{
|
|
|
|
game.fadetolab = true;
|
|
|
|
game.fadetolabdelay = 16;
|
|
|
|
}
|
2020-06-23 00:35:26 +02:00
|
|
|
break;
|
2020-06-23 00:47:25 +02:00
|
|
|
case 30:
|
|
|
|
// Return to game
|
|
|
|
graphics.resumegamemode = true;
|
|
|
|
break;
|
|
|
|
case 31:
|
|
|
|
// Go to quit prompt
|
|
|
|
music.playef(11);
|
|
|
|
game.menupage = 10;
|
|
|
|
break;
|
|
|
|
case 32:
|
|
|
|
case 33:
|
2020-06-23 01:52:40 +02:00
|
|
|
// Graphic options and game options
|
2020-06-23 00:47:25 +02:00
|
|
|
music.playef(11);
|
|
|
|
game.gamestate = TITLEMODE;
|
2020-06-23 06:41:21 +02:00
|
|
|
graphics.flipmode = false;
|
2020-06-23 01:51:16 +02:00
|
|
|
game.ingame_titlemode = true;
|
Fix kludge_ingametemp being assigned after menu creation
While working on #535, I noticed this bug.
When going to Graphic Options or Game Options from the pause menu,
kludge_ingametemp was intended to save the current menu stack frame
BEFORE either of those menus got created. However, it was actually
assigned afterwards, meaning kludge_ingametemp would always be either
Menu::graphicoptions or Menu::options.
This meant that the returntomenu() in returntopausemenu() would always
attempt to return to the current in-game menu, and seeing as it's the
same menu, would re-create the menu, instead of returning to the
previous menu before it.
This patch also fixes a potential source of a trivial memory leak, if
someone were to keep entering and exiting Graphic Options or Game
Options from the pause menu. It would keep piling up duplicate Graphic
Options or Game Options stack frames, which would never get removed.
However, they do get removed when you exit to the menu properly, by
returntomenu() again, so this doesn't seem like that serious of an
issue, but it's still good to fix.
2020-12-25 23:02:00 +01:00
|
|
|
|
|
|
|
// Set this before we create the menu
|
|
|
|
game.kludge_ingametemp = game.currentmenuname;
|
|
|
|
|
2020-06-23 01:52:40 +02:00
|
|
|
if (game.menupage == 32)
|
|
|
|
{
|
|
|
|
game.createmenu(Menu::graphicoptions);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
game.createmenu(Menu::options);
|
|
|
|
}
|
2020-06-23 02:14:01 +02:00
|
|
|
|
2020-06-23 05:49:16 +02:00
|
|
|
map.nexttowercolour();
|
2020-06-23 01:41:07 +02:00
|
|
|
|
|
|
|
// Fix delta rendering glitch
|
2020-11-03 00:23:53 +01:00
|
|
|
graphics.updatetowerbackground(graphics.titlebg);
|
2020-06-23 01:41:07 +02:00
|
|
|
titleupdatetextcol();
|
2020-06-23 00:47:25 +02:00
|
|
|
break;
|
2020-06-23 00:31:14 +02:00
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
2020-04-01 23:52:45 +02:00
|
|
|
void teleporterinput()
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
//Todo Mouseinput!
|
|
|
|
//game.mx = (mouseX / 2);
|
|
|
|
//game.my = (mouseY / 2);
|
|
|
|
|
|
|
|
int tempx, tempy;
|
|
|
|
|
|
|
|
game.press_left = false;
|
|
|
|
game.press_right = false;
|
|
|
|
game.press_action = false;
|
|
|
|
game.press_map = false;
|
|
|
|
|
2020-04-01 23:52:45 +02:00
|
|
|
if(graphics.menuoffset==0)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
if (key.isDown(KEYBOARD_LEFT)|| key.isDown(KEYBOARD_a) || key.controllerWantsLeft(false) ) game.press_left = true;
|
|
|
|
if (key.isDown(KEYBOARD_RIGHT) || key.isDown(KEYBOARD_d)|| key.controllerWantsRight(false) ) game.press_right = true;
|
|
|
|
if (key.isDown(KEYBOARD_z) || key.isDown(KEYBOARD_SPACE) || key.isDown(KEYBOARD_v)
|
|
|
|
|| key.isDown(KEYBOARD_UP) || key.isDown(KEYBOARD_DOWN)|| key.isDown(KEYBOARD_w)|| key.isDown(KEYBOARD_s) || key.isDown(game.controllerButton_flip)) game.press_action = true;
|
|
|
|
if (key.isDown(KEYBOARD_ENTER) || key.isDown(game.controllerButton_map)) game.press_map = true;
|
|
|
|
|
|
|
|
//In the menu system, all keypresses are single taps rather than holds. Therefore this test has to be done for all presses
|
|
|
|
if (!game.press_action && !game.press_left && !game.press_right) game.jumpheld = false;
|
|
|
|
if (!game.press_map) game.mapheld = false;
|
2020-06-21 02:34:45 +02:00
|
|
|
|
|
|
|
if (key.isDown(27))
|
|
|
|
{
|
2020-07-11 09:15:06 +02:00
|
|
|
if (!map.custommode || map.custommodeforreal)
|
|
|
|
{
|
2020-07-11 09:21:23 +02:00
|
|
|
// Go to pause menu
|
2020-07-11 09:15:06 +02:00
|
|
|
game.mapheld = true;
|
2020-07-11 09:21:23 +02:00
|
|
|
game.menupage = 30;
|
2020-07-11 09:15:06 +02:00
|
|
|
game.gamestate = MAPMODE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Close teleporter menu
|
|
|
|
graphics.resumegamemode = true;
|
|
|
|
}
|
2020-06-21 02:34:45 +02:00
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
game.mapheld = true;
|
|
|
|
game.jumpheld = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!game.jumpheld)
|
|
|
|
{
|
|
|
|
if (game.press_action || game.press_left || game.press_right || game.press_map)
|
|
|
|
{
|
|
|
|
game.jumpheld = true;
|
|
|
|
}
|
|
|
|
|
2020-07-05 03:58:13 +02:00
|
|
|
bool any_tele_unlocked = false;
|
|
|
|
if (game.press_left || game.press_right)
|
|
|
|
{
|
|
|
|
for (size_t i = 0; i < map.teleporters.size(); i++)
|
|
|
|
{
|
|
|
|
point& tele = map.teleporters[i];
|
|
|
|
|
|
|
|
if (map.explored[tele.x + tele.y*20])
|
|
|
|
{
|
|
|
|
any_tele_unlocked = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (game.press_left && any_tele_unlocked)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-07-05 03:50:58 +02:00
|
|
|
do
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
game.teleport_to_teleporter--;
|
2020-04-15 04:32:30 +02:00
|
|
|
if (game.teleport_to_teleporter < 0) game.teleport_to_teleporter = map.teleporters.size() - 1;
|
2020-01-01 21:29:24 +01:00
|
|
|
tempx = map.teleporters[game.teleport_to_teleporter].x;
|
|
|
|
tempy = map.teleporters[game.teleport_to_teleporter].y;
|
|
|
|
}
|
2020-07-05 03:50:58 +02:00
|
|
|
while (map.explored[tempx + (20 * tempy)] == 0);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
2020-07-05 03:58:13 +02:00
|
|
|
else if (game.press_right && any_tele_unlocked)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-07-05 03:50:58 +02:00
|
|
|
do
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
game.teleport_to_teleporter++;
|
2020-04-15 04:32:30 +02:00
|
|
|
if (game.teleport_to_teleporter >= (int) map.teleporters.size()) game.teleport_to_teleporter = 0;
|
2020-01-01 21:29:24 +01:00
|
|
|
tempx = map.teleporters[game.teleport_to_teleporter].x;
|
|
|
|
tempy = map.teleporters[game.teleport_to_teleporter].y;
|
|
|
|
}
|
2020-07-05 03:50:58 +02:00
|
|
|
while (map.explored[tempx + (20 * tempy)] == 0);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (game.press_map)
|
|
|
|
{
|
|
|
|
tempx = map.teleporters[game.teleport_to_teleporter].x;
|
|
|
|
tempy = map.teleporters[game.teleport_to_teleporter].y;
|
|
|
|
if (game.roomx == tempx + 100 && game.roomy == tempy + 100)
|
|
|
|
{
|
|
|
|
//cancel!
|
2020-04-01 23:52:45 +02:00
|
|
|
graphics.resumegamemode = true;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//teleport
|
2020-04-01 23:52:45 +02:00
|
|
|
graphics.resumegamemode = true;
|
2020-01-01 21:29:24 +01:00
|
|
|
game.teleport_to_x = tempx;
|
|
|
|
game.teleport_to_y = tempy;
|
|
|
|
|
|
|
|
//trace(game.recordstring);
|
|
|
|
//We're teleporting! Yey!
|
|
|
|
game.activetele = false;
|
|
|
|
game.hascontrol = false;
|
|
|
|
|
|
|
|
int i = obj.getplayer();
|
Use explicit INBOUNDS_VEC() instead of checking sentinel -1
It's better to do INBOUNDS_VEC(i, obj.entities) instead of 'i > -1'.
'i > -1' is used in cases like obj.getplayer(), which COULD return a
sentinel value of -1 and so correct code will have to check that value.
However, I am now of the opinion that INBOUNDS_VEC() should be used and
isn't unnecessary.
Consider the case of the face() script command: it's not enough to check
i > -1, you should read the routine carefully. Because if you look
closely, you'll see that it's not guaranteed that 'i' will be initialized
at all in that command. Indeed, if you call face() with invalid
arguments, it won't be. And so, 'i' could be something like 215, and
that would index out-of-bounds, and that wouldn't be good. Therefore,
it's better to have the full bounds check instead of checking only one
bounds. Many commands are like this, after some searching I can also
name position(), changemood(), changetile(), changegravity(), etc.
It also makes the code more explicit. Now you don't have to wonder what
-1 means or why it's being checked, you can just read the 'INBOUNDS' and
go "oh, that checks if it's actually inbounds or not".
2020-09-09 13:15:14 +02:00
|
|
|
if (INBOUNDS_VEC(i, obj.entities))
|
2020-06-13 05:36:08 +02:00
|
|
|
{
|
|
|
|
obj.entities[i].colour = 102;
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
i = obj.getteleporter();
|
Use explicit INBOUNDS_VEC() instead of checking sentinel -1
It's better to do INBOUNDS_VEC(i, obj.entities) instead of 'i > -1'.
'i > -1' is used in cases like obj.getplayer(), which COULD return a
sentinel value of -1 and so correct code will have to check that value.
However, I am now of the opinion that INBOUNDS_VEC() should be used and
isn't unnecessary.
Consider the case of the face() script command: it's not enough to check
i > -1, you should read the routine carefully. Because if you look
closely, you'll see that it's not guaranteed that 'i' will be initialized
at all in that command. Indeed, if you call face() with invalid
arguments, it won't be. And so, 'i' could be something like 215, and
that would index out-of-bounds, and that wouldn't be good. Therefore,
it's better to have the full bounds check instead of checking only one
bounds. Many commands are like this, after some searching I can also
name position(), changemood(), changetile(), changegravity(), etc.
It also makes the code more explicit. Now you don't have to wonder what
-1 means or why it's being checked, you can just read the 'INBOUNDS' and
go "oh, that checks if it's actually inbounds or not".
2020-09-09 13:15:14 +02:00
|
|
|
if (INBOUNDS_VEC(i, obj.entities))
|
2020-06-13 04:31:08 +02:00
|
|
|
{
|
|
|
|
obj.entities[i].tile = 6;
|
|
|
|
obj.entities[i].colour = 102;
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
//which teleporter script do we use? it depends on the companion!
|
|
|
|
game.state = 4000;
|
|
|
|
game.statedelay = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-01 23:52:45 +02:00
|
|
|
void gamecompleteinput()
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
game.press_left = false;
|
|
|
|
game.press_right = false;
|
|
|
|
game.press_action = false;
|
|
|
|
game.press_map = false;
|
|
|
|
|
2020-04-30 20:13:02 +02:00
|
|
|
//Do this before we update map.bypos
|
|
|
|
if (!game.colourblindmode)
|
|
|
|
{
|
2020-11-03 00:23:53 +01:00
|
|
|
graphics.updatetowerbackground(graphics.titlebg);
|
2020-04-30 20:13:02 +02:00
|
|
|
}
|
|
|
|
|
2020-04-30 19:56:27 +02:00
|
|
|
//Do these here because input comes first
|
2020-11-03 00:23:53 +01:00
|
|
|
graphics.titlebg.bypos += graphics.titlebg.bscroll;
|
2020-04-30 19:56:27 +02:00
|
|
|
game.oldcreditposition = game.creditposition;
|
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:52:33 +02:00
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
if (key.isDown(KEYBOARD_z) || key.isDown(KEYBOARD_SPACE) || key.isDown(KEYBOARD_v) || key.isDown(game.controllerButton_flip))
|
|
|
|
{
|
|
|
|
game.creditposition -= 6;
|
Turn (super)patrons/githubfriends into arrays & move them to new file
So, originally, I wanted to keep them on Game, but it turns out that if
I initialize it in Game.cpp, the compiler will complain that other files
won't know what's actually inside the array. To do that, I'd have to
initialize it in Game.h. But I don't want to initialize it in Game.h
because that'd mean recompiling a lot of unnecessary files whenever
someone gets added to the credits.
So, I moved all the patrons, superpatrons, and GitHub contributors to a
new file, Credits.h, which only contains the list (and the credits max
position calculation). That way, whenever someone gets added, only the
minimal amount of files need to be recompiled.
2020-07-03 12:13:15 +02:00
|
|
|
if (game.creditposition <= -Credits::creditmaxposition)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-04-01 23:52:45 +02:00
|
|
|
if(graphics.fademode==0)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-04-01 23:52:45 +02:00
|
|
|
graphics.fademode = 2;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
Turn (super)patrons/githubfriends into arrays & move them to new file
So, originally, I wanted to keep them on Game, but it turns out that if
I initialize it in Game.cpp, the compiler will complain that other files
won't know what's actually inside the array. To do that, I'd have to
initialize it in Game.h. But I don't want to initialize it in Game.h
because that'd mean recompiling a lot of unnecessary files whenever
someone gets added to the credits.
So, I moved all the patrons, superpatrons, and GitHub contributors to a
new file, Credits.h, which only contains the list (and the credits max
position calculation). That way, whenever someone gets added, only the
minimal amount of files need to be recompiled.
2020-07-03 12:13:15 +02:00
|
|
|
game.creditposition = -Credits::creditmaxposition;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-11-03 00:23:53 +01:00
|
|
|
graphics.titlebg.bscroll = +7;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
game.press_action = true;
|
|
|
|
}
|
|
|
|
if (key.isDown(KEYBOARD_ENTER)|| key.isDown(game.controllerButton_map)) game.press_map = true;
|
|
|
|
|
|
|
|
if (!game.mapheld)
|
|
|
|
{
|
|
|
|
if(game.press_map)
|
|
|
|
{
|
|
|
|
//Return to game
|
2020-04-01 23:52:45 +02:00
|
|
|
if(graphics.fademode==0)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-04-01 23:52:45 +02:00
|
|
|
graphics.fademode = 2;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-01 23:52:45 +02:00
|
|
|
void gamecompleteinput2()
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
game.press_left = false;
|
|
|
|
game.press_right = false;
|
|
|
|
game.press_action = false;
|
|
|
|
game.press_map = false;
|
|
|
|
|
2020-05-02 03:23:52 +02:00
|
|
|
//Do this here because input comes first
|
|
|
|
game.oldcreditposx = game.creditposx;
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
if (key.isDown(KEYBOARD_z) || key.isDown(KEYBOARD_SPACE) || key.isDown(KEYBOARD_v) || key.isDown(game.controllerButton_flip))
|
|
|
|
{
|
|
|
|
game.creditposx++;
|
2020-05-02 03:23:52 +02:00
|
|
|
game.oldcreditposx++;
|
2020-01-01 21:29:24 +01:00
|
|
|
if (game.creditposy >= 30)
|
|
|
|
{
|
2020-04-01 23:52:45 +02:00
|
|
|
if(graphics.fademode==0)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-04-01 23:52:45 +02:00
|
|
|
graphics.fademode = 2;
|
2020-01-01 21:29:24 +01:00
|
|
|
music.fadeout();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
game.press_action = true;
|
|
|
|
}
|
|
|
|
if (key.isDown(KEYBOARD_ENTER) || key.isDown(game.controllerButton_map)) game.press_map = true;
|
|
|
|
|
|
|
|
if (!game.mapheld)
|
|
|
|
{
|
|
|
|
if(game.press_map)
|
|
|
|
{
|
|
|
|
//Return to game
|
2020-04-01 23:52:45 +02:00
|
|
|
if(graphics.fademode==0)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-04-01 23:52:45 +02:00
|
|
|
graphics.fademode = 2;
|
2020-01-01 21:29:24 +01:00
|
|
|
music.fadeout();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|