1
0
Fork 0
mirror of https://github.com/TerryCavanagh/VVVVVV.git synced 2024-11-13 06:29:41 +01:00
Commit graph

2183 commits

Author SHA1 Message Date
Ethan Lee
1eda3647ff Move the mute logic to musicclass.
This moves the last of the SDL_mixer calls to Music.cpp.
2021-12-26 08:48:23 -05:00
Ethan Lee
579f0f763a Update docs for MusicTrack/SoundTrack 2021-12-26 08:41:57 -05:00
Ethan Lee
230859f8f9 Inline SoundSystem into musicclass constructor 2021-12-26 08:41:01 -05:00
Ethan Lee
c87f0e1a0c Consolidate SoundSystem into Music.
It's just some small wrappers, and SoundSystem can be inlined trivially.
2021-12-26 08:38:19 -05:00
Ethan Lee
f723e03871 Remove unused MusicTrack constructor.
This wouldn't work anyway since music would need to be loaded via physfs.
2021-12-26 08:31:40 -05:00
Misa
dfb1e31d78 Optimization: Don't outline if room name BG opaque
This is quite simple. Just use a function pointer that switches out
which function we're going to use.

...Or not. C++ syntax makes this a bit awful since the function is a
member of a class. Did I mention how much I don't like C++?
2021-12-26 00:04:20 -08:00
Misa
8f226ced84 De-duplicate finalmode glitchname printing
Instead of copy-pasting the call twice, just use a variable to switch
between the two names.
2021-12-26 00:03:18 -08:00
Misa
276aab1209 Default to integer scaling mode
Issue #849 suggested making integer be the default on Big Picture and
Steam Deck, but after thinking about it more, I think it's better and
more simple to just default to integer mode in general.

Reason being that people in Big Picture shouldn't expect the picture to
look different if they're out of Big Picture but still in fullscreen, or
have the picture look different in fullscreen depending on if they
launched the game for the first time in Big Picture or not. And besides,
the less lines of code, the better. So I'm just making integer mode the
default.
2021-12-25 23:14:43 -08:00
Misa
550e76a6dc Add and use scaling mode enum
This enum is to just make each mode be readable, instead of mysterious
0/1/2 values. It's not a strictly-typed enum because we still have to
serialize it as ints in the XML, but it's better than just leaving them
as ints.

This also adds a NUM_SCALING_MODES enum, so we don't have to hardcode
that 3 when cycling scaling modes anymore.
2021-12-25 23:14:12 -08:00
Misa
f5166c437e Add forced fullscreen mode
This is mainly to make sure the game is definitely set to fullscreen in
Big Picture and on the Steam Deck, and to also remove windowed options
that wouldn't make sense if you're not on a desktop (toggling
fullscreen, resize to nearest). Those options would also be removed on
console and mobile too.

There's a bit of an annoying bug where if you launch the game in forced
fullscreen mode, but then exit and relaunch in normal mode, your game
will have fullscreen window sizes but it won't be fullscreen. This is
because forced fullscreen mode tries to preserve your non-forced
fullscreen setting, but due to the way window sizes are stored and
queried, it can't preserve the non-forced window size. This is a bit
difficult to work around, so I'm just putting in a FIXME here because we
can fix it later and I'd rather have a slightly buggy forced fullscreen
mode than not have one at all.

Closes #849.
2021-12-25 23:01:45 -08:00
Dav999-v
3e36bfd56f Simplify time formatting functions
Here's my notes on all the existing functions and what kind of time
formats they output:

- Game::giventimestring(int hrs, int min, int sec)
	H:MM:SS
	MM:SS

- Game::timestring()
// uses game.hours/minutes/seconds
	H:MM:SS
	MM:SS

- Game::partimestring()
// uses game.timetrialpar (seconds)
	MM:SS

- Game::resulttimestring()
// uses game.timetrialresulttime (sec) + timetrialresultframes (1/30s)
	MM:SS.CC

- Game::timetstring(int t)
// t = seconds
	MM:SS

- Game::timestringcenti(char* buffer, const size_t buffer_size)
// uses game.hours/minutes/seconds/frames
	H:MM:SS.CC
	MM:SS.CC

- UtilityClass::timestring(int t)
// t = frames, 30 frames = 1 second
	S:CC
	M:SS:CC

This is kind of a mess, and there's a lot of functions that do the same
thing except using different variables. For localization, I also want
translators to be able to localize all these time formats - many
languages use the decimal comma instead of the decimal point (12:34,56)
maybe some languages really prefer something like 1時02分11秒44瞬...
Which I don't know to be correct, but it's good to be prepared for it
and not restrict translators arbitrarily to only changing ":" and "."
when we can start making the system better in the first place.

I added a new function, UtilityClass::format_time. This is the place
where all time formats come together, given the number of seconds and
optionally frames. I have simplified the above-mentioned functions
somewhat, but I haven't given them a complete refactor or renaming -
I mainly made sure that they all use the same backend so I can make the
formats consistent and properly localizable.

(And before we start shoving more temporary char buffers everywhere
just to get rid of the std::string's, maybe we need to think of a
globally used working buffer of size SCREEN_WIDTH_CHARS+1, as a
register of sorts, for when any line of text needs to be made or
processed, then printed, and then goes unused. Maybe help.textrow,
or something like that.)

As for this commit, the available time formats are now more consistent
and changed a little in some places. Leading zeroes for the first unit
are now no longer included, time trial results and the Super Gravitron
can now display hours when they went to 60 minutes before, and we now
always use .CC instead of :CC. These are the formats:
- H:MM:SS
- H:MM:SS.CC
- M:SS
- M:SS.CC
- S.CC  (only used when always_minutes=false, for the Gravitrons)

Here's what changes to the current functions:
- Game::partimestring() is removed - it was used in two places, and
  could be replaced by game.timetstring(game.timetrialpar)
- Game::giventimestring(h,m,s) and Game::timestring() are now wrappers
  for the other functions
- The four remaining functions (Game::resulttimestring(),
  Game::timetstring(t), Game::timestringcenti(buffer, buffer_size)
  and UtilityClass::timestring(t)) are now wrappers for the "central
  function", UtilityClass::format_time.
- UtilityClass::twodigits(int t) is now unused so it's also removed.
- I also added int UtilityClass::hms_to_seconds(int h, int m, int s)
2021-12-25 11:38:12 -08:00
Misa
dd24343141 Use LoadImage in LoadIcon
This de-duplicates the code, simplifying the codebase and reducing the
number of code paths that needs to be maintained. It also adds
robustness checks to LoadIcon that weren't there before (checking that
loading the file succeeded and that decoding the file also succeeded).

Now, you might think that loading the image with alpha will change
things in some way. But actually, I tested it, and I'm pretty sure it
doesn't. Since my window manager, i3, doesn't display icons, I've had to
resort to this hacky multi-liner
( https://unix.stackexchange.com/a/48866 ) to dump the icon to a PAM
file. I don't know what a PAM file is and all my various attempts to
convert it into something readable failed. But what I did instead was
just grab the icon of the game before this commit (on 2.3, just to be
extra sure), and `diff`ed it with the grabbed icon now, and they end up
being the exact same file. So there's literally no difference.

The only other consideration is that LoadImage needs to be exported,
since it's implemented in GraphicsResources.cpp. I just opted to
forward-declare it right before LoadIcon in Screen.cpp, since it's
really the only other time it's used. No need to create a new header
file for it or anything.
2021-12-25 01:29:24 -08:00
Misa
a5c3bd97a0 Remove noAlpha argument from LoadImage
This is just to simplify the function. I really don't see any point in
taking away the alpha for some images, other than to disappoint people
who mod the game assets. It just complicates loading the image with no
real gain. To reduce maintenance costs, let's remove this alternate code
path.

Also it's a default argument and I don't like default arguments.
2021-12-25 01:29:12 -08:00
Misa
3108178c53 Remove noBlend argument from LoadImage
This argument... doesn't do anything.

First off, setting it to true explicitly enables blending on the
resulting surface, which is kind of the exact opposite of the variable
name and is misleading to say the least? And secondly, SDL surfaces have
blending enabled by default anyways, so it still doesn't even do
anything.

It's also a default argument, and I'm not one to shy away from removing
such default arguments.
2021-12-25 01:26:42 -08:00
Misa
a6b076e234 Explicitly zero declared struct ScreenSettingss
Performance cost is negligible and well worth being safe in case there
are more members added in the future but we forget to initialize them.
2021-12-25 00:30:10 -08:00
Misa
1e157f3cc9 De-C++-ify struct ScreenSettings
This includes:
- Removing the constructor in favor of actually being able to see that
  there's an actual function called being made initializing the struct
- Removing the use of a reference in Screen::init() in favor of using a
  pointer
- Adding the struct qualifier everywhere (it's not much typing),
  although technically you could typedef it in C, but I'd rather much
  not typedef just to remove a tag qualifier
2021-12-25 00:30:10 -08:00
Misa
d0ffafe117 Extern gameScreen, remove screenbuffer
I know earlier I removed the gameScreen extern in favor of using
screenbuffer, but that was only to be consistent. After further
consideration, I have found that it's actually really stupid.

There's no reason to be accessing it through screenbuffer, and it's
probably an artifact of 2.0-2.2 passing stack-allocated otherwise-global
classes everywhere through function arguments. Also, it leads to stupid
bugs where screenbuffer could potentially be NULL, which has already
resulted in various annoying crashes in the past. Although those could
be fixed by simply initializing screenbuffer at the very top of main(),
but, why not just scrap the whole thing anyway?

So that's what I'm doing.

As a nice side effect, I've removed the transitive include of Screen.h
from Graphics.h. This could've been done already since it only includes
it for the pointer anyway, but it's still good to do it now.
2021-12-25 00:29:28 -08:00
Misa
b7cbdfe8f9 Fix char overflow in Analogue Mode
In aa7b63fa5f, I didn't notice that the
result was implicitly being converted to int by the min/max from before.
I instead added it to the existing char, but that resulted in a char
overflow (it's unsigned, so thankfully not undefined behavior).

But of course the entire point of that commit is to make it explicitly
clear when you are converting between types, intentionally or otherwise,
in min/max comparisons. So despite causing a regression (which I have
now fixed), at least it did its job.
2021-12-22 21:49:08 -08:00
Misa
816a0b9eb7 Move filterSubrect off of Screen
It's only used in FlipScreen.
2021-12-22 20:39:11 -08:00
Misa
f7b4ac8322 Rename stretch mode to scaling mode internally
It's been long overdue that this variable be named properly. 2.2 added
integer scaling mode (thanks Ethan), 2.3 renamed it to scaling mode. Now
2.4 will properly call it what it is so people won't be confused by it.

The ScreenSettings struct member is renamed from stretch to scalingMode
along with the Screen class member being renamed, as well as the
toggleStretchMode function being renamed to toggleScalingMode as well.
Unfortunately, due to compatibility, we can't change the <stretch> XML
tag.
2021-12-22 19:54:59 -08:00
Misa
aa7b63fa5f Remove VVV_min/max in favor of SDL_min/max
VVV_min/max are functions that only operate on ints, and SDL_min/max are
macros that operate on any type but double-evaluate everything.

I know I more-or-less said earlier that SDL_min/max were dumb but I've
changed my mind and think it's better to use them, taking care to make
sure you don't double-evaluate, rather than trying to generate your own
litany of functions with either your own hand-rolled generation macros,
C++ templates, C11 generics, or GCC extensions (that last one you'd
technically use in a macro but it doesn't really matter), all of which
have more downsides than just not double-evaluating.

And the upside of not double-evaluating is that you're disencouraged
from having really complicated single-line min/max expressions and
encouraged to precompute the values beforehand anyway so the final
min/max is more readable. And furthermore you'll notice when you
yourself end up doing double-evaluations anyway. I removed a couple
instances of Graphics::len() being double-evaluated in this commit (as
well as cleaned up some other min/max-using code). Although the only
downside to those double-evaluations was unnecessary computation,
rather than checking the wrong result or having multiple side effects,
thankfully, it's still good to minimize double-evaluations where
possible.
2021-12-22 16:43:31 -08:00
Misa
f7454baffa Hide level path by default
You will now need to go through another confirm menu in order to print
your level path. The confirm menu warns you may leak sensitive
information if you are streaming.

Screenshots:
https://i.imgur.com/0Dc9jsZ.png
https://i.imgur.com/UhDgXqj.png
https://i.imgur.com/Z0ftQnH.png

Fixes #853.
2021-12-22 00:58:27 -08:00
Misa
8ba1325d0f Fix regression with wall stuck flipping behavior exactly reversed
The reason why the wall stuck flipping behavior happened in the first
place was because the code went like this:

    if (jumppressed)
    {
        if (onground && gravitycontrol == 0)
        {
            gravitycontrol = 1;
        }
        if (onroof && gravitycontrol == 1)
        {
            gravitycontrol = 0;
        }
    }

Basically, if you were both on ground and on a roof (i.e. stuck in a
wall), you would flip, but then due to code order and the fact that the
statement is not connected to the previous one, you would immediately
unflip afterwards. But if you were already flipped then the only path
that can be taken is to unflip you, since it's the statement that
appears last.

52fceb3f69 replaces the onground/onroof
conditionals with any_onground/any_onroof, so any player entity would
allow you to flip. But otherwise the code is the same. So is that the
problem?

No; tracing it through with GDB reveals that when you flip,
gravitycontrol is being set to 1, but never being set to 0. And it turns
out that's because any_onroof is not getting set. And that happens
because of another thing that 52fceb3f69
did - which was to set any_onground/any_onroof to true if indeed any
player entity was on ground or on a roof.

Unfortunately, the way Leo did it was to make the two statements
mutually exclusive - an 'if'-'else if' instead of two separate
statements. So a single entity could not mark both any_onground and
any_onroof as true (and the majority of the time, you will be a single
entity).

Thus, the solution is to just drop that 'else'.

Fixes #855.
2021-12-22 00:25:19 -08:00
Misa
caebde9e33 Fix warp sprites of big sprites sometimes not being drawn
I noticed when going frame-by-frame in Vertigo that sometimes the
wrapping enemies at the top sometimes just "popped" in frame. This is
because the sprite warp code only draws the warping sprite of sprites at
the bottom of the screen if they're below y=210. However, the warp point
starts at y=232, and warp sprites can be at most 32x32, which is exactly
the case with the Vertigo sprites, which are exactly 32x32. So the warp
code should start warping sprites if they're below y=200 (232 - 32)
instead.

Horizontal warping also has this problem; it warps at x=320 and
starts drawing warp sprites at x=300, even though it should start
drawing at x=288 (320 - 32). I've gone ahead and fixed that as well.
2021-12-20 20:18:24 -08:00
Misa
44ebb19d77 Outline "NO SIGNAL"
This is just in case the background gets changed by a custom level or
something to be something that would otherwise result in bad contrast.
Also if it needs to go outside the box for some reason. And I just like
the look of the outline.
2021-12-20 20:07:38 -08:00
Misa
9cddae8cc3 Outline trophy text
Whew, look at all those copy-pasted print statements!

Doing this because of the in-game timer feature. The text would
otherwise clash harshly with the timer otherwise. Even with the outline
it still clashes, but at least there's an outline so it's not as harsh.
2021-12-20 20:02:07 -08:00
Misa
1d6a808cbd Add centiseconds to timer overlays
This adds centiseconds to the in-game timer, as well as the time trial
timer.

This is to aid speedrun moderators in determining when exactly a run was
completed, which they can't easily do if the timer only has a precision
up to a second.
2021-12-20 19:26:01 -08:00
Misa
51fac68d3a Fix in-game timer going away after playing Super Gravitron
The problem was that it also needed to check that game.swnmode was true,
in addition to game.swngame being 1, to actually check that the Super
Gravitron was being played.
2021-12-20 17:44:34 -08:00
Misa
b7b9caacfc Remove unused game-gamestates
These were `CLICKTOSTART` and `FOCUSMODE`.
2021-12-18 00:01:32 -08:00
Misa
119e25d0bb Change all game-gamestates to use an enum type
Currently, all game-gamestate variables are just ints. This is not
particularly type-safe, in case the number of enums changes. To verify
that all current uses of the game-gamestate variables actually use the
enums, change them to be typed with the enum instead.

(As an aside, we should probably rename this so that it can't be
confused with Terry's state machine that has several different ways to
exploit to warp you to the credits, but that's something to do later.)
2021-12-17 23:57:55 -08:00
Misa
b67386894c hardreset: Reset ingame_titlemode
You'll note that getting in to the glitchy state of the game (the state
where you could play the game after it had hardreset() called on it)
required the player to quit to menu with ingame_titlemode set to true.
Well, quitting to menu calls hardreset(). So if hardreset() is called
when quitting, then you can no longer preserve ingame_titlemode that
way. This is a bit overkill, but I'm just taking precautions.
2021-12-17 23:39:26 -08:00
Misa
7f9247b0c7 Add asserts if ingame_titlemode in unexpected places
The game will now assert if the main menu is created while
ingame_titlemode is true, or if we attempt to load into a mode while
it's true. And if assertions are disabled then it just stops doing it
anyway.

I don't think there's any way to get a glitched ingame_titlemode again,
ever since I removed save data deletion taking you back to the main
menu. But I've had enough bugs with the fact that we more-or-less use
the same state for main menu options and in-game options, and that
glitched ingame_titlemode bug DID just happen, so I'm taking
precautions.
2021-12-17 23:36:13 -08:00
Misa
5ebc65d1a2 Pull out fade mode handling into separate function
The next commit will add logic that more-or-less quits the whole block
if ingame_titlemode, and instead of adding another layer of indentation
I will just pull this into its own function so we can use a return
statement.
2021-12-17 23:35:08 -08:00
Misa
cc9c71a94a deletestats: Properly reset bestgamedeaths
While I was testing deleting data while you were in-game, I noticed that
deleting data gave you all the "Win with less than X deaths" trophies,
even if you never got any of them before deleting data. Well, it turns
out that if you have the best game death count of 0, then you win every
trophy, and if you have the best game death count of -1 then that means
you haven't completed the game yet.

This reset was added in e3bfc79d4a, so at
least it's not in 2.3, but I only have myself to blame for making this
mistake. Whoops.
2021-12-17 23:34:44 -08:00
Misa
2770353142 Don't go back to main menu when deleting main game save data
Going back to the main menu allowed for glitchiness to occur if you
deleted your save data while in in-game options. This meant you could
then load back in to the game, and then quit to the menu, then open the
options and then jump back in-game, exploring the state of the game
after hardreset() had been called on it. Which is: pretty glitchy.

For example, this meant having your room coordinates be 0,0 (which is
different from 100,100, which is the actual 0,0, thanks for the
100-indexing Terry), which caused some of the room transitions to be
disabled because room transitions were disabled if the
game.door_up/down/left/right variables were -2 or less, and they were
computed based on room coordinates, which meant some of them went
negative if you were 0,0 and not 100,100. At least this was the case
until I removed those variables for, at best, doing nothing, and at
worst, being actively harmful.

Anyways, so deleting your save data now just takes you back to the
previous menu, much like deleting custom level data does. I don't know
why deleting save data put you back on the main menu in the first place.
It's not like the options menu needed to be reloaded or anything. I
checked and this was the behavior in 2.0 as well, so it was probably
added for a dumb reason.

I considered prohibiting data deletion if you were ingame_titlemode, but
as of the moment it seems to be okay (if albeit weird, e.g. returning to
menu while in Secret Lab doesn't place your cursor on the "play"
button), and I can always add such a prohibition later if it was really
causing problems. Can't think of anything bad off of the top of my head,
though.

Btw thanks to Elomavi for discovering that you could do this glitch.
2021-12-17 23:34:25 -08:00
Misa
1924ca53ac Remove game.door_left/right/up/down variables
These don't do anything, and in fact are actively harmful by disabling
room transitions if your roomx/roomy is glitched.
2021-12-17 19:43:29 -08:00
Misa
a345cf93b8 Fix elephant placement across rooms
Okay, so, this is the elephant sprite, right?

https://i.imgur.com/dtS70zk.png

This is how it looks in the actual game, when you stitch all the rooms
together:

https://i.imgur.com/aztVnFT.png

Looks kind of messed-up, doesn't it?

Okay, so, in the bottom two rooms (11,9) and (12,9), the elephant is
placed at y-position -152. But in (11,8) and (12,8), it's placed at
y-position 96. This is despite the fact that -152 plus 240 is 88, not
96.

Similarly, in the left two rooms (11,8) and (11,9), the elephant is
placed at x-position 64, but in the right two rooms (12,8) and (12,9),
the elephant is placed at -264. This is despite the fact that 64 minus
320 is -256, not -264.

All of this stems from the calculations in Otherlevel.cpp using offsets
of -248 and -328 instead of -240 and -320.

So there's an 8-pixel offset that causes the elephant to be chopped off
when viewed with all the rooms stitched together. Simple enough to fix.
For the y-position fixes, I decremented the initial 8-pixel multiplier
as well, else the elephant would sink into the floor.

And this is what the elephant looks like now after stitching:

https://i.imgur.com/27ePLm1.png

Thanks to Tzann for pointing this out.
2021-12-08 16:25:18 -08:00
Dav999-v
f60d2a2964 Fix -Wformat-security warnings
These warnings are kinda spammy, and they make sense in principle.
vlog_error takes a format string, so passing it an arbitrary string
(even error messages from libraries) isn't a good idea.
2021-12-05 10:45:36 -08:00
Misa
6e832cae20 LoadImage: Check LodePNG return value and print errors
Dvoid from Discord just reported a crash when trying to load a
custom tiles2.png that was encoded weirdly.

The problem is that we don't check the return value from LodePNG, so
LodePNG gives us a null pointer, and then
SDL_CreateRGBSurfaceWithFormatFrom doesn't check this null pointer,
which then propagates until we crash in SDL_ConvertSurfaceFormat (or
rather, one of its sub-functions), and we would probably crash somewhere
else anyway if it continued.

After properly checking LodePNG's return value, along with printing the
error, it turns out that Dvoid's custom tiles2.png had an "invalid CRC".
I don't know what this means but it sounds worrying. `feh` can read the
file correctly but it also reports a "CRC error".
2021-11-14 14:02:51 -08:00
Misa
a6728c4648 README.md: Link to #618 for old Ubuntu versions
While we can't fix Canonical, we can at least work around them, and help
people on Ubuntu out by linking them to my comment listing the
currently-known workarounds.
2021-11-14 10:11:33 -08:00
Misa
cd15ae0fdc Use SDL_FALLTHROUGH if available
The SDL_FALLTHROUGH macro has been added to SDL 2.0.18. Until 2.0.18 is
released, use it if it's available.
2021-11-11 23:48:41 -08:00
Misa
0c1f756af8 Switch over to using SDL_GetTicks64()
SDL_GetTicks64() is a function that got added in SDL 2.0.18, which is
just an SDL_GetTicks() without a value that wraps every ~49 days,
instead wrapping after the sun explodes and kills us all. Oh sorry,
didn't mean to get existential.

For now, put this behind an SDL_VERSION_ATLEAST guard, which will be
removed when SDL 2.0.18 officially releases and we can update to it.
2021-11-01 11:37:50 -07:00
Misa
75e031cef0 Don't toggle VSync twice
The vsync variable is already toggled in toggleVSync(). Whoops.
2021-10-29 12:24:10 -07:00
Misa
d0992e18a4 Fix regression with rainbow lab BG in editor
731fb89c90 was partially reverted by #624
because of my bad rebase.
2021-10-28 17:27:13 -07:00
Misa
1bc1149ab5 Fix regression with counting out-of-bounds custom entities
My latest rebase of #624 (refactoring/splitting editor.cpp) accidentally
overwrote #787 and essentially reverted it entirely. So, add it back in.

This is the same as #787 except it uses the new names, uses SDL_INLINE
to inline the function, and uses named constants.
2021-10-27 16:49:57 -07:00
Misa
58c518c856 Silence GCC warnings about void*-to-function-pointer casts
GCC warns on casting `void*` to function pointers. This is because the C
standard makes a clear distinction between pointers to objects (`void*`)
and pointers to functions (function pointers), and does not specify
anything related to being able to cast object pointers to function
pointers.

The warning message is factually wrong, though - it states that it is
forbidden by ISO C, when in fact it is not, and is actually just
unspecified.

We can't get rid of the cast entirely, because we need the explicit cast
(the C standard _does_ mandate you need an explicit cast when converting
between object pointers and function pointers), and at the end of the
day, this is simply how `SDL_LoadFunction()` works (and more
importantly, how `dlsym()` works), so we can't get rid of it, and we
have no reason to anyways since it means we don't have a hard runtime
dependency on Steam (unlike some other games) and casting `void*` to
function pointers always behaves well on every single platform we ship
on that supports Steam.

Unfortunately, this warning seems to be a part of -Wpedantic, and
there's no way to disable this warning specifically without disabling
-Wpedantic. Luckily, I've found a workaround - just cast to `intptr_t`
before casting to the function pointer. Hopefully the compiler doesn't
get smarter in the future and this ends up breaking or anything...
2021-10-21 01:00:06 -07:00
Ally
f3786a8e3f
Add setactivityposition(x,y), add new textbox color transparent (#847)
* Add `setactivityposition(x,y)`, add new textbox color `transparent`

This commit adds a new internal command as a part of the visual activity zone changes I've been making.
This one allows the user to reposition the activity zone to anywhere on the screen.
In addition, this commit adds the textbox color `transparent`, which just sets r, g and b to 0.
rgb(0, 0, 0) normally creates the color black, however in VVVVVV textboxes, it makes the background
of them invisible, and makes the text the off-white color which the game uses elsewhere.

* add new variables to hardreset

* Fix unwanted text centering; offset position by 16, 4

It makes sense for `setactivityposition(0, 0)` to place the activity zone in the default position,
so the x has been offset by 16, and the y has been offset by 4.

Text was being automatically centered, meaning any activity zone which wasn't centered had misplaced text.
This has been fixed by calculating the center manually, and offsetting it by the passed value.
2021-10-13 15:38:51 -07:00
Misa
700be11137 Remove space at end of Press %s to Teleport
This wasn't there in 2.2 and previous. I accidentally introduced it in.
2021-10-12 16:59:36 -07:00
Misa
449526bb4f Fix regression with per-pixel collision colors
In previous versions, the game mistakenly checked the wrong color
channel of sprites, checking the red channel instead of the alpha
channel. I abuse this in some of my levels. Then I broke it when
refactoring masks so the game now no longer checks the red channel but
seems to check the blue channel instead. So re-fix this to the previous
bug, and preserve the previous bug with a comment explaining why.
2021-10-06 23:18:58 -07:00
Misa
2f25ab77b1 Fix regression with tile 10 not having nothing behind it
This broke when I was refactoring things earlier, because we no longer
have a direct reference to the contents array, instead using a copied
int. But we have a settile() function anyway, so why not use it?
2021-10-06 17:00:50 -07:00
Misa
038f15f4a6 Remove outdated FIXMEs from Screen.cpp
The VSync renderer workaround is no longer a thing, so these comments
should go away.
2021-10-03 13:23:12 -07:00
Misa
7eea59a7e8 Make impossible time trial save screen message less verbose
Ally asked me why it was so verbose, and recommended wording it like
this instead. Not that it should matter much, since it _is_ impossible,
but...
2021-10-02 09:24:44 -07:00
Misa
0ed0892977 Add impossible message for quicksave screen in time trials
It is impossible to get on the quicksave screen in time trials, because
Enter is always bound to restarting time trials in a time trial, and
there's no way to open the map screen otherwise.

So, I've decided to add a fun little message in case someone somehow
manages to get to this screen in a time trial.
2021-10-01 21:13:51 -07:00
Misa
db8e0cd70a De-duplicate map menu quicksave screen
As is typical, the code was copy-pasted to account for Flip Mode, and
then copy-pasted again to account for custom levels, leading to four
instances of the same code.

I clean this up while also improving code style. This is where the new
FLIP macro and the fixed PrintWrap help a lot - otherwise the "Game
saved ok!" screen would look really wrong without the height
corrections.
2021-10-01 21:06:31 -07:00
Misa
b26ccd914d Simplify flipme text box position correction
It now looks more like the FLIP macro in Render.cpp: The y-position is
simply the height of the area the object is being flipped in, minus the
y-position itself, minus the height of the object. So:

    flipped_yp = constant - yp - height

This is just a mathematical simplification of the existing statement,
which is:

    flipped_yp = yp + 2 * (constant/2 - yp) - height

Using algebra, the 2 distributes into the parentheses, so

    flipped_yp = yp + constant - 2 * yp - height

And the two `yp`s add together, so

    flipped_yp = constant - yp - height

It's more readable this way.

Also I am using a named constant instead of a hardcoded one.
2021-10-01 20:59:55 -07:00
Misa
98b392197c PrintWrap: Account for height in Flip Mode
Otherwise, the text will be in the wrong position compared to normal
mode.

PrintWrap is not used in Flip Mode yet, but it will be used on the map
screen in an upcoming change of mine. The FLIP macro in Render.cpp can't
help us there, since it would need to know the height of the wrapped
text at compile time, when the height is only figured out at runtime
based off of the string (or, well, right _now_ the string _is_ known,
but we are going to merge localization for 2.4, and it's better to
future-proof...), and only PrintWrap itself can figure out the height of
the text. (Or, well, I suppose you could call it from outside the
function, but that's not very separation-of-concernsy style.)
2021-10-01 20:49:27 -07:00
Misa
517e20cecb Account for heights in the FLIP macro
Flipping objects in Flip Mode needs to account for the heights of those
objects (that's why flipme text boxes in Flip Mode in 2.2 were
positioned wrongly).

Also, turn it into a macro instead of an inline function.

This changes the positions of all existing de-duplicated map menu text
in Flip Mode, but it'll be more correct.
2021-10-01 20:39:24 -07:00
Misa
3a911a9a9b Fix SCREEN_HEIGHT_PIXELS being wrong constant
Whoops.
2021-10-01 09:35:28 -07:00
Misa
a346379413 Remove unused math.h include from Maths.h
Apparently this was in here, just completely unused.
2021-09-27 23:11:20 -07:00
Misa
3decf54dbc Mark all vlog functions with printf attributes
This ensures that compiler warnings about format strings will apply to
all calls of these functions as well.
2021-09-27 20:49:09 -07:00
Misa
5533215019 Use SDL_NORETURN
I misread SDL's code and thought that SDL's `begin_code.h` was internal
only to SDL. It turns out you get it when you include basically any
header, such as `SDL_stdinc.h`. So use it directly instead of copying it
for our own.
2021-09-27 10:32:23 -07:00
Misa
c3dfd4a4b1 De-duplicate map menu stats screen rendering code
Between accounting for Flip Mode and custom levels, this code was
copy-pasted three times, leading to _four_ instances of one code!

Anyways, I've cleaned it up. The position of the text in Flip Mode is
going to differ by 4 pixels from how it was previously, but that really
shouldn't matter.
2021-09-25 17:16:52 -07:00
Misa
e9351b4a00 Fix winning in No Death Mode saying "One trinkets"
While dying in No Death Mode was fixed to no longer say "One trinkets"
in 2.3, if you win in No Death Mode with one trinket, the game would say
"One trinkets".

So to fix this, just slot a ternary in there. The code is already kind
of bad anyways and is going to be refactored/de-STLed in the future
regardless, so I'm not feeling too badly about shoving a ternary in
there like that.
2021-09-25 17:06:59 -07:00
Misa
38b2213745 Rename number to number_words
This is to clarify that it returns the word forms of numbers, not
numbers themselves.
2021-09-25 15:08:13 -07:00
Misa
409f7b078f Update SDL version in README.md to 2.0.16
The game uses SDL 2.0.16 now. In fact, it already uses SDL 2.0.17 as
well, and will be definitely using SDL 2.0.18 when it releases.
2021-09-24 21:33:10 -07:00
Misa
cace685020 Add POS_MOD macro and use for all positive modulos
This macro is to make it so it won't be error-prone to write the
semi-confusing `(a % b + b) % b` statement, and you can just use an easy
macro instead.

Currently, the only places a positive modulo is needed is when switching
tilesets, enemies, and warp directions in the editor, as well as when
getting a tile in the tower, since towers just repeat themselves
vertically. Towers used this weird while-loop to sort of emulate a
modulo, which isn't half-bad, but is unnecessary, and I don't think any
compiler would recognize it as a modulo. (And if it's not optimized to a
proper modulo... what happens if the number being moduloed is really,
really big?)
2021-09-24 17:48:15 -07:00
Misa
891ca527f9 Remove overcomplicated integer divisions
Believe it or not, there are still some remnants of the ActionScript
coding standards in the codebase! And one of them sometimes pops up
whenever an integer division happens.

As it so happens, it seems like division in ActionScript automatically
produces a decimal number. So to prevent that, the game sometimes
subtracts off the remainder of the number to be divided before
performing the division on it.

Thus, we get statements that look like

    (a - (a % b)) / b

And probably more parentheses surrounding it too, since it would be
copy-pasted into yet another larger expression, because of course it
would.

`(a % b)` here is subtracting the remainder of `a` divided by `b`, using
the modulo operator, before it gets divided by `b`. Thus, the number
will always be divisible by `b`, so dividing it will mathematically not
produce a decimal number.

Needless to say, this is unnecessary, and very unreadable. In fact, when
I saw these for the first time, I thought they were overcomplicated
_modulos_, _not_ integer division! In C and C++, dividing an integer by
an integer will always result in an integer, so there's no need to do
all this runaround just to divide two integers.

To find all of these, I used the command

    rg --pcre2 '(.+?).+?-.+?(?=\1).+?%.+?([\d]+?).+?\/.+?(?=\2)'

which basically matches expressions of the form 'a - a % b / b', where
'a' and 'b' are identical and there could be any characters in the
spaces.
2021-09-24 17:39:31 -07:00
Misa
6192269128 Remove vmult lookup tables
There's really no need to put the y-multiplication in a lookup table.
The compiler will optimize the multiplication better than putting it in
a lookup table will.

To improve readability and to hardcode things less, the new
SCREEN_WIDTH_TILES and SCREEN_HEIGHT_TILES constant names are used, as
well as adding a new TILE_IDX macro to calculate the index of a tile in
a concatenated-rows (row-major in formal parlance) array. Also, tile
numbers are stored in a temporary variable to improve readability as
well (no more copy-pasting `contents[i + vmult[j]]` over and over
again).
2021-09-24 16:37:27 -07:00
Misa
491f3732aa Fix trailing whitespace in CustomLevels.h
Really not sure how they got there. I think it was because of my naive
indentation fix, so.
2021-09-24 16:36:54 -07:00
Misa
f9573a036d Remove commented-out old spike block code
This seems to be code for creating spike blocks in a previous version of
the game. It's unused and commented out, so, remove it.
2021-09-24 16:26:11 -07:00
Misa
3fcab3a395 Remove splitseconds lookup table and inline it
There's really no reason for this simple multiplication plus division to
be in a lookup table. The compiler will optimize it faster than putting
it in a lookup table will, I'm sure.
2021-09-24 16:03:14 -07:00
Misa
f48e385e68 Remove Ethan's binary-or comment
This comment was referring to a now-deleted variable named mkdirResult
that was binary-"or"ed with all mkdir() results... except for the saves
directory. That variable was only used for save file migration, which is
now axed, so this comment is referring to nothing now.

I don't really know the answer to Ethan's question, but it doesn't
matter now.
2021-09-23 23:26:28 -07:00
Misa
1b7a1248a8 Declare Windows mkdir as static
It's not going to be used in any other files so... best to declare it
static.
2021-09-23 23:26:00 -07:00
Misa
eabb3941fd Mark VVV_exit implementation as VVV_NORETURN
For consistency. And in case it matters that much (which I don't really
think it does).
2021-09-23 23:02:46 -07:00
Misa
32bd6c41bc Fix regression with VVV_COMPILEMUSIC aborting
So, it turns out freeing everything in binaryBlob::clear() without
checking for NULL results in an abort() because clear() gets called on
musicWriteBlob after it attempts to write the compiled music. It's just
that no one's using VVV_COMPILEMUSIC, so no one's ran into this.

I'm keeping VVV_COMPILEMUSIC around so in the future people can compile
music directly from the game (and probably half the existing
VVV_COMPILEMUSIC code is going to be thrown out, but oh well).
2021-09-23 22:35:52 -07:00
Misa
0c5024f7e7 Use fixed-size int types for resourceheader
Since this refers to specific exported file data, let's make sure this
is portable. I'm not sure if we'll ever ship on systems where
sizeof(int) != 4 or sizeof(bool) != 1, but better to be safer and
future-proof than not.
2021-09-23 22:21:49 -07:00
Misa
51bfed2032 Ifdef numberofHeaders out if not compiling music
This variable is only used when compiling music. Since it doesn't
actually keep track of the number of headers otherwise, ifdef it behind
VVV_COMPILEMUSIC.
2021-09-23 21:55:58 -07:00
Misa
1297b09c47 Fix regression from 2.3 with destroy(platforms)
2.3 introduced a regression with destroy(platforms). The problem was
that isplatform wasn't being set to false when the entity got disabled,
so if the platform was moving, it would keep moving until it hit a wall,
instead of stopping immediately.
2021-09-23 13:16:57 -07:00
Misa
9926d15465 Update Dockerfile to SDL 2.0.16
This is so future CentOS images will be generated with the new SDL
version.
2021-09-23 12:26:50 -07:00
Misa
c94d04a932 Use SDL_isxdigit() in favor of VVV_isxdigit()
SDL_isxdigit() was added in SDL 2.0.16, so we no longer have to
implement isxdigit() ourselves.
2021-09-23 12:26:50 -07:00
Misa
b74dcdc7ee Remove unused Steam GetStat/SetStat
Forgot these when I was cleaning up the unused achievement percentages
functions...
2021-09-22 20:04:34 -07:00
Misa
bf2f33f1ca Add noreturn qualifier to VVV_exit
This function doesn't return, so we mark it as noreturn if the compiler
supports it.
2021-09-22 19:58:31 -07:00
Misa
b2d7a0b4b6 Rewrite STDIN loading to not use STL
Previously, loading STDIN used std::istreambuf_iterator and std::vector
and whatnot because... I guess it was less typing? But this isn't 1989;
we have the disk space to spare and we don't need to use fancy stuff
just to save on typing. It's not that hard to implement an array that
regrows to the nearest power of two every time.
2021-09-22 19:55:28 -07:00
Misa
dbe9f7c2a0 Declare emscriptenloop as static
It's not going to link with anything in a different translation unit, so
just to make sure, we declare it as static.
2021-09-20 13:48:49 -07:00
Misa
1d0401ef83 Move Emscripten includes to top of main.cpp
All system header includes should come before project-specific includes
(includes specific to this game), while coming after the include
specific to the given file (if any; main.cpp doesn't have any).
2021-09-20 13:47:53 -07:00
Misa
4eb7f973ef Axe NETWORK_[set/get]AchievementProgress()
These are unused.

Ethan originally added them in case Terry wanted achievement
percentages. But he didn't add them, and I don't think the achievements
are changing anytime soon, so it's safe to remove this dead code.
2021-09-19 21:49:54 -07:00
Misa
e13d3af2eb Use stub types instead of intptr_t
This is so there are at least compiler warnings raised if one of the
pointers mismatch their types.
2021-09-17 21:11:25 -07:00
Misa
1a0e720be8 Don't use print formatting for hardcoded strings
If the string is hardcoded, then use compile-time string literal
concatenation instead.

I don't know if compilers are smart enough to recognize when you're
passing in hardcoded strings and to concatenate them into the string
literal at compile time instead. I also don't know that if compilers are
smart enough to recognize that, that further they recognize all the
logging functions are just wrappers around printf, and so they can
perform the same optimization at those function call sites, too. So it's
better to just do the string concatenation explicitly instead.
2021-09-17 14:05:23 -07:00
Misa
32f30020fa Name the return types rettype instead of retval
Minor code style fix. They are return types, not return values.
2021-09-17 13:58:44 -07:00
Misa
9d1659c3a4 De-duplicate Steam network function list
Instead of having three separate copies of the function list, use macro
magic to make it so there is only one list that we use in three
different cases.
2021-09-17 13:55:16 -07:00
Misa
135ff36409 Remove <stdio.h> include from SteamNetwork.c
It's unused.
2021-09-17 13:55:16 -07:00
Misa
6ba7058a0e Fix VSync renderer workaround
SDL just got an API to toggle VSync without having to tear down the
renderer ( libsdl-org/SDL#4157 ). We can remove the workaround and use
that instead. For now, we are putting it behind an ifdef until SDL
2.0.18 officially releases in November.

Fixes #831.
2021-09-14 20:23:22 -07:00
Misa
8d0a90a588 Avoid function call to check empty room name
Instead, a simple comparison of the first element will do.
2021-09-12 21:54:47 -07:00
Misa
ddff461a6c Replace hardcoded temp buffer sizes with a named constant
Constants.h will house constants like the screen size and others. But
basically only the screen size for now.

Now we don't have to type that "4 bytes per 40 chars (whole screen)"
comment everywhere...
2021-09-12 21:40:20 -07:00
Misa
ffe53746bc Rename textbox to textboxes and textbox line to lines
It's really dumb that these array names aren't plural when they should
be, because they contain more than one thing.
2021-09-12 21:06:27 -07:00
Misa
a50e8ecf48 Replace roomnames/hiddennames/glitchnames with const char*
Since those are all downstream recipients of either static storage or
memory that doesn't move for the duration of the custom level, it's okay
to make these be `const char*`s without having to redo any of the RAII
memory management.

mapclass::currentarea() is included in this as well. I also cleaned up
Tower.cpp's headers to fix some transitive includes because I was
removing UtilityClass.h includes from all other level files too.

The "Untitled room" names no longer show any coordinates, because doing
so would require complicated memory management that's completely
unneeded. No one will ever see them, and if they do they already know
they have a problem anyway. The only time they might be able to see them
is if they corrupted the areamap, but this was only possible in 2.2 and
previous by dying outside the room deaths array in Outside Dimension
VVVVVV, which has since been patched out. Besides, sometimes the
"Untitled room" gets overwritten by something else anyway (especially in
Finalclass.cpp), so it really, really doesn't matter.
2021-09-12 21:06:26 -07:00
Misa
a10342f5e6 Replace setblockcolour() argument with const char*
There's no reason it needs to be an std::string here.

Although, realistically, we should be using an enum instead of
string-typing, but, eh, that can be fixed later.
2021-09-12 21:06:26 -07:00
Misa
2991b2341a Fix regression with companions not spawning
Companions would not spawn if you didn't load the current room via a
room transition. This meant that companions wouldn't spawn if you loaded
a save file with a companion, at least not until you moved to a
different room and triggered a screen transition. But most importantly,
it meant that the Intermission 1 supercrewmate would never spawn,
because going to Intermission 1 does a straight gotoroom, and does not
do a room transition.

Turns out the roomchange refactor broke things, because of course it
did. The companion logic was implicitly relying on that bool to be set,
because...? Either way, it doesn't make sense. Using roomchange implied
that the code wanted to be ran only when doing a room transition, which
is clearly not the case here. The best thing to do here is to just move
it to a separate function that gets called at the end of
mapclass::gotoroom().
2021-09-11 22:53:07 -07:00
Misa
a7ae3e0fb0 Remove scmmoveme
So, I ended up breaking supercrewmate spawning with that roomchange
refactor. However, upon investigating how to fix it, I was running into
a weird interpolation issue due to scmmoveme, as well as the companion
spawning in the ground in "Very Good". And I was wondering why I or no
one else ended up running into them.

Well, as it turns out, scmmoveme ends up doing absolutely nothing. There
are only two instances where scmmoveme is used. The first is if you
respawn in "Very Good", and somehow have your scmprogress set to that
room. But that's impossible, because whenever you respawn, your
scmprogress is always set to the one after the room you respawn in. Even
if you respawned in the room previous to "Very Good" (which is "Don't
Get Ahead of Yourself!"), it still wouldn't work, since the logic always
kicks in when a gotoroom happens, and not only when a supercrewmate is
actually spawned. Since the scmprogress doesn't match, that case never
gets triggered, and we get to the second time scmmoveme is used, which
is in the catch-all case that always executes.

This second instance... also does nothing, because since we just
respawned, and our scmprogress got set to the room ahead of us, there is
no supercrewmate on screen. Then getscm() returns 0, and the player is
always indice 0, so the only thing we end up doing is setting the
player's x-position to their own x-position. Brilliant.

Anyway, this code results in interpolation issues and the supercrewmate
spawning in the ground on "Very Good" if you die, when my fix is
applied, because my fix moves this logic around to a different frame
order, and that actually ends up making scmmoveme no longer dead code.

So to recap: we have dead code, which looks like it does something, but
doesn't. But if you move it around in a certain way, it ends up having
harmful effects. One of the joys of working on this game...

It's also hilarious that it gets saved to the save file. Why? The only
time this variable is true, it is for literally less than a frame,
because it always gets set to false, because you always respawn using a
gotoroom whenever the supercrewmate dies, because you never respawn in
the same room as a supercrewmate, because Intermission 1 was
deliberately designed that way (else you'd keep continually dying since
the supercrewmate wouldn't move out of the way).
2021-09-11 22:23:47 -07:00
Misa
029463ad47 Remove unused or useless SDL_Rects from Graphics
These were bfont_rect, bg_rect, foot_rect, and images_rect.

bg_rect was only used once to draw the ghost buffer in the editor, but
that was only because Ally didn't know you could just pass NULL in, cuz
the ghost buffer is the same size as the backbuffer.
2021-09-11 02:24:55 -07:00
Misa
d3a868b566 Axe RGBflip() in favor of getRGB()
RGBflip() does the exact same thing as getRGB(), now that all the
surface masks have been fixed. This axes RGBflip() and changes all
callers to use getRGB() instead. It is more readable that way.

By doing this, there is less copy-pasting. Additionally, it is now
easier to search for RGBf() - which is an ENTIRELY different function
than RGBflip() - now that the name of RGBf is no longer the first four
characters of some different, unrelated function. Previously I would've
had to do `rg 'RGBf[^\w]'` which was stupid and awful and I hated it.
2021-09-11 02:15:20 -07:00
Misa
f237f41d8e Remove useless arguments from drawimagecol()
Turns out, the r, g, and b arguments don't actually do anything!

There was a call to RGBf() in the function. RGBf() is just getRGB() but
first adds 128 and then divides by 3 to each of the color channels
beforehand. Unfortunately, RGBf() does not have any side effects, and
the function threw away the return value. Bravo.

This also reveals that the website images drawn in the credits in the
main menu are only recolored because of a stale `ct` set by the previous
graphics.bigprint(), and not because any color values were passed in to
drawimagecol()... What fun surprises the game has in store for me every
day.
2021-09-11 02:12:03 -07:00
Misa
58ae93c4cc Music: Do not do fades if not playing
This fixes a regression where entering playtesting while a track was
fading out (by exiting out of playtesting with a track playing and then
immediately entering back in with the level start music set) would
result in no music.

The cause is the game doing fades even though nothing is playing, which
puts it in a confusing state.
2021-09-10 19:37:33 -07:00
Misa
8e02b90b76 Move Mix_PausedMusic() call into wrapper function
This wrapper function is for (a) future-proofing (b) proactive
prevention of future copy-pasting (c) to clarify that we never actually
halt music in the SDL_mixer sense, we only pause it, so to check if the
music is halted we actually check if the music is paused instead. This
is important because Mix_PlayingMusic() does not check if the music is
paused and Mix_PausedMusic() does not check if the music is halted.
2021-09-10 19:37:31 -07:00
Misa
06a88eff39 Kludge-fix being able to play music in editor
When you're on the music changing screen in the editor, it plays the
current track. When you return, it stops playing the track. However, if
you press escape, it doesn't stop playing the track. This is because
pressing escape just returns to the previous menu without stopping
playing the track.

To fix this, I just added some kludge in the return menu function. This
is kinda super bad but it works for now and is just something to clean
up later. Maybe like each menu having exit callbacks or something, I
dunno.

This is kinda a regression, kinda sorta not. In 2.2 and previous,
pressing escape would just close the settings menu entirely, which also
bypassed the music fadeout. 2.3 made it so pressing escape doesn't
entirely close the settings menu, and just returns to the previous menu,
which fails in a different way. But the intended way is definitely to
select the return option and having the music fade out.
2021-09-10 18:56:12 -07:00
Misa
e3bfc79d4a Reset some stats that weren't being reset in deletestats
This function now properly deletes the Super Gravitron record, the Super
Gravitron rank, and the best game deaths. They were not being properly
reset previously, meaning you would have to go into your save file to
properly clean out your save data.
2021-09-10 18:02:52 -07:00
Misa
74b7ce9d80 Reset fade booleans when silencing music
This fixes a bug where the music would keep playing when a collection
prompt appeared if the music was still fading in at that time.
2021-09-10 17:02:24 -07:00
Misa
6f499abef0 Fix platv values outside map size being saved as 67372036
If the map size was less than 20x20, platv values outside the map would
end up being saved as 67372036.

This happens because SDL_memset() operates on the byte level, and not
the multi-byte level. So it takes only the lower 8 bits of 4 and repeats
it for each byte in each integer, creating 67372036.
2021-09-10 16:58:53 -07:00
Misa
07bbc5b2de Don't check !muted when fading music after completion prompt
This was done in 2.2 and previous probably to fix the fact that there
were multiple conflicting audio controls (the player wants to mute the
audio but the game wants to fade in the audio), but is now actively
harmful since 2.3, because muting the game while finishing the
completion prompt means the music will never come back in, even after
unmuting.

I also notice that when collecting a custom crewmate, the game checks
for the level's start music instead of if there's actually a current
song playing right now. I don't know why this was done, because it
would've been better to copy-paste the trinket collection logic here.
It's entirely possible for the audio to just be muted and never come
back if the level has no start music but plays a song by using a script.
Anyways, leaving it alone because it's quite possible that a level might
be intentionally designed around this, I can't really tell the
intentions of every level creator, and it's easy to work around (either
don't use custom crewmates, which every modern level basically does
nowadays, or just set the start music).
2021-09-10 15:48:18 -07:00
Misa
3185d88776 Don't touch music when completing custom level
For some reason, when completing a custom level and fading to the menu,
the game attempts to fade the music in and also fade the music out at
the same time. This results in nothing happening at all, and in 2.2 and
previous, results in audio fading out from max volume while the game is
frozen on a black screen after the fadeout.

To avoid any potential badness, just remove these.
2021-09-10 15:42:25 -07:00
Misa
91b63e7f88 Fix dying during collection prompt persisting effects
In the main game, if you press R during the trinket collection prompt
after collecting a trinket, AND you have never entered Comms Relay, and
you respawn in a different room, the trinket collection gamestate will
be interrupted, but you will still be left with the advance text prompt,
cutscene bars, and muted music.

The previous workaround to fix the music would be to mute and then
unmute the game, but due to the new music changes, this workaround
(which in and of itself is a bug) no longer works. Instead, the music
would have to be restarted by going into another zone on the map.

Having an advance text prompt outside of a cutscene results in the
player being unable to flip, but they can still move around left and
right.

Speedrunners previously used the no-Comms-Relay interrupting behavior to
skip certain trinket collection prompts entirely with a frame-perfect R
press, so I can't patch that out. Having an advance text prompt outside
of a cutscene is (ab)used in custom levels to intentionally prevent the
player from flipping, and furthermore, it's also used in credits warp
runs of the main game to increment the gamestate; so I cannot patch that
out. The ability to press R everywhere even during cutscenes was added
for good reason - to make it less likely that a softlock can happen - so
I don't want to revert it.

But I still think this is worth fixing because previously, the
punishment for missing the frame-perfect window late was simply not
skipping the trinket prompt (since the R-press would be ignored), but
now the punishment is basically having to reset because of the advance
text prompt.

I would usually handle this in gamestate 0, but awful custom levels
might want to intentionally interrupt the gamestate to do, I don't know,
something. No level does that so far, but I'd like to do the least
invasive thing.

So what I've done is made it so the effects of interruption are undone
if you press R and the gamestate is interrupted. This is handled in
mapclass::resetplayer().
2021-09-10 11:49:46 -07:00
Misa
c83a360dd3 Fix unused variable warning on non-Emscripten
Otherwise, the compiler would warn that `sync` is unused.
2021-09-08 11:43:23 -07:00
leo60228
15b6fb0edd Remove -sFORCE_FILESYSTEM=1 from compile options
The latest Emscripten will warn that it should only be passed as a
linker option.
2021-09-07 09:43:48 -07:00
leo60228
7560b8b60b Handle lost focus on Emscripten
This was previously disabled, since it didn't seem to work. However, the
previous commit fixes the root issue.
2021-09-07 09:43:48 -07:00
leo60228
d40af63aa3 Split Func_input and Func_delta when unfocused
Without this, `fixedloop` will loop infinitely until focus is regained.
However, Emscripten won't actually know that focus is regained until
`fixedloop` returns.
2021-09-07 09:43:48 -07:00
Misa
7430be69e3 Remove getBGR
getBGR, when used in FillRect, was actually passing colors in RGB order.
But now the masks are fixed, so remove it, and fix up all existing
getBGR colors to use getRGB instead.
2021-09-06 20:12:48 -07:00
Misa
f6c9ff848f Fix all FillRect getRGB calls to be passed in RGB order
Due to the mask inconsistencies, getRGB calls that were passed to
FillRect ended up actually being passed in BGR order. But now that the
masks are fixed, all these BGR colors look wrong. So, fix up all of them
(...that's a _lot_ of copy-pasted code...) to be passed in RGB order.
2021-09-06 20:12:48 -07:00
Misa
d0b81d8eff Simplify clearing surface in preloader with ClearSurface()
It conveys intent better.
2021-09-06 20:12:48 -07:00
Misa
37b7615b71 Fix surface color masks
This fixes the color ordering of every SDL_Surface in the game.

Basically, images need to be loaded in ABGR format (except if they don't
have alpha, then you use RGB? I'm not sure what's going on here), and
then they will be converted to RGB/RGBA afterwards.

Due to the surfaces actually being BGR/BGRA, the game used to use
getRGBA/getRGB to swap the colors back around to BGRA/BGR, but I've
fixed those too.
2021-09-06 20:12:48 -07:00
Misa
2c0d6920e8 bprintalpha: Call PrintAlpha with a false cen
Whoops.

This fixes it so the outlines actually show up on the horizontal sides
of the outlined text.
2021-09-06 19:50:24 -07:00
Misa
c64fd89325 Untabify every single file
YOLO.

This is a repeat of #642. As before, I just did

    rg -l '\t' | xargs -n 1 sed -i -e 's/\t/    /g'

inside the desktop_version/ folder.
2021-09-06 18:56:39 -07:00
Misa
b3f437fe55 Rename respawncolour to savecolour
Since it's a variable like saverx/savery/savex/savey, it should be
renamed to savecolour and placed with all of them.
2021-09-06 18:28:28 -07:00
Misa
8e61a04937 Add changerespawncolour() script command
This command simply changes the color that the player respawns with upon
death. The respawn color also persists through custom save files.

Closes #830.
2021-09-06 16:11:19 -07:00
Misa
33c5b8b7c0 Use const std::string& where possible in function params
If it's at all possible to use `const std::string&` when passing
`std::string`s around, then we use it. This is to limit the amount of
memory usage as a result of the frequent use of `std::string`s, so the
game no longer unnecessarily copies strings when it doesn't need to.
2021-09-06 15:43:59 -07:00
Misa
ff07f9c268 De-duplicate text printing functions
I've made a new function, Graphics::do_print(), that does the actual
text printing itself. All the interfaces of the other functions have
been left alone, but now just call do_print() instead.

I also removed PrintOffAlpha() and just calculated the center x-position
in bprintalpha() itself (like bigbprint() does) to make it easier to
de-duplicate code.
2021-09-06 15:43:59 -07:00
Misa
730c935218 Textboxes: Don't use separate RGB variables
Text boxes have `r`, `g`, and `b`, and `tr`, `tg`, and `tb`. `tr`, `tg`,
and `tb` are the real colors of the text box, and `r`, `g`, and `b` are
merely the colors of the text box as the text box's alpha value is
applied to them.

Compare this with, say, activity zones (which are drawn like text boxes
but aren't text boxes): There is `activity_r`, `activity_g`, and
`activity_b`, and when they're drawn they're all multiplied by
`act_alpha`.

So just do the same thing here. Ditch the `tr`, `tg`, and `tb`
variables, and make `r`, `g`, and `b` the new `tr`, `tg`, and `tb`
variables. That way, there's simply less state to have to update
separately. So we can get rid of `textboxclass::setcol()` as well.
2021-09-06 00:56:49 -07:00
Misa
13a0c1282d drawgui: Don't declare loop vars in for initializers
Sneaky no-code-and-declarations-mixing fix.
2021-09-06 00:56:49 -07:00
Misa
a7aa92232f Remove redundant FillRect when drawing text boxes
This was already done in the drawtextbox function... so we were just
double-drawing the text box backing for absolutely no reason.
2021-09-06 00:56:49 -07:00
Misa
e9c3b03eba Remove unused SDL.h include from Textbox.h
Really unsure why it was included here. Not even any downstream users of
Textbox.h use any SDL functions from this include.
2021-09-06 00:56:49 -07:00
Misa
69fcdf9217 Remove useless variable lw from textboxclass
This variable is only assigned to, but never read from. Hence, it is
useless, and should be removed to make code analysis less complicated.
2021-09-06 00:56:49 -07:00
Misa
e47ff8131b Move max off of textboxclass
This is a variable that's only used in one method, and it's always
initialized beforehand. No need to carry it around, taking up memory,
and making code analysis more complicated.
2021-09-06 00:56:49 -07:00
Misa
9a637d0c0f Clean up style of drawcoloredtile
All unmutated parameters have been made const.

Declarations and code are no longer mixed.

Spacing has been made consistent.
2021-09-06 00:56:49 -07:00
Misa
1b236d5ec7 Clean up style of drawtextbox/drawpixeltextbox
All parameters are now made const, to aid in the reader in knowing that
they aren't ever changed.

Useless comments have been removed and been replaced with helpful
comments.

Useless parentheses have been removed.

Spacing has been made consistent.

Declarations and code are no longer mixed.
2021-09-06 00:56:49 -07:00
Misa
36d0056c2c drawtextbox: Use drawpixeltextbox
Since these two are so similar, why not just use this one for the other?
Saves on copy-pasting code.
2021-09-06 00:56:49 -07:00
Misa
9767eb91f4 drawpixeltextbox: Remove now-unused parameters
They go bye-bye.

This is a friendly reminder that the map menu rendering code is heavily
copy-pasted, dear god...
2021-09-06 00:56:49 -07:00
Misa
31844eabc6 Axe drawcustompixeltextbox in favor of drawpixeltextbox
I'm honestly not too sure why drawcustompixeltextbox ever existed? All
it seemed to do was draw even more horizontal/vertical tiles to finish
any gaps in the tiling... which was all completely unnecessary and
wasteful, because even the previous drawpixeltextbox implementation
covered all gaps in all custom level map sizes that I tried.

Anyway, that at least gets rid of one copy-pasted function.
2021-09-06 00:56:48 -07:00
Misa
02b1fedeb1 drawpixeltextbox: Draw remaining horz/vert tile if non-multiple-8
This draws the remaining horizontal/vertical tile just beside the final
corner if the width/height is not a multiple of 8. (It'd be wasteful to
draw it if the width/height was a perfect multiple of 8, and result in
double-drawing translucent pixels if there were any.)

This has an advantage over the previous system of shifting the
horizontal/vertical tiling, in that custom corner textures don't look
weird due to overlapping like this. Now, custom horizontal/vertical
tiles _can_ look weird if they don't completely tile correctly (or if
they have translucent pixels), but that's better than mucking up the
corners.
2021-09-06 00:56:48 -07:00
Misa
1eb3e73c00 drawpixeltextbox: Don't use unneeded variables
`w` and `h` are provided alongside `w2` and `h2`. `w2` and `h2` are in
blocks of 8, while `w` and `h` are in pixels. Therefore, `w2` and `h2`
can just be figured out by diving `w` and `h` by 8.

Also, `xo` and `yo` were used to slide the horizontal/vertical tiling of
the text box a bit into one set of corners, so the horizontal/vertical
tiling wouldn't visibly overlap with the other corners, if using default
textures. This requires hardcoding it for each width/height of text box,
which isn't something that's generalizable. Also, it results in corners
that look weird if the corners have custom textures that don't adhere to
the same shape as default textures.

In the next commit I'll fix the non-multiple-of-8 text box dimensions
differently. Can't do it in this commit or the diff looks weird (at
least with my diff algorithm).
2021-09-06 00:56:48 -07:00
Misa
651cd4b674 Use drawtextbox() to draw text boxes
I have no idea why this perfectly good function was unused in favor of
copy-pasting all of its code.
2021-09-06 00:56:48 -07:00
Misa
fc2de88b03 Use SDL_BlitScaled in ScaleSurface
Why do all this error-prone per-pixel work when you can just use an SDL
function instead?
2021-09-05 20:07:18 -07:00
Misa
77696c0d55 Don't check map.extrarow when opening map
This is just to make sure there aren't any more inconsistencies with
regards to the value of graphics.menuoffset. Can't hurt to be sure.
2021-09-05 17:04:26 -07:00
Misa
edf949bd9c Use resumegamemode to track menu animation
This fixes a bug where the player could bring up the map on the very
first frame of a gamemode(game) animation. This is because the menu
animation checked graphics.menuoffset, but graphics.menuoffset wouldn't
have changed at that point because it only set graphics.resumegamemode.

Instead, just check for graphics.resumegamemode directly. We also need
to assign it to false whenever the map is closed so the player won't be
prevented from using the map screen again.
2021-09-05 16:59:05 -07:00
Misa
da6c524db5 Don't use map.extrarow for menu animations
This fixes all the headaches about map.extrarow having to be the correct
value and which way it should be and whatnot. The latest headache was
the detection that prevent user-initiated menu animations while an
animation was already happening being tripped because
graphics.menuoffset would be 230 (due to closing the menu while being in
a room without a room name), but then going to a room with a room name
would check for 240 instead, and 230 is less than 240. (The numbers are
the wrong way round because I got the ternaries the wrong way round, but
even if the numbers are the correct way round, the bug would still
happen, but it would just be reversed.)

So instead, I've just made it 240 for both. This doesn't change the
duration of the menu animation (because the animation moves in
increments of 25, and 230 / 25 == 240 / 25 under integer division). It
might change the animation slightly, but it was already inconsistent
anyway because map.extrarow was always set to be 1 in custom levels, and
I legitimately would not be able to tell the difference without
recording the animations and nitpicking it frame-by-frame.

Fixes #841.
2021-09-03 17:13:03 -07:00
Misa
727400ff27 Only reset fade booleans when music is actually played
Otherwise, the block that fades existing music out if m_doFadeOutVol is
true will never execute, because m_doFadeOutVol would always be false!
2021-09-03 16:38:34 -07:00
Ethan Lee
aba3a8ee9d Updated .ico 2021-09-03 15:57:16 -04:00
Misa
4339bbadbb Add message when player is kicked out of Super Gravitron
The player gets kicked out of the Super Gravitron if they have
invincibility or slowdown enabled. However, this can be confusing if no
message pops up
( https://steamcommunity.com/app/70300/discussions/0/3039355280230178910/ )
. So I've made it so that a text box will pop up when they get kicked
out.
2021-09-03 12:08:31 -07:00
leo60228
d64608ecaa Correct onground/onroof check 2021-09-02 16:09:06 -07:00
leo60228
72ade2ce49 Only execute flip logic when has_control 2021-09-02 16:09:06 -07:00
leo60228
58098dc748 Only apply flip momentum to player entities on ground/roof 2021-09-02 16:09:06 -07:00
Misa
e30fc4500e gamemode(teleporter): Set gamestate to GAMEMODE
This makes it so gamemode(teleporter) will always do an animation, even
if the game is already in TELEPORTERMODE.

I used this script to test:

    gamemode(teleporter)
    delay(5)
    gamemode(teleporter)
    delay(5)
    gamemode(teleporter)

In 2.2, this script starts the map menu bringing-up animation three
times.

In previous 2.3, this script starts the map menu bringing-up animation
once, but then the next gamemode(teleporter) immediately finishes the
animation, and the third gamemode(teleporter) does nothing.

This commit restores it to 2.2 behavior.
2021-09-02 12:23:17 -07:00
Misa
5b10164659 Prevent user-initiated map menu changes during menu animations
This makes it so it's not even possible to stay on the TELEPORTERMODE
screen by opening the map while it's being brought down. It also makes
it so the map animation is able to be canceled when being brought up
just by opening the map and closing it.

Fixes #833.
2021-09-02 12:21:46 -07:00
Misa
e9ec34e1f5 Call teleporterrenderfixed in TELEPORTERMODE
This restores it to 2.2 behavior, where the cutscene bars timer also
ticked in TELEPORTERMODE. It was a 2.3 regression that the cutscene bars
timer didn't tick there.

This makes it so if you manage to get stuck in TELEPORTERMODE when a
cutscene ends, the cutscene won't be stuck on untilbars() waiting for
the cutscene bars to go away, since the cutscene bars timer now ticks.
2021-09-02 11:46:56 -07:00
leo60228
be2b1564a8
Call FS.syncfs on Emscripten (#838)
Also, add a sync parameter to avoid calling syncfs too often.

Calling syncfs twice in a row is both inefficient and leads to errors
displaying twice. This allows us to bypass it when saving unlock.vvv as
part of savestatsandsettings.
2021-09-02 13:19:51 -04:00
Misa
3c318814a4 Remove EditorData and put its attributes on customlevelclass
This object basically had no reason to exist... it was just more verbose
to use, which really reminded me of Java. Anyway, this is the last thing
named after the editor for no reason when it should be a part of the
customlevelclass, so I moved its attributes to customlevelclass.
2021-09-01 15:30:02 -07:00
Misa
8bff287907 Rename edentity to customentities
This fixes the fact that the name of the singular type is plural, but
the name of the plural array is singular. Which has always annoyed me,
too. Also this makes it more clear that custom entities don't have much
to do with the editor.
2021-09-01 15:30:02 -07:00
Misa
47d01277bf Rename edentities to CustomEntity
That's what it is - it's an entity in a custom level. Not something to
do with the editor, necessarily. Like before, the name of the XML
element will remain the same.
2021-09-01 15:30:02 -07:00
Misa
3c30d9b7f0 Rename cl.level to cl.roomproperties
I mean, that's what they are. Room properties are within a level, not a
level themselves. So...
2021-09-01 15:30:02 -07:00
Misa
d549a535e0 Rename edlevelclass to RoomProperty
That's what edlevelclass is... so that's what it should be named. (Also
removes that "ed", too, making this less coupled to the in-game editor.)

Unfortunately, for compatibility reasons, the name of the XML element
will still remain the same.
2021-09-01 15:30:02 -07:00
Misa
86b47878f9 Fix number of spaces of indentation of CustomLevels.h
CustomLevels.h now uses 4-space indents - like all other space-indented
files - instead of 2-space indents. This has bugged me for a while and I
decided to just fix it now.
2021-09-01 15:30:02 -07:00
Misa
a23014350f Move all editor-specific attributes to a new editorclass
This is a pretty hefty commit! But essentially, I made a new editorclass
object, and moved all functions and variables that only get used in the
in-game level editor to that class. This cleanly demarcates which things
are in the editor and which things are just general custom level stuff.

Then I fixed up all the callers. I also fixed up some NO_CUSTOM_LEVELS
and NO_EDITOR ifdefs, too, in several places.
2021-09-01 15:30:02 -07:00
Misa
987ae88909 Remove comment from top of editorclass
There's no need for this comment; it's quite obvious that editorclass is
a class about the editor and will contain editor variables.
2021-09-01 15:30:02 -07:00
Misa
6df182b38d Remove getLevelDirFileNames() from editorclass
As far as I can tell, this function has never been implemented, and only
existed in this header file. FILESYSTEM_getLevelDirFileNames() already
exists (well, used to exist; it's been changed and renamed to
FILESYSTEM_enumerateLevelDirFileNames()), so I'm removing this now.
2021-09-01 15:30:02 -07:00
Misa
83cccbed07 Remove contents memset from editorclass constructor
It gets (re-) initialized in editorclass::reset() anyway, so I'm just
removing this for code clarity.
2021-09-01 15:30:02 -07:00
Misa
6f0177ec04 Move editor functions to separate header
Editor functions now live in Editor.h, which is a new file - the
existing editor.h has been renamed to CustomLevels.h.
2021-09-01 15:30:02 -07:00
Misa
3e380e23fb Rename editor.h to CustomLevels.h
This accompanies the editor.cpp -> CustomLevels.cpp change; I'll be
splitting out the editor functions in the next commit. The name of the
include guard has been changed as well, but not anything else.
2021-09-01 15:30:02 -07:00
Misa
3fe0f01bcc Move editor functions to separate file
This moves editorrenderfixed(), editorrender(), editorinput(),
editorlogic(), and their associated functions to a new file named
Editor.cpp - which is exactly what it says on the tin; it stores all the
functions related to the actual in-game editor loop. Also, the existing
editor.cpp has been renamed to CustomLevels.cpp.
2021-09-01 15:30:02 -07:00
Misa
3ef5248db9 Simplify and print XML errors from TinyXML-2
All XML functions now check the return value of
tinyxml2::XMLDocument::Error() after each document gets loaded in to
TinyXML-2. If there's an error, then all functions return. This isn't
strictly necessary, but printing the error message that TinyXML-2 is the
bare minimum we could do to be useful.

Additionally, I've standardized the error messages of missing or
corrupted XML files.

Also, the way the game went about making the XML handles was... a bit
roundabout. There were two XML handles, one for the document and one for
the root element - although only one XML handle suffices. So I've
cleaned that up too.

I could've gone further and added error checking for a whole bunch of
things (e.g. missing elements, missing attributes), but this is good
enough.

Also, if unlock.vvv or settings.vvv don't exist yet, the game is
guaranteed to no-op instead of continuing with the function. Nothing bad
seems to happen if the function continues, but the return statements
should be there anyway to clearly indicate intent.
2021-09-01 15:09:40 -07:00
Misa
cbc84edb0e Remove superfluous message if settings.vvv/unlock.vvv don't exist
If settings.vvv doesn't exist, loadsettings() calls savesettings(), but
savesettings() already prints a message if settings.vvv doesn't exist.
So then the output would look like

    No settings.vvv found. Creating new file
    No settings.vvv found

Which is clearly redundant.

The same thing happens with unlock.vvv, but in that case the following
prints instead

    No unlock.vvv found. Creating new file
    No Stats found. Assuming a new player
2021-09-01 15:09:40 -07:00
Misa
73535b4342 De-duplicate loadsummary parsing and move to different function
I will need to be able to return from this function if there's an XML
error, otherwise writing out the control flow manually gets really
nasty. And while I'm at it, it's some a nice de-duplication as well.

To do this, we create a temporary struct that bundles up all the
information we want for the summary, and pass it in to the intermediate
load function.

Furthermore, we can get rid of reading map.finalstretch - it affects
nothing. map.finalmode is still needed, however, because of the usage of
map.area().
2021-09-01 15:09:40 -07:00
Misa
bbc2f06d81 De-duplicate quick/telesummary fetching in Game::init()
The less copy-pasted code, the less work for me later.
2021-09-01 15:09:40 -07:00
Misa
c58c357a81 Simplify Flip Mode rendering code with SDL_RenderCopyEx
Previously, Flip Mode rendering had to be complicated and allocate
another buffer to call FlipSurfaceVerticle, and it was just a mess.

Instead, why not just do SDL_RenderCopyEx, and let SDL flip the screen
for us? This ends up pretty massively simplifying the rendering code.
2021-09-01 14:44:59 -07:00
Misa
23a2f57a70 Replace some info logs with debug logs
These are a bit noisy, so I've replaced them instead.
2021-09-01 14:34:55 -07:00
Misa
b652d327dc Add debug logs
These are disabled by default, because they're noisy. To enable them,
pass -debug.
2021-09-01 14:34:55 -07:00
Misa
2eb9e23ecc Allow disabling output/fine-tuning output
-nooutput disables output completely (both STDOUT and STDERR). -noinfo
disables INFO lines.  -nowarn disables WARN lines. -noerror disables
ERROR lines.
2021-09-01 14:34:55 -07:00
Misa
c68a274c4f Add command-line options to force-enable/disable color
`-forcecolor` will force color to be on. `-nocolor` will force color to
be off.

And just because I'm a nice person, I've also added British versions of
those flags. As a treat.
2021-09-01 14:34:55 -07:00
Misa
ac85f57441 Add colors to logging
This includes the bold as well.

INFO is just default, WARN is yellow, ERROR is red.

We try to automatically detect if the output is a TTY (and thus supports
colors), and don't emit colors if so. Windows 10 supports ANSI color
codes starting with a specific build, but we don't care to emit whatever
garbage Microsoft invented for builds older than that.
2021-09-01 14:34:55 -07:00
Misa
96539f891c Replace all print calls with vlog calls
This is pretty straight-forward to do.
2021-09-01 14:34:55 -07:00
Misa
d9737589de Add logging functions
Named "vlogs" because they're logs for VVVVVV. Also it's a funny name.
2021-09-01 14:34:55 -07:00
Ethan Lee
ac0644a70a Added my quick script to fixup Mac dylib paths 2021-09-01 12:07:57 -04:00
Misa
5abe615507 Fix Pauli Kohberger's name stopping being drawn too early
This is because the y-position of the graphics.onscreen() check was a
little too high. Then their name (under Beta Testing) would suddenly
disappear too early. You'd have to look real close to spot it, but it
does happen. It's cuz the credits are all kinda hardcoded, which is
probably bad, but fixing that would have to come later...
2021-08-31 23:23:27 -07:00
Misa
4c69281738 Move Misa to C++ credits
I talked with Ethan earlier about this. For 2.3, he wanted me in GitHub
contributors (well, still separate from the rest), to really highlight
the source-code-release community-driven nature of 2.3, but he said it'd
be fine to put me in C++ credits in 2.4.
2021-08-31 23:22:22 -07:00
Misa
0028e314e4 Suppress unused i warning if NUM_BACKENDS is 0
Else this warning would pop up if not compiling an OFFICIAL_BUILD.
2021-08-31 23:12:38 -07:00
Misa
146678aac4 Make PhysFS RWops work with -DBUNDLE_DEPENDENCIES=OFF
The RWops stuff isn't a part of any standard PhysFS package (and given
that it explicitly wraps around SDL I'm not sure how you _would_ package
it). So we need to get the physfsrwops.h include in if
BUNDLE_DEPENDENCIES is off, otherwise this results in a compile-time
include-not-found failure.

Additionally, I've placed the PhysFS RWops stuff in their own extras/
folder, so none of the other PhysFS stuff gets included in a
-DBUNDLE_DEPENDENCIES=OFF build.
2021-08-31 23:09:13 -07:00
Ethan Lee
342dfcb48d Minor VS buildfix 2021-08-31 19:07:24 -04:00
leo60228
14c24069fd Fix indentation consistency 2021-08-31 15:37:52 -07:00
leo60228
52fceb3f69 Allow any player entity to be on the ground/roof to flip
This re-adds the midair flip glitch.
2021-08-31 15:37:52 -07:00
leo60228
1e8b5a6ba7 Actually move checks out of loop
How did this ever work?
2021-08-31 15:37:52 -07:00
leo60228
cd4ce05cb3 Split out tap_left and tap_right from player input loop
The game will freeze the player immediately if they release a
directional button within 3 frames of pressing it. Similar to flipping,
this involves global state, and will only apply to the first player
entity.
2021-08-31 15:37:52 -07:00
leo60228
1eb8570329 Split flip logic from player input logic
Closes #484

Flipping only applies momentum to the player entity currently being
processed. This normally wouldn't be a problem. However, flipping
involves global state, and only one flip can occur per frame. This means
that additional player entities don't get this boost of momentum, which
feels somewhat unnatural during gameplay.

This commit fixes this by splitting flip logic out of the loop over
player entities, and applying the flip momentum to all player entities.
2021-08-31 15:37:52 -07:00
Misa
416fe00c9d Fix not-Flip-Mode flag turning off when returning from options menu
We need to check for graphics.setflipmode, not graphics.flipmode,
because graphics.flipmode only gets assigned at the end of the frame
(due to the deferred callback). Otherwise, returning from the options
menu would always turn flag 73 on, which would make you ineligible to
get the Flip Mode trophy, even if you're in Flip Mode.
2021-08-31 15:33:20 -07:00
leo60228
de0998ca34 Compile physfsrwops with VVVVVV because of SDL dependency 2021-08-31 15:30:23 -07:00
leo60228
668c3d91d6 Return false from unPackBinary if no tracks are valid 2021-08-31 15:30:23 -07:00
leo60228
f86a67456b Remove data/ from track name list, refactor music loading, and support loose ogg music
(these should be separate commits but they're annoying to split after
the fact, oh well)
2021-08-31 15:30:23 -07:00
leo60228
5b6c4b6b28 Add physfsrwops 2021-08-31 15:30:23 -07:00
Ally
64be7dbd53
Refactor colors in internal commands
Originally this started as a "deduplicate a bunch of duplicated code in script commands" PR,
but as I was working on that, I discovered there's a lot more that needs to be done than
just deduplication.
Anything which needs a crewmate entity now calls `getcrewmanfromname(name)`, and anything which
just needs the crewmate's color calls `getcolorfromname(name)`. This was done to make sure that
everything works consistently and no copy/pasting is required. Next is the fallback; instead of
giving up and doing various things when it can't find a specific color, it now attempts to treat
the color name as an ID, and if it can't then it returns -1, where each individual command handles
that return value. This means we can keep around AEM -- a bug used in custom levels -- by not
doing anything with the return value if it's -1.

Also, for some reason, there were two `crewcolour` functions, so I stripped out the one in
entityclass and left (and modified) the one in the graphics class, since the graphics class also
has the `crewcolourreal` function.
2021-08-31 15:09:51 -07:00
Ethan Lee
8ebf8a21e4 Default to VSync being enabled 2021-08-31 15:08:46 -04:00
AllyTally
1c34dc2533 Reset new variables in hardreset 2021-08-31 11:17:00 -07:00
AllyTally
656941202a Fix formatting and add an INBOUNDS_VEC
If `setactivitytext` was the last line in a script,
the command would index the vector out of bounds.

I also modified the formatting to keep consistent
with the rest of the codebase.
2021-08-31 11:17:00 -07:00
AllyTally
b15e25f106 Add setactivitycolour(colour) and setactivitytext() commands
These commands will change the colour and text of the next
activity zone that gets spawned. `setactivitycolour` takes all
textbox colors, and `setactivitytext` will take the text on
the next line. These commands were designed this way
to avoid breaking forwards compatibility.
2021-08-31 11:17:00 -07:00
AllyTally
0685cade69 Change the text of custom activity zones
When an activity zone is spawned through the
use of `createactivityzone`, and `i` is 35,
then it'll change the activity zone text to
"Press ENTER to interact".
2021-08-31 11:17:00 -07:00
leo60228
1cbc3bdc7c Treat __unix__ define as generic Unix 2021-08-31 10:35:20 -07:00
leo60228
6abf87f1e4 Explicitly use void in emscriptenloop declaration
Co-authored-by: Misa <infoteddy@infoteddy.info>
2021-08-31 10:28:55 -07:00
leo60228
46ee84d6ef Disable unfocus on Emscripten 2021-08-31 10:28:55 -07:00
leo60228
0063e1c3bc Use Emscripten's main loop
On Emscripten, SDL_Delay is implemented as a busy loop. In addition,
everything happens on a single thread. This effectively means that
you have to let Emscripten manage the main loop, since if you do it
yourself the browser will just be frozen.
2021-08-31 10:28:55 -07:00
leo60228
7baf143a6b Add necessary Emscripten linker flags 2021-08-31 10:28:55 -07:00
leo60228
6d57ccc25b Support Emscripten in FileSystemUtils 2021-08-31 10:28:55 -07:00
leo60228
a689c3ab96 Support Emscripten's SDL2
Emscripten defaults to using SDL 2.0.10, but
`export EMCC_LOCAL_PORTS=sdl2=/path/to/SDL2` seems to work.
2021-08-31 10:28:55 -07:00
Misa
62cff254b7 Bump version to 2.4 2021-08-31 10:25:29 -07:00
Misa
c97b28f238 Don't hardcode destroy() arguments in loadcustom()
Otherwise, the new arguments to destroy(), which are 'moving' and
'disappear', would be thrown away by the simplified parser. Let's create
less work for ourselves to do and simply not have a hardcoded list of
allowed arguments for destroy() in the parser.
2021-08-31 09:26:39 -07:00
Misa
08971b3311 Fix destroy(platforms), implement under different names
destroy(platforms) has been bugged since 2.0. The problem with it is
that it removes the platform entity, but doesn't remove its block. This
results in essentially turning the platorm invisible and stopping it
from moving.

This error should be fixed, but some levels (including my own) rely on
the invisible platform trick. So instead, the fixed version will be
implemented under a different name, destroy(moving).

There's also another problem with destroy(platforms), which is that the
name is misleading and it doesn't additionally destroy disappearing
platforms. I would also fix this, but in order to not run the risk of
breakage, it will have to be implemented under a different name, too. So
this will be destroy(disappear). As an added benefit, it's also more
granular to have platform-destroying functions under different names
than it is to consolidate them under the same name.
2021-08-31 09:26:39 -07:00
Misa
bca8d39bd7 Axe save file migration
The chances of someone using 2.0, then directly jumping to 2.4, are
pretty low - 2.0 is almost a decade old at this point.
2021-08-31 09:26:14 -07:00
Misa
85dc6db85b Axe screen_transition variable in favor of roomchange
When I added the two-frame delay fix, I didn't realize that Game had a
roomchange variable that was being used as a temporary variable here.
Now that it's fully spelled out and obvious (just look at the top of
gamelogic()), I realize that the variable exists and is being used, and
other readers will realize it's being used too - so now that I know it
exists, I can axe the screen_transition variable I added in favor of
using roomchange instead.
2021-08-31 09:25:47 -07:00
Misa
7a598f5811 Move roomchange off of Game
The purpose of this variable was to keep track of if gamelogic() called
map.gotoroom() at any point during its execution. So map.gotoroom()
always unconditionally set it to true, and then gamelogic() would check
it later.

Well, there's no need to put that in a global variable and do it like
that! It makes it less clear when you do that.

So what I've done instead is made a temporary macro wrapper around
map.gotoroom() that also sets roomchange to true. I've also made it so
any attempt to use map.gotoroom() directly results in failure (and since
then using map.gotoroom() in the wrapper macro would also fail, I've had
to make a gotoroom wrapper function around map.gotoroom() so the wrapper
macro itself doesn't fail).
2021-08-31 09:25:47 -07:00
Misa
75ed9f9631 Move linecrosskludge off of entityclass
This is a temporary vector that only gets used in mapclass::gotoroom().
It's always guaranteed to be cleared, so it's safe to move it off.

I'm fine with using references here because, like, it's a C++ STL vector
anyway - when we switch away from the STL (which is a precondition for
moving to C), we'll be passing around raw pointers here instead, and
won't be using references here anyway.
2021-08-31 09:25:47 -07:00
Misa
382b83a54d Move roomchangedir off of Game
This is a temporary variable that doesn't need to be on Game. It is
guaranteed to be initialized every time mapclass::gotoroom() gets
called, so it's safe to move it off.
2021-08-31 09:25:47 -07:00
Misa
48cddf57a6 Reset obj.customscript in hardreset()
This prevents yet another place where stale level data from one level
could have affected another level...
2021-08-31 07:55:40 -07:00
Misa
fea2010204 Fix enemy/plat bounds not being drawn if any side touches a screen edge
Enemy/platform bounds are intended to not be drawn if they cover the
whole screen, since that's what their default bounds are.

However, the code inadvertently made it so if ANY of the bounds touched
a screen edge, the bounds wouldn't be drawn. This is because the
conditionals used "and"s instead of "or"s. The proper way to write the
positive conditional is "x1 is 0 and y1 is 0 and x2 is 320 and y2 is
240", and when you invert that conditional, you need to also invert all
"and"s to be "or"s. This is not the first time that the game developers
failed to properly negate conjunctional statements...
2021-08-28 13:03:04 -07:00
Ethan Lee
fe1c8d3336 Embedded .ico 2021-08-28 11:21:49 -04:00
Misa
fd4415317d Replace Gravitron RNG with seeded Xoshiro
This is to make it so RNG is deterministic when played back with the
same inputs in a libTAS movie even if screen effects or backgrounds are
disabled.

That way, Gravitron RNG is on its own system (seeded in hardreset()),
separate from the constant fRandom() calls that go to visual systems and
don't do anything of actual consequence.

The seed is based off of SDL_GetTicks(), so RTA runners don't get the
same Gravitron RNG every time. This also paves the way for a future
in-built input-based recording system, which now only has to save the
seed for a given recording in order for it to play back
deterministically.
2021-08-27 12:28:35 -07:00
Misa
69e36229ec Add -A Win32 flag to README
This avoids failure modes made possible by mismatching 32-bit and 64-bit
settings.
2021-08-26 13:29:05 -07:00
Misa
c591b79daf Reset words array in hardreset()
Otherwise, levels could leave stale arguments in the array, and then the
behavior of another level loaded right after might end up being
different because of that.
2021-08-25 11:12:23 -07:00
Misa
580096dded Update comments about contributor ordering
I reordered them but forgot to update these comments...
2021-08-24 09:42:23 -07:00
Misa
d472363542 Fix positioning of "Thanks for playing!"
When the screen reached the bottom of the credits, it ended up being 10
pixels higher (and not perfectly centered) than in 2.2 and previous.
2021-08-24 09:39:20 -07:00
Misa
676294332f Add Vee to credits
He did say to feel free to not credit him, but I'd like to add him
anyways just for completeness's sake.
2021-08-24 09:39:19 -07:00
Misa
e69fd80bac Add KyoZM to Credits.h
They were in CONTRIBUTORS.txt but not Credits.h.

In the future we ought to just parse CONTRIBUTORS.txt directly somehow,
but This Works Okay for now.
2021-08-24 09:38:36 -07:00
Misa
b9c028fd9b Alphabetically sort contributors by first name, not last
This is done for consistency with Terry's patrons, which are sorted by
first name and not last.

Also some people go with their usernames and so don't have a last name
to speak of, which ended up being pretty weird.
2021-08-24 09:37:36 -07:00
Misa
89d1873a5a Add Elijah Stone's GitHub handle to CONTRIBUTORS.txt
They were the odd one out out of everyone else.
2021-08-24 09:31:59 -07:00
Misa
da6871f6f4 Fix missing at-symbols on people in CONTRIBUTORS.txt
For consistency.
2021-08-24 09:14:42 -07:00
Misa
9bdd45b7e1 Update Misa's name in credits
Kai is my last name. Elizabeth is my middle name. I went with my middle
name as last name for a while before figuring out what I wanted my last
name to be.
2021-08-24 09:13:07 -07:00
Misa
950b9523ce Add Visual Studio string list
If people compile with VS 2019, then putting in VS 2010 will just result
in a weird error that's not really indicative of anything.
2021-08-24 09:11:02 -07:00
Misa
749a885d9a Actually finally fix createentity default args
Third time's the charm.

The fundamental problem with the previous attempts was that they ended
up saying arguments existed due to stale `words` anyway. So to actually
know if an argument exists or not, we need to assign to `argexists` _as_
we parse the line.

And make sure to take care of that last argument too.

Also I thoroughly tested this this time around. I'm done pulling my hair
out over this.
2021-08-22 22:47:47 -07:00
Misa
01ae5c6c70 Allow custom levels to use 2 billion tile numbers once again
Ever since tilesheets got expanded, custom levels could use as many
tiles as they wanted, as long as it fit under the 32-bit signed integer
limit.

Until 6c85fae339 happened and they were
reduced to 32,767 tiles.

So I'm being generous again and changing the type of the contents array
(in mapclass and editorclass) back to int. This won't affect the
existing tilemaps of the main game, they'll still stay short arrays. But
it means level makers can use 2 billion tiles once again.
2021-08-22 21:30:53 -07:00
Misa
92aace50f6 Don't assume tilesheet size in Direct Mode
This lets users place down tiles above 1199 in Direct Mode, if their
tilesheet has more than 1200 tiles.

I don't like the copy-pasted code here but it'll have to make do.
2021-08-22 21:13:28 -07:00
Misa
731fb89c90 Add being able to use Lab rainbow background in editor
If you use Lab tilecol 6, you get the rainbow background. However, this
is unintended, because the associated autotiling is... not very good.

To combat that, Ved disallows using the Lab rainbow background outside
of Direct Mode. We will follow Ved here and only allow switching to the
rainbow background if you're in Direct Mode. Also make sure if someone
is disabling Direct Mode with the rainbow background that it gets reset
properly.
2021-08-22 20:56:47 -07:00
Misa
3947949ebb Add being able to use Shift+W to change warp dir backwards
A minor convenience, but a convenience is a convenience.
2021-08-22 20:51:51 -07:00
Misa
d2153aee87 Refactor warp dir switching to separate function
This is so the same code can be used to go in reverse instead of
copy-pasting it.
2021-08-22 20:51:21 -07:00
Misa
0489293885 Remove default arguments from ed switch_* funcs
I don't like default arguments and if we're going to be moving to C
we'll need to remove them anyway.
2021-08-22 20:44:18 -07:00
Misa
52918ba510 Increment total flips for flip tokens and flipgravity(player)
They flip the player, they should count towards total flips like gravity
lines do.
2021-08-22 20:39:05 -07:00
Misa
8329afc6df Replace main game music with music area map
The main game used a set of copy-pasted code to set the music of each
area. There WAS some redundancy built-in, but only three rooms in each
direction from the entrance of a zone.

Given this, it's completely possible for players to mismatch the music
of the area and level. In fact, it's easy to do it even on accident,
especially since 2.3 now lets you quicksave and quit during cutscenes.
Just play a cutscene that has Pause music, then quicksave, quit, and
reload. Also some other accidental ways that I've forgotten about.

To fix this, I've done what mapclass has and made an areamap. Except for
music. This map is the map of the track number of every single room,
except for three special cases: -1 for do nothing and don't change music
(usually because multiple different tracks can be played in this room),
-2 for Tower music (needs to be track 2 or 9 depending on Flip Mode),
and -3 for the start of Space Station 2 (track 1 in time trials, track 4
otherwise).

I've thoroughly tested this areamap by playing through the game and
entering every single room. Additionally I've also thoroughly tested all
special cases (entering the Ship through the teleporter or main
entrance, using the Ship's jukebox, the Tower in Flip Mode and regular
mode, and the start of Space Station 2 in time trial and in regular
mode).

Closes #449.
2021-08-22 20:35:06 -07:00
Misa
5bb12a7fc1 Set Secret Lab/Super Gravitron hidden names
It seems appropriate that these rooms should have their names shown on
the map screen.
2021-08-22 20:33:03 -07:00
Misa
2af04ad0fa Make fade out duration proportional to volume
This is the same behavior as SDL_mixer. Else, a fadeout would last the
same amount of time no matter the volume, which is a regression.
2021-08-22 16:57:13 -07:00
Misa
ad88939dbb Fix regression with niceplay() moving back and forth between zones
2.3 has a regression where if you move back and forth between a zone,
you can get the wrong music playing in a zone. An example is the
Overworld and Lab. Just walk in to the Lab and immediately walk back
out, and you'll get Potential for Anything playing in the Overworld.

This regression was caused by facb079b35.
That commit removed assigning -1 to currentsong when a fadeout was
called.

Basically, the previous behavior was: currentsong is 4, we enter Lab and
nicechange gets queued to 3 but currentsong gets set to -1, then going
back nicechange gets queued to 4 again.

However, if we don't assign -1, then going back will keep nicechange at
3. Why? Because niceplay() checks for currentsong before assigning
nicechange. If currentsong is still the same then it doesn't assign
nicechange.

To fix this, just always unconditionally assign nicechange.
2021-08-22 16:57:11 -07:00
Misa
1c3274645d Fix up style in musicclass::play()
- Multiline comment instead of single-line.
- Spacing fixes.
- Long line broken up into smaller ones.
2021-08-22 15:27:39 -07:00
mothbeanie
1ec06c6f5c Standardize punctuation and style for the new options menu 2021-08-19 17:17:36 -07:00
Misa
4f881b9e26 Fix enemy movement types 10/12 causing memory leaks
If spawned as a custom enemy (createentity entry 56), or spawned outside
of the rooms they spawn in in the main game, they will repeatedly clone
themselves every frame, which profusely leaks memory. In fact it quickly
causes a crash in 2.2 and previous, but 2.3 fixes that crash, so it just
keeps spawning enemies endlessly, which eventually lags the game, and
eventually can out-of-memory your system (bad!).

The problem is those movement types rely on entclass::setenemyroom() to
change their `behave` to be 11 or 13. Else, the new entity created will
still have `behave` 10 or 12, which will create ANOTHER entity in the
same way, and so on, and so forth.

So to fix this, just make it so if an enemy is still `behave` 10 or 12
by the end, then, just set it to -1. That way it'll stay still and won't
cause any harm.

I considered setting the `behave` to 11 or 13 respectively, but, that's
probably going farther than just fixing a memory leak, and anyways, it's
not that much useful for me as a custom level maker, and the entities
spawned aren't really controllable.
2021-08-19 16:50:44 -07:00
Misa
7c18123327 Wrap level dir enumerate callback pointer in struct
In order to let callers provide their OWN callback functions through the
callback function WE provide to PhysFS, we casted the function pointer
to a void pointer.

Unfortunately, this is apparently undefined behavior... if your compiler
doesn't have an extension for it. And most compilers on most
architectures do. (In fact compilers on POSIX systems most certainly
have it due to dlsym() returning a void* which could actually be a
pointer to a function sometimes.)

But imo, it's better to be safe than sorry in this regard. Especially
when given GCC's approach to optimizing int + 100 > int (spoilers: they
remove it entirely! It's faster, but also broken!).

I've decided to wrap it in a struct. And as a nice side effect, if we
ever need more data to be passed through... well we already have this
struct.

Technically, it's also standards-compliant to cast a _pointer to_ a
function pointer to a void pointer. But that extra layer of pointer
indirection would get real confusing to conceptualize real fast (or at
least is more confusing than just putting it in a struct).
2021-08-19 00:48:05 -07:00
Misa
8bade56841 Fix regression with regaining focus resuming music
Since you've been able to resume music stopped by stopmusic() with
resumemusic(), if a track was stopped by stopmusic(), the unfocus pause
itself would end up resuming the track when regaining focus.

The solution is to simply check for if music.currentsong is -1 or not.
2021-08-18 20:50:02 -07:00
Misa
208382a8d1 Fix regression with platv values not parsed as 2.2-and-prev
So, platv is a room property that controls the speed of custom entity
platforms in the room (unless, of course, they're created with
createentity). Problem is, this is how 2.2-and-previous coding standards
were:

    ed.level[game.roomx-100+((game.roomy-100)*ed.maxwidth)]

Overly long, verbose, not entirely clear unless you already know what it
means? Copy-pasted over and over due to all of the above? Surely a
recipe for not making any coding errors!

Ironically enough, copy-pasting is basically the best approach here
(short of refactoring the whole thing, like I did in
945d5f244a), since if you don't ACTUALLY
copy-paste and just re-type it on your own, you'll end up making more
mistakes. Like what happened here:

    ed.level[game.roomx-100+((game.roomy-100)*ed.mapwidth)].platv

Do you see the mistake...? Yeah, mapwidth (with a P) instead of maxwidth
(with an X). You'd have to look closely to find it.

So what does this mean for platv? Well, it means that it multiples the
y-coordinate of the room by the map width instead of the max width (20),
like every other room property. So that means if your map width is less
than 20, like say, map width 10, the platv value for (2,2) will be
stored in (2,1)'s room properties instead of (2,2)'s. Because if you go
off of map width, the room index for (2,2) is 2 + 2 * 10 = 22, but if
you go off of max width, the room index for (2,1) is 2 + 1 * 20 = 22.

Now this wouldn't be bad, except for another 2.2-and-previous
standard... kind of just not exposing things directly to the end user.
Whether that's simply not documenting something (as in the case of
ifwarp and warpdir, which by all measures were completely intended to be
used in custom levels but just simply were never known properly until I
discovered how to use them in 2019), or in this case, not giving any way
for the user to fiddle with platv from the in-game editor. Because if
there was a way to do that, and someone decided to test to see if platv
worked okay, they would discover something was up.

So... since I refactored room properties in
945d5f244a, I kind of broke platv by
fixing it. Now levels that relied on platv being the broken way don't
work.

How do I fix it, and thus break it again? Well, I'll do what I did for
scripts - handle the scrambling when reading and writing the level, and
keep things sane at least internally.

Thus: editorclass::load() will unscramble platv data in the right way,
and editorclass::save() will re-scramble platv in the right way too.
2021-08-18 19:19:33 -07:00
Misa
a13d26d866 Add option to delete all custom level save data
To match the option to nuke all main game save data, there is also now
an option to nuke all custom level save data separately (which is just
all custom level quicksaves, along with stars for level completion). It
has its own confirmation menu too. It does not delete any levels from
the levels folder.
2021-08-18 16:02:11 -07:00
Misa
3a2265ef0d Add being able to delete a custom level quicksave
Custom level quicksaves are NOT affected by the clear data menu, so the
player should be able to delete quicksaves this way. The quicksave
confirmation menu now has an extra option to delete the save (and that
option also has its own confirmation menu before deleting).
2021-08-18 16:02:11 -07:00