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

Merge remote-tracking branch 'upstream/master' into auto-center-menu

Fix one conflict.
This commit is contained in:
Dav999-v 2020-06-29 23:40:10 +02:00
commit cc538a0965
12 changed files with 298 additions and 93 deletions

View File

@ -4780,6 +4780,7 @@ void entityclass::entitycollisioncheck()
}
}
// WARNING: If updating this code, don't forget to update Map.cpp mapclass::twoframedelayfix()
activetrigger = -1;
if (checktrigger() > -1)
{

View File

@ -116,6 +116,13 @@ bool GetButtonFromString(const char *pText, SDL_GameControllerButton *button)
void Game::init(void)
{
roomx = 0;
roomy = 0;
prevroomx = 0;
prevroomy = 0;
saverx = 0;
savery = 0;
mutebutton = 0;
muted = false;
musicmuted = false;
@ -387,6 +394,7 @@ void Game::init(void)
#endif
over30mode = false;
glitchrunnermode = false;
ingame_titlemode = false;
kludge_ingametemp = Menu::mainmenu;
@ -1745,6 +1753,7 @@ void Game::updatestate()
break;
// WARNING: If updating this code, make sure to update Map.cpp mapclass::twoframedelayfix()
case 300:
startscript = true;
newscript="custom_"+customscript[0];
@ -4756,6 +4765,11 @@ void Game::loadstats()
over30mode = atoi(pText);
}
if (pKey == "glitchrunnermode")
{
glitchrunnermode = atoi(pText);
}
if (pKey == "vsync")
{
graphics.vsync = atoi(pText);
@ -5010,6 +5024,10 @@ void Game::savestats()
msg->LinkEndChild(doc.NewText(help.String((int) over30mode).c_str()));
dataNode->LinkEndChild(msg);
msg = doc.NewElement("glitchrunnermode");
msg->LinkEndChild(doc.NewText(help.String((int) glitchrunnermode).c_str()));
dataNode->LinkEndChild(msg);
msg = doc.NewElement("vsync");
msg->LinkEndChild(doc.NewText(help.String((int) graphics.vsync).c_str()));
dataNode->LinkEndChild(msg);
@ -7126,6 +7144,7 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
break;
case Menu::options:
option("accessibility options");
option("glitchrunner mode");
#if !defined(MAKEANDPLAY)
option("unlock play modes");
#endif
@ -7630,7 +7649,7 @@ bool Game::anything_unlocked()
{
if (unlock[i] &&
(i == 8 // Secret Lab
|| i >= 9 || i <= 14 // any Time Trial
|| (i >= 9 && i <= 14) // any Time Trial
|| i == 16 // Intermission replays
|| i == 17 // No Death Mode
|| i == 18)) // Flip Mode

View File

@ -405,6 +405,7 @@ public:
}
bool over30mode;
bool glitchrunnermode; // Have fun speedrunners! <3 Misa
bool ingame_titlemode;

View File

@ -200,20 +200,58 @@ void Graphics::updatetitlecolours()
col_trinket = ct.colour;
}
#define PROCESS_TILESHEET_CHECK_ERROR(tilesheet, tile_square) \
if (grphx.im_##tilesheet->w % tile_square != 0 \
|| grphx.im_##tilesheet->h % tile_square != 0) \
{ \
const char* error = "Error: %s.png dimensions not exact multiples of %i!"; \
char message[128]; \
SDL_snprintf(message, sizeof(message), error, #tilesheet, tile_square); \
\
const char* error_title = "Error with %s.png"; \
char message_title[128]; \
SDL_snprintf(message_title, sizeof(message_title), error_title, #tilesheet); \
\
puts(message); \
\
SDL_ShowSimpleMessageBox( \
SDL_MESSAGEBOX_ERROR, \
message_title, \
message, \
NULL \
); \
\
exit(1); \
}
#define PROCESS_TILESHEET_RENAME(tilesheet, vector, tile_square, extra_code) \
PROCESS_TILESHEET_CHECK_ERROR(tilesheet, tile_square) \
\
for (int j = 0; j < grphx.im_##tilesheet->h / tile_square; j++) \
{ \
for (int i = 0; i < grphx.im_##tilesheet->w / tile_square; i++) \
{ \
SDL_Surface* temp = GetSubSurface( \
grphx.im_##tilesheet, \
i * tile_square, j * tile_square, \
tile_square, tile_square \
); \
vector.push_back(temp); \
\
extra_code \
} \
}
#define PROCESS_TILESHEET(tilesheet, tile_square, extra_code) \
PROCESS_TILESHEET_RENAME(tilesheet, tilesheet, tile_square, extra_code)
void Graphics::Makebfont()
{
for (int j = 0; j < (grphx.im_bfont->h / 8); j++)
PROCESS_TILESHEET(bfont, 8,
{
for (int i = 0; i < 16; i++)
{
SDL_Surface* temp = GetSubSurface(grphx.im_bfont,i*8,j*8,8,8);
bfont.push_back(temp);
SDL_Surface* TempFlipped = FlipSurfaceVerticle(temp);
flipbfont.push_back(TempFlipped);
}
}
SDL_Surface* TempFlipped = FlipSurfaceVerticle(temp);
flipbfont.push_back(TempFlipped);
})
unsigned char* charmap = NULL;
size_t length;
@ -241,65 +279,27 @@ int Graphics::bfontlen(uint32_t ch) {
void Graphics::MakeTileArray()
{
for(int j = 0; j <30; j++)
{
for(int i = 0; i <40; i++)
{
SDL_Surface* temp = GetSubSurface(grphx.im_tiles,i*8,j*8,8,8);
tiles.push_back(temp);
}
}
for(int j = 0; j <30; j++)
{
for(int i = 0; i <40; i++)
{
SDL_Surface* temp = GetSubSurface(grphx.im_tiles2,i*8,j*8,8,8);
tiles2.push_back(temp);
}
}
for(int j = 0; j <30; j++)
{
for(int i = 0; i <30; i++)
{
SDL_Surface* temp = GetSubSurface(grphx.im_tiles3,i*8,j*8,8,8);
tiles3.push_back(temp);
}
}
for(int j = 0; j <60; j++)
{
for(int i = 0; i <12; i++)
{
SDL_Surface* temp = GetSubSurface(grphx.im_entcolours,i*8,j*8,8,8);
entcolours.push_back(temp);
}
}
PROCESS_TILESHEET(tiles, 8, )
PROCESS_TILESHEET(tiles2, 8, )
PROCESS_TILESHEET(tiles3, 8, )
PROCESS_TILESHEET(entcolours, 8, )
}
void Graphics::maketelearray()
{
for (int i = 0; i < 10; i++)
{
SDL_Surface* temp = GetSubSurface(grphx.im_teleporter,i*96,0,96,96);
tele.push_back(temp);
}
PROCESS_TILESHEET_RENAME(teleporter, tele, 96, )
}
void Graphics::MakeSpriteArray()
{
for(int j = 0; j <16; j++)
{
for(int i = 0; i <12; i++)
{
SDL_Surface* temp = GetSubSurface(grphx.im_sprites,i*32,j*32,32,32);
sprites.push_back(temp);
temp = GetSubSurface(grphx.im_flipsprites,i*32,j*32,32,32);
flipsprites.push_back(temp);
}
}
PROCESS_TILESHEET(sprites, 32, )
PROCESS_TILESHEET(flipsprites, 32, )
}
#undef PROCESS_TILESHEET
#undef PROCESS_TILESHEET_RENAME
#undef PROCESS_TILESHEET_CHECK_ERROR
void Graphics::map_tab(int opt, const std::string& text, bool selected /*= false*/)
{
@ -1141,16 +1141,34 @@ void Graphics::textboxremove()
void Graphics::textboxtimer( int t )
{
if (!INBOUNDS(m, textbox))
{
puts("textboxtimer() out-of-bounds!");
return;
}
textbox[m].timer=t;
}
void Graphics::addline( std::string t )
{
if (!INBOUNDS(m, textbox))
{
puts("addline() out-of-bounds!");
return;
}
textbox[m].addline(t);
}
void Graphics::textboxadjust()
{
if (!INBOUNDS(m, textbox))
{
puts("textboxadjust() out-of-bounds!");
return;
}
textbox[m].adjust();
}
@ -2787,33 +2805,69 @@ void Graphics::setwarprect( int a, int b, int c, int d )
void Graphics::textboxcenter()
{
if (!INBOUNDS(m, textbox))
{
puts("textboxcenter() out-of-bounds!");
return;
}
textbox[m].centerx();
textbox[m].centery();
}
void Graphics::textboxcenterx()
{
if (!INBOUNDS(m, textbox))
{
puts("textboxcenterx() out-of-bounds!");
return;
}
textbox[m].centerx();
}
int Graphics::textboxwidth()
{
if (!INBOUNDS(m, textbox))
{
puts("textboxwidth() out-of-bounds!");
return 0;
}
return textbox[m].w;
}
void Graphics::textboxmove(int xo, int yo)
{
if (!INBOUNDS(m, textbox))
{
puts("textboxmove() out-of-bounds!");
return;
}
textbox[m].xp += xo;
textbox[m].yp += yo;
}
void Graphics::textboxmoveto(int xo)
{
if (!INBOUNDS(m, textbox))
{
puts("textboxmoveto() out-of-bounds!");
return;
}
textbox[m].xp = xo;
}
void Graphics::textboxcentery()
{
if (!INBOUNDS(m, textbox))
{
puts("textboxcentery() out-of-bounds!");
return;
}
textbox[m].centery();
}

View File

@ -564,21 +564,26 @@ void menuactionpress()
game.createmenu(Menu::accessibility);
map.nexttowercolour();
break;
#if !defined(MAKEANDPLAY)
case 1:
// Glitchrunner mode
music.playef(11);
game.glitchrunnermode = !game.glitchrunnermode;
break;
#if !defined(MAKEANDPLAY)
case 2:
//unlock play options
music.playef(11);
game.createmenu(Menu::unlockmenu);
map.nexttowercolour();
break;
#endif
case OFFSET+2:
case OFFSET+3:
//clear data menu
music.playef(11);
game.createmenu(Menu::controller);
map.nexttowercolour();
break;
case OFFSET+3:
case OFFSET+4:
//clear data menu
music.playef(11);
game.createmenu(Menu::cleardatamenu);
@ -587,7 +592,7 @@ void menuactionpress()
}
int mmmmmm_offset = music.mmmmmm ? 0 : -1;
if (game.currentmenuoption == OFFSET+4+mmmmmm_offset)
if (game.currentmenuoption == OFFSET+5+mmmmmm_offset)
{
//**** TOGGLE MMMMMM
if(game.usingmmmmmm > 0){
@ -600,7 +605,7 @@ void menuactionpress()
music.play(music.currentsong);
game.savestats();
}
else if (game.currentmenuoption == OFFSET+5+mmmmmm_offset)
else if (game.currentmenuoption == OFFSET+6+mmmmmm_offset)
{
//back
music.playef(11);
@ -1592,10 +1597,11 @@ void gameinput()
}
else
{
if(!game.glitchrunkludge) game.state++;
if(game.glitchrunnermode || !game.glitchrunkludge) game.state++;
game.jumpheld = true;
game.glitchrunkludge=true;
//Bug fix! You should only be able to do this ONCE.
//...Unless you're in glitchrunner mode
}
}
}
@ -1910,7 +1916,41 @@ void mapinput()
game.press_action = false;
game.press_map = false;
if (game.fadetomenu)
if (game.glitchrunnermode && graphics.fademode == 1 && graphics.menuoffset == 0)
{
// Deliberate re-addition of the glitchy gamestate-based fadeout!
// First of all, detecting a black screen means if the glitchy fadeout
// gets interrupted but you're still on a black screen, opening a menu
// immediately quits you to the title. This has the side effect that if
// you accidentally press Esc during a cutscene when it's black, you'll
// immediately be quit and lose all your progress, but that's fair in
// glitchrunner mode.
// Also have to check graphics.menuoffset so this doesn't run every frame
// Have to close the menu in order to run gamestates. This adds
// about an extra half second of completely black screen.
graphics.resumegamemode = true;
// Technically this was in <=2.2 as well
obj.removeallblocks();
if (game.menupage >= 20 && game.menupage <= 21)
{
game.state = 96;
game.statedelay = 0;
}
else
{
// Produces more glitchiness! Necessary for credits warp to work.
script.hardreset();
game.state = 80;
game.statedelay = 0;
}
}
if (game.fadetomenu && !game.glitchrunnermode)
{
if (game.fadetomenudelay > 0)
{
@ -1923,7 +1963,7 @@ void mapinput()
}
}
if (game.fadetolab)
if (game.fadetolab && !game.glitchrunnermode)
{
if (game.fadetolabdelay > 0)
{
@ -1936,7 +1976,9 @@ void mapinput()
}
}
if(graphics.menuoffset==0 && game.fadetomenudelay <= 0 && game.fadetolabdelay <= 0)
if(graphics.menuoffset==0
&& (!game.glitchrunnermode || graphics.fademode == 0)
&& game.fadetomenudelay <= 0 && game.fadetolabdelay <= 0)
{
if (graphics.flipmode)
{
@ -2113,8 +2155,11 @@ void mapmenuactionpress()
graphics.fademode = 2;
music.fadeout();
map.nexttowercolour();
game.fadetomenu = true;
game.fadetomenudelay = 16;
if (!game.glitchrunnermode)
{
game.fadetomenu = true;
game.fadetomenudelay = 16;
}
break;
case 20:

View File

@ -83,7 +83,7 @@ void maplogic()
{
game.shouldreturntopausemenu = false;
graphics.backgrounddrawn = false;
if (map.background == 3 || map.background || 4)
if (map.background == 3 || map.background == 4)
{
graphics.updatebackground(map.background);
}
@ -1117,6 +1117,8 @@ void gamelogic()
}
}
bool screen_transition = false;
if (!map.warpy && !map.towermode)
{
//Normal! Just change room
@ -1125,11 +1127,13 @@ void gamelogic()
{
obj.entities[player].yp -= 240;
map.gotoroom(game.roomx, game.roomy + 1);
screen_transition = true;
}
if (player > -1 && game.door_up > -2 && obj.entities[player].yp < -2)
{
obj.entities[player].yp += 240;
map.gotoroom(game.roomx, game.roomy - 1);
screen_transition = true;
}
}
@ -1141,11 +1145,13 @@ void gamelogic()
{
obj.entities[player].xp += 320;
map.gotoroom(game.roomx - 1, game.roomy);
screen_transition = true;
}
if (player > -1 && game.door_right > -2 && obj.entities[player].xp >= 308)
{
obj.entities[player].xp -= 320;
map.gotoroom(game.roomx + 1, game.roomy);
screen_transition = true;
}
}
@ -1364,6 +1370,11 @@ void gamelogic()
}
}
}
if (screen_transition)
{
map.twoframedelayfix();
}
}
//Update colour cycling for final level

View File

@ -31,6 +31,10 @@ mapclass::mapclass()
cursorstate = 0;
cursordelay = 0;
towermode = false;
cameraseekframe = 0;
resumedelay = 0;
final_colormode = false;
final_colorframe = 0;
final_colorframedelay = 0;
@ -788,10 +792,13 @@ void mapclass::resetplayer()
obj.entities[i].colour = 0;
game.lifeseq = 10;
obj.entities[i].invis = true;
obj.entities[i].size = 0;
obj.entities[i].cx = 6;
obj.entities[i].cy = 2;
obj.entities[i].h = 21;
if (!game.glitchrunnermode)
{
obj.entities[i].size = 0;
obj.entities[i].cx = 6;
obj.entities[i].cy = 2;
obj.entities[i].h = 21;
}
// If we entered a tower as part of respawn, reposition camera
if (!was_in_tower && towermode)
@ -1163,8 +1170,6 @@ void mapclass::loadlevel(int rx, int ry)
obj.customwarpmodevon=false;
obj.customwarpmodehon=false;
std::vector<std::string> tmap;
if (finalmode)
{
t = 6;
@ -1975,3 +1980,30 @@ void mapclass::loadlevel(int rx, int ry)
}
}
}
void mapclass::twoframedelayfix()
{
// Fixes the two-frame delay in custom levels that use scripts to spawn an entity upon room load.
// Because when the room loads and newscript is set to run, newscript has already ran for that frame,
// and when the script gets loaded script.run() has already ran for that frame, too.
// A bit kludge-y, but it's the least we can do without changing the frame ordering.
if (game.deathseq != -1
// obj.checktrigger() sets obj.activetrigger
|| obj.checktrigger() <= -1
|| obj.activetrigger < 300)
{
return;
}
game.newscript = "custom_" + game.customscript[obj.activetrigger - 300];
obj.removetrigger(obj.activetrigger);
game.state = 0;
game.statedelay = 0;
script.load(game.newscript);
if (script.running)
{
script.run();
script.dontrunnextframe = true;
}
}

View File

@ -75,6 +75,8 @@ public:
void loadlevel(int rx, int ry);
void twoframedelayfix();
std::vector <int> roomdeaths;
std::vector <int> roomdeathsfinal;
@ -82,7 +84,6 @@ public:
std::vector <int> contents;
std::vector <int> explored;
std::vector <int> vmult;
std::vector <std::string> tmap;
int temp;
int temp2;

View File

@ -88,24 +88,37 @@ void menurender()
graphics.Print( -1, 65, "Disable screen effects, enable", tr, tg, tb, true);
graphics.Print( -1, 75, "slowdown modes or invincibility", tr, tg, tb, true);
break;
#if !defined(MAKEANDPLAY)
case 1:
graphics.bigprint( -1, 30, "Glitchrunner Mode", tr, tg, tb, true);
graphics.Print( -1, 65, "Re-enable glitches that existed", tr, tg, tb, true);
graphics.Print( -1, 75, "in previous versions of the game", tr, tg, tb, true);
if (game.glitchrunnermode)
{
graphics.Print( -1, 95, "Glitchrunner mode is ON", tr, tg, tb, true);
}
else
{
graphics.Print( -1, 95, "Glitchrunner mode is OFF", tr/2, tg/2, tb/2, true);
}
break;
#if !defined(MAKEANDPLAY)
case 2:
graphics.bigprint( -1, 30, "Unlock Play Modes", tr, tg, tb, true);
graphics.Print( -1, 65, "Unlock parts of the game normally", tr, tg, tb, true);
graphics.Print( -1, 75, "unlocked as you progress", tr, tg, tb, true);
break;
#endif
case OFFSET+2:
case OFFSET+3:
graphics.bigprint( -1, 30, "Game Pad Options", tr, tg, tb, true);
graphics.Print( -1, 65, "Rebind your controller's buttons", tr, tg, tb, true);
graphics.Print( -1, 75, "and adjust sensitivity", tr, tg, tb, true);
break;
case OFFSET+3:
case OFFSET+4:
graphics.bigprint( -1, 30, "Clear Data", tr, tg, tb, true);
graphics.Print( -1, 65, "Delete your save data", tr, tg, tb, true);
graphics.Print( -1, 75, "and unlocked play modes", tr, tg, tb, true);
break;
case OFFSET+4:
case OFFSET+5:
if(music.mmmmmm){
graphics.bigprint( -1, 30, "Soundtrack", tr, tg, tb, true);
graphics.Print( -1, 65, "Toggle between MMMMMM and PPPPPP", tr, tg, tb, true);
@ -2323,7 +2336,10 @@ void maprender()
if (graphics.fademode == 3 || graphics.fademode == 5)
// We need to draw the black screen above the menu in order to disguise it
// being jankily brought down in glitchrunner mode when exiting to the title
// Otherwise, there's no reason to obscure the menu
if (game.glitchrunnermode || graphics.fademode == 3 || graphics.fademode == 5)
{
graphics.drawfade();
}

View File

@ -16,6 +16,7 @@ scriptclass::scriptclass()
position = 0;
scriptdelay = 0;
running = false;
dontrunnextframe = false;
b = 0;
g = 0;
@ -3482,8 +3483,12 @@ void scriptclass::hardreset()
game.teleport = false;
game.companion = 0;
game.roomchange = false;
game.roomx = 0;
game.roomy = 0;
if (!game.glitchrunnermode)
{
// Ironically, resetting more variables makes the janky fadeout system in glitchrunnermode even more glitchy
game.roomx = 0;
game.roomy = 0;
}
game.prevroomx = 0;
game.prevroomy = 0;
game.teleport_to_new_area = false;
@ -3521,8 +3526,12 @@ void scriptclass::hardreset()
game.savetime = "00:00";
game.savearea = "nowhere";
game.savetrinkets = 0;
game.saverx = 0;
game.savery = 0;
if (!game.glitchrunnermode)
{
// Ironically, resetting more variables makes the janky fadeout system in glitchrunnermode even more glitchy
game.saverx = 0;
game.savery = 0;
}
game.intimetrial = false;
game.timetrialcountdown = 0;
@ -3564,7 +3573,12 @@ void scriptclass::hardreset()
game.statedelay = 0;
game.hascontrol = true;
game.advancetext = false;
if (!game.glitchrunnermode)
{
// Keep the "- Press ACTION to advance text -" prompt around,
// apparently the speedrunners call it the "text storage" glitch
game.advancetext = false;
}
game.pausescript = false;
@ -3601,7 +3615,11 @@ void scriptclass::hardreset()
map.resetnames();
map.custommode=false;
map.custommodeforreal=false;
map.towermode=false;
if (!game.glitchrunnermode)
{
// Ironically, resetting more variables makes the janky fadeout system even more glitchy
map.towermode=false;
}
map.cameraseekframe = 0;
map.resumedelay = 0;
map.scrolldir = 0;

View File

@ -56,7 +56,7 @@ public:
int looppoint, loopcount;
int scriptdelay;
bool running;
bool running, dontrunnextframe;
std::string tempword;
std::string currentletter;

View File

@ -542,7 +542,14 @@ void inline fixedloop()
titlelogic();
break;
case GAMEMODE:
if (script.running)
// WARNING: If updating this code, don't forget to update Map.cpp mapclass::twoframedelayfix()
// Ugh, I hate this kludge variable but it's the only way to do it
if (script.dontrunnextframe)
{
script.dontrunnextframe = false;
}
else if (script.running)
{
script.run();
}