1
0
mirror of https://github.com/TerryCavanagh/VVVVVV.git synced 2024-06-01 18:43:33 +02:00
VVVVVV/desktop_version/src/Game.h

612 lines
14 KiB
C
Raw Normal View History

2020-01-01 21:29:24 +01:00
#ifndef GAME_H
#define GAME_H
#include <SDL.h>
#include <map>
#include <string>
#include <vector>
2020-01-01 21:29:24 +01:00
#include "Font.h"
#include "ScreenSettings.h"
/* FIXME: Can't forward declare this enum in C++, unfortunately.
* In C, enum sizes are always the same, so you can forward declare them.
* In C++ instead, enum sizes are based on how many enums there are.
* You cannot specify the underlying type until C++11.
* But bumping the standard opens up a can of worms. I'd rather just move to C. -Misa */
#include "Enums.h"
// Forward decl without including all of <tinyxml2.h>
namespace tinyxml2
{
class XMLDocument;
class XMLElement;
}
/* 40 chars (160 bytes) covers the entire screen, + 1 more for null terminator */
#define MENU_TEXT_BYTES 161
struct MenuOption
{
char text[MENU_TEXT_BYTES];
bool active;
uint32_t print_flags;
};
//Menu IDs
namespace Menu
{
enum MenuName
{
mainmenu,
playerworlds,
confirmshowlevelspath,
showlevelspath,
levellist,
quickloadlevel,
deletequicklevel,
youwannaquit,
errornostart,
errorsavingsettings,
errorloadinglevel,
warninglevellist,
graphicoptions,
ed_settings,
ed_desc,
ed_music,
ed_quit,
ed_font,
options,
gameplayoptions,
speedrunneroptions,
setglitchrunner,
advancedoptions,
audiooptions,
accessibility,
controller,
language,
translator_main,
translator_options,
translator_options_limitscheck,
translator_options_stats,
Add level exploring menu for translators I would, of course, recommend translators to translate the roomnames while playing the full game (optionally in invincibility) so they can immediately get all the context and maybe the most inspiration. And if you want to go back into a specific level, then there's always the time trials and intermission replays which will give you full coverage of all the room names. However, the time trials weren't really made for room name translation. They have some annoying features like the instant restart when you press ENTER at the wrong time, they remove context clues like teleporters and companions, but the worst problem is that the last room in a level is often completely untranslatable inside the time trials because you immediately get sent to the results screen... So, I added a new menu in the translator options, "explore game", which gives you access to all the time trials and the two intermissions, from the same menu. All these time trials (which they're still based off of, under the hood) are stripped of the annoying features that come with time trials. These are the changes I made to time trial behavior in translator exploring mode: - No 3-2-1-Go! countdown - No on-screen time/death/shiny/par - ENTER doesn't restart, and the map menu works. The entire map is also revealed. - Prize for the Reckless is in its normal form - The teleporters in Entanglement Generator, Wheeler's Wormhole and Level Complete are restored as context for room names (actually, we should probably restore them in time trials anyway? Their "press to teleport" prompt is already blocked out in time trials and they do nothing other than being a checkpoint. I guess the reason they were removed was to stop people from opening the teleporter menu when that was not specifically blocked out in time trials yet.) - The companions are there at the end of levels, and behave like in no death mode (become happy and follow you to the teleporter). Also for context. - At the end of each level, you're not suddenly sent to the menu, but you can use the teleporter at your leisure just like in the intermission replays. In the Final Level, you do get sent to the menu automatically, but after a longer delay. I made another mark on VVVVVV: don't be startled, I added gamestates. I wanted all teleporters at the end of levels to behave like the ones at the end of the intermission replays, and all handling for teleporting with specific companions is already done in gamestates, so rather than adding conditional blocks across 5 or so different gamestates, it made more sense to make a single gamestate for "teleporting in translator exploring mode" (3090). I also added an alternative to having to use gamestate 3500 or 82 for the end of the final level: 3091-3092. One other thing I want to add to the "explore game" menu: a per-level count of how many room names are left to translate. That shouldn't be too difficult, and I'm planning that for the next commit.
2022-11-26 03:33:17 +01:00
translator_options_exploregame,
translator_options_cutscenetest,
translator_maintenance,
translator_maintenance_sync,
translator_error_setlangwritedir,
cleardatamenu,
clearcustomdatamenu,
setinvincibility,
setslowdown,
unlockmenu,
credits,
credits2,
credits25,
credits3,
credits4,
credits5,
credits6,
credits_localisations_implementation,
credits_localisations_translations,
play,
unlocktimetrial,
unlocktimetrials,
unlocknodeathmode,
unlockintermission,
unlockflipmode,
newgamewarning,
playmodes,
intermissionmenu,
playint1,
playint2,
continuemenu,
startnodeathmode,
gameover,
gameover2,
unlockmenutrials,
timetrials,
nodeathmodecomplete,
nodeathmodecomplete2,
timetrialcomplete,
timetrialcomplete2,
timetrialcomplete3,
gamecompletecontinue
};
}
enum SLIDERMODE
{
SLIDER_NONE,
SLIDER_MUSICVOLUME,
SLIDER_SOUNDVOLUME
};
/* enums for swngame variable */
enum SWNMODE
{
SWN_GRAVITRON,
SWN_SUPERGRAVITRON,
SWN_START_GRAVITRON_STEP_3,
SWN_START_GRAVITRON_STEP_2,
SWN_START_GRAVITRON_STEP_1,
SWN_FINISH_GRAVITRON_STEP_1,
SWN_START_SUPERGRAVITRON_STEP_1,
SWN_START_SUPERGRAVITRON_STEP_2,
SWN_FINISH_GRAVITRON_STEP_2,
SWN_NONE
};
/* enums for unlock, unlocknotify arrays and unlocknum function */
enum
{
Unlock_SPACESTATION1_COMPLETE = 0,
Unlock_LABORATORY_COMPLETE = 1,
Unlock_TOWER_COMPLETE = 2,
Unlock_SPACESTATION2_COMPLETE = 3,
Unlock_WARPZONE_COMPLETE = 4,
UnlockTrophy_GAME_COMPLETE = 5,
Unlock_INTERMISSION1_COMPLETE = 6,
Unlock_INTERMISSION2_COMPLETE = 7,
Unlock_SECRETLAB = 8,
Unlock_TIMETRIAL_SPACESTATION1 = 9,
Unlock_TIMETRIAL_LABORATORY = 10,
Unlock_TIMETRIAL_TOWER = 11,
Unlock_TIMETRIAL_SPACESTATION2 = 12,
Unlock_TIMETRIAL_WARPZONE = 13,
Unlock_TIMETRIAL_FINALLEVEL = 14,
Unlock_INTERMISSION_UNUSED = 15,
Unlock_INTERMISSION_REPLAYS = 16,
Unlock_NODEATHMODE = 17,
Unlock_FLIPMODE = 18,
UnlockTrophy_FLIPMODE_COMPLETE = 19,
UnlockTrophy_NODEATHMODE_COMPLETE = 20
};
/* enums for bestrank, bestlives, besttrinkets, besttimes, bestframes arrays
* and timetriallevel */
enum
{
TimeTrial_SPACESTATION1 = 0,
TimeTrial_LABORATORY = 1,
TimeTrial_TOWER = 2,
TimeTrial_SPACESTATION2 = 3,
TimeTrial_WARPZONE = 4,
TimeTrial_FINALLEVEL = 5
};
struct MenuStackFrame
{
int option;
enum Menu::MenuName name;
};
2020-01-01 21:29:24 +01:00
class Game
{
char magic[16];
2020-01-01 21:29:24 +01:00
public:
Allow using help/graphics/music/game/key/map/obj everywhere This commit makes `help`, `graphics`, `music`, `game`, `key`, `map`, and `obj` essentially static global objects that can be used everywhere. This is useful in case we ever need to add a new function in the future, so we don't have to bother with passing a new argument in which means we have to pass a new argument in to the function that calls that function which means having to pass a new argument into the function that calls THAT function, etc. which is a real headache when working on fan mods of the source code. Note that this changes NONE of the existing function signatures, it merely just makes those variables accessible everywhere in the same way `script` and `ed` are. Also note that some classes had to be initialized after the filesystem was initialized, but C++ would keep initializing them before the filesystem got initialized, because I *had* to put them at the top of `main.cpp`, or else they wouldn't be global variables. The only way to work around this was to use entityclass's initialization style (which I'm pretty sure entityclass of all things doesn't need to be initialized this way), where you actually initialize the class in an `init()` function, and so then you do `graphics.init()` after the filesystem initialization, AFTER doing `Graphics graphics` up at the top. I've had to do this for `graphics` (but only because its child GraphicsResources `grphx` needs to be initialized this way), `music`, and `game`. I don't think this will affect anything. Other than that, `help`, `key`, and `map` are still using the C++-intended method of having ClassName::ClassName() functions.
2020-01-29 08:35:03 +01:00
void init(void);
void setdefaultcontrollerbuttons(void);
2020-01-01 21:29:24 +01:00
int crewrescued(void);
2020-01-01 21:29:24 +01:00
std::string unrescued(void);
2020-01-01 21:29:24 +01:00
void resetgameclock(void);
2020-01-01 21:29:24 +01:00
bool customsavequick(const std::string& savfile);
bool savequick(void);
2020-01-01 21:29:24 +01:00
void gameclock(void);
2020-01-01 21:29:24 +01:00
std::string giventimestring(int hrs, int min, int sec);
2020-01-01 21:29:24 +01:00
std::string timestring(void);
2020-01-01 21:29:24 +01:00
std::string resulttimestring(void);
2020-01-01 21:29:24 +01:00
std::string timetstring(int t);
2020-01-01 21:29:24 +01:00
void timestringcenti(char* buffer, size_t buffer_size);
void returnmenu(void);
void returntomenu(enum Menu::MenuName t);
void createmenu(enum Menu::MenuName t, bool samemenu = false);
bool can_unlock_ndm(void);
void unlock_ndm(void);
2020-01-01 21:29:24 +01:00
void lifesequence(void);
2020-01-01 21:29:24 +01:00
void gethardestroom(void);
2020-01-01 21:29:24 +01:00
void levelcomplete_textbox(void);
void crewmate_textbox(const int color);
void remaining_textbox(void);
void actionprompt_textbox(void);
void savetele_textbox(void);
2022-12-07 00:20:48 +01:00
void setstate(int gamestate);
void incstate(void);
2022-12-07 00:20:48 +01:00
2022-12-07 00:35:06 +01:00
void setstatedelay(int delay);
void lockstate(void);
2022-12-07 00:20:48 +01:00
void unlockstate(void);
2022-12-07 00:20:48 +01:00
void updatestate(void);
2020-01-01 21:29:24 +01:00
void unlocknum(int t);
2020-01-01 21:29:24 +01:00
void loadstats(struct ScreenSettings* screen_settings);
2020-01-01 21:29:24 +01:00
bool savestats(const struct ScreenSettings* screen_settings, bool sync = true);
bool savestats(bool sync = true);
2020-01-01 21:29:24 +01:00
void deletestats(void);
2020-01-01 21:29:24 +01:00
void deserializesettings(tinyxml2::XMLElement* dataNode, struct ScreenSettings* screen_settings);
void serializesettings(tinyxml2::XMLElement* dataNode, const struct ScreenSettings* screen_settings);
void loadsettings(struct ScreenSettings* screen_settings);
bool savesettings(const struct ScreenSettings* screen_settings);
bool savesettings(void);
bool savestatsandsettings(void);
void savestatsandsettings_menu(void);
void deletesettings(void);
void deletequick(void);
2020-01-01 21:29:24 +01:00
bool savetele(void);
2020-01-01 21:29:24 +01:00
void loadtele(void);
2020-01-01 21:29:24 +01:00
void deletetele(void);
2020-01-01 21:29:24 +01:00
void customstart(void);
2020-01-01 21:29:24 +01:00
void start(void);
2020-01-01 21:29:24 +01:00
void startspecial(int t);
2020-01-01 21:29:24 +01:00
void starttrial(int t);
2020-01-01 21:29:24 +01:00
void swnpenalty(void);
2020-01-01 21:29:24 +01:00
void deathsequence(void);
2020-01-01 21:29:24 +01:00
void customloadquick(const std::string& savfile);
void loadquick(void);
2020-01-01 21:29:24 +01:00
void customdeletequick(const std::string& file);
void loadsummary(void);
2020-01-01 21:29:24 +01:00
static const int numcrew = 6;
struct Summary
{
bool exists;
int seconds;
int minutes;
int hours;
int saverx;
int savery;
int trinkets;
bool crewstats[numcrew];
};
struct Summary last_telesave, last_quicksave;
bool save_exists(void);
void readmaingamesave(const char* savename, tinyxml2::XMLDocument& doc);
struct Summary writemaingamesave(tinyxml2::XMLDocument& doc);
void initteleportermode(void);
2020-01-01 21:29:24 +01:00
const char* saveFilePath;
2020-01-01 21:29:24 +01:00
int roomx, roomy;
int prevroomx, prevroomy;
2020-01-01 21:29:24 +01:00
int savex, savey, saverx, savery;
int savegc, savedir;
int savecolour;
2020-01-01 21:29:24 +01:00
//Added for port
int edsavex, edsavey, edsaverx, edsavery;
int edsavegc, edsavedir;
//State logic stuff
int state, statedelay;
bool glitchrunkludge;
2020-01-01 21:29:24 +01:00
enum GameGamestate gamestate;
enum GameGamestate prevgamestate; //only used sometimes
2020-01-01 21:29:24 +01:00
bool hascontrol, jumpheld;
int jumppressed;
int gravitycontrol;
bool isingamecompletescreen(void);
2020-01-01 21:29:24 +01:00
bool muted;
int mutebutton;
bool musicmuted;
int musicmutebutton;
2020-01-01 21:29:24 +01:00
int tapleft, tapright;
//Menu interaction stuff
void mapmenuchange(const enum GameGamestate newgamestate, const bool user_initiated);
2020-01-01 21:29:24 +01:00
bool mapheld;
int menupage;
int lastsaved;
int deathcounts;
int framecounter;
bool seed_use_sdl_getticks;
bool editor_disabled;
2020-01-01 21:29:24 +01:00
int frames, seconds, minutes, hours;
bool gamesaved;
2020-11-04 03:45:33 +01:00
bool gamesavefailed;
2020-01-01 21:29:24 +01:00
std::string savetime;
int saveframes, saveseconds;
2020-01-01 21:29:24 +01:00
int savetrinkets;
bool startscript;
std::string newscript;
bool menustart;
//Teleporting
bool teleport_to_new_area;
int teleport_to_x, teleport_to_y;
std::string teleportscript;
bool useteleporter;
int teleport_to_teleporter;
//Main Menu Variables
std::vector<MenuOption> menuoptions;
int currentmenuoption ;
bool menutestmode;
enum Menu::MenuName currentmenuname;
enum Menu::MenuName kludge_ingametemp;
enum SLIDERMODE slidermode;
int current_credits_list_index;
int translator_credits_pagenum;
2020-01-01 21:29:24 +01:00
int menuxoff, menuyoff;
Make menus automatically centered and narrowed All menus had a hardcoded X position (offset to an arbitrary starting point of 110) and a hardcoded horizontal spacing for the "staircasing" (mostly 30 pixels, but for some specific menus hardcoded to 15, 20 or something else). Not all menus were centered, and seem to have been manually made narrower (with lower horizontal spacing) whenever text ran offscreen during development. This system may already be hard to work with in an English-only menu system, since you may need to adjust horizontal spacing or positioning when adding an option. The main reason I made this change is that it's even less optimal when menu options have to be translated, since maximum string lengths are hard to determine, and it's easy to have menu options running offscreen, especially when not all menus are checked for all languages and when options could be added in the middle of a menu after translations of that menu are already checked. Now, menus are automatically centered based on their options, and they are automatically made narrower if they won't fit with the default horizontal spacing of 30 pixels (with some padding). The game.menuxoff variable for the menu X position is now also offset to 0 instead of 110 The _default_ horizontal spacing can be changed on a per-menu basis, and most menus (not all) which already had a narrower spacing set, retain that as a maximum spacing, simply because they looked odd with 30 pixels of spacing (especially the main menu). They will be made even narrower automatically if needed. In the most extreme case, the spacing can go down to 0 and options will be displayed right below each other. This isn't in the usual style of the game, but at least we did the best we could to prevent options running offscreen. The only exception to automatic menu centering and narrowing is the list of player levels, because it's a special case and existing behavior would be better than automatic centering there.
2020-06-29 02:09:52 +02:00
int menuspacing;
std::vector<MenuStackFrame> menustack;
2020-01-01 21:29:24 +01:00
void inline option(const char* text, bool active = true, uint32_t print_flags = PR_RTL_XFLIP)
{
MenuOption menuoption;
SDL_strlcpy(menuoption.text, text, sizeof(menuoption.text));
menuoption.active = active;
menuoption.print_flags = print_flags;
menuoptions.push_back(menuoption);
}
2020-01-01 21:29:24 +01:00
int menucountdown;
enum Menu::MenuName menudest;
2020-01-01 21:29:24 +01:00
int creditposx, creditposy, creditposdelay;
int oldcreditposx;
2020-01-01 21:29:24 +01:00
bool silence_settings_error;
2020-01-01 21:29:24 +01:00
//Sine Wave Ninja Minigame
bool swnmode;
enum SWNMODE swngame;
int swnstate, swnstate2, swnstate3, swnstate4, swndelay, swndeaths;
2020-01-01 21:29:24 +01:00
int swntimer, swncolstate, swncoldelay;
int swnrecord, swnbestrank, swnrank, swnmessage;
//SuperCrewMate Stuff
Remove `scmmoveme` So, I ended up breaking supercrewmate spawning with that roomchange refactor. However, upon investigating how to fix it, I was running into a weird interpolation issue due to scmmoveme, as well as the companion spawning in the ground in "Very Good". And I was wondering why I or no one else ended up running into them. Well, as it turns out, scmmoveme ends up doing absolutely nothing. There are only two instances where scmmoveme is used. The first is if you respawn in "Very Good", and somehow have your scmprogress set to that room. But that's impossible, because whenever you respawn, your scmprogress is always set to the one after the room you respawn in. Even if you respawned in the room previous to "Very Good" (which is "Don't Get Ahead of Yourself!"), it still wouldn't work, since the logic always kicks in when a gotoroom happens, and not only when a supercrewmate is actually spawned. Since the scmprogress doesn't match, that case never gets triggered, and we get to the second time scmmoveme is used, which is in the catch-all case that always executes. This second instance... also does nothing, because since we just respawned, and our scmprogress got set to the room ahead of us, there is no supercrewmate on screen. Then getscm() returns 0, and the player is always indice 0, so the only thing we end up doing is setting the player's x-position to their own x-position. Brilliant. Anyway, this code results in interpolation issues and the supercrewmate spawning in the ground on "Very Good" if you die, when my fix is applied, because my fix moves this logic around to a different frame order, and that actually ends up making scmmoveme no longer dead code. So to recap: we have dead code, which looks like it does something, but doesn't. But if you move it around in a certain way, it ends up having harmful effects. One of the joys of working on this game... It's also hilarious that it gets saved to the save file. Why? The only time this variable is true, it is for literally less than a frame, because it always gets set to false, because you always respawn using a gotoroom whenever the supercrewmate dies, because you never respawn in the same room as a supercrewmate, because Intermission 1 was deliberately designed that way (else you'd keep continually dying since the supercrewmate wouldn't move out of the way).
2021-09-12 07:23:47 +02:00
bool supercrewmate, scmhurt;
2020-01-01 21:29:24 +01:00
int scmprogress;
//Accessibility Options
bool colourblindmode;
bool noflashingmode;
int slowdown;
int get_timestep(void);
bool physics_frozen(void);
2020-01-01 21:29:24 +01:00
bool nodeathmode;
int gameoverdelay;
bool nocutscenes;
int ndmresultcrewrescued;
int ndmresulttrinkets;
std::string ndmresulthardestroom;
int ndmresulthardestroom_x;
int ndmresulthardestroom_y;
bool ndmresulthardestroom_specialname;
void copyndmresults(void);
2020-01-01 21:29:24 +01:00
//Time Trials
bool intimetrial, timetrialparlost;
int timetrialcountdown, timetrialshinytarget, timetriallevel;
int timetrialpar, timetrialresulttime, timetrialresultframes, timetrialrank;
bool timetrialcheater;
int timetrialresultshinytarget, timetrialresulttrinkets, timetrialresultpar;
int timetrialresultdeaths;
2020-01-01 21:29:24 +01:00
Add level exploring menu for translators I would, of course, recommend translators to translate the roomnames while playing the full game (optionally in invincibility) so they can immediately get all the context and maybe the most inspiration. And if you want to go back into a specific level, then there's always the time trials and intermission replays which will give you full coverage of all the room names. However, the time trials weren't really made for room name translation. They have some annoying features like the instant restart when you press ENTER at the wrong time, they remove context clues like teleporters and companions, but the worst problem is that the last room in a level is often completely untranslatable inside the time trials because you immediately get sent to the results screen... So, I added a new menu in the translator options, "explore game", which gives you access to all the time trials and the two intermissions, from the same menu. All these time trials (which they're still based off of, under the hood) are stripped of the annoying features that come with time trials. These are the changes I made to time trial behavior in translator exploring mode: - No 3-2-1-Go! countdown - No on-screen time/death/shiny/par - ENTER doesn't restart, and the map menu works. The entire map is also revealed. - Prize for the Reckless is in its normal form - The teleporters in Entanglement Generator, Wheeler's Wormhole and Level Complete are restored as context for room names (actually, we should probably restore them in time trials anyway? Their "press to teleport" prompt is already blocked out in time trials and they do nothing other than being a checkpoint. I guess the reason they were removed was to stop people from opening the teleporter menu when that was not specifically blocked out in time trials yet.) - The companions are there at the end of levels, and behave like in no death mode (become happy and follow you to the teleporter). Also for context. - At the end of each level, you're not suddenly sent to the menu, but you can use the teleporter at your leisure just like in the intermission replays. In the Final Level, you do get sent to the menu automatically, but after a longer delay. I made another mark on VVVVVV: don't be startled, I added gamestates. I wanted all teleporters at the end of levels to behave like the ones at the end of the intermission replays, and all handling for teleporting with specific companions is already done in gamestates, so rather than adding conditional blocks across 5 or so different gamestates, it made more sense to make a single gamestate for "teleporting in translator exploring mode" (3090). I also added an alternative to having to use gamestate 3500 or 82 for the end of the final level: 3091-3092. One other thing I want to add to the "explore game" menu: a per-level count of how many room names are left to translate. That shouldn't be too difficult, and I'm planning that for the next commit.
2022-11-26 03:33:17 +01:00
bool start_translator_exploring;
bool translator_exploring;
bool translator_exploring_allowtele;
bool translator_cutscene_test;
size_t cutscenetest_menu_page;
std::string cutscenetest_menu_play_id;
Add level exploring menu for translators I would, of course, recommend translators to translate the roomnames while playing the full game (optionally in invincibility) so they can immediately get all the context and maybe the most inspiration. And if you want to go back into a specific level, then there's always the time trials and intermission replays which will give you full coverage of all the room names. However, the time trials weren't really made for room name translation. They have some annoying features like the instant restart when you press ENTER at the wrong time, they remove context clues like teleporters and companions, but the worst problem is that the last room in a level is often completely untranslatable inside the time trials because you immediately get sent to the results screen... So, I added a new menu in the translator options, "explore game", which gives you access to all the time trials and the two intermissions, from the same menu. All these time trials (which they're still based off of, under the hood) are stripped of the annoying features that come with time trials. These are the changes I made to time trial behavior in translator exploring mode: - No 3-2-1-Go! countdown - No on-screen time/death/shiny/par - ENTER doesn't restart, and the map menu works. The entire map is also revealed. - Prize for the Reckless is in its normal form - The teleporters in Entanglement Generator, Wheeler's Wormhole and Level Complete are restored as context for room names (actually, we should probably restore them in time trials anyway? Their "press to teleport" prompt is already blocked out in time trials and they do nothing other than being a checkpoint. I guess the reason they were removed was to stop people from opening the teleporter menu when that was not specifically blocked out in time trials yet.) - The companions are there at the end of levels, and behave like in no death mode (become happy and follow you to the teleporter). Also for context. - At the end of each level, you're not suddenly sent to the menu, but you can use the teleporter at your leisure just like in the intermission replays. In the Final Level, you do get sent to the menu automatically, but after a longer delay. I made another mark on VVVVVV: don't be startled, I added gamestates. I wanted all teleporters at the end of levels to behave like the ones at the end of the intermission replays, and all handling for teleporting with specific companions is already done in gamestates, so rather than adding conditional blocks across 5 or so different gamestates, it made more sense to make a single gamestate for "teleporting in translator exploring mode" (3090). I also added an alternative to having to use gamestate 3500 or 82 for the end of the final level: 3091-3092. One other thing I want to add to the "explore game" menu: a per-level count of how many room names are left to translate. That shouldn't be too difficult, and I'm planning that for the next commit.
2022-11-26 03:33:17 +01:00
2020-01-01 21:29:24 +01:00
int creditposition;
int oldcreditposition;
2020-01-01 21:29:24 +01:00
bool insecretlab;
bool inintermission;
bool crewstats[numcrew];
bool ndmresultcrewstats[numcrew];
2020-01-01 21:29:24 +01:00
bool alarmon;
int alarmdelay;
bool blackout;
static const int numunlock = 25;
bool unlock[numunlock];
bool unlocknotify[numunlock];
bool anything_unlocked(void);
2020-01-01 21:29:24 +01:00
int stat_trinkets;
int bestgamedeaths;
static const int numtrials = 6;
int besttimes[numtrials];
int bestframes[numtrials];
int besttrinkets[numtrials];
int bestlives[numtrials];
int bestrank[numtrials];
2020-01-01 21:29:24 +01:00
int screenshake, flashlight;
bool advancetext, pausescript;
int deathseq, lifeseq;
int trinkets(void);
int crewmates(void);
int savepoint, teleportxpos;
bool teleport;
2020-01-01 21:29:24 +01:00
int edteleportent;
bool completestop;
float inertia;
int companion;
SDL_Rect teleblock;
bool activetele;
int readytotele;
int oldreadytotele;
int activity_r, activity_g, activity_b, activity_y;
2020-01-01 21:29:24 +01:00
std::string activity_lastprompt;
bool activity_gettext;
2020-01-01 21:29:24 +01:00
bool backgroundtext;
int activeactivity, act_fade;
int prev_act_fade;
2020-01-01 21:29:24 +01:00
bool press_left, press_right, press_action, press_map, press_interact;
bool interactheld;
bool separate_interact;
2020-01-01 21:29:24 +01:00
//Some stats:
int totalflips;
std::string hardestroom; // don't change to C string unless you wanna handle when this string is loaded from the XML
2020-01-01 21:29:24 +01:00
int hardestroomdeaths, currentroomdeaths;
int hardestroom_x, hardestroom_y;
bool hardestroom_specialname;
bool hardestroom_finalstretch;
2020-01-01 21:29:24 +01:00
bool quickrestartkludge;
//Custom stuff
std::string customscript[50];
int customcol;
int levelpage;
int playcustomlevel;
std::string customleveltitle;
std::string customlevelfilename;
void clearcustomlevelstats(void);
void loadcustomlevelstats(void);
void savecustomlevelstats(void);
2020-01-01 21:29:24 +01:00
void updatecustomlevelstats(std::string clevel, int cscore);
void deletecustomlevelstats(void);
2020-01-01 21:29:24 +01:00
// name -> score. 0 - not played, 1 - finished, 2 - all trinkets, 3 - finished, all trinkets
std::map<std::string, int> customlevelstats;
2020-01-01 21:29:24 +01:00
std::vector<SDL_GameControllerButton> controllerButton_map;
std::vector<SDL_GameControllerButton> controllerButton_flip;
std::vector<SDL_GameControllerButton> controllerButton_esc;
std::vector<SDL_GameControllerButton> controllerButton_restart;
std::vector<SDL_GameControllerButton> controllerButton_interact;
2020-01-01 21:29:24 +01:00
bool skipfakeload;
bool ghostsenabled;
bool cliplaytest;
int playx;
int playy;
int playrx;
int playry;
int playgc;
int playmusic;
std::string playassets;
void quittomenu(void);
void returntolab(void);
bool fadetomenu;
int fadetomenudelay;
bool fadetolab;
int fadetolabdelay;
void returntoeditor(void);
bool inline inspecial(void)
{
return inintermission || insecretlab || intimetrial || nodeathmode || translator_exploring;
}
bool incompetitive(void);
bool nocompetitive(void);
bool nocompetitive_unless_translator(void);
void sabotage_time_trial(void);
bool over30mode;
2021-08-05 23:31:20 +02:00
bool showingametimer;
bool ingame_titlemode;
bool ingame_editormode;
void returntoingame(void);
2020-08-01 21:51:11 +02:00
void unlockAchievement(const char *name);
bool disablepause;
bool disableaudiopause;
bool disabletemporaryaudiopause;
bool inputdelay;
2022-12-07 00:20:48 +01:00
bool statelocked;
int old_skip_message_timer;
int skip_message_timer;
int old_mode_indicator_timer;
int mode_indicator_timer;
int old_screenshot_border_timer;
int screenshot_border_timer;
bool screenshot_saved_success;
2020-01-01 21:29:24 +01:00
};
#ifndef GAME_DEFINITION
Allow using help/graphics/music/game/key/map/obj everywhere This commit makes `help`, `graphics`, `music`, `game`, `key`, `map`, and `obj` essentially static global objects that can be used everywhere. This is useful in case we ever need to add a new function in the future, so we don't have to bother with passing a new argument in which means we have to pass a new argument in to the function that calls that function which means having to pass a new argument into the function that calls THAT function, etc. which is a real headache when working on fan mods of the source code. Note that this changes NONE of the existing function signatures, it merely just makes those variables accessible everywhere in the same way `script` and `ed` are. Also note that some classes had to be initialized after the filesystem was initialized, but C++ would keep initializing them before the filesystem got initialized, because I *had* to put them at the top of `main.cpp`, or else they wouldn't be global variables. The only way to work around this was to use entityclass's initialization style (which I'm pretty sure entityclass of all things doesn't need to be initialized this way), where you actually initialize the class in an `init()` function, and so then you do `graphics.init()` after the filesystem initialization, AFTER doing `Graphics graphics` up at the top. I've had to do this for `graphics` (but only because its child GraphicsResources `grphx` needs to be initialized this way), `music`, and `game`. I don't think this will affect anything. Other than that, `help`, `key`, and `map` are still using the C++-intended method of having ClassName::ClassName() functions.
2020-01-29 08:35:03 +01:00
extern Game game;
#endif
Allow using help/graphics/music/game/key/map/obj everywhere This commit makes `help`, `graphics`, `music`, `game`, `key`, `map`, and `obj` essentially static global objects that can be used everywhere. This is useful in case we ever need to add a new function in the future, so we don't have to bother with passing a new argument in which means we have to pass a new argument in to the function that calls that function which means having to pass a new argument into the function that calls THAT function, etc. which is a real headache when working on fan mods of the source code. Note that this changes NONE of the existing function signatures, it merely just makes those variables accessible everywhere in the same way `script` and `ed` are. Also note that some classes had to be initialized after the filesystem was initialized, but C++ would keep initializing them before the filesystem got initialized, because I *had* to put them at the top of `main.cpp`, or else they wouldn't be global variables. The only way to work around this was to use entityclass's initialization style (which I'm pretty sure entityclass of all things doesn't need to be initialized this way), where you actually initialize the class in an `init()` function, and so then you do `graphics.init()` after the filesystem initialization, AFTER doing `Graphics graphics` up at the top. I've had to do this for `graphics` (but only because its child GraphicsResources `grphx` needs to be initialized this way), `music`, and `game`. I don't think this will affect anything. Other than that, `help`, `key`, and `map` are still using the C++-intended method of having ClassName::ClassName() functions.
2020-01-29 08:35:03 +01:00
2020-01-01 21:29:24 +01:00
#endif /* GAME_H */