1
0
Fork 0
mirror of https://github.com/TerryCavanagh/VVVVVV.git synced 2024-11-10 21:19:43 +01:00
Commit graph

1029 commits

Author SHA1 Message Date
Dav999-v
e20c01deed Move "resize to nearest" grouped with other resolution-related options
The options for fullscreen and scaling mode were at the top, then there
were various other graphical options, and then the option to resize to
the nearest window size that is of an integer multiple was all the way
below that. Now that last option is moved to be right below the other
options related to window sizing.
2020-06-30 16:53:33 -04:00
Dav999-v
a2d8e57af0 Move some options to a new menu, "advanced options"
VVVVVV's menus are kind of packed to the brim, so I thought it was time
to recategorize the menus a little bit. There's now a new "advanced
options" menu which holds the following options which were moved out of
graphic options, game options and especially accessibility options:

- toggle mouse
- unfocus pause
- fake load screen
- room name background
- glitchrunner mode

I also made the positioning of the titles and descriptions more
consistent, and made some options which were moved to the new menu not
so abbreviated ("load screen" and "room name bg")
2020-06-30 16:53:33 -04:00
Misa
de2d6a1e86 Expose all 9 arguments of createentity()
For whatever reason, not all arguments of createentity() are exposed in
the command.

We have to keep in mind that (1) unspecified arguments default to 0
(instead of the 320 and 240 for argument 8 and 9 that createentity()
usually defaults to), and that (2) arguments persist across commands.
(Why not get rid of argument persistence, you say? Unfortunately, some
levels rely on argument persistence to call gotoposition() without
specifying the third argument, even though you're supposed to specify
all three arguments.)

To add these arguments without breaking levels, I re-added the
createentity() defaults of 320 and 240 for args 8 and 9, and then I
reset the new arguments afterwards when I'm done. Technically this could
be bad if other commands used those higher arguments, but none of them
really do. (Except createcrewman(), but it only sets argument 6 to 0
sometimes anyway, but argument 6 is already supposed to default to 0.)
2020-06-30 16:50:56 -04:00
Misa
db06b336b6 Don't set showtrinkets when loading custom quicksave
Otherwise trinkets could randomly show up on the minimap when levels
don't want them to.
2020-06-30 16:30:09 -04:00
Misa
15e10af08e Display trinkets on the minimap in custommode
I don't really like how copy-pasted the minimap rendering code is, but
whatever. We can refactor it later.
2020-06-30 16:30:09 -04:00
Misa
9e9b1b3c6d Scan for trinkets and put them into shinytrinkets in customs
For showtrinkets() to work, we'll need the correct map data in custom
levels.
2020-06-30 16:30:09 -04:00
Misa
3f7ed4b94a Don't selectively undraw tiles in towers if backgrounds are off
The game for some reason had this thing where it would not draw the
diagonal background tiles if you had animated backgrounds turned off.
Which is weird, because spikes with that background are still drawn as
spikes with that background. And also, it doesn't do this for any of the
tower hallway rooms, which is inconsistent.

Better to simplify the logic in Render.cpp anyways by removing
graphics.drawtower_nobackground() and making it really clear what
exactly we'll do if backgrounds are turned off. ("Aren't we already not
drawing the background? What's this _nobackground() function for?")
2020-06-30 14:34:42 -04:00
Misa
2c18d28880 Add Flip Mode to game options if in M&P or in-game menu and unlocked
Flip Mode will now be in the game options menu if either:
 (1) You're playing the M&P version.
 (2) You have it unlocked and you came here from the in-game pause
     screen.

This is because if you're playing M&P, you'd have to close the game,
edit unlock.vvv, and re-launch the game to toggle Flip Mode, since
there's no other way to do so. And if you're playing the full version,
you'd have to save and exit your session in order to toggle Flip Mode.
2020-06-30 09:21:25 -04:00
Misa
7ce4f1173d 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 09:21:00 -04:00
Misa
e331abcd7e Fix Alt+Enter Glitch if not in glitchrunner mode
The Alt+Enter Glitch is a funny glitch where if you press any toggle
fullscreen keybind during a cutscene, Viridian will stop moving (if
they're being moved by a walk()) and ACTION will start being held down
for them. Meaning in most cases you can interrupt a walk and flip at the
same time.

This can obviously break cutscenes if a casual just wants to toggle
fullscreen, so I'm fixing it. But it will be unfixed in glitchrunner
mode in case you want to glitch out custom levels (I know I do).

More information on the Alt+Enter Glitch is available here:
https://gitgud.io/infoteddy/vvvvvv-knowledge/blob/master/bugs/bugs.md#the-altenter-glitch
(The page is a bit outdated, some bugs have been fixed in 2.3 already.)
2020-06-30 00:20:03 -04:00
Misa
35c540449e Add being able to disable unfocus pause
It's sometimes unwanted by people, and it's unwanted enough that there
exist instructions to hexedit the binary to remove it (
https://distractionware.com/forum/index.php?topic=3247.0 ).

Fun fact, the unfocus pause didn't exist in 2.0.
2020-06-29 22:59:16 -04:00
Misa
3f077ee56a Don't gray out invincibility/slowdown in intermission
When I re-enabled them for intermissions earlier, I forgot to un-gray
them out.
2020-06-29 22:59:16 -04:00
Ethan Lee
e85d5a8714
Merge pull request #326 from InfoTeddy/general-refactors
Refactor how custom level stats are stored, read, and written
2020-06-29 22:31:03 -04:00
Misa
b9bf2cc1c5 Unindent loadcustomlevelstats from previous commit
Done in a separate commit to reduce diff noise.
2020-06-29 18:47:45 -07:00
Misa
be9c405ddd Use returns and don't have rest of loadcustomlevelstats in an 'else'
This will cut down on unnecessary indentation levels.
2020-06-29 18:44:54 -07:00
Misa
9a008dc77c Refactor how custom level stats are stored, read, and written
There were a few problems with the old way of doing things:

(1) Level stats were an ad-hoc object. Basically, it's an object whose
attributes are stored in separate arrays, instead of being an actual
object with its attributes stored in one array.
(2) Level filenames with pipes in them could cause trouble. This is
because the filename attribute array was stored in the XML by being
separated by pipes.
(3) There was an arbitrary limit of only having 200 level stats, for
whatever reason.

To remedy this issue, I've made a new struct named CustomLevelStat that
is a proper object. The separate attribute arrays have been replaced
with a proper vector, which also doesn't have a size limit.

For compatibility with versions 2.2 and below, I've kept being able to
read the old format. This only happens if the new format doesn't exist.
However, I also WRITE the old format as well, in case you want to go
back to version 2.2 or below for whatever reason. It's slightly
wasteful to have both, but that way there's no risk of breaking
compatibility.
2020-06-29 18:39:22 -07:00
Ethan Lee
38a42b484d
Merge pull request #322 from Dav999-v/auto-center-menu
Make menus automatically centered and narrowed
2020-06-29 19:10:39 -04:00
Misa
f64e9237c4 Display centiseconds on time trial result and Game Complete
Centiseconds won't be saved to any save file or anything. This is just
to make speedrunning a bit more competitive, being able to know the
precise time of a time trial or full game run.

The time trial par time on the result screen always has ".99" after it.
This is basically due to the game comparing the number of seconds to the
par number of seconds using less-than-or-equal-to instead of simply
less-than.
2020-06-29 19:09:11 -04:00
Misa
ad27a5c154 Reset width of player in mapclass::resetplayer()
The width of the player can be changed by using the Gravitron OoB
glitch. It will not be reset if the game is in glitchrunner mode.
2020-06-29 19:08:22 -04:00
Misa
66d19d4cf4 Disable two-frame delay fix in glitchrunner mode
The two-frame delay can be utilized to trigger a glitch that spawns
entities in the wrong room.
2020-06-29 19:08:22 -04:00
Misa
d4592cd6b3 Add special case to color gray Warp Zone entities gray
The only reason why gray Warp Zone entities were green originally was
because there is a giant concatenated list of tileset+tilecol
combinations, and by using tileset 3 tilecol 6 you're using the entry
of tileset 4 tilecol 0, which is the green Ship tileset.

So without interfering with the green Ship tileset's entry, I've decided
that the best thing to do is to just add special cases. The enemy color
was easy enough to fix. The platform color was also easy to fix.
However, there exist no existing textures for gray conveyors, so at that
point I decided to just tint the existing green one gray, and then I did
the same for platforms.
2020-06-29 19:07:45 -04:00
Misa
584f73f0a4 Add BlitSurfaceTinted()
This will be used to change the color of existing textures while
preserving their lightness values.
2020-06-29 19:07:45 -04:00
Dav999-v
cc538a0965 Merge remote-tracking branch 'upstream/master' into auto-center-menu
Fix one conflict.
2020-06-29 23:40:10 +02:00
Dav999-v
803d0f45de Document menu width limit better
The reason for the menu width to be limited to 272 pixels was rather
undocumented in the code, now the comment explains more about it.
2020-06-29 23:18:33 +02:00
Misa
ebd381c228 Fix the two-frame-delay when entering a room with an "init" script
This patch is very kludge-y, but at least it fixes a semi-noticeable
visual issue in custom levels that use internal scripts to spawn
entities when loading a room.

Basically, the problem here is that when the game checks for script
boxes and sets newscript, newscript has already been processed for that
frame, and when the game does load a script, script.run() has already
been processed for that frame.

That issue can be fixed, but it turns out that due to my over-30-FPS
game loop changes, there's now ANOTHER visible frame of delay between
room load and entity creation, because the render function gets called
in between the script being loaded at the end of gamelogic() and the
script actually getting run.

So... I have to temporary move script.run() to the end of gamelogic()
(in map.twoframedelayfix()), and make sure it doesn't get run next
frame, because double-evaluations are bad. To do that, I have to
introduce the kludge variable script.dontrunnextframe, which does
exactly as it says.

And with all that work, the two-frame (now three-frame) delay is fixed.
2020-06-29 15:42:51 -04:00
Misa
baf879d9fd Remove unused tmap vars from mapclass
These used to be relevant when the main game tilemaps were stored in
strings, but now they no longer are.
2020-06-29 15:42:51 -04:00
Misa
e1a114d1a5 Un-fix hitbox persistence in map.resetplayer()
It's annoying for casuals to have to close the game if they manage to
get themselves to turn into VVVVVV-Man, but it's amusing enough to
glitchrunners that they mess about with VVVVVV-Man in the main game,
clipping through walls everywhere (well, they call it Big Viridian, but
still).
2020-06-29 15:12:35 -04:00
Misa
387ee4dc79 Un-hardreset certain variables for glitchrunner mode
Ironically enough, resetting more variables in script.hardreset() makes
the glitchy fadeout system even more glitchy. Resetting map.towermode,
for example, makes it so that if you're in towers when you quit to the
menu, script.hardreset() makes it so that the game thinks you're no
longer inbounds (because it no longer thinks you're in a tower and thus
considers coordinates in the space of 40x30 tiles to be inbounds instead
of 40x700 or 40x100 tiles to be inbounds), calls map.gotoroom(), which
resets the gamestate to 0. So if we're using the old system, it's better
to reset only as much as needed.

And furthermore, we shouldn't be relying on script.hardreset() to
initialize variables for us. That should be done at the class
constructor level. So I've gone ahead and initialized the variables in
class constructors, too.
2020-06-29 15:12:35 -04:00
Misa
cb8540d7bd Restore janky gamestate-based quit-to-title system in glitchrunnermode
This was fixed in 2.3 because one of the side effects of this janky
system was being able to accidentally immediately quit to the title if
the screen was black during a cutscene, which is something very likely
to happen to casual players.

Anyway, credits warp uses this gamestate-based system because it
utilizes quitting to the title screen doing gamestate 80. From there,
you increment the gamestate to gamestate 94 to use the Space Station 2
expo script.
2020-06-29 15:12:35 -04:00
Misa
9bab6bd0cb Don't hardreset() game.advancetext in glitchrunner mode
This is the second part of what is necessary for credits warp to work.

The speedrunners call this "text storage". You need to get the
advancetext prompt up without a text box in order to be able to
increment the gamestate without bound. In 2.0, script.hardreset() reset
the text boxes, but not the prompt.
2020-06-29 15:12:35 -04:00
Misa
5848330e66 Re-enable unbounded gamestate increment in glitchrunner mode
This is the first part of what is necessary for credits warp to work.

If the "- Press ACTION to advance text -" prompt is up, and you manage
to keep it up, then you can indefinitely increment the gamestate by
pressing ACTION.

This is first used in credits warp to teleport to the start of Space
Station 2 (by utilizing the Eurogame expo script, triggered by a
gamestate), and then again later by using a teleporter that has a high
gamestate number to increment to the [C[C[C[C[Captain!] cutscene.
2020-06-29 15:12:35 -04:00
Misa
779083b417 Add glitchrunner mode, in game options
Glitchrunner mode is intended to re-enable glitches that existed in
older versions of VVVVVV. These glitches were removed because they could
legitimately affect a casual player's experience. Glitches like various
R-pressing screwery, Space Station 1 skip, telejumping, Gravitron
out-of-bounds, etc. will not be patched.
2020-06-29 15:12:35 -04:00
Dav999-v
46d5fc6576 Correct minimum horizontal spacing check
It should've checked the final spacing and not the intermediate maximum
value. I had changed some things around, and now the minimum spacing
was 5 instead of 0 by mistake.
2020-06-29 02:58:38 +02:00
Dav999-v
0023c821db 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
Misa
18b34d0066 Add logs if a Graphics func was stopped from indexing OoB
This doesn't happen too often, but it'll be useful to people making
custom levels so they know that it can happen, when it does.
2020-06-28 15:48:48 -04:00
Misa
c95c1ab250 Add bounds check to textbox functions that use m
It seems to be a bit bad to blindly use `m` without checking it. In
fact, this has caused a few segfaults already, actually.
2020-06-28 15:48:48 -04:00
Misa
a0f10d80e5 Refactor, de-duplicate, and clean up tilesheet processing
The tilesheets in question are font.png, tiles.png, tiles2.png,
tiles3.png, entcolours.png, teleporter.png, sprites.png, and
flipsprites.png.

This patch removes the hardcoded dimensions when scanning the
tilesheets, because it's simpler that way. It also de-duplicates it so
it isn't a bunch of copy-paste, by using macros. (I had to use macros
because it was the easiest way to optionally pass in some extra code in
the innermost for-loop.)

Also, if the dimensions of a scanned tilesheet aren't exactly multiples
of the dimensions of the tile unit for that given tilesheet (e.g. if the
dimensions of a scanned tiles.png are not exact multiples of 8), then an
SDL_SimpleMessageBox will show up with the error message, a puts() of
the error message will be called, and the program will exit.
2020-06-28 08:44:35 -04:00
Misa
7627a37216 Change a '||' to a '=='
Whoops.
2020-06-28 08:41:19 -04:00
Misa
9363cf4c40 Fix Game::anything_unlocked() always evaluating to true
Whoops.
2020-06-28 08:41:00 -04:00
Misa
22738cdb97 Remove unused/useless vars music.custompd/musicfade(in)/volume
I have no idea why these are here, but it'll simplify readability and
reduce the chance of confusion if I remove them.
2020-06-27 17:23:07 -04:00
Misa
facb079b35 Fix resumemusic/musicfadein not working
It seems like they were unfinished. This commit makes them properly
work.

When a track is stopped with stopmusic() or musicfadeout(),
resumemusic() will resume from where the track stopped. musicfadein()
does the same but does it with a gradual fade instead of suddenly
playing it at full volume.

I changed several interfaces around for this. First, setting currentsong
to -1 when music is stopped is handled in the hook callback that gets
called by SDL_mixer whenever the music stops. Otherwise, it'd be
problematic if currentsong was set to -1 when the song starts fading out
instead of when the song actually ends.

Also, music.play() has a few optional arguments now, to reduce the
copying-and-pasting of music code.

Lastly, we have to roll our own tracker of music length by using
SDL_GetPerformanceCounter(), because there's no way to get the music
position if a song fades out. (We could implicitly keep the music
position if we abruptly stopped the song using Mix_PauseMusic(), and
resume it using Mix_ResumeMusic(), but ignoring the fact that those two
functions are also used on the unfocus-pause (which, as it turns out, is
basically a non-issue because the unfocus-pause can use some other
functions), there's no equivalent for fading out, i.e. there's no
"fade out and pause when it fully fades out" function in SDL_mixer.) And
then we have to account for the unfocus-pause in our manual tracker.

Other than that, these commands are now fully functional.
2020-06-27 17:23:07 -04:00
Misa
2662cd4d06 Refactor KeyPoll::Poll() to use case-switch statements
Reduces the amount of copy-pasted if-expressions.
2020-06-27 17:23:07 -04:00
Misa
a87ebd2945 Remove unnecessary middleman game.infocus
It does the same thing as key.isActive, so no need to make it a separate
variable.
2020-06-27 17:23:07 -04:00
Misa
5052391f60 Make warpdir only re-draw BG if targeted room is current room
It's unnecessary to re-draw the background if you're modifying the warp
direction of some other room.
2020-06-26 10:22:05 -04:00
Misa
1cbecdda86 Use returntomenu(timetrials) instead of returnmenu in timetrialcomplete3
This fixes a corner case where using gamestate 82 from the editor would
put you in a softlock because it would return to the editor settings
menu, which only functions in EDITORMODE and results in a softlock in
TITLEMODE.
2020-06-25 20:27:51 -04:00
Ethan Lee
9804fbc383 Fix gamecontrollerdb.txt path 2020-06-23 19:08:08 -04:00
Misa
94a67ca0aa Only check Secret Lab/Time Trial/NDM for slowdown if ingame_titlemode
This is already done for invincibility. It's kind of unnecessary, but
it's just to make sure if for some reason in the future variables like
insecretlab/intimetrial/nodeathmode don't get reset when exiting to the
menu.
2020-06-23 15:23:57 -04:00
Misa
a3f171b018 Allow toggling invincibility/slowdown in intermission replays
inspecial() includes being in intermission replays, but it's not
necessary to disable invincibility/slowdown for them.
2020-06-23 15:23:57 -04:00
Misa
65f84b15f4 Fix deltaframe tower BG flicker when exiting menu in H/V warp room
To fix this annoying flicker (which, btw, took me WAY too long to do), I
had to introduce yet another kludge variable to signal that the
horizontal/vertical warp background should be re-initialized on the
pause screen.

I think I could technically keep the 'graphics.backgrounddrawn = false;'
in maplogic() and remove the 'graphics.backgrounddrawn = false;' in
Game::returntopausemenu(), but I'm keeping that other one around because
it doesn't hurt and just as a general precaution and safety measure.
2020-06-23 15:23:57 -04:00
Misa
16ebb807db Set backgrounddrawn to false when returning to pause menu
This makes it so the tower background doesn't persist and scroll upwards
if you exit the menu in a warp zone horizontal or vertical room.

Ugh, and while we're on the subject of separating the in-game tower
background and the menu tower background, could we PLEASE separate the
horizontal / vertical warp backgrounds from the tower backgrounds, too?!
2020-06-23 15:23:57 -04:00
Misa
441e7babd7 Fix Flip Mode persisting in in-game options menu
Now graphics.flipmode is turned off when going into the menu, and turned
back on if necessary when exiting.
2020-06-23 15:23:57 -04:00
Misa
c5a5589ce5 Allow pressing Esc to close Esc menu
Another thing that's annoyed me a lot is being unable to simply press
Esc to close the pause menu. You'd have to hover over the "return to
game" or "keep playing" option. This would be even more annoying with
more options on the menu, so allowing to press Esc is a nice
quality-of-life thing.
2020-06-23 15:23:57 -04:00
Misa
f6d73c62ec Allow pressing Esc to go back to pause menu from quit prompt
Allowing for more actions makes things feel smoother.
2020-06-23 15:23:57 -04:00
Misa
b63347b70c Prevent menu input if fading out
Otherwise you could keep re-pressing ACTION on the "yes" option and keep
stalling it until it finally faded out, or quickly go back past menu
options or something.
2020-06-23 15:23:57 -04:00
Misa
3c5ed04678 Make "no, keep playing" go back to pause menu
This is so the menus can stack on top of each other. Well, technically
they don't, but it's the same thing.
2020-06-23 15:23:57 -04:00
Misa
f6330c57fd Reset map.bypos when entering options menus in-game
Otherwise the menu background would have this rendering glitch where the
bypos of the in-game tower wouldn't divide easily and have a bunch of
jitters in an otherwise smooth but overall still somewhat smooth
background.
2020-06-23 15:23:57 -04:00
Misa
ccd6cfab7f Round map.colstate to nearest 5 when entering options menus
Also set map.tdrawback to true when leaving the menu.

This is to fix the interpolated color of the tower background
persisting, as well as making sure the menu background doesn't persist
when exiting.
2020-06-23 15:23:57 -04:00
Misa
8ed9ee1ca2 Fix Graphics::map_option() not uppercasing selected text
Forgot to do this earlier, whoops.
2020-06-23 15:23:57 -04:00
Misa
8c4b48fbfd Fix toggling MMMMMM always playing Presenting VVVVVV
This would be fine, under the assumption that you could never reach the
menu from outside the menu. Well, now you can, so now this has to play
the correct song instead of track 6.
2020-06-23 15:23:57 -04:00
Misa
caa4f0f5c9 Prevent turning on invincibility/slowdown in in-game options menu
Would've been the easiest exploit ever! But I gotta patch it.
2020-06-23 15:23:57 -04:00
Misa
a476121432 Make pressing Esc in ingame_titlemode go back to pause menu
You shouldn't be able to bring up the youwannaquit menu while you're
in-game, that should only be when you're actually not in game.
2020-06-23 15:23:57 -04:00
Misa
aa40eb6327 Move returning to pause menu code to separate function
This code is getting a bit more complicated now, we should maybe stop
copy-pasting it everywhere.
2020-06-23 15:23:57 -04:00
Misa
6582801dc9 Save current menu to temp variable when entering options from in-game
This is to pre-emptively prevent piling up stack frames for what I'll be
adding next, which is pressing Esc in the options menu in-game
automatically moving you back to MAPMODE.
2020-06-23 15:23:57 -04:00
Misa
75326ca2ee Save BG vars to temp vars when entering menu and revert them upon exit
Since the exact same tower background is also used on the menu, we need
to save the current state of the background when entering the menu
(before overwriting it), and then put it back when we're done. Maybe we
ought to separate the in-game and menu tower backgrounds...

This also fixes a semi-hilarious bug where you could make Panic Room go
in the other direction by simply going to the options menu in-game.

This is accomplished by adding convenience functions
mapclass::bg_to_kludge() and mapclass::kludge_to_bg().
2020-06-23 15:23:57 -04:00
Misa
46d1e4053e Set map.scrolldir when going to options in-game
This ensures that the background doesn't start scrolling the wrong way
in the menu.
2020-06-23 15:23:57 -04:00
Misa
a46dd32f12 Consolidate common case 32/33 code
If most of the code in the cases is the same, then just consolidate and
de-duplicate them. It's less error-prone this way.
2020-06-23 15:23:57 -04:00
Misa
6d7bff61b2 Make returning from game/graphic options return to MAPMODE
This is so return doesn't just lead back to more TITLEMODE.
2020-06-23 15:23:57 -04:00
Misa
4c5b018f6c Fix delta rendering glitch when going to options from new Esc menu
Well this is a bit annoying. I can call graphics.updatetowerbackground()
just fine, but I have to get at the title color update routine inside
titlelogic(), which is hard-baked in. So I have to pull that code
outside of the function, export it in the header, and then call it when
I transition to TITLEMODE.
2020-06-23 15:23:57 -04:00
Misa
06102e2db3 Make better Esc menu functional
So now the options do what they do. However, I still need to fix the
1-frame glitch when switching to TITLEMODE, as well as make returning
from the menu return back to MAPMODE, as well as making this better menu
integrate seamlessly with the existing menus.
2020-06-23 15:23:57 -04:00
Misa
4274843a4b Use game.inspecial() in mapmenuactionpress()
Apart from covering more cases with the SHIP option, it also makes the
if-guard for case 3 much less noisy on the eyes.
2020-06-23 15:23:57 -04:00
Misa
949e99c950 Use case-switch in mapmenuactionpress()
This prevents from having to repeat 'if (game.menupage == ...)'
everywhere, which makes for more concise code.

I know you're technically supposed to indent the cases surrounded by
if-guards, but I don't think indenting them here would help anything.
I'd only indent it if the 'if' had an 'else', for example. But if it
surrounds the whole case, then there's no need for indentation.
2020-06-23 15:23:57 -04:00
Misa
5717afaa37 Pull the game.press_action conditional out of all the if-statements
No need to repeat yourself if you can just surround the whole thing in
an 'if (game.press_action)' block, which is much easier.
2020-06-23 15:23:57 -04:00
Misa
13cc7b2a4b Unindent mapmenuactionpress()
Done in a separate commit to minimize diff noise.
2020-06-23 15:23:57 -04:00
Misa
55d001b4f6 Move mapinput() ACTION press handling to separate function
It's a bit too much to consolidate all the ACTION press handling into
one function, especially given the increasing amount of indentation
levels.
2020-06-23 15:23:57 -04:00
Misa
92154f4be1 Add start of better Esc menu
It's not functional yet, but here are the options:

    return to game
        quit to menu
            graphic options
                game options
2020-06-23 15:23:57 -04:00
Misa
a402c990bf Add Graphics::map_option()
Similar to Graphics::map_tab(), this ensures that I don't have to
copy-paste printing the map options for every single game.menupage case
I want, and in this case that's a good thing because there'll be 4
game.menupage cases I'll be using.
2020-06-23 15:23:57 -04:00
Misa
b8403ffe1e Use game.inspecial() for special mode checks in maprender()
This basically adds an extra '|| game.inintermission' because it seems
like the original code forgot about that conditional. You can't save in
level replays, so there's no need to say "You will lose any unsaved
progress." in intermission replays.
2020-06-23 15:23:57 -04:00
Misa
6648246662 Fix -playx/y/rx/ry/gc/music looking at wrong argument
In my previous PR, I wrongly assumed that I could just replace the `i`
handling code of those options with an `i++;` at the beginning, and thus
I could put all blocks' `i++;` into ARG_INNER(). Well I was wrong,
because the code was written the original way for a reason, namely that
we still need `i` to point to the -playx/y/rx/ry/gc/music argv so we can
re-compare which argument led us into this code block.
2020-06-21 21:44:02 -04:00
Misa
33aed057ba Add note to README about "compiler quirks" only applying to 2.2
Only the 2.2 version has these problems, so you don't need to worry
about this section when compiling 2.3.
2020-06-21 20:51:04 -04:00
Misa
b66d303540 De-duplicate 'ed.numcrewmates() - game.crewmates()'
Any decent compiler will optimize this so that it's still only two
function calls (or it gets inlined). However, it's still not very
readable, so I've assigned the result to a variable and used that
instead.
2020-06-21 20:50:39 -04:00
Misa
8a110ead34 De-duplicate 'ed.ListOfMetaData[game.playcustomlevel]'
Whoa, that's a long identifier! Better to replace it with something
short, like 'meta', to save on typing and improve readability.
2020-06-21 20:50:39 -04:00
Misa
b480d5e5a9 De-duplicate Flip Mode code for custom levels' CREW page
Instead of copy-pasting everything and changing a few parts, just have
something that handles that tiny part. This reduces the amount of code
size the custom level CREW page takes up by half.
2020-06-21 20:50:39 -04:00
Misa
9d20f754bc Add macro-like inline func FLIP()
This will be used to keep some text positions the same when in Flip
Mode, instead of having to copy and paste code.

This function being at the very top of the file kind of violates
locality, but it has to be done because it can't be a macro.
2020-06-21 20:50:39 -04:00
Misa
6876dbf70c De-duplicate menu tab rendering
Previously, the code to print all tab names was copied to every single
tab, resulting in 12 more superfluous print statements than needed. This
commit uses graphics.map_tab to de-duplicate all the code.
2020-06-21 20:50:39 -04:00
Misa
aa3c1c8053 Add Graphics::map_tab()
This function is useful to de-duplicate all the map page names at the
bottom, which are MAP, CREW/SHIP/GRAV, STATS, and SAVE. If selected, it
will surround the text in square brackets and automatically handle the
positioning.

Shamelessly copy-pasted from Dav999's localization branch.
2020-06-21 20:50:39 -04:00
Misa
8c9c3d3751 Add being able to press Esc to go to quit menu from teleporter menu
It's always been a bit annoying that if you're in the teleporter menu,
you can't press Escape to go to the "Do you want to quit?" menu.
2020-06-21 20:50:06 -04:00
Misa
afd16ebc73 Add puts() if FILESYSTEM_init() fails
Just to be helpful if someone has a failing FILESYSTEM_init(), but
doesn't know that's their issue and keeps wondering why VVVVVV just
exits with code 1.
2020-06-21 20:25:22 -04:00
Misa
9001a68833 De-duplicate and add safety checks to CLI args, fix brace style
The command-line argument parsing code has a lot of copy-paste. This
copy-paste would get even worse if I added safety checks to make sure
you couldn't index argv out-of-bounds by having an argument like
`-renderer` without having anything after it, i.e. you'd be doing the
command `./VVVVVV -renderer`.

Previously, only the playtest arguments (apart from the recently-added
`playassets`) had this safety check, but the message it printed whenever
the safety check failed was always "-playing option requires one
argument" regardless of whatever argument actually failed to be parsed.
So I fixed it so that all arguments actually output the correct
corresponding failed argument instead.

Also, `strcmp(argv[i], <name>) == 0` is really kind of noisy, even if
you understand what it does perfectly well.

So I refactored it with a bunch of macros. ARG() just does the strcmp()
char* comparison, and ARG_INNER() does the safety check and returns 1,
along with printing a message, if the safety check fails.
2020-06-21 20:25:22 -04:00
Misa
93b13cadac Add -playassets command-line option
This is used if you're loading a level file from STDIN. The game needs
to know the actual level assets directory you're referring to, since
when it gets the level from STDIN, it doesn't know the actual filename
of the level.

Fixes #309.
2020-06-21 20:25:22 -04:00
Misa
d45ff4c269 Abstract assets mounting to FileSystemUtils.cpp
The assets mounting code was put directly in editorclass::load(), but
now it's in a neat little function so it can be called from multiple
places without having to call editorclass::load().
2020-06-21 20:25:22 -04:00
Misa
34e89bfcd3 Move endsWith() to UtilityClass.cpp and put it in header file
This ensures that endsWith() can be used outside of editor.cpp.

When leo60228 originally wrote endsWith(), it was static, but I asked
him on Discord just now and he more-or-less confirmed that it's fine if
it's not static. If it was static, it would be confined to
UtilityClass.cpp now instead!
2020-06-21 20:25:22 -04:00
Misa
ed527bc872 Remove unnecessary music.init() from asset mounting code
graphics.reloadresources() already does music.init().
2020-06-21 20:25:22 -04:00
Misa
c6e800db6f Add '#if !defined(NO_EDITOR)' guards around editorinput/render/logic
These functions aren't needed in a NO_EDITOR build, so it's useful to
reduce the binary size this way.
2020-06-19 18:35:03 -04:00
Misa
5c7e869ee7 Work around SDL2 bug where VSync hint only applies on renderer creation
Ugh, this is terrible and stupid and I hate myself for it.

Anyway, since the SDL2 VSync hint only applies when the renderer is
created, we have to re-create the renderer whenever VSync is toggled.
However, this also means we need to re-create m_screenTexture as well,
AND call ResizeScreen() after that or else the letterbox/integer modes
won't be applied.

Unfortunately, this means that in main(), gameScreen.init() will create
a renderer only to be destroyed later by graphics.processVsync().
There's not much we can do about this. Fixing this would require putting
graphics.processVsync() before gameScreen.init(). However, in order to
know whether the user has VSync set, we would have to call
game.loadstats() first, but wait, we can't, because game.loadstats()
mutates gameScreen! Gahhhhhh!!!!

@leo60228 suggested to fix that problem (
https://github.com/TerryCavanagh/VVVVVV/pull/220#issuecomment-624217939
) by adding NULL checks to game.loadstats() and then calling it twice,
but then you're trading wastefully creating a renderer only to be
destroyed, for wastefully opening and parsing unlock.vvv twice instead
of once. In either case, you're doing something twice and wasting work.
2020-06-19 17:44:53 -04:00
Misa
d898597c1e Don't extern gameScreen, use *graphics.screenbuffer instead
Externing gameScreen is just unnecessary. Still a good idea to have it
off the stack, though.
2020-06-19 17:44:53 -04:00
Misa
0cb21f407e Add inline directives to gameloop(), deltaloop(), fixedloop()
This is to make sure that there's no cost splitting up the game loop
into several different functions to increase code readability.
2020-06-19 09:05:48 -04:00
Misa
7640f8cc8f Add NO_CUSTOM_LEVELS guard around EDITORMODE in deltaloop()
Otherwise a NO_CUSTOM_LEVELS build would fail. Also I got rid of the
'graphics.flipmode = false;' in the fixed loop because I don't think it
does anything.
2020-06-19 09:05:48 -04:00
Misa
867e7bc1e6 Move infocus and network updates to fixedloop()
Updating them every delta frame is way too fast.
2020-06-19 09:05:48 -04:00
Misa
acf47bfeac Unindent fixedloop()
If I did it in the previous commit, it would've been too noisy.
2020-06-19 09:05:48 -04:00
Misa
a9f07ccc8f Move fixed loop to its own function
To improve code readability because otherwise the code would be one
giant blob.
2020-06-19 09:05:48 -04:00
Misa
1fbec9c427 Unindent deltaloop()
Doing it in the same commit makes the diffs too noisy...
2020-06-19 09:05:48 -04:00
Misa
c9aea52385 Move delta loop to its own function
Makes the code less of a giant blob, again.
2020-06-19 09:05:48 -04:00
Misa
e294b92785 Unindent gameloop()
You know the drill, diffs are too impatient to properly illustrate an
indentation change without adding a bunch of noise.
2020-06-19 09:05:48 -04:00
Misa
a8d2994223 Put the main game loop inside its own function
Makes main() less of one giant blob of code.
2020-06-19 09:05:48 -04:00
Misa
3d674a6550 Rename time to time_
This is needed for the next step. I want to put all the loop stuff in
their own functions so the code isn't one huge blob, but to do that I'll
need to make 'time' a global variable, but I can't do that because
actually 'time' is already a function, apparently, and you're only
allowed to shadow variables when already inside a function.
2020-06-19 09:05:48 -04:00
Misa
f151cff34d Fix editor ghost colors updating too fast
Like actual entities, editor ghost colors were updating every render
frame instead of logic frame. So just like actual entities, I added a
realcol attribute to them that editorrender() uses instead, and added
code to update said realcol attribute in editorlogic(). That way the
colors don't go by too quickly (especially the death color).
2020-06-19 09:05:48 -04:00
Misa
d1b1ed830b Fix ed.currentghosts updating way too fast
Just like all the other fixes, the variable that controls the amount of
ghosts to show was being updated every render frame instead of every
logic frame.
2020-06-19 09:05:48 -04:00
Misa
92ff6ac8fc Fix editor ghosts being added multiple times per frame
This just results in a messy splotchy effect. Instead, move the ghost
adding outside of the render function.
2020-06-19 09:05:48 -04:00
Misa
2f447fd794 Fix H/V warp BG not resetting when returning to editor (again)
This is because due to the game loop changes in this over-30-FPS patch,
editorrender() can be called and undo graphics.backgrounddrawn being set
to false once again. Solution here is to make it so it keeps being set
to false until game.shouldreturntoeditor is turned off, which has also
been moved to editorlogic().
2020-06-19 09:05:48 -04:00
Misa
057bdc9b68 Add 1 to fade-to-menu/lab delay
This fixes an off-by-one interpolation visual bug when exiting to the
menu or lab in over-30-FPS mode.
2020-06-19 09:05:48 -04:00
Misa
18ecc00d6d Set alpha to 1 in 30-FPS-only mode
This is to make sure no lerping occurs in 30-FPS mode, otherwise things
might look weird. A good case that this fixes is how entities look in a
double-gotoroom (they should be completely frozen in 30-FPS mode).
2020-06-19 09:05:48 -04:00
Misa
694e8f42ab Add VSync graphics option, off by default
This is if you want delta-timesteps to go as quickly as possible. Also
it seems like on Windows this only has an effect in exclusive fullscreen
mode.
2020-06-19 09:05:48 -04:00
Misa
179315c889 Indent game loop yet again
This is because in the previous commit I put braces around it because I
needed to have a delta-timestep limiter.
2020-06-19 09:05:48 -04:00
Misa
7f526f3ef2 Add being able to toggle over/fixed-30-FPS, off by default
There is now an option in "graphic options" named "toggle fps", which
toggles whether the game visually runs at 1000/34 FPS or over 1000/34
FPS. It is off by default.

I've had to put the entire game loop in yet another set of braces, I'll
indent it next commit.
2020-06-19 09:05:48 -04:00
Misa
eaf9eec3dc Fix animating entities' drawframes not being updated for 1 frame
What happens here is that the entity gets created and then gets
immediately updated on the next frame, but there's no time for their
walkingframe of 0 to be rendered, so it'll look like they have just
started with walkingframe 1. However in the delta-timestep rendering
it'll render with walkingframe 0. So we need to fix their drawframe and
increment it when creating them.
2020-06-19 09:05:48 -04:00
Misa
b5b958561c Move preloader update code to new function preloaderlogic()
Otherwise the preloader will go by way too quickly.
2020-06-19 09:05:48 -04:00
Misa
97b8e062ff Move analogue mode filter update logic to fixed-timestep loop
Otherwise if the analogue filter is scrolling, it'll scroll by REALLY
fast.
2020-06-19 09:05:48 -04:00
Misa
995f0f126f Fix 1-frame glitch when entering a room with plats in finalmode
Looks like mapclass::changefinalcol() is called whenever you enter a
room in Outside Dimension VVVVVV.

mapclass::changefinalcol() changes the tile, but it doesn't update their
drawframe. So after that function is called, update their drawframe.

If you update their drawframe while inside that function, then when the
platform actually cycles color it'll cycle backwards quickly sometimes,
which is not ideal.
2020-06-19 09:05:48 -04:00
Misa
d88b603019 Fix 1 frame where sad crewmates' drawframes weren't updated
When I loaded the room where Vitellary is in Space Station 2, I saw this
1-frame glitch happen despite my previous efforts to prevent it. So now
it's fixed.
2020-06-19 09:05:48 -04:00
Misa
2333087c27 Remove duplicate -renderer option
Guess this was here from when Leo added command-line playtesting.
2020-06-19 09:05:48 -04:00
Misa
4be18ff9fe Add v-sync hint
This is because otherwise, on my Linux system at least, the game will
take up a lot of CPU that it doesn't really need to (I only have a 60hz
monitor).

On Windows, it looks like Windows already enforces V-sync for
applications anyway, unless they have exclusive fullscreen control.
Linux doesn't enforce V-sync on apps and lets them take up as much CPU
as they want, so I'm putting this here to limit the framerate.

The game is already actually 30 FPS anyway, the nice smooth FPS is just
visual. V-sync won't introduce any more "input lag" than already exists.
2020-06-19 09:05:48 -04:00
Misa
ad6adcb3c0 Refactor how "hidden names" work
By "hidden names", I'm referring to "Dimension VVVVVV" and "The Ship"
popping up on the quit/pause/teleporter screens, even though those rooms
don't have any roomnames.

Apparently my commit to fix roomname re-draw bleed on the
quit/pause/teleporter screens exposed yet another hardreset()-caused
bug. The issue here is that since hardreset() sets game.roomx and
game.roomy to 0, map.area() will no longer work properly, and since the
hidden roomname check is based on map.area(), it will no longer display
"Dimension VVVVVV" or "The Ship" once you press ACTION to quit. It used
to do this due to the re-draw bleed, but now it doesn't.

I saw that roomnames didn't get reset in hardreset(), so the solution
here is to re-factor hidden names to be an actual variable, instead of
being implicit. map.hiddenname is a variable that's set in
mapclass::loadlevel(), and if isn't empty, it will be drawn on the
quit/pause/teleporter screens. That way it will still display "Dimension
VVVVVV" and "The Ship" when you press ACTION to quit to the menu.

EDIT: Since PR #230 got merged, this commit is no longer strictly
necessary, but it's still good to refactor hidden names like this.
2020-06-19 09:05:48 -04:00
Misa
c009ab67d9 Make slowdown only apply in GAMEMODE/MAPMODE/TELEPORTERMODE
As much as it looks cool to have a slowly-scrolling background on the
title screen, it's quite annoying that slowmode applying on the title
screen mean that your keypresses are less responsive.
2020-06-19 09:05:48 -04:00
Misa
49fbe18d34 Make sure sprite colors in the editor don't update more than 30 FPS
This adds Graphics::crewcolourreal(), which is like the
entityclass::crewcolour() that the editor already uses, except for the
real color instead of the color ID. Also, editorclass now has an
attribute `entcolreal` so enemy colors don't update more than 30 frames
a second.
2020-06-19 09:05:48 -04:00
Misa
98e033e5d0 Fix red pill/mannequins/transmittor/radar dish being offset for 1 frame
Forgot to update their oldxp/oldyp when their xp/yp got updated upon
setenemyroom() being called.
2020-06-19 09:05:48 -04:00
Misa
349702c92c Fix flickering when holding down ACTION in credits scroll
The solution is to draw another row of incoming textures. And also just
draw another row of textures when the background needs to be redrawn,
otherwise it'll flicker when the color changes while you're holding down
ACTION.
2020-06-19 09:05:48 -04:00
Misa
1e81aef58a Fix flickering on bottom/right of screen with H/V warp BGs
To fix this, I draw another row/column of incoming textures. But of
course, I have to extend the size of the towerbuffer, otherwise the
incoming textures will just be gone.
2020-06-19 09:05:48 -04:00
Misa
45fecf71b2 Fix overdraw bug in tower background
This could happen if you held down ACTION in the credits, looks like the
background doesn't keep up for some reason. That's another bug to fix,
but at least I can fix this overdraw.
2020-06-19 09:05:48 -04:00
Misa
69b3a5dff2 Fix roomname being continuously drawn on top of itself
This is only noticeable if you have a font with translucent pixels, like
I do. But it gets really noticeable really quickly with this over-30-FPS
patch because the render functions are continuously called every
delta-timestep. To prevent this, just fill the backbuffer with black
before rendering anything.
2020-06-19 09:05:48 -04:00
Misa
c289128693 Fix overdraw at bottom/right screen edges with H/V warp BGs
There's still a problem in that the flickering that would lead to this
overdraw in the first place still exists. But at least if it'll flicker,
it'll flicker black and not overdraw.
2020-06-19 09:05:48 -04:00
Misa
93d8220388 Fix off-by-one in interpolation of extending gravity line
Currently it interpolates it based on the current state of game.swngame,
but when game.swngame changes the interpolation doesn't know that it has
JUST changed or anything. So add a kludge variable to fix this
off-by-one.
2020-06-19 09:05:48 -04:00
Misa
df2d8e881e Make player not suddenly stop when screen transitioning
This was especially noticeable in slowmode, where after going to an
adjacent room, it would look like they stopped for a split second. This
commit makes it so they smoothly continue their journey after switching
rooms.

The integer cast is to round off any fractional part of the velocity so
that they don't make a difference and result in the oldxp/oldyp being
one pixel off. Especially since the player's y-velocity fluctuates while
standing unflipped on the floor.

Incidentally enough, this seems to only have been a problem with screen
transitions for some reason. No other uses of gotoroom() (such as the
one where gotoroom() is called every other frame, or every frame) seem
to have resulted in this "pausing" behavior, or at least a reversion
back to 30 FPS movement. I don't know why.
2020-06-19 09:05:48 -04:00
Misa
9256b4da56 Smoothly interpolate "[Press ENTER to return to editor]" fadeout
Now it'll be real smooth at 60 FPS. Or above. Or whichever one you want
above 30.
2020-06-19 09:05:48 -04:00
Misa
5daad95f1d Move "return to editor" alpha timer update to logic functions
Otherwise it'll go by too quickly.

Also something subtle here - I didn't make it conditional on
game.advancetext, so now it'll still decrement even if you have
advancetext up.
2020-06-19 09:05:48 -04:00
Misa
ca9f44c3b8 Smoothly interpolate editor notedelay
This makes editor notes fade out smoothly. And even though the notedelay
only gets decremented by one every editor-frame (the editor runs at
1000/24 FPS fixed-timestep here), it actually gets multiplied by 4, so a
floating-point interpolated value would make a difference here.
2020-06-19 09:05:48 -04:00
Misa
68fe5bd72d Move glitch roomname updating to logic functions
Otherwise they go by so fast that it's basically impossible to see them.
2020-06-19 09:05:48 -04:00
Misa
90280b0f92 Interpolate end picture reveal scroll
This is so it looks smooth at framerates above 30.
2020-06-19 09:05:48 -04:00
Misa
4641b53603 Interpolate gravitron top line extending
Otherwise it'll extend at 30 FPS only which would be kind of jarring.
2020-06-19 09:05:48 -04:00
Misa
91468542a9 Fix ZZT centipedes (or ASCII snakes) zipping around
This is because their oldxp wasn't being updated when they move (or
rather, teleport) and wrap around the screen.

These enemies are ZZT centipedes, but they're referred to as ASCII
snakes in comments in the code.
2020-06-19 09:05:48 -04:00
Misa
82a7ff0357 Fix off-by-one in "- Press ENTER to Teleport -" interpolation
Otherwise it would be clipped off too early, if it was even noticeable
without using slowmode.
2020-06-19 09:05:48 -04:00
Misa
52f4799405 Fix off-by-one in trophy text interpolation
Otherwise it would appear to be clipped off too early, if that was even
noticeable.
2020-06-19 09:05:48 -04:00
Misa
c3df1bcc3f Fix off-by-one in activity zone prompt fading interpolation
Otherwise it would appear to cut off too early when fading away. This is
only noticeable in slowmode, if even that.
2020-06-19 09:05:48 -04:00
Misa
a884bb1dc1 Fix off-by-one in menuoffrender interpolation
Otherwise, when you brought down the quit/pause/teleporter screen, it
would appear to cut off too early.
2020-06-19 09:05:48 -04:00
Misa
11803b0229 Fix colors updating too fast in TITLEMODE/MAPMODE/GAMECOMPLETEMODE
These colors were of the colors of each crewmate, the inactive crewmate
color, and the color of the trinket and clock on the quicksave/summary
screens.

These colors all used fRandom() and so kept updating too quickly because
they would be recalculated every time the delta-timestep render function
got called, which isn't ideal. Thus, I've had to add attributes onto the
Graphics class to store these colors and make sure they're only
recalculated in logic functions instead.

Thankfully, the color used for the sprites on the time trial results
screen doesn't use fRandom(), so I don't have to worry about those.

There's a new version of Graphics::drawsprite() that takes in a pre-made
color already, instead of a color ID. As well, I've also added
Graphics::updatetitlecolours() to update these colors on the title
screen.
2020-06-19 09:05:48 -04:00
Misa
3699adec82 Fix, for in-GAMEMODE sprites, their colors updating too fast
Okay, so the problem here is that Graphics::setcol() is called right
before a sprite is drawn in a render function, but render functions are
done in deltatime, meaning that the color of a sprite keeps being
recalculated every time. This only affects sprites that use fRandom()
(the other thing that can dynamically determine a color is help.glow,
but that's only updated in the fixed-timestep loop), but is especially
noticeable for sprites that flash wildly, like the teleporter, trinket,
and elephant.

To fix this, we need to make the color be recalculated only in the
fixed-timestep loop. However, this means that we MUST store the color of
the sprite SOMEWHERE for the delta-timesteps to render it, otherwise the
color calculation will just be lost or something.

So each entity now has a new attribute, `realcol`, which is the actual
raw color used to render the sprite in render functions. This is not to
be confused with their `colour` attribute, which is more akin to a color
"ID" of sorts, but which isn't an actual color.

At the end of gamelogic(), as well as when an entity is first created,
the `colour` is given to Graphics::setcol() and then `realcol` gets set
to the actual color. Then when it comes time to render the entity,
`realcol` gets used instead.

Gravitron squares are a somewhat tricky case where there's technically
TWO colors for it - one is the actual sprite itself and the other is the
indicator. However, usually the indicator and the square aren't both
onscreen at the same time, so we can simply switch the realcol between
the two as needed.

However, we can't use this system for the sprite colors used on the
title and map screen, so we'll have to do something else for those.
2020-06-19 09:05:48 -04:00
Misa
4c2d219e45 Move big chunky pixel colors to separate function
Again, to make sure colors don't update more than 1000/34 frames a
second, we'll need to separate this color calculation from rendeirng
functions.
2020-06-19 09:05:48 -04:00
Misa
fce56fde09 Move setcol part of drawhuetile() to separate function
In order to make sure colors don't update more than 1000/34 frames per
second, I'll have to move the color-setting part of this function
somewhere else.
2020-06-19 09:05:48 -04:00
Misa
2e17e872e4 Interpolate spikeleveltop and spikelevelbottom
This doesn't have much effect, except for when the spikes quickly move,
because the spikes only usually move at 1 pixel per frame anyway.
2020-06-19 09:05:48 -04:00
Misa
5ff4a09acc Reset spikeleveltop and spikelevelbottom in mapclass::loadlevel()
Just a small thing, but if you teleported out of a tower with the
top/bottom screen spikes being onscreen (by dying, for example), they
would retract once you went back in to a tower. Small little thing, but
it's a good thing to polish.
2020-06-19 09:05:48 -04:00
Misa
92c0f93a6f Move finalstretch animation code to gamelogic()
Otherwise, the tile animations will go too fast. However, the overall
color cycling hasn't been going fast, since it was never in gamerender()
in the first place.
2020-06-19 09:05:48 -04:00
Misa
0e54aa2f51 Set map.ypos when entering tower
To prevent the camera "zipping" when entering a tower.
2020-06-19 09:05:48 -04:00
Misa
fe1045b515 Interpolate tower scrolling
Now tower scrolling will look smooth ayy-eff.
2020-06-19 09:05:48 -04:00
Misa
880465c2e5 Fix credits position being 1 frame off w/ BG when press/release ACTION
When you pressed and released ACTION to speed up the credits, the
credits position would end up being 1 frame off from the background.

This is due to the fact that we update the tower background after we
update the credits position, so this commit moves the tower background
update before the credits position update.
2020-06-19 09:05:48 -04:00
Misa
e1fdfb7cdb Interpolate credits position
So that it's as smooth as possible, especially when holding down ACTION
to make it go really fast.
2020-06-19 09:05:48 -04:00
Misa
b3f7c174ea Fix special text box images sometimes flashing
These special images are the crewmates, Level Complete, and Game
Complete images. They flashed depending on if you were lucky and
happened to got your delta-timesteps just right when text boxes were
fading in and out.

Honestly, I'm surprised text box fading in/out hasn't ran into this
issue before. It's insane luck that this issue hasn't occurred before or
anything.

Well, anyways, to fix this, there's now an attribute `allowspecial` on
text boxes, and an optional parameter of the same name for
Graphics::createtextbox(). This attribute is the only thing that will
let these special text box images render. And any createtextbox()es that
utilize these special images have been updated accordingly.
2020-06-19 09:05:48 -04:00
Misa
27fe7ff8f9 Fix crewmates facing wrong way or not being flipped for <1 frame
By "frame" here I'm referring to the fixed-timestep, not a visual
delta-timestep.

Anyway, the problem is because crewmates' drawframes wait for
entityclass::animateentities() to be called in gamelogic(). In the
old, 30-FPS-only system, this entityclass::animateentities() would be
called in gamerender(), before any actual rendering would take place.
However, I've had to move it out of gamerender() because otherwise
entities would animate too fast. As a result, since gamerender() could
be called in between the entity creation and gamelogic(), a
less-than-1-frame visual glitch could happen.

The solution is to set the entity's drawframe as well when fixing facing
the player in Map.cpp.
2020-06-19 09:05:48 -04:00
Misa
b4142976f2 Move crewframedelay to titlelogic() and maplogic()
Incidentally enough, this de-duplicates the amount of times this code
has been copy-pasted from 4 times to 2.

Anyways, this makes it so the crew don't go lightning fast on the
summary screen, the NDM game-over screen, the NDM win screen, and the
pause screen in the main game. It was slightly hilarious seeing them go
really quickly, actually. It was like they were running away from a
giant monster or something.
2020-06-19 09:05:48 -04:00
Misa
1d669dffeb Interpolate "- Press ENTER to Teleport -" prompt
This is only really noticeable in slowmode, but if you're playing in
slowmode it'll be pretty smooth.
2020-06-19 09:05:48 -04:00
Misa
dcc9520d8f Interpolate trophy text
Just to make sure it's extra smooth. Not that it will be noticeable, and
you can't access the Secret Lab in slowmode without modifying the game,
but it's nice to have this.
2020-06-19 09:05:48 -04:00
Misa
a69bb84eaf Interpolate all-sides warp BG
Again, it was only noticeable at 40% speed that it updated at 1000/34
FPS before.
2020-06-19 09:05:48 -04:00
Misa
66ac035576 Move all-sides warp background update code to logic functions
Otherwise it'll go by really fast and rapidly pulsate. To the point
where it seems like it would be an epilepsy trigger, although I
wouldn't know anything about epilepsy other than that it's bad.
2020-06-19 09:05:48 -04:00
Misa
8184a392eb Interpolate tower background
Ok, now THIS takes the cake for "only really noticeable in slowmode",
because it only ever moves at 1 pixel per second. And even then,
slowmode shouldn't apply on the title screen, so it won't even show up
there once I get around to doing that change.
2020-06-19 09:05:48 -04:00
Misa
118401f17e Move tower background update code to logic functions
Otherwise it'll go really really quickly, which is not good.
2020-06-19 09:05:48 -04:00
Misa
7810e99507 Interpolate vertical warp background
So it'll look very smooth. Again, only really noticeable in slowdown
(although I could kind of tell the difference at full speed).
2020-06-19 09:05:48 -04:00
Misa
921960d23a Move vertical warp background updating to Graphics::updatebackground()
Otherwise it will zoom by pretty quickly.
2020-06-19 09:05:48 -04:00
Misa
c7d3a684ea Interpolate horizontal warp BG
So that it's really, really smooth. Only noticeable in slowdown mode,
though.
2020-06-19 09:05:48 -04:00
Misa
c9c55d0c8b Move horizontal warp background to Graphics::updatebackground()
This is so the background doesn't NYOOOOM past at light speed. Although
for a game set in space like VVVVVV, light speed ain't bad.

And this finally requires that editorlogic() have a call to
Graphics::updatebackground().
2020-06-19 09:05:48 -04:00
Misa
9d104b68ee Simplify "else if" braces and indentation in activity prompt rendering
No need for it to be inside another whole indented block if it's just an
"else if".
2020-06-19 09:05:48 -04:00
Misa
f53ed222d3 Interpolate activity zone prompt fading in and out
To make it real smooth, just in case it was noticeable that it only
updated at 1000/34 FPS before (well, except in slowmode, it's really
noticeable THERE).

Also this removes the re-typing out of (game.act_fade/10.0f) for every
single R, G, and B in gamerender().
2020-06-19 09:05:48 -04:00
Misa
c56df48d75 Interpolate text box alpha
This makes text boxes fade in and out pretty smoothly.

This requires that the textboxclass::setcol() be in Graphics::drawgui(),
so now it's moved there.

Text box fading is only really noticeable if you're playing in slowmode.
2020-06-19 09:05:48 -04:00
Misa
4ba9954eb8 Move cursor delay update logic to maplogic()
Otherwise it'll go really really fast.

Incidentally this also basically de-duplicates it and results in less
copy-pasted code overall.
2020-06-19 09:05:48 -04:00
Misa
837ccfc735 Move gravity line color updating to gamelogic()
So it doesn't keep updating really quickly.
2020-06-19 09:05:48 -04:00
Misa
40cedc8c94 Move general oldxp/oldyp updating to just before gameinput()
This has to be done in order to fix rendering when on a conveyor or
moving platform and actively moving with or against it. Pretty sure this
shouldn't break anything, oldxp/oldyp is mostly visual after all (and by
the time it's used for gravity line collision checking,
updateentitylogic() would've already gotten around to it anyway).

Incidentally, this also fixes a jitter that would occur if you were
moving at the time you died or collected a trinket or custom crewmate,
due to the game temporarily freezing and either doing deathsequence or
completestop.
2020-06-19 09:05:48 -04:00
Misa
3b41721563 Interpolate bringing up and down quit/pause/teleporter screen
Now it's really, really smooth. Except for like the last frame when it
goes down, which I sometimes didn't notice (but maybe it didn't happen
every time due to being lucky on the delta timesteps or something,
whatevs.)
2020-06-19 09:05:48 -04:00
Misa
45c7292096 Simplify menu-off rendering/logic code
Since "if (graphics.resumegamemode)" and "if (menuoffset > 0)" both do
the same thing, they've been combined with an "or" conjunction.

As well, the map.extrarow check in maplogic() has been refactored to use
a variable instead of duplicating the entire code block. Not that it
matters anyway, because the difference between 240 and 230 is only 10
pixels, far short of the 25 pixel increment that bringing the menu up
and down uses, and both 240 and 230 integer-divided by 25 have the same
non-remainder value of 9.
2020-06-19 09:05:48 -04:00
Misa
a22a872886 Move menu offset logic to maplogic()
This is the logic that handles the timer that brings up and down the
teleporter, pause screen, and Esc screen. So now it doesn't go crazy
fast.
2020-06-19 09:05:48 -04:00
Misa
9ea5734abb Move backboxrect off of Graphics
No need for a temporary rect to be on the Graphics class itself.
2020-06-19 09:05:48 -04:00
Misa
4e533c65a5 Interpolate upwards-moving star BG
So that it's smooth at full FPS.
2020-06-19 09:05:48 -04:00
Misa
3b09bb36e8 Move upwards-moving star BG to Graphics::updatebackground()
So it doesn't go really really quick.
2020-06-19 09:05:48 -04:00
Misa
61d2526669 Put rainbow BG timer in Graphics::updatebackground()
Otherwise it'll go way too fast.
2020-06-19 09:05:48 -04:00
Misa
684aa38ff2 Interpolate Lab backboxes
So that they look buttery smooth.
2020-06-19 09:05:48 -04:00
Misa
1c38b63a37 Move Lab backbox updates to Graphics::updatebackground()
So that the backboxes don't go NYOOOOOOOOM.
2020-06-19 09:05:48 -04:00
Misa
92cd695859 Interpolate left-moving star background
So that it looks all smooth and such.
2020-06-19 09:05:48 -04:00
Misa
55ae3c73a9 Update left-moving star BG in fixed timestep loop
Otherwise they will move too fast.
2020-06-19 09:05:48 -04:00
Misa
495bea2e87 Update text boxes in the inner fixed-timestep loop
So they don't go really quickly.
2020-06-19 09:05:48 -04:00
Misa
4e3406d5aa Remove useless function Graphics::textboxcleanup()
It was made useless after my refactor to remove the 'active' system from
text boxes.
2020-06-19 09:05:48 -04:00
Misa
905696c263 Update trophy text timer in fixed-timestep gamelogic()
Otherwise it, too, goes by too quickly.
2020-06-19 09:05:48 -04:00
Misa
92ee33043d Update activity prompt fade in fixed-timestep gamelogic()
Otherwise it goes by too quickly.
2020-06-19 09:05:48 -04:00
Misa
e897543383 Interpolate fade amount
This makes the fadeouts and fadeins (screenwipes) much more buttery
smooth.
2020-06-19 09:05:48 -04:00
Misa
8fde6f28a3 Update screenshake position in fixed-timestep loop
Otherwise the screen will shake too fast for my liking.

Also I'm planning to add an FPS limiting option later (because right
now, un-capping the FPS is pretty wasteful and eats up lots of
resources, especially since I have only a 60hz monitor), and it'd feel
weird if screen shaking updated every delta timestep.
2020-06-19 09:05:48 -04:00
Misa
57f87dc820 Reduce indentation of "else if" in Graphics::cutscenebars()
There's no need to put the if-statement inside an entire else-block if
it's the only if-statement in there.
2020-06-19 09:05:48 -04:00
Misa
2510d3a6ba Interpolate cutscene bars position
Cutscene bars will now smoothly fade in and out at above 30 FPS instead
of at 30 FPS only.
2020-06-19 09:05:48 -04:00
Misa
6655ae418c Update cutscene bars in fixed-timestep loop
This prevents cutscene bars from going really really fast.
2020-06-19 09:05:48 -04:00
Misa
a479c61141 Simplify "else if" indentation for right-side tower screen wrapping
No need to make an entire else-block and indent it when you can just do
"else if" instead.
2020-06-19 09:05:48 -04:00
Misa
a7b62d1098 Update oldxp/oldyp when screen wrapping
This is so it doesn't look like entities "zip" across the room.
2020-06-19 09:05:48 -04:00
Misa
f06ca9172a Set drawframe to tile when creating an entity
This fixes entities being drawframe 0 for 1 frame when being first
created. Incidentally, this also fixes entities created during
completestop being the player sprite, too, which is something not many
people notice.
2020-06-19 09:05:48 -04:00
Misa
298aa95259 Move onground/onroof/animateentities logic to start of gamelogic()
For some reason, it was put near the start of gamerender(), even though
since it handles edge-flipping it seems like it should be in the logic
function already.

This makes sure entity animations don't animate as fast as possible, and
also fixes edge-flipping on normal surfaces.
2020-06-19 09:05:48 -04:00
Misa
57b643d22a Use case-switch for para-check in entclass::setenemy()
It's less verbose this way, and less typing.
2020-06-19 09:05:48 -04:00
Misa
c6659ef656 Initialize oldxp/oldyp in createentity()
This prevents undefined behavior because we use oldxp/oldyp to do linear
interpolation.

It's also initialized in entclass::entclass(), just to be sure. And I've
deduplicated the regular xp/yp initialization in createentity(), too.
2020-06-19 09:05:48 -04:00
Misa
4f4d400ce0 Add linear interpolation of rendered entities
I've added a function Graphics::lerp() which simply interpolates between
two values given a certain alpha value. It's just like drawing a
straight line between two points.

Also, Graphics now has an `alpha` attribute, and it is set on every
deltatime update to be used in linear interpolation.
2020-06-19 09:05:48 -04:00
Misa
fd44098f38 Move render functions to outer deltatime loop
Ok, and this is where the fun starts.

In an ideal world, this would be the end of this patch. However, of
course, there are many, MANY places in the game that update
fixed-timestep timers DIRECTLY inside the render function, which is not
ideal because it means those timers go super fast.

I'll have to fix those later.
2020-06-19 09:05:48 -04:00
Misa
c63036fcd3 Indent timestep loop
Ok, NOW indent it. I didn't indent it previously because the diffs are
annoying to read if there's an indent that doesn't otherwise change
anything (and even now it's pretty annoying to read).
2020-06-19 09:05:48 -04:00
Misa
e2fe2d4c2b Replace SDL_Delay() with an accumulator
Alright, this is the start of the over-30-FPS patch!

First things first, we'll need to make it possible to have a separate
deltatime loop outside of the fixed timestep loop. And for that, we
can't be using SDL_Delay(), as SDL_Delay() (as you might imagine) blocks
the whole program.

Instead we'll be using this thing called an accumulator. It looks at how
long the previous poll took (the raw deltatime), and lets timesteps pass
accordingly.

On a side note, I've had to split the `time` and `timePrev` declaration
each onto their own separate line, otherwise there's undefined behavior
from `time` not being initialized.

I use `accumulator = fmodf(...)` instead of `accumulator -=
timesteplimit` because otherwise it'll fast-forward if it's behind,
which is a jarring thing to see.

Also in preparation for what's going to come down the over-30-FPS road,
I've also added `deltatime` and `alpha`. `deltatime` is going to be used
if the game is in slowdown mode, and `alpha` is going to be used for
linear interpolation of animations.

By the way, what was the main game loop previously (and is now the new
timestep loop) is now in an extra set of curly braces, but I haven't
indented it yet to reduce the noise in this commit.
2020-06-19 09:05:48 -04:00
Misa
62441edbc9 Account for hours when calculating time trial result time
This prevents being able to "roll over" the amount of minutes to 0 (by
simply waiting for the timer to tick past one hour) and being able to
get a result of 00:13 when your result is really 01:00:13.

By looking only at the minutes, the game would read 01:00:13 as 00:13
instead. So simply add the amount of hours to the time trial result.
2020-06-18 08:42:15 -04:00
Misa
0ee5c07f4a Add #define _POSIX_SOURCE
This is needed for MinGW when compiling C++98, apparently. I put it in
an if-guard because otherwise there'll be a warning from MY compiler
about redefinitions.
2020-06-17 19:15:07 -04:00
Misa
3428d962b3 Add #define __STDC_FORMAT_MACROS
This define is needed in order for the SCNx32/SCNu32 in find_tag() to be
compiled correctly on older `glibc`s.
2020-06-17 19:15:07 -04:00
AllyTally
5e43a44d9a Add 7x7, 9x9, full horizontal and vertical brush sizes 2020-06-17 19:13:48 -04:00
AllyTally
d7dac6b9be Allow using Warp Zone gray tileset in editor
Originally written by Info Teddy
2020-06-17 17:20:43 -04:00
Misa
fc265e3c75 Fix unmounting assets exiting to menu resulting in silence
If you exited to the menu normally (i.e. got on a code path that went
through Game::quittomenu()), the menu music wouldn't play. This is
because FILESYSTEM_unmountassets() was put after music.play(6). So the
game would play the custom level's track 6, and then unmount it, which
meant it could no longer play track 6, but there's nothing telling the
game to play track 6 again. So I just changed the frame ordering around.

I also added a comment to make sure anyone reading the code is aware of
the frame order dependency.
2020-06-17 06:02:26 -04:00
Misa
44bd4ec0b7 Fix custom assets not being unmounted when exiting from editor/credits
If you exited from the editor, custom assets would not be unmounted. But
I made sure to put the FILESYSTEM_unmountassets() before the
music.play(6) because otherwise the menu music wouldn't play.

You could also exit to the menu from a custom level using the
rollcredits() command, so I made sure to put a
FILESYSTEM_unmountassets() when returning to the menu from the credits
as well. I also made sure to put it before the music.playef(18) so
there's no risk of the sound effect not playing properly, or not playing
the non-level-specific one.

I added a comment to both FILESYSTEM_unmountasset()s to make sure anyone
reading the code is aware of the frame order dependency.
2020-06-17 06:02:26 -04:00
Misa
f9dfae0144 Hardcode fix for next-line </edentity>
This is really awful, but there's not much we can do.

TinyXML-2 no matter what will never stop on newlines, so without
changing the XML parser, this is the best we can do - just remove the
"\n            " (that's a linefeed plus exactly 12 spaces) if it
appears at the end of the contents of an edentity tag.

Also a giant comment for good measure.
2020-06-16 21:44:57 -04:00
Misa
bc9f21d7f8 Revert "Fix loading levels saved with 2.2 or earlier"
This reverts commit c2c0644453.

The correct solution for this wasn't to set the whitespace mode to
COLLAPSE_WHITESPACE.
2020-06-16 21:44:57 -04:00
Misa
9a8dc4b6ff Only remove duplicate player entities in scriptclass::hardreset()
Looks like duplicate player entities persisting across rooms is a
semi-useful feature used by some levels. Still, though, it's a bit of a
nuisance to have duplicate player entities persisting across game
sessions. And levels can't rely on this persistence anyway, anyone could
just close the game and re-open it to get rid of the duplicate entities
regardless.
2020-06-15 21:30:39 -04:00
Misa
a8cedd2f91 Prevent out-of-bounds indexing with trinket/crewmate IDs
If a trinket or crewmate ID is out-of-bounds, it will not be created.
This is not only because the `collect`/`customcollect` check in
entityclass::createentity() would then be out-of-bounds, but also
touching it would also be out-of-bounds, too.

Display trinkets will always be created if the ID is out-of-bounds.
Apparently some people (@AllyTally) have been creating display trinkets
with IDs of -1 in order to get a display trinket that always shows up,
which is rather horrifying. But it makes sense, there's a lot more
nonzero int values than there are the amount of int values that are
zero, so it's fairly likely that the `collect` check will always come up
to be true (nonzero). Also, it's more useful to be able to have a
display trinket that always shows up without having to collect a trinket
beforehand, than it is to have it not be created (because technically by
default, you're already in the world where you don't have it created).

Display trinkets still have their `para` set to their ID, though, and if
they managed to gain an `onentity` of 1, bad things could happen... So
just to be sure, I added INBOUNDS checks to crewmates and trinkets in
entityclass::updateentities() so no UB will happen if you collect a
crewmate/trinket with an out-of-bounds ID. Also, I de-duplicated the
`collect`/`customcollect` setting, too.
2020-06-15 21:28:21 -04:00
Terry Cavanagh
9de61c5b76
Merge pull request #293 from InfoTeddy/general-improvements
Make elephant not be flashy if screen effects are disabled
2020-06-16 11:15:08 +10:30
leo60228
a99e976402 Support hex entities in metadata 2020-06-15 20:32:10 -04:00
Misa
529c7bae23 Make elephant not be flashy if screen effects are disabled
The flashy color of the elephant can be hard on people's eyes,
especially if they're the type who want screen effects disabled because
they might have epilepsy. The elephant takes up a good 3/4ths of the
screen, you know. If screen effects are disabled, the elephant will use
color 22, which is a neutral gray.

I'm only adding this because the VVVVVV speedrun mods (@tzann, @mohoc)
invalidate all runs that have the elephant texture removed, even though
many people would be looking at a potentially epilepsy-inducing image
many times a day grinding 100% speedruns. (Imo, their justification for
this is flimsy at best.)
2020-06-15 15:19:50 -07:00
Ethan Lee
f0ec627628 Sigh. 2020-06-15 07:37:05 -04:00
Ethan Lee
3323b7e3cf Maybe check the right size m8 2020-06-14 22:44:34 -04:00
Ethan Lee
bd71fb8a68 Disallow negative size values in BinaryBlob 2020-06-14 22:43:58 -04:00
Ethan Lee
4894639b3a valid needs to have either exactly 1 or 0 2020-06-14 22:40:57 -04:00
Ethan Lee
06a71bab18 Some sanity checks for BinaryBlob header data 2020-06-14 22:39:06 -04:00
Misa
33fd589616 Fix time trial result displaying 00:60 instead of 01:00
If your time was exactly 60 seconds, it would display 00:60 instead of
01:00.
2020-06-14 21:51:41 -04:00
Misa
b53d2ae53f Remove i/j/k attributes from classes that don't need them
The only class that actually needs its i/j/k kept is scriptclass,
because some custom levels rely on it for creating custom activity
zones. So I haven't touched that.

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

Interestingly enough, otherlevelclass and towerclass have unused i/k
variables for whatever reason.
2020-06-14 14:37:29 -04:00
Misa
1f360620cf Add inspecial() checks to savetele() and savequick()
This prevents the game from being saved if you manage to trigger a
savetele() during a "special" gamemode (like if you use the Gravitron
out-of-bounds glitch when replaying Intermission 2, then go to Game
Complete that way).
2020-06-14 07:24:28 -04:00
Misa
93a67bd357 Add Game::inspecial()
It's a function marked for inline that's just a simple shorthand,
because I don't want to type all of those conditionals out.
2020-06-14 07:24:28 -04:00
Misa
da1b58d771 Override custommode if in finalmode when drawing tilesvec
When in finalmode, custommode shouldn't take priority, as finalmode is
main game stuff.
2020-06-13 22:31:12 -04:00
Misa
2d49988f5d Fix indexing out-of-bounds with font printing functions
If you don't have a font.txt, it could happen that a font index is
requested that's out-of-bounds. And that would result in a segfault. So
to fix that I'm adding INBOUNDS checks to all functions that index the
fontmap.
2020-06-13 22:31:12 -04:00
Misa
3b0ec54164 De-duplicate flip mode code with font printing functions
Wow, all 9 functions in total have copy-pasted flip mode code! Glad I
cleaned all that up.
2020-06-13 22:31:12 -04:00
Misa
031402e4bb Fix indexing out-of-bounds with miscellaneous images
This fixes indexing out-of-bounds in the functions that draw all the
special images such as the elephant and teleporters. Let's make sure the
game doesn't segfault.
2020-06-13 22:31:12 -04:00
Misa
d03d8afedf Fix indexing out-of-bounds via tile numbers
If a graphics function was provided an out-of-bounds tile number, it
would happily segfault the game. So I'm adding checks to prevent that.
2020-06-13 22:31:12 -04:00
Misa
5195299e65 Fix indexing out-of-bounds via an entity's drawframe
I tracked down all the functions that took in an entity's drawframe and
made sure that no matter what value an entity's drawframe was, the game
would never segfault.
2020-06-13 22:31:12 -04:00
Misa
6900553f57 Add INBOUNDS macro
I mean, I probably should've done this earlier, but using this saves on
typing and improves readability.
2020-06-13 22:31:12 -04:00
Misa
a922420066 De-duplicate flipmode check in entityclass::entitycollisioncheck()
To deal with using a different image file for Flip Mode, it looks like
copy-paste was used. This isn't exactly maintainable code. So I'm
replacing it with a reference that changes depending on if the game is
in Flip Mode or not, instead.
2020-06-13 22:31:12 -04:00
Misa
4f50883d58 Prevent removing the player entity
Removing the player entity has all sorts of nasty effects, such as
softlocking the game because many inputs require there to be a player
present, such as opening the quit menu.

The most infamous glitch to remove the player entity is the Gravitron
Fling, where the game doesn't see a gravity line at a specific
y-position in the current room, and when it moves the bottom gravity
line it moves the player instead. When the gravity line gets outside the
room, it gets destroyed, so if the player gets dragged outside the room,
they get destroyed, too. (Don't misinterpret this as saying anytime the
player gets dragged outside the room, they get destroyed - it's only the
Gravitron logic that destroys them.)

Also, there are many places in the code that use entity-getting
functions that have a fallback value of 0. If it was possible to remove
the player, then it's possible for this fallback value of 0 to index
obj.entities out-of-bounds, which is not good.

To fix this, entityclass::removeentity() is now a bool that signifies if
the entity was successfully removed or not. If the entity given is the
player (meaning it first checks if it's rule 0, just so in 99% of cases
it'll short-circuit and won't do the next check, which is if
entityclass::getplayer() says the indice to be removed is the player),
then it'll refuse to remove the entity, and return false.

This is a change in behavior where callers might expect
entityclass::removeentity() to always succeed, so I changed the
removeentity_iter() macro to only decrement if removing the entity
succeeded. I also changed entityclass::updateentities() from
'removeentity(i); return true;' to 'return removeentity(i);'.
2020-06-13 15:41:44 -04:00
Misa
51d852601d Remove passing around pointer to gameScreen from KeyPoll::Poll()
Makes for cleaner code this way.
2020-06-13 14:50:33 -04:00
Misa
30bcc08bec Move gameScreen off of the stack and onto the heap
Just so it can be properly used globally like all the other classes.
2020-06-13 14:50:33 -04:00
Misa
60a2e100fc Fix 'if (key.resetWindow)' indentation
It was being indented with tabs instead of spaces.
2020-06-13 14:50:33 -04:00
Ethan Lee
a15d01ad80 Fix fullscreen focus behavior 2020-06-13 10:35:05 -04:00
Ethan Lee
506628cef1 Revert "Fix unfocusing the game while in fullscreen mode"
This reverts commit c322ae131e.
2020-06-13 10:23:52 -04:00
Misa
884035fd2e Add unsigned char static_cast to argument of std::isdigit()
Apparently it results in Undefined Behavior if the argument given isn't
representable as an unsigned char. This means that (potentially) plain
char and signed chars could be unsafe to use as well.

It's rare that this could happen in practice, though. std::isdigit() is
only used by is_positive_num() which is only used by find_tag(), so
someone would have to deliberately put something crazy after an `&#` in
a custom level file in order for this to happen. Still, better to be
safe than sorry and all.
2020-06-13 01:25:17 -04:00
Misa
fdb44cc209 Add <cctype> include
This fixes a compile error that could happen where the compiler doesn't
know what std::isdigit() is, but I'm puzzled as to why this wasn't
happening earlier, 'cause I've only been reported that it happens by
only one person.
2020-06-13 01:25:17 -04:00
Misa
14afae1a40 Add bounds checks to script commands that didn't have them
Continuing from #280, another potential source of out-of-bounds indexing
(and thus, Undefined Behavior badness) comes from script commands. A
majority of them don't do any input validation at all, which means the
potential for out-of-bounds indexing and segfaulting in custom levels.
So it's always good to add bounds checks to them.

Interesting note, the only existing command that has bounds checks is
the flag() command. That means you can't turn out-of-bounds flags on or
off. But there's no bounds checks for ifflag(), or customifflag(), which
means you CAN index out-of-bounds with those commands! That's a bit bad
to do, so.

Also, I decided to add the bounds checks for playef() at the
musicclass::playef() level, instead of just the level of the playef()
command. I don't know of any other cases outside of the command where
musicclass::playef() will index out of bounds, but musicclass is the one
containing the indexed vector anyway, I wanted to cover more cases, and
it's better to be safe than sorry.
2020-06-13 01:24:42 -04:00
Misa
fdce412680 Guard all cases obj.getcompanion() is used unchecked
And this the function with the least amount of cases where its sentinel
value is used unchecked. Thankfully. obj.getplayer() was a bit of a slug
to get through.
2020-06-12 23:55:48 -04:00
Misa
beab344267 Guard all cases obj.getplayer() is used unchecked
obj.getplayer() can return -1, which can cause out-of-bounds indexing of
obj.entities, which is really bad. This was by far the most changes, as
obj.getplayer() is the most used entity-getting function that returns
-1, as well as the most-used function whose sentinel value goes
unchecked.

To deal with the usage of obj.getplayer() in mapclass::warpto(), I just
added general bounds checks inside that function instead of changing all
the callers.
2020-06-12 23:55:48 -04:00
Misa
08e47e839f Guard all cases obj.getteleporter() is used unchecked
obj.getteleporter() is able to return -1. If there's no check on it, it
will end up indexing out-of-bounds, which is Undefined Behavior.
2020-06-12 23:55:48 -04:00
AllyTally
3b76713441 Only add editor ghosts if the editor exists 2020-06-12 19:11:48 -04:00
AllyTally
5c80a4c25e Remove another header initialization 2020-06-12 19:11:48 -04:00
AllyTally
d740205138 Don't initialize game.gametimer in the header file
That's a C++ thing apparently.
2020-06-12 19:11:48 -04:00
AllyTally
805992a1e1 Fix mixed indentation
The editors I use replace tabs with spaces, so I never really thought about mixed indentation happening. Whoops.
2020-06-12 19:11:48 -04:00