Compare commits

...

26 commits

Author SHA1 Message Date
Ethan Lee
3469a44489 2.3.4 2021-09-11 02:06:16 -04:00
Misa
222e45ada1 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:50:47 -07:00
Misa
6c848a8bb9 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:50:33 -07:00
Misa
b5501e4b29 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 19:49:49 -07:00
Misa
7c29bb862a 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 19:49:45 -07:00
Misa
2b9b4c39cb 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 19:49:45 -07:00
Misa
3c6cb0167d 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 19:49:27 -07:00
Misa
406a19ceb6 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 19:49:08 -07:00
Misa
3d090792d2 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 19:49:02 -07:00
Misa
b6645de749 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 19:49:01 -07:00
Misa
25af54529b 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:06:56 -07:00
Misa
f467f86dc2 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 17:06:55 -07:00
Ethan Lee
ca35c53c1a 2.3.3 2021-09-04 16:31:56 -04:00
Misa
b667e44bcf 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:18:17 -07:00
Misa
70d3c999be 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:44:19 -07:00
Ethan Lee
6f315af42d Updated .ico 2021-09-03 15:57:30 -04:00
Ethan Lee
c8fcbc1256 2.3.2 2021-09-03 15:26:38 -04:00
Misa
a302692ab2 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
( 3039355280/ )
. So I've made it so that a text box will pop up when they get kicked
out.
2021-09-03 12:09:53 -07:00
Misa
a59e9d51db 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:29:55 -07:00
Misa
82971296c2 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:29:55 -07:00
Misa
4ecec8a327 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 12:29:55 -07:00
Ethan Lee
f1ae40a7c5 2.3.1 2021-09-01 12:26:53 -04:00
Ethan Lee
d501a6245f Added my quick script to fixup Mac dylib paths 2021-09-01 12:08:12 -04:00
Ethan Lee
514d56ee20 Minor VS buildfix 2021-08-31 19:07:36 -04:00
Misa
9cfbd1ae51 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:34:32 -07:00
Ethan Lee
96812f8046 Default to VSync being enabled 2021-08-31 15:09:07 -04:00
16 changed files with 109 additions and 29 deletions

8
desktop_version/fixupMac.sh Executable file
View file

@ -0,0 +1,8 @@
#!/bin/bash
# flibit has this solely for convenience when cleaning up Mac binaries.
install_name_tool -change /usr/local/lib/libSDL2-2.0.0.dylib @rpath/libSDL2-2.0.0.dylib VVVVVV
install_name_tool -change /usr/local/lib/libSDL2_mixer-2.0.0.dylib @rpath/libSDL2_mixer-2.0.0.dylib VVVVVV
strip -S VVVVVV
otool -L VVVVVV

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Before After
Before After

View file

@ -813,6 +813,10 @@ void Game::updatestate(void)
if (!map.custommode && nocompetitive())
{
returntolab();
startscript = true;
newscript = "disableaccessibility";
state = 0;
break;
}
@ -1884,7 +1888,10 @@ void Game::updatestate(void)
advancetext = false;
completestop = false;
state = 0;
if(!muted && music.currentsong>-1) music.fadeMusicVolumeIn(3000);
if (music.currentsong > -1)
{
music.fadeMusicVolumeIn(3000);
}
graphics.showcutscenebars = false;
break;
@ -1938,20 +1945,19 @@ void Game::updatestate(void)
if(map.custommodeforreal)
{
graphics.fademode = 2;
if(!muted && ed.levmusic>0) music.fadeMusicVolumeIn(3000);
if(ed.levmusic>0) music.fadeout();
state=1014;
}
else
{
returntoeditor();
if(!muted && ed.levmusic>0) music.fadeMusicVolumeIn(3000);
if(ed.levmusic>0) music.fadeout();
}
}
else
{
if(!muted && ed.levmusic>0) music.fadeMusicVolumeIn(3000);
if (ed.levmusic > 0)
{
music.fadeMusicVolumeIn(3000);
}
}
graphics.showcutscenebars = false;
break;
@ -4001,6 +4007,9 @@ void Game::deletestats(void)
bestlives[i] = -1;
bestrank[i] = -1;
}
swnrecord = 0;
swnbestrank = 0;
bestgamedeaths = 0;
#ifndef MAKEANDPLAY
graphics.setflipmode = false;
#endif
@ -5853,6 +5862,12 @@ void Game::returnmenu(void)
return;
}
/* FIXME: Super bad kludge, don't hardcode this! */
if (currentmenuname == Menu::ed_music)
{
music.fadeout();
}
MenuStackFrame& frame = menustack[menustack.size()-1];
//Store this in case createmenu() removes the stack frame
@ -6874,7 +6889,7 @@ void Game::returntoingame(void)
gamestate = MAPMODE;
DEFER_CALLBACK(setflipmode);
DEFER_CALLBACK(setfademode);
if (!map.custommode && !graphics.flipmode)
if (!map.custommode && !graphics.setflipmode)
{
obj.flags[73] = true;
}
@ -6888,8 +6903,13 @@ void Game::unlockAchievement(const char *name) {
#endif
}
void Game::mapmenuchange(const int newgamestate)
void Game::mapmenuchange(const int newgamestate, const bool user_initiated)
{
if (user_initiated && graphics.resumegamemode)
{
return;
}
prevgamestate = gamestate;
gamestate = newgamestate;
graphics.resumegamemode = false;
@ -6898,10 +6918,6 @@ void Game::mapmenuchange(const int newgamestate)
if (prevgamestate == GAMEMODE)
{
graphics.menuoffset = 240;
if (map.extrarow)
{
graphics.menuoffset -= 10;
}
}
else
{

View file

@ -245,7 +245,7 @@ public:
int tapleft, tapright;
//Menu interaction stuff
void mapmenuchange(const int newgamestate);
void mapmenuchange(const int newgamestate, const bool user_initiated);
bool mapheld;
int menupage;
int lastsaved;

View file

@ -2124,7 +2124,7 @@ void gameinput(void)
else if (game.companion == 0)
{
//Alright, normal teleporting
game.mapmenuchange(TELEPORTERMODE);
game.mapmenuchange(TELEPORTERMODE, true);
game.useteleporter = true;
game.initteleportermode();
@ -2279,7 +2279,7 @@ void gameinput(void)
//quitting the super gravitron
game.mapheld = true;
//Quit menu, same conditions as in game menu
game.mapmenuchange(MAPMODE);
game.mapmenuchange(MAPMODE, true);
game.gamesaved = false;
game.gamesavefailed = false;
game.menupage = 20; // The Map Page
@ -2299,7 +2299,7 @@ void gameinput(void)
else
{
//Normal map screen, do transition later
game.mapmenuchange(MAPMODE);
game.mapmenuchange(MAPMODE, true);
map.cursordelay = 0;
map.cursorstate = 0;
game.gamesaved = false;
@ -2320,7 +2320,7 @@ void gameinput(void)
{
game.mapheld = true;
//Quit menu, same conditions as in game menu
game.mapmenuchange(MAPMODE);
game.mapmenuchange(MAPMODE, true);
game.gamesaved = false;
game.gamesavefailed = false;
game.menupage = 30; // Pause screen

View file

@ -865,6 +865,18 @@ void mapclass::resetplayer(const bool player_died)
}
}
if (game.state == 0 && !script.running && game.completestop)
{
/* Looks like a collection dialogue was interrupted.
* Undo its effects! */
game.advancetext = false;
graphics.showcutscenebars = false;
if (music.currentsong > -1)
{
music.fadeMusicVolumeIn(3000);
}
}
game.scmhurt = false; //Just in case the supercrewmate is fucking this up!
if (game.supercrewmate)
{

View file

@ -202,9 +202,6 @@ void musicclass::play(int t)
return;
}
m_doFadeInVol = false;
m_doFadeOutVol = false;
if (currentsong == 0 || currentsong == 7 || (!map.custommode && (currentsong == 0+num_mmmmmm_tracks || currentsong == 7+num_mmmmmm_tracks)))
{
// Level Complete theme, no fade in or repeat
@ -214,6 +211,8 @@ void musicclass::play(int t)
}
else
{
m_doFadeInVol = false;
m_doFadeOutVol = false;
musicVolume = MIX_MAX_VOLUME;
Mix_VolumeMusic(musicVolume);
}
@ -242,6 +241,8 @@ void musicclass::play(int t)
}
else
{
m_doFadeInVol = false;
m_doFadeOutVol = false;
fadeMusicVolumeIn(3000);
}
}
@ -280,6 +281,8 @@ void musicclass::haltdasmusik(void)
void musicclass::silencedasmusik(void)
{
musicVolume = 0;
m_doFadeInVol = false;
m_doFadeOutVol = false;
}
struct FadeState
@ -325,6 +328,11 @@ static enum FadeCode processmusicfade(struct FadeState* state, int* volume)
void musicclass::fadeMusicVolumeIn(int ms)
{
if (halted())
{
return;
}
m_doFadeInVol = true;
m_doFadeOutVol = false;
@ -342,6 +350,11 @@ void musicclass::fadeMusicVolumeIn(int ms)
void musicclass::fadeMusicVolumeOut(const int fadeout_ms)
{
if (halted())
{
return;
}
m_doFadeInVol = false;
m_doFadeOutVol = true;
@ -396,7 +409,7 @@ void musicclass::processmusic(void)
}
/* This needs to come after processing fades */
if (nicefade && Mix_PausedMusic() == 1)
if (nicefade && halted())
{
play(nicechange);
nicechange = -1;
@ -522,3 +535,8 @@ void musicclass::resumeef(void)
{
Mix_Resume(-1);
}
bool musicclass::halted(void)
{
return Mix_PausedMusic() == 1;
}

View file

@ -44,6 +44,8 @@ public:
void pauseef(void);
void resumeef(void);
bool halted(void);
std::vector<SoundTrack> soundTracks;
std::vector<MusicTrack> musicTracks;
SoundSystem soundSystem;

View file

@ -56,7 +56,7 @@ static NetworkBackend backends[NUM_BACKENDS];
int NETWORK_init(void)
{
int32_t any = 0;
int32_t i, any = 0;
#define ASSIGN_BACKEND(name, index) \
backends[index].Init = name##_init; \
backends[index].Shutdown = name##_shutdown; \
@ -72,7 +72,6 @@ int NETWORK_init(void)
#endif
#undef ASSIGN_BACKEND
#if NUM_BACKENDS > 0
int32_t i;
for (i = 0; i < NUM_BACKENDS; i += 1)
{
backends[i].IsInit = backends[i].Init();

View file

@ -159,7 +159,7 @@ static void menurender(void)
#ifdef INTERIM_COMMIT
graphics.Print( 310 - (SDL_arraysize(INTERIM_COMMIT) - 1) * 8, 220, INTERIM_COMMIT, tr/2, tg/2, tb/2);
#endif
graphics.Print( 310 - (4*8), 230, "v2.3", tr/2, tg/2, tb/2);
graphics.Print( 310 - (6*8), 230, "v2.3.4", tr/2, tg/2, tb/2);
if(music.mmmmmm){
graphics.Print( 10, 230, "[MMMMMM Mod Installed]", tr/2, tg/2, tb/2);

View file

@ -205,13 +205,14 @@ void maprenderfixed(void)
|| !script.running)
{
graphics.menuoffset += 25;
int threshold = map.extrarow ? 230 : 240;
int threshold = 240;
if (graphics.menuoffset >= threshold)
{
graphics.menuoffset = threshold;
//go back to gamemode!
game.mapheld = true;
game.gamestate = GAMEMODE;
graphics.resumegamemode = false;
}
}
else

View file

@ -24,7 +24,7 @@ ScreenSettings::ScreenSettings(void)
windowWidth = 320;
windowHeight = 240;
fullscreen = false;
useVsync = false;
useVsync = true; // Now that uncapped is the default...
stretch = 0;
linearFilter = false;
badSignal = false;

View file

@ -1349,7 +1349,8 @@ void scriptclass::run(void)
{
if (words[1] == "teleporter")
{
game.mapmenuchange(TELEPORTERMODE);
game.gamestate = GAMEMODE; /* to set prevgamestate */
game.mapmenuchange(TELEPORTERMODE, false);
game.useteleporter = false; //good heavens don't actually use it
}

View file

@ -6724,6 +6724,26 @@ void scriptclass::load(const std::string& name)
};
filllines(lines);
}
else if (SDL_strcmp(t, "disableaccessibility") == 0)
{
static const char* lines[] = {
"cutscene()",
"untilbars()",
"squeak(terminal)",
"text(gray,0,114,3)",
"Please disable invincibility",
"and/or slowdown before entering",
"the Super Gravitron.",
"position(center)",
"speak",
"endtext",
"endcutscene()",
"untilbars()",
};
filllines(lines);
}
else
{
loadother(t);

View file

@ -2232,7 +2232,10 @@ bool editorclass::save(std::string& _path)
msg = xml::update_element_delete_contents(data, "levelMetaData");
int temp_platv[numrooms];
SDL_memset(temp_platv, 4 /* default */, sizeof(temp_platv));
for (size_t i = 0; i < SDL_arraysize(temp_platv); ++i)
{
temp_platv[i] = 4; /* default */
}
if (mapwidth < maxwidth)
{

View file

@ -143,7 +143,7 @@ static const inline struct ImplFunc* get_gamestate_funcs(
FUNC_LIST_END
FUNC_LIST_BEGIN(TELEPORTERMODE)
{Func_fixed, maprenderfixed},
{Func_fixed, teleporterrenderfixed},
{Func_delta, teleporterrender},
{Func_input, teleportermodeinput},
{Func_fixed, maplogic},