Commit Graph

1950 Commits

Author SHA1 Message Date
Misa b114be88d5 Disable final color animations if screen effects off
Similar to disabling the elephant flashiness, at least one
photosensitive person has told me the flashy color animation makes their
eyes kind of hurt a little bit. Also it screws up the compression really
badly when they record (especially the green noisy tiles!).

The colors will still cycle, but the individual animations within each
color will be completely static.
2021-08-07 19:22:00 -04:00
Misa 1841f1886a Do not close game if fallback character is missing
It's quite rude to close the game. Especially if the user does not use
the console. They won't know why the game closed.

Instead, just return -1. All usages of font_idx() should be and are
bounds checked anyways. This will result in missing characters, but,
it's not like the characters had a font image in the first place,
otherwise we wouldn't be here. And if the user sees a bunch of
characters missing in their font, they'll probably work out what the
problem is even without having a console. And it's still far better than
abruptly closing the game.

And use WHINE_ONCE to prevent spamming the console.
2021-08-07 13:09:05 -04:00
Misa 3094ddb8f3 Enforce semicolons after usage of WHINE_ONCE
For consistency.

Since WHINE_ONCE ends with a block, the only way to make the compiler
enforce it is to end it with a `do { } while (false)`.
2021-08-07 13:09:05 -04:00
Misa 4a07e98015 Zips: Don't print redundant message if file not found
Let's say you have a zip named LEVELNAME.zip, but the only .vvvvvv file
it contains is NOTLEVELNAME.vvvvvv. This zip would end up printing both
the 'LEVELNAME.vvvvvv is missing' and 'It has .vvvvvv file(s) other than
LEVELNAME.vvvvvv' messages, even though we already know there's
something wrong with the zip, and the 'other level files' message is
redundant, since in this case the problem here is simply just the
.vvvvvv file being named the wrong way.

The 'other level files' message is only intended to be printed when
LEVELNAME.vvvvvv *does* exist, but there's additional .vvvvvv files in
the zip on top of that, so don't print this message if LEVELNAME.vvvvvv
exists.
2021-08-07 13:04:19 -04:00
Misa 8f70cb8667 Fix regression with chunky pixels being the wrong color
Since colors going into FillRect() need to be in BGR format, we need to
use getBGR instead. (Well, actually, it gets passed in RGB, but then at
some point the order gets switched around, and, really, this game's
masks are all over the place, I'm going to fix that in 2.4.)
2021-08-05 22:57:41 -04:00
Misa 45dd7c39b7 Fix cycling title BG more than once per frame
This can happen if you select an option in a menu that (A) returns to
the previous menu and (B) saves settings. If the settings save fails,
this will create another menu on the same frame that cycles the tower BG
after it's already been cycled for that frame. Examples are the slowdown
and glitchrunner menus.

I could fix this by creating a new function that copy-pastes all of
Game::savestatsandsettings_menu() except for the map.nexttowercolour()
at the end. But that's copy-pasting code.

Instead what I've done is added a variable to signal if the color has
already been cycled this frame, so we don't cycle it again. This also
covers cases of possible double-cycling in the future as well.
2021-08-05 21:42:59 -04:00
Misa b9202dee8b Fix frame flickers when fading during loads/exits
This is because the fade delay did not last long enough.

I was under the mistaken impression that the fade animation lasts for 15
frames. However, this does not account for the fact that the offset of
each fade bar is dependent on RNG, and the worst case scenario is that
they have an offset of 96 pixels (in the opposite direction of the
fade).

The actual fade animation timer accounts for the worst case scenario, so
the fade animation actually lasts for (320 pixels plus 96 pixels is 416
pixels, 416 pixels divided by 24 pixels per frame equals 17.333...
frames, but since the actual timer keeps adding/subtracting 24 pixels
per frame until it passes the 416-pixel threshold, that gets rounded up
to...) 18 frames.

And an extra frame to make it so deltaframe interpolation doesn't
suddenly stop on the last deltaframes before the screen is completely
black.

I also need to draw the screen black on the map screen when glitchrunner
mode is off, if there's a fadeout going on. Else that would introduce
yet another frame flicker.
2021-08-05 19:12:23 -04:00
Misa 90660d67a7 Fix trailing whitespace introduced by lssa
No comment.
2021-08-05 19:12:23 -04:00
lsaa 6c66f7248d
Add in-game timer option (#790) 2021-08-05 17:31:20 -04:00
Misa 6c6d347ccf Always reset player when starting gamemode
This fixes a bug where the player would always be facing right if they
were loading in for the first time. This essentially made them always
ignore the facing direction set in the save file if the facing direction
was leftwards.

The problem is facing direction only gets set in map.resetplayer(), but
if loading in for the first time, that path is never taken (unless you
are loading a main game quicksave that's inside a tower). The solution
is to always reset the player, even after creating them for the first
time.
2021-08-05 17:30:25 -04:00
Misa 0dda1ca5e4 Save stats when setting stat_trinkets
This ensures that if the game crashes afterwards, the new stat_trinkets
value won't be lost.
2021-08-05 17:22:39 -04:00
Misa e184923667 Don't take editor input when fading out
This fixes being able to re-trigger the fadeout while a fadeout is
already happening. It also fixes being able to enter playtesting during
the fadeout, which means the level now has a fadeout you normally can't
do in actual gameplay.
2021-08-05 17:22:20 -04:00
Misa 48a1c7ee61 Don't lerp when drawing all-sides warp background
There's nothing to interpolate. It moves at one pixel per frame. And
interpolating sometimes results in the box being short by 1 pixel to
cover the whole screen on deltaframes, so if you stand on the right edge
of the screen and have a translucent sprite, it will quickly draw over
itself many times, and it looks glitchy. This commit fixes that bug.
2021-08-05 16:44:44 -04:00
Misa be69d76f4f Play Viridian squeak when exiting to menu
For consistency.
2021-08-05 14:56:19 -04:00
Misa 243f9b92f8 Split glitchrunner mode into multiple versions
Previously, turning glitchrunner mode on essentially locked you to
emulating 2.0, and turning it off just meant normal 2.3 behavior. But
what if you wanted 2.2 behavior instead? Well, that's what I had to ask
when a TAS of mine would desync in 2.3 because of the two-frame delay
fix (glitchrunner off), but would also desync because of 2.0 warp lines
(glitchrunner on).

What I've done is made it so there are three states to glitchrunner mode
now: 2.0 (previously just the "on" state), 2.2 (previously a state you
couldn't use), and "off". Furthermore, I made it an enum, so in case
future versions of the game patch out more glitches, we can add them to
the enum (and the only other thing we have to update is a lookup table
in GlitchrunnerMode.c). Also, 2.2 glitches exist in 2.0, so you'll want
to use GlitchrunnerMode_less_than_or_equal() to check glitchrunner
version.
2021-08-05 13:35:21 -04:00
Misa b09d0c48e4 Play Viridian squeak when pressing Esc in teleporter menu
For consistency, this should be done to match pressing Esc on the map
screen.
2021-08-05 13:33:17 -04:00
Misa 80dda53603 Play Viridian squeak when returning to Super Gravitron
For consistency.
2021-08-05 13:21:02 -04:00
Misa c0e11d65f2 Play Viridian squeak when returning to Secret Lab
For consistency.
2021-08-05 13:20:51 -04:00
Misa f3ca4ab2e7 Fix generateBase36 generating more than base 36
Two problems: the fRandom() range was from 0..36, but that's 37
characters, not 36. And the check to sort the lower 26 values into the
Latin alphabet used a 'lesser-than-or-equal-to 26' check, even though
that checks for the range of values of 0..26, which is 27 letters, even
though the alphabet only has 26 letters. So just drop the equals sign
from that check.
2021-08-05 08:58:54 -04:00
Misa db76735c07 Fix zip structure checks checking for wrong filename
It was checking for .vvv-mnt-temp-XXXXXX/LEVELNAME.vvvvvv instead of
LEVELNAME.vvvvvv. When PhysFS enumerates the folder, it only gives us
LEVELNAME.vvvvvv, and not .vvv-mnt-temp-XXXXXX/LEVELNAME.vvvvvv.
2021-08-05 08:58:23 -04:00
Misa 3ca7b09012 Fix regression: quick stopping changing drawframe
This fixes a regression that desyncs my Nova TAS after re-removing the
1-frame input delay.

Quick stopping is simply holding left/right but for less than 5 frames.
Viridian doesn't decelerate when you let go and they immediately stop in
place. (The code calls this tapping, but "quick stopping" is a better
name because you can immediately counter-strafe to stop yourself from
decelrating in the first place, and that works because of this same
code.)

So, the sequence of events in 2.2 and previous looks like this:

- gameinput()
  - If quick stopping, set vx to 0
- gamerender()
  - Change drawframe depending on vx
- gamelogic()
  - Use drawframe for collision (whyyyyyyyyyyyyyyyyyyyyyyyyyyy)

And now (ignoring the intermediate period where the whole loop order was
wrong), the sequence of events in 2.3 looks like this:

- gamerenderfixed()
  - Change drawframe depending on vx
- gamerender()
- gameinput()
  - If quick stopping, set vx to 0
- gamelogic()
  - Use drawframe for collision (my mind has become numb to pain)

So, this means that all the player movement stuff is completely the
same. Except their drawframe is going to be different.

Unfortunately, I had overlooked that gameinput() sets vx and that
animateentities() (in gamerenderfixed()) checks vx. Although, to be
fair, it's a pretty dumb decision to make collision detection be based
on the actual sprites' pixels themselves, instead of a hitbox, in the
first place, so you'd expect THAT to be the end of the dumb parade. Or
maybe you shouldn't, I don't know.

So, what's the solution?

What I've done here is added duplicates of framedelay, drawframe, and
walkingframe, for collision use only. They get updated in gamelogic(),
after gameinput(), which is after when vx could be set to 0.

I've kept the original framedelay, drawframe, and walkingframe around,
to keep the same visuals as closely as possible.

However, due to the removal of the input delay, whenever you quick stop,
your sprite will be wrong for just 1 frame - because when you let go of
the direction key, the game will set your vx to 0 and the logical
drawframe will update to reflect that, but the previous frame cannot
know in advance that you'll release the key on the next frame, and so
the visual drawframe will assume that you keep holding the key.

Whereas in 2.2 and below, when you release a direction key, the player's
position will only update to reflect that on the next frame, but the
current frame can immediately recognize that and update the drawframe
now, instead of retconning it later.

Basically the visual drawframe assumes that you keep holding the key,
and if you don't, then it takes on the value of the collision drawframe
anyway, so it's okay. And it's only visual, anyway - the collision
drawframe of the next frame (when you release the key) will be the same
as the drawframe of the frame you release the key in 2.2 and below.

But I really don't care to try and fix this for if you re-enable the
input delay because it's minor and it'd be more complicated.
2021-07-28 20:11:16 -04:00
treacherousfiend f77723d12f Update project generation snippet
The project generation code snippet currently still references SDL2 2.0.10 even though building now requires 2.0.14, just a minor nitpick on my part.
2021-07-25 14:36:51 -04:00
Misa 95ffc3a62b Fix wrong bounds check when colliding with activity zones
I am so stupid.
2021-06-26 15:59:17 -04:00
Misa 88d31ab3b6 Custom levels: only count inbounds trinkets/crew
In the past, people have reported having glitched levels where they
can't get the trinket star or can't complete the level because the
number of trinkets or crewmates is one higher than what can be obtained
in the level.

How did this happen? Well, it turns out that if you place an entity, and
then resize the level to be smaller, that entity still exists. This is
inconsequential for most entities, but if the entity is a trinket or
crewmate, that entity is still counted towards the number of trinkets or
crewmates in the level.

One fix would be to just remove entities whenever the level is
downsized, but then if someone accidentally downsizes the level and
wants to go back, that entity will be gone. Plus, it would be
inconsistent with tiles, because tiles don't get removed when you
downsize the level. Also, it wouldn't fix existing levels where people
have managed to place trinkets or crewmates out of bounds.

So instead, ed.numtrinkets() and ed.numcrewmates() should simply ignore
trinkets and crewmates that are outside the playable area. That way,
levels with glitched trinkets and crewmates can still be completed, and
can still be completed with the trinket star.
2021-06-19 14:01:38 -04:00
Misa 571f6a7098 Re-add playtesting passthrough code block for non-separate interact
This fixes a regression where you're unable to activate activity zones
in in-editor playtesting if your interact button is not separate from
the map button.

When I originally did #743, I didn't have an option to set the bind to
be non-separate, so I removed this logic without adding a
game.separate_interact check. But when I added the option, I overlooked
this code, and so this regression happened. Whoops.
2021-06-18 10:59:43 -04:00
Ethan Lee 43e8d31aa9 Music: Enforce the quick fade time as soon as we know it's happening.
Not every music path will trip the quick_fade bool that resets the timer to
500ms, so we need to do this as soon as it's asked of us. This fixes the fade
when quitting to the main menu.

Fixes #764
2021-06-14 15:11:39 -04:00
Ethan Lee 8520533296 Music: Reset step_ms on every fade call.
Without this you end up with two problems:
- Fades will start past their fade time, causing it to just not fade at all
- Fades will start in the middle of their fade time, causing dramatic changes
  in volume that are unintentional

The fade system already preserves the volume that music is playing during a
previous fade, so we can always reset the timer and get a good result.

Part of #764
2021-06-14 15:09:23 -04:00
Misa a0c5724283 Set visualonroof/visualonground to 1 on vertical platforms
This fixes one of two desyncs in my Nova TAS.

The problem is that by adding two frames of edge-flipping to vertically
moving platforms, Viridian's framedelay is updated for one extra frame
after they step off of a vertically-moving platform. This then messes up
Viridian's drawframe for the rest of the TAS until they die in a
drawframe-sensitive trick.

The solution here is to only set the visual onroof/onground to 1
instead. The logical onroof/onground is still 2, so players still have
two frames of edge-flipping off of vertically-moving platforms - it just
won't really look like it (not that you could easily tell anyway).
2021-06-14 14:55:51 -04:00
Terry Cavanagh 67d1d6f01d
Merge pull request #778 from InfoTeddy/general-bug-fixes-7
Use hiddenname for hardestroom if roomname is empty
2021-06-14 13:04:44 +10:30
striker.sh 9188bd23d3 Support for OpenBSD
- use fseeko and ftello like FreeBSD in tinyxml2
- use current directory as basePath if NULL (OpenBSD doesn't actually support this feature it is disabled via a patch in their ports)
2021-06-13 10:48:20 -04:00
Misa c02bd9235f Outline text outline text and draw backing
In order to help players spot the difference between outlined text and
non-outlined text, we now outline the text outline text itself (if text
outline is enabled, of course). But drawing the outline alone doesn't
stand out enough, so we have to draw a solid backing against the text as
well, in order to properly show the contrast.
2021-06-12 19:02:14 -04:00
Misa 9c226ab5aa Play Viridian squeak when using return button in audio options
For some reason this button was missing the Viridian squeak.
2021-06-12 19:01:51 -04:00
Misa 3b6c0befb1 Fix being able to start flipped in time trials
This fixes a regression where you're able to start flipped by restarting
and then holding ACTION.

This happens because when the game resets all variables, it turns
hascontrol back on (because of hardreset()). However, this is handled in
the input function, and it's handled before player input is handled, so
the player is able to get 1 frame of being able to flip after a time
trial resets.

Why didn't this happen in 2.2? Because resetplayer() in 2.2 would set
lifeseq to 10, as if the player had died. However, this is inconsistent,
because loading in to the game for the first time would not result in a
lifeseq of 10. So, in 2.2, restarting the time trial would remove that 1
frame of being able to flip because of lifeseq, while 2.3 doesn't set
lifeseq because the player hasn't died.

I could have fixed this by setting lifeseq in the time trial restart
code, but I decided to just set hascontrol to false instead.

Fixes #770.
2021-06-12 18:17:31 -04:00
Terry Cavanagh 1d66cfccab
Merge pull request #777 from InfoTeddy/general-improvements
Outline time trial countdown
2021-06-12 22:35:31 +10:30
Terry Cavanagh 2efe7724a7
Merge pull request #775 from InfoTeddy/general-bug-fixes-5
Interpolate gravitron square indicators
2021-06-12 22:35:07 +10:30
Terry Cavanagh b07d92ac44
Merge pull request #776 from InfoTeddy/general-bug-fixes-6
Explore all rooms when entering Secret Lab
2021-06-12 22:33:37 +10:30
Terry Cavanagh b06b278bb0
Merge pull request #774 from InfoTeddy/general-bug-fixes-4
Prevent losing level data with rollcredits
2021-06-12 22:33:17 +10:30
Terry Cavanagh fa3021c714
Merge pull request #773 from InfoTeddy/general-bug-fixes-3
Fix being able to see box corners on map screen with custom graphics
2021-06-12 22:32:36 +10:30
Terry Cavanagh eb0b7c8e87
Merge pull request #772 from InfoTeddy/general-bug-fixes-2
Fix inconsistencies with controller keybind options
2021-06-12 22:31:50 +10:30
Terry Cavanagh da22d395bb
Merge pull request #771 from InfoTeddy/general-bug-fixes
Play Viridian squeak when editing level desc fields
2021-06-12 22:31:26 +10:30
Misa d292b64c6d Use hiddenname for hardestroom if roomname is empty
In earlier 2.3, if the roomname was empty, Dimension VVVVVV was used
instead. However, instead of doing that, it's better to just use the
hiddenname instead. Both because it's less hardcoded, and some rooms
have hidden names that aren't Dimension VVVVVV.
2021-06-11 23:58:18 -07:00
Misa f205147eaa Outline time trial countdown
This makes the text much more readable against certain backgrounds (if
you have text outline enabled), especially against the Warp Zone
background (when you start in "This is how it is").
2021-06-11 23:56:33 -07:00
Misa 6dd01495f3 Explore all rooms when entering Secret Lab
If you enter the Secret Lab from the title screen, all rooms will be
explored. However, if you enter the Secret Lab via the Secret Lab
entrance cutscene (epilogue), not all rooms will be explored, which is
inconsistent.

To do this, just do an SDL_memset() for the entersecretlab script
command.
2021-06-11 23:51:48 -07:00
Misa d404986e6f Use memset to give 20 trinkets and explore all rooms
SDL_memset() conveys intent better and is snappier than using a
for-loop. Also, using SDL_memset() to explore all rooms is more
future-proof, in case the size of map.explored were to change in the
future, and it's more conducive to optimization.

However, the `i` variable has to be explicitly set because it was
previously used here, but it's much better that it's explicitly set here
rather than being subtlely hidden in the inner for-loop initialization.
2021-06-11 23:51:37 -07:00
Misa 37fd24bd85 Interpolate gravitron square indicators
This is more future-proofing than anything else. The position of the
indicators is just the x-position of the gravitron square divided by 10,
but the gravitron squares will always only ever move at 7 pixels per
frame - so the distance an indicator travels on each frame will only
ever be at most 1 pixel. But just in case in the future gravitron
squares become faster than 10 pixels per frame, their indicators will be
interpolated as well.
2021-06-11 22:20:06 -07:00
Misa 6767249558 Prevent losing level data with rollcredits
When rollcredits is ran during in-editor playtesting, all unsaved data
is lost. To prevent this, just return to the editor if rollcredits is
ran, with a note saying "Rolled credits".
2021-06-11 15:30:29 -07:00
Misa 47460143e2 Fix being able to see box corners on map screen with custom graphics
The text box drawn at the bottom of the map screen isn't wide enough, so
it's possible to see the corners on the right side of the text box if
you have custom graphics like I do.

The solution is to increase the width of the text box by one tile.
2021-06-11 15:07:08 -07:00
Misa 74bbf45fa7 Play Viridian squeak when updating controller keybinds
For consistency, the Viridian squeak is now played whenever the user
updates their controller keybinds.
2021-06-11 12:56:07 -07:00
Misa d25243943e Save settings after changing controller keybind
The game automatically writes settings to disk after any other setting
is changed, so it should do the same whenever the user changes
controller keybinds.
2021-06-11 12:54:36 -07:00
Misa 1ccf85a260 Play Viridian squeak when editing level desc fields
For consistency, the Viridian squeak will now play whenever you start
editing a level description field, or finish editing it (either by
pressing Esc or Enter).
2021-06-11 12:52:28 -07:00