1
0
mirror of https://github.com/TerryCavanagh/VVVVVV.git synced 2024-06-25 22:18:30 +02:00
VVVVVV/desktop_version/src/Logic.cpp
Misa f93ce4ea4a Fix Prize for the Reckless moving platform losing its block when...
...you die and the platform's x-coordinate is to the left of x=152.
Which means if you die and the platform isn't completely clear of the
space of its adjacent disappearing platform.

The block needs to be updated accordingly with calls to
obj.nocollisionat() and obj.moveblockto(), else the block will simply be
left behind and the platform will no longer have any collision. This is
in contrast to 2.2 behavior, where the platform would simply
unconditionally create a new block, which would actually end up with a
duplicate block since the previous block didn't get cleaned up, but this
didn't cause any problems because the room was carefully designed so you
would never be able to touch that previous block after you died and
respawned at the checkpoint. But it's still there.

I also added comments to document what this kludge code did, because
otherwise it would be mysterious to readers who are unfamiliar with it.

Fixes #543.
2020-11-12 17:06:31 -05:00

1781 lines
60 KiB
C++

#include "Credits.h"
#include "editor.h"
#include "Entity.h"
#include "Enums.h"
#include "FileSystemUtils.h"
#include "Game.h"
#include "Graphics.h"
#include "Map.h"
#include "Music.h"
#include "Network.h"
#include "Script.h"
#include "UtilityClass.h"
void titleupdatetextcol()
{
graphics.col_tr = map.r - (help.glow / 4) - int(fRandom() * 4);
graphics.col_tg = map.g - (help.glow / 4) - int(fRandom() * 4);
graphics.col_tb = map.b - (help.glow / 4) - int(fRandom() * 4);
if (graphics.col_tr < 0) graphics.col_tr = 0;
if(graphics.col_tr>255) graphics.col_tr=255;
if (graphics.col_tg < 0) graphics.col_tg = 0;
if(graphics.col_tg>255) graphics.col_tg=255;
if (graphics.col_tb < 0) graphics.col_tb = 0;
if(graphics.col_tb>255) graphics.col_tb=255;
}
void titlelogic()
{
//Misc
//map.updatetowerglow(graphics.titlebg);
help.updateglow();
graphics.titlebg.bypos -= 2;
graphics.titlebg.bscroll = -2;
if (!game.colourblindmode)
{
graphics.updatetowerbackground(graphics.titlebg);
}
if (!game.menustart)
{
graphics.col_tr = (int)(164 - (help.glow / 2) - int(fRandom() * 4));
graphics.col_tg = 164 - (help.glow / 2) - int(fRandom() * 4);
graphics.col_tb = 164 - (help.glow / 2) - int(fRandom() * 4);
}
else
{
titleupdatetextcol();
graphics.updatetitlecolours();
}
graphics.crewframedelay--;
if (graphics.crewframedelay <= 0)
{
graphics.crewframedelay = 8;
graphics.crewframe = (graphics.crewframe + 1) % 2;
}
if (game.menucountdown > 0)
{
game.menucountdown--;
if (game.menucountdown == 0)
{
if (game.menudest == Menu::mainmenu)
{
music.play(6);
}
else if (game.menudest == Menu::gameover2)
{
music.playef(11);
}
else if (game.menudest == Menu::timetrialcomplete3)
{
music.playef(3);
}
game.createmenu(game.menudest, true);
}
}
}
void maplogic()
{
//Misc
help.updateglow();
graphics.updatetextboxes();
graphics.updatetitlecolours();
graphics.crewframedelay--;
if (graphics.crewframedelay <= 0)
{
graphics.crewframedelay = 8;
graphics.crewframe = (graphics.crewframe + 1) % 2;
}
graphics.oldmenuoffset = graphics.menuoffset;
if (graphics.resumegamemode)
{
graphics.menuoffset += 25;
int threshold = map.extrarow ? 230 : 240;
if (graphics.menuoffset >= threshold)
{
graphics.menuoffset = threshold;
//go back to gamemode!
game.mapheld = true;
game.gamestate = GAMEMODE;
}
}
else if (graphics.menuoffset > 0)
{
graphics.menuoffset -= 25;
if (graphics.menuoffset < 0)
{
graphics.menuoffset = 0;
}
}
if (map.cursorstate == 0){
map.cursordelay++;
if (map.cursordelay > 10){
map.cursorstate = 1;
map.cursordelay = 0;
}
}else if (map.cursorstate == 1){
map.cursordelay++;
if (map.cursordelay > 30) map.cursorstate = 2;
}else if (map.cursorstate == 2){
map.cursordelay++;
}
if (map.finalmode)
{
map.glitchname = map.getglitchname(game.roomx, game.roomy);
}
}
void gamecompletelogic()
{
//Misc
map.updatetowerglow(graphics.titlebg);
help.updateglow();
graphics.crewframe = 0;
graphics.titlebg.scrolldir = 1;
graphics.updatetitlecolours();
titleupdatetextcol();
game.creditposition--;
if (game.creditposition <= -Credits::creditmaxposition)
{
game.creditposition = -Credits::creditmaxposition;
graphics.titlebg.bscroll = 0;
}
else if (!game.press_action)
{
graphics.titlebg.bscroll = +1;
}
if (graphics.fademode == 1)
{
//Fix some graphical things
graphics.showcutscenebars = false;
graphics.cutscenebarspos = 0;
graphics.oldcutscenebarspos = 0;
graphics.titlebg.scrolldir = 0;
graphics.titlebg.bypos = 0;
//Return to game
game.gamestate = GAMECOMPLETE2;
graphics.fademode = 4;
}
}
void gamecompletelogic2()
{
//Misc
map.updatetowerglow(graphics.titlebg);
help.updateglow();
game.creditposdelay--;
if (game.creditposdelay <= 0)
{
game.creditposdelay = 1;
game.creditposx++;
if (game.creditposx > 40)
{
game.creditposy++;
game.creditposx = 0;
if (game.creditposy > 30) game.creditposy = 30;
}
}
if (graphics.fademode == 1)
{
//Fix some graphical things
graphics.showcutscenebars = false;
graphics.cutscenebarspos = 0;
//Fix the save thingy
game.deletequick();
int tmp=music.currentsong;
music.currentsong=4;
obj.flags[67] = true;
game.savetele();
music.currentsong=tmp;
//Return to game
graphics.titlebg.colstate = 10;
game.gamestate = TITLEMODE;
graphics.fademode = 4;
FILESYSTEM_unmountassets(); // should be before music.playef(18)
music.playef(18);
game.returntomenu(Menu::play);
game.createmenu(Menu::gamecompletecontinue);
map.nexttowercolour();
}
}
void gamelogic()
{
if (!game.blackout && !game.completestop)
{
for (size_t i = 0; i < obj.entities.size(); i++)
{
//Is this entity on the ground? (needed for jumping)
if (obj.entitycollidefloor(i))
{
obj.entities[i].onground = 2;
}
else
{
obj.entities[i].onground--;
}
if (obj.entitycollideroof(i))
{
obj.entities[i].onroof = 2;
}
else
{
obj.entities[i].onroof--;
}
//Animate the entities
obj.animateentities(i);
}
}
//Misc
if (map.towermode)
{
map.updatetowerglow(graphics.towerbg);
}
help.updateglow();
if (game.alarmon)
{
game.alarmdelay--;
if (game.alarmdelay <= 0)
{
music.playef(19);
game.alarmdelay = 20;
}
}
if (obj.nearelephant)
{
obj.upset++;
if (obj.upset == 300)
{
obj.upsetmode = true;
//change player to sad
int i = obj.getplayer();
if (INBOUNDS_VEC(i, obj.entities))
{
obj.entities[i].tile = 144;
}
music.playef(2);
}
if (obj.upset > 301) obj.upset = 301;
}
else if (obj.upsetmode)
{
obj.upset--;
if (obj.upset <= 0)
{
obj.upset = 0;
obj.upsetmode = false;
//change player to happy
int i = obj.getplayer();
if (INBOUNDS_VEC(i, obj.entities))
{
obj.entities[i].tile = 0;
}
}
}
else
{
obj.upset = 0;
}
obj.oldtrophytext = obj.trophytext;
if (map.towermode)
{
map.oldypos = map.ypos;
map.oldspikeleveltop = map.spikeleveltop;
map.oldspikelevelbottom = map.spikelevelbottom;
if(!game.completestop)
{
if (map.cameramode == 0)
{
//do nothing!
//a trigger will set this off in the game
map.cameramode = 1;
graphics.towerbg.bscroll = 0;
}
else if (map.cameramode == 1)
{
//move normally
if(graphics.towerbg.scrolldir==0)
{
map.ypos -= 2;
graphics.towerbg.bypos -= 1;
graphics.towerbg.bscroll = -1;
}
else
{
map.ypos += 2;
graphics.towerbg.bypos += 1;
graphics.towerbg.bscroll = 1;
}
}
else if (map.cameramode == 2)
{
//do nothing, but cycle colours (for taking damage)
graphics.towerbg.bscroll = 0;
}
else if (map.cameramode == 4)
{
int i = obj.getplayer();
if (INBOUNDS_VEC(i, obj.entities))
{
map.cameraseek = map.ypos - (obj.entities[i].yp - 120);
}
map.cameraseek = map.cameraseek / 10;
map.cameraseekframe = 10;
map.cameramode = 5;
graphics.towerbg.bscroll = map.cameraseek/2;
}
else if (map.cameramode == 5)
{
//actually do it
if (map.spikeleveltop > 0) map.spikeleveltop-=2;
if (map.spikelevelbottom > 0) map.spikelevelbottom-=2;
if (map.cameraseekframe > 0)
{
int i = obj.getplayer();
map.ypos -= map.cameraseek;
if (map.cameraseek > 0 && INBOUNDS_VEC(i, obj.entities))
{
if (map.ypos < obj.entities[i].yp - 120)
{
map.ypos = obj.entities[i].yp - 120;
}
}
else if (INBOUNDS_VEC(i, obj.entities))
{
if (map.ypos > obj.entities[i].yp - 120)
{
map.ypos = obj.entities[i].yp - 120;
}
}
map.cameraseekframe--;
graphics.towerbg.bypos = map.ypos / 2;
}
else
{
int i = obj.getplayer();
if (INBOUNDS_VEC(i, obj.entities))
{
map.ypos = obj.entities[i].yp - 120;
}
graphics.towerbg.bypos = map.ypos / 2;
map.cameramode = 0;
map.colsuperstate = 0;
}
}
}
else
{
graphics.towerbg.bscroll = 0;
}
if (map.ypos <= 0)
{
map.ypos = 0;
graphics.towerbg.bypos = 0;
graphics.towerbg.bscroll = 0;
}
if (map.towermode && map.minitowermode)
{
if (map.ypos >= 568)
{
map.ypos = 568;
graphics.towerbg.bypos = map.ypos / 2;
graphics.towerbg.bscroll = 0;
} //100-29 * 8 = 568
}
else
{
if (map.ypos >= 5368)
{
map.ypos = 5368; //700-29 * 8 = 5368
graphics.towerbg.bypos = map.ypos / 2.0;
}
}
if (game.lifeseq > 0)
{
if (map.cameramode == 2)
{
map.cameraseekframe = 20;
map.cameramode = 4;
map.resumedelay = 4;
}
if (map.cameraseekframe <= 0)
{
if (map.resumedelay <= 0)
{
game.lifesequence();
if (game.lifeseq == 0) map.cameramode = 1;
}
else
{
map.resumedelay--;
}
}
}
}
else
{
game.lifesequence();
}
graphics.kludgeswnlinewidth = false;
if (game.deathseq != -1)
{
if (map.towermode)
{
map.colsuperstate = 1;
map.cameramode = 2;
}
for (size_t i = 0; i < obj.entities.size(); i++)
{
if (game.roomx == 111 && game.roomy == 107 && !map.custommode)
{
if (obj.entities[i].type == 1)
{
if (obj.entities[i].xp < 152)
{
//Move the platform to the right side of the disappearing platform,
//otherwise it will get stuck on the kludge 18,9 tile we placed
//(and if the tile wasn't there it would pass straight through again)
int prevx = obj.entities[i].xp;
int prevy = obj.entities[i].yp;
obj.nocollisionat(prevx, prevy);
obj.entities[i].xp = 152;
obj.entities[i].newxp = 152;
obj.moveblockto(prevx, prevy, obj.entities[i].xp, obj.entities[i].yp, obj.entities[i].w, obj.entities[i].h);
}
}
}
if (obj.entities[i].type == 2 && obj.entities[i].state == 3)
{
//Ok! super magical exception for the room with the intention death for the shiny trinket
//fix this when the maps are finalised
if (game.roomx != 111 || game.roomy != 107 || map.custommode)
{
obj.entities[i].state = 4;
}
else
{
obj.entities[i].state = 4;
map.settile(18, 9, 59);
}
}
else if (obj.entities[i].type == 2 && obj.entities[i].state == 2)
{
//ok, unfortunate case where the disappearing platform hasn't fully disappeared. Accept a little
//graphical uglyness to avoid breaking the room!
bool entitygone = false;
while (obj.entities[i].state == 2)
{
entitygone = obj.updateentities(i);
if (entitygone)
{
i--;
break;
}
}
if (!entitygone) obj.entities[i].state = 4;
}
else if (map.finalstretch && obj.entities[i].type == 2)
{
//for the final level. probably something 99% of players won't see.
bool entitygone = false;
while (obj.entities[i].state == 2)
{
entitygone = obj.updateentities(i);
if (entitygone)
{
i--;
break;
}
}
if (!entitygone) obj.entities[i].state = 4;
}
else if (obj.entities[i].type == 23 && game.swnmode && game.deathseq<15)
{
//if playing SWN, get the enemies offscreen.
obj.entities[i].xp += obj.entities[i].vx*5;
obj.entities[i].yp += obj.entities[i].vy*5;
}
}
if (game.swnmode)
{
//if playing SWN game a, push the clock back to the nearest 10 second interval
if (game.swngame == 0)
{
game.swnpenalty();
}
else if (game.swngame == 1)
{
game.swnstate = 0;
game.swnstate2 = 0;
game.swnstate3 = 0;
game.swnstate4 = 0;
game.swndelay = 0;
if (game.swntimer >= game.swnrecord)
{
game.swnrecord = game.swntimer;
if (game.swnmessage == 0)
{
music.playef(25);
game.savestats();
}
game.swnmessage = 1;
}
}
}
game.deathsequence();
game.deathseq--;
if (game.deathseq <= 0)
{
if (game.nodeathmode)
{
game.deathseq = 1;
game.gethardestroom();
//start depressing sequence here...
if (game.gameoverdelay <= -10 && graphics.fademode==0) graphics.fademode = 2;
if (graphics.fademode == 1) script.resetgametomenu();
}
else
{
if (game.swnmode)
{
//if playing SWN game b, reset the clock
if (game.swngame == 1)
{
game.swntimer = 0;
game.swnmessage = 0;
game.swnrank = 0;
}
}
game.gethardestroom();
game.hascontrol = true;
game.gravitycontrol = game.savegc;
graphics.textboxremove();
map.resetplayer();
}
}
}
else
{
//Update colour thingy
if (map.finalmode)
{
if (map.final_colormode)
{
if (map.final_colorframe > 0)
{
map.final_colorframedelay--;
if (map.final_colorframedelay <= 0)
{
if (map.final_colorframe == 1)
{
map.final_colorframedelay = 40;
int temp = 1+int(fRandom() * 6);
if (temp == map.final_mapcol) temp = (temp + 1) % 6;
if (temp == 0) temp = 6;
map.changefinalcol(temp);
}
else if (map.final_colorframe == 2)
{
map.final_colorframedelay = 15;
int temp = 1+int(fRandom() * 6);
if (temp == map.final_mapcol) temp = (temp + 1) % 6;
if (temp == 0) temp = 6;
map.changefinalcol(temp);
}
}
}
}
}
//State machine for game logic
game.updatestate();
if (game.startscript)
{
script.load(game.newscript);
game.startscript = false;
}
//Intermission 1 Logic
//Player can't walk off a screen with SCM on it until they've left
if (game.supercrewmate)
{
if (game.roomx == 41 + game.scmprogress) //he's in the same room
{
int i = obj.getplayer();
if (INBOUNDS_VEC(i, obj.entities) && obj.entities[i].ax > 0 && obj.entities[i].xp > 280)
{
obj.entities[i].ax = 0;
obj.entities[i].dir = 0;
}
}
}
//SWN Minigame Logic
if (game.swnmode) //which game?
{
if(game.swngame==0) //intermission, survive 60 seconds game
{
game.swntimer -= 1;
if (game.swntimer <= 0)
{
music.niceplay(8);
game.swngame = 5;
}
else
{
obj.generateswnwave(0);
}
}
else if(game.swngame==1) //super gravitron game
{
game.swntimer += 1;
if (game.swntimer > game.swnrecord) game.swnrecord = game.swntimer;
if (game.swntimer >= 150 && game.swnrank == 0)
{
game.swnrank = 1;
if (game.swnbestrank < 1)
{
game.unlockAchievement("vvvvvvsupgrav5");
game.swnbestrank = 1;
game.swnmessage = 2+30;
music.playef(26);
}
}
else if (game.swntimer >= 300 && game.swnrank == 1)
{
game.swnrank = 2;
if (game.swnbestrank < 2)
{
game.unlockAchievement("vvvvvvsupgrav10");
game.swnbestrank = 2;
game.swnmessage = 2+30;
music.playef(26);
}
}
else if (game.swntimer >= 450 && game.swnrank == 2)
{
game.swnrank = 3;
if (game.swnbestrank < 3)
{
game.unlockAchievement("vvvvvvsupgrav15");
game.swnbestrank = 3;
game.swnmessage = 2+30;
music.playef(26);
}
}
else if (game.swntimer >= 600 && game.swnrank == 3)
{
game.swnrank = 4;
if (game.swnbestrank < 4)
{
game.unlockAchievement("vvvvvvsupgrav20");
game.swnbestrank = 4;
game.swnmessage = 2+30;
music.playef(26);
}
}
else if (game.swntimer >= 900 && game.swnrank == 4)
{
game.swnrank = 5;
if (game.swnbestrank < 5)
{
game.unlockAchievement("vvvvvvsupgrav30");
game.swnbestrank = 5;
game.swnmessage = 2+30;
music.playef(26);
}
}
else if (game.swntimer >= 1800 && game.swnrank == 5)
{
game.swnrank = 6;
if (game.swnbestrank < 6)
{
game.unlockAchievement("vvvvvvsupgrav60");
game.swnbestrank = 6;
game.swnmessage = 2+30;
music.playef(26);
}
}
obj.generateswnwave(1);
game.swncoldelay--;
if(game.swncoldelay<=0)
{
game.swncolstate = (game.swncolstate+1)%6;
game.swncoldelay = 30;
graphics.rcol = game.swncolstate;
obj.swnenemiescol(game.swncolstate);
}
}
else if (game.swngame == 2) //introduce game a
{
game.swndelay--;
if (game.swndelay <= 0)
{
game.swngame = 0;
game.swndelay = 0;
game.swntimer = (60 * 30) - 1;
//game.swntimer = 15;
}
}
else if (game.swngame == 3) //extend line
{
int line = obj.getlineat(84 - 32);
if (INBOUNDS_VEC(line, obj.entities))
{
obj.entities[line].w += 24;
if (obj.entities[line].w > 332)
{
obj.entities[line].w = 332;
game.swngame = 2;
graphics.kludgeswnlinewidth = true;
}
}
}
else if (game.swngame == 4) //create top line
{
game.swngame = 3;
obj.createentity(-8, 84 - 32, 11, 8); // (horizontal gravity line)
music.niceplay(2);
game.swndeaths = game.deathcounts;
}
else if (game.swngame == 5) //remove line
{
int line = obj.getlineat(148 + 32);
if (INBOUNDS_VEC(line, obj.entities))
{
obj.entities[line].xp += 24;
if (obj.entities[line].xp > 320)
{
obj.removeentity(line);
game.swnmode = false;
game.swngame = 6;
}
}
}
else if (game.swngame == 6) //Init the super gravitron
{
game.swngame = 7;
music.niceplay(3);
}
else if (game.swngame == 7) //introduce game b
{
game.swndelay--;
if (game.swndelay <= 0)
{
game.swngame = 1;
game.swndelay = 0;
game.swntimer = 0;
game.swncolstate = 3;
game.swncoldelay = 30;
}
}
}
//Time trial stuff
if (game.intimetrial)
{
if (game.timetrialcountdown > 0)
{
game.timetrialparlost = false;
game.hascontrol = true;
game.timetrialcountdown--;
if (game.timetrialcountdown > 30)
{
game.hascontrol = false;
}
if(game.timetrialcountdown == 120) music.playef(21);
if(game.timetrialcountdown == 90) music.playef(21);
if(game.timetrialcountdown == 60) music.playef(21);
if (game.timetrialcountdown == 30)
{
switch(game.timetriallevel)
{
case 0:
music.play(1);
break;
case 1:
music.play(3);
break;
case 2:
music.play(2);
break;
case 3:
music.play(1);
break;
case 4:
music.play(12);
break;
case 5:
music.play(15);
break;
}
music.playef(22);
}
}
//Have we lost the par?
if (!game.timetrialparlost)
{
if ((game.minutes * 60) + game.seconds > game.timetrialpar)
{
game.timetrialparlost = true;
int i = obj.getplayer();
if (INBOUNDS_VEC(i, obj.entities))
{
obj.entities[i].tile = 144;
}
music.playef(2);
}
}
}
//Update entities
//Ok, moving platform fuckers
if(!game.completestop)
{
if(obj.vertplatforms)
{
for (int i = obj.entities.size() - 1; i >= 0; i--)
{
if (!obj.entities[i].isplatform
|| SDL_abs(obj.entities[i].vx) >= 0.000001f)
{
continue;
}
int prevx = obj.entities[i].xp;
int prevy = obj.entities[i].yp;
obj.nocollisionat(prevx, prevy);
bool entitygone = obj.updateentities(i); // Behavioral logic
if (entitygone) continue;
obj.updateentitylogic(i); // Basic Physics
obj.entitymapcollision(i); // Collisions with walls
obj.moveblockto(prevx, prevy, obj.entities[i].xp, obj.entities[i].yp, obj.entities[i].w, obj.entities[i].h);
obj.movingplatformfix(i, obj.getplayer());
if (game.supercrewmate)
{
obj.movingplatformfix(i, obj.getscm());
}
}
}
if(obj.horplatforms)
{
for (int ie = obj.entities.size() - 1; ie >= 0; ie--)
{
if (!obj.entities[ie].isplatform
|| SDL_abs(obj.entities[ie].vy) >= 0.000001f)
{
continue;
}
int prevx = obj.entities[ie].xp;
int prevy = obj.entities[ie].yp;
obj.nocollisionat(prevx, prevy);
bool entitygone = obj.updateentities(ie); // Behavioral logic
if (entitygone) continue;
obj.updateentitylogic(ie); // Basic Physics
obj.entitymapcollision(ie); // Collisions with walls
obj.moveblockto(prevx, prevy, obj.entities[ie].xp, obj.entities[ie].yp, obj.entities[ie].w, obj.entities[ie].h);
}
//is the player standing on a moving platform?
int i = obj.getplayer();
float j = obj.entitycollideplatformfloor(i);
if (INBOUNDS_VEC(i, obj.entities) && j > -1000)
{
obj.entities[i].newxp = obj.entities[i].xp + j;
obj.entities[i].newyp = obj.entities[i].yp;
obj.entitymapcollision(i);
}
else
{
j = obj.entitycollideplatformroof(i);
if (INBOUNDS_VEC(i, obj.entities) && j > -1000)
{
obj.entities[i].newxp = obj.entities[i].xp + j;
obj.entities[i].newyp = obj.entities[i].yp;
obj.entitymapcollision(i);
}
}
}
for (int ie = obj.entities.size() - 1; ie >= 0; ie--)
{
if (obj.entities[ie].isplatform)
{
continue;
}
bool entitygone = obj.updateentities(ie); // Behavioral logic
if (entitygone) continue;
obj.updateentitylogic(ie); // Basic Physics
obj.entitymapcollision(ie); // Collisions with walls
}
obj.entitycollisioncheck(); // Check ent v ent collisions, update states
if (map.towermode)
{
//special for tower: is the player touching any spike blocks?
int player = obj.getplayer();
if(INBOUNDS_VEC(player, obj.entities) && obj.checktowerspikes(player) && graphics.fademode==0)
{
game.deathseq = 30;
}
}
if(map.towermode && game.lifeseq==0)
{
int player = obj.getplayer();
if(!map.invincibility && INBOUNDS_VEC(player, obj.entities))
{
if (obj.entities[player].yp-map.ypos <= 0)
{
game.deathseq = 30;
}
else if (obj.entities[player].yp-map.ypos >= 208)
{
game.deathseq = 30;
}
}
else if (INBOUNDS_VEC(player, obj.entities))
{
if (obj.entities[player].yp-map.ypos <= 0)
{
map.ypos-=10;
graphics.towerbg.bypos = map.ypos / 2;
graphics.towerbg.bscroll = 0;
}
else if (obj.entities[player].yp-map.ypos >= 208)
{
map.ypos+=2;
graphics.towerbg.bypos = map.ypos / 2;
graphics.towerbg.bscroll = 0;
}
}
if (INBOUNDS_VEC(player, obj.entities) && obj.entities[player].yp - map.ypos <= 40)
{
map.spikeleveltop++;
if (map.spikeleveltop >= 8) map.spikeleveltop = 8;
}
else
{
if (map.spikeleveltop > 0) map.spikeleveltop--;
}
if (INBOUNDS_VEC(player, obj.entities) && obj.entities[player].yp - map.ypos >= 164)
{
map.spikelevelbottom++;
if (map.spikelevelbottom >= 8) map.spikelevelbottom = 8;
}
else
{
if (map.spikelevelbottom > 0) map.spikelevelbottom--;
}
}
}
//Using warplines?
if (obj.customwarpmode) {
if (!game.glitchrunnermode) {
//Rewritten system for mobile update: basically, the new logic is to
//check if the player is leaving the map, and if so do a special check against
//warp lines for collision
obj.customwarpmodehon = false;
obj.customwarpmodevon = false;
int i = obj.getplayer();
if (INBOUNDS_VEC(i, obj.entities) && ((game.door_down > -2 && obj.entities[i].yp >= 226-16) || (game.door_up > -2 && obj.entities[i].yp < -2+16) || (game.door_left > -2 && obj.entities[i].xp < -14+16) || (game.door_right > -2 && obj.entities[i].xp >= 308-16))){
//Player is leaving room
obj.customwarplinecheck(i);
}
}
if(obj.customwarpmodehon){ map.warpy=true;
}else{ map.warpy=false; }
if(obj.customwarpmodevon){ map.warpx=true;
}else{ map.warpx=false; }
}
//Finally: Are we changing room?
if (map.warpx && !map.towermode)
{
for (size_t i = 0; i < obj.entities.size(); i++)
{
if(obj.entities[i].type<50 //Don't warp warp lines
&& obj.entities[i].size < 12) //Don't wrap SWN enemies
{
if (game.roomx == 118 && game.roomy == 102 && obj.entities[i].rule==1 && !map.custommode)
{
//ascii snakes
if (obj.entities[i].xp <= -80)
{
if (obj.entities[i].isplatform)
{
obj.moveblockto(obj.entities[i].xp, obj.entities[i].yp, obj.entities[i].xp + 400, obj.entities[i].yp, obj.entities[i].w, obj.entities[i].h);
}
obj.entities[i].xp += 400;
obj.entities[i].lerpoldxp += 400;
}
else if (obj.entities[i].xp > 320)
{
if (obj.entities[i].isplatform)
{
obj.moveblockto(obj.entities[i].xp, obj.entities[i].yp, obj.entities[i].xp - 400, obj.entities[i].yp, obj.entities[i].w, obj.entities[i].h);
}
obj.entities[i].xp -= 400;
obj.entities[i].lerpoldxp -= 400;
}
}
else
{
if (obj.entities[i].xp <= -10)
{
if (obj.entities[i].isplatform)
{
obj.moveblockto(obj.entities[i].xp, obj.entities[i].yp, obj.entities[i].xp + 320, obj.entities[i].yp, obj.entities[i].w, obj.entities[i].h);
}
obj.entities[i].xp += 320;
obj.entities[i].lerpoldxp += 320;
}
else if (obj.entities[i].xp > 310)
{
if (obj.entities[i].isplatform)
{
obj.moveblockto(obj.entities[i].xp, obj.entities[i].yp, obj.entities[i].xp - 320, obj.entities[i].yp, obj.entities[i].w, obj.entities[i].h);
}
obj.entities[i].xp -= 320;
obj.entities[i].lerpoldxp -= 320;
}
}
}
}
}
if (map.warpy && !map.towermode)
{
for (size_t i = 0; i < obj.entities.size(); i++)
{
if(obj.entities[i].type<50){ //Don't warp warp lines
if (obj.entities[i].yp <= -12)
{
if (obj.entities[i].isplatform)
{
obj.moveblockto(obj.entities[i].xp, obj.entities[i].yp, obj.entities[i].xp, obj.entities[i].yp + 232, obj.entities[i].w, obj.entities[i].h);
}
obj.entities[i].yp += 232;
obj.entities[i].lerpoldyp += 232;
}
else if (obj.entities[i].yp > 226)
{
if (obj.entities[i].isplatform)
{
obj.moveblockto(obj.entities[i].xp, obj.entities[i].yp, obj.entities[i].xp, obj.entities[i].yp - 232, obj.entities[i].w, obj.entities[i].h);
}
obj.entities[i].yp -= 232;
obj.entities[i].lerpoldyp -= 232;
}
}
}
}
if (map.warpy && !map.warpx && !map.towermode)
{
for (size_t i = 0; i < obj.entities.size(); i++)
{
if(obj.entities[i].type<50 //Don't warp warp lines
&&obj.entities[i].rule!=0)
{
if (obj.entities[i].xp <= -30)
{
if (obj.entities[i].isplatform)
{
obj.moveblockto(obj.entities[i].xp, obj.entities[i].yp, obj.entities[i].xp + 350, obj.entities[i].yp, obj.entities[i].w, obj.entities[i].h);
}
obj.entities[i].xp += 350;
obj.entities[i].lerpoldxp += 350;
}
else if (obj.entities[i].xp > 320)
{
if (obj.entities[i].isplatform)
{
obj.moveblockto(obj.entities[i].xp, obj.entities[i].yp, obj.entities[i].xp - 350, obj.entities[i].yp, obj.entities[i].w, obj.entities[i].h);
}
obj.entities[i].xp -= 350;
obj.entities[i].lerpoldxp -= 350;
}
}
}
}
bool screen_transition = false;
if (!map.warpy && !map.towermode)
{
//Normal! Just change room
int player = obj.getplayer();
if (INBOUNDS_VEC(player, obj.entities) && game.door_down > -2 && obj.entities[player].yp >= 238)
{
obj.entities[player].yp -= 240;
map.gotoroom(game.roomx, game.roomy + 1);
screen_transition = true;
}
if (INBOUNDS_VEC(player, obj.entities) && game.door_up > -2 && obj.entities[player].yp < -2)
{
obj.entities[player].yp += 240;
map.gotoroom(game.roomx, game.roomy - 1);
screen_transition = true;
}
}
if (!map.warpx && !map.towermode)
{
//Normal! Just change room
int player = obj.getplayer();
if (INBOUNDS_VEC(player, obj.entities) && game.door_left > -2 && obj.entities[player].xp < -14)
{
obj.entities[player].xp += 320;
map.gotoroom(game.roomx - 1, game.roomy);
screen_transition = true;
}
if (INBOUNDS_VEC(player, obj.entities) && game.door_right > -2 && obj.entities[player].xp >= 308)
{
obj.entities[player].xp -= 320;
map.gotoroom(game.roomx + 1, game.roomy);
screen_transition = true;
}
}
//Right so! Screenwraping for tower:
if (map.towermode && map.minitowermode)
{
if (graphics.towerbg.scrolldir == 1)
{
//This is minitower 1!
int player = obj.getplayer();
if (INBOUNDS_VEC(player, obj.entities) && game.door_left > -2 && obj.entities[player].xp < -14)
{
obj.entities[player].xp += 320;
map.gotoroom(48, 52);
}
if (INBOUNDS_VEC(player, obj.entities) && game.door_right > -2 && obj.entities[player].xp >= 308)
{
obj.entities[player].xp -= 320;
obj.entities[player].yp -= (71*8);
map.gotoroom(game.roomx + 1, game.roomy+1);
}
}
else
{
//This is minitower 2!
int player = obj.getplayer();
if (INBOUNDS_VEC(player, obj.entities) && game.door_left > -2 && obj.entities[player].xp < -14)
{
if (obj.entities[player].yp > 300)
{
obj.entities[player].xp += 320;
obj.entities[player].yp -= (71 * 8);
map.gotoroom(50, 54);
}
else
{
obj.entities[player].xp += 320;
map.gotoroom(50, 53);
}
}
if (INBOUNDS_VEC(player, obj.entities) && game.door_right > -2 && obj.entities[player].xp >= 308)
{
obj.entities[player].xp -= 320;
map.gotoroom(52, 53);
}
}
}
else if (map.towermode)
{
//Always wrap except for the very top and very bottom of the tower
if(map.ypos>=500 && map.ypos <=5000)
{
for (size_t i = 0; i < obj.entities.size(); i++)
{
if (obj.entities[i].xp <= -10)
{
obj.entities[i].xp += 320;
obj.entities[i].lerpoldxp += 320;
}
else if (obj.entities[i].xp > 310)
{
obj.entities[i].xp -= 320;
obj.entities[i].lerpoldxp -= 320;
}
}
}
else
{
//Do not wrap! Instead, go to the correct room
int player = obj.getplayer();
if (INBOUNDS_VEC(player, obj.entities) && game.door_left > -2 && obj.entities[player].xp < -14)
{
obj.entities[player].xp += 320;
obj.entities[player].yp -= (671 * 8);
map.gotoroom(108, 109);
}
if (INBOUNDS_VEC(player, obj.entities) && game.door_right > -2 && obj.entities[player].xp >= 308)
{
obj.entities[player].xp -= 320;
map.gotoroom(110, 104);
}
}
}
//Warp tokens
if (map.custommode){
if (game.teleport)
{
int edi=obj.entities[game.edteleportent].behave;
int edj=obj.entities[game.edteleportent].para;
int edi2, edj2;
edi2 = (edi-(edi%40))/40;
edj2 = (edj-(edj%30))/30;
map.warpto(100+edi2, 100+edj2, obj.getplayer(), edi%40, (edj%30)+2);
game.teleport = false;
if (game.teleport == false)
{
game.flashlight = 6;
game.screenshake = 25;
}
}
}else{
if (game.teleport)
{
if (game.roomx == 117 && game.roomy == 102)
{
int i = obj.getplayer();
if (INBOUNDS_VEC(i, obj.entities))
{
obj.entities[i].yp = 225;
}
map.gotoroom(119, 100);
game.teleport = false;
}
else if (game.roomx == 119 && game.roomy == 100)
{
int i = obj.getplayer();
if (INBOUNDS_VEC(i, obj.entities))
{
obj.entities[i].yp = 225;
}
map.gotoroom(119, 103);
game.teleport = false;
}
else if (game.roomx == 119 && game.roomy == 103)
{
int i = obj.getplayer();
if (INBOUNDS_VEC(i, obj.entities))
{
obj.entities[i].xp = 0;
}
map.gotoroom(116, 103);
game.teleport = false;
}
else if (game.roomx == 116 && game.roomy == 103)
{
int i = obj.getplayer();
if (INBOUNDS_VEC(i, obj.entities))
{
obj.entities[i].yp = 225;
}
map.gotoroom(116, 100);
game.teleport = false;
}
else if (game.roomx == 116 && game.roomy == 100)
{
int i = obj.getplayer();
if (INBOUNDS_VEC(i, obj.entities))
{
obj.entities[i].xp = 0;
}
map.gotoroom(114, 102);
game.teleport = false;
}
else if (game.roomx == 114 && game.roomy == 102)
{
int i = obj.getplayer();
if (INBOUNDS_VEC(i, obj.entities))
{
obj.entities[i].yp = 225;
}
map.gotoroom(113, 100);
game.teleport = false;
}
else if (game.roomx == 116 && game.roomy == 104)
{
//pre warp zone here
map.warpto(107, 101, obj.getplayer(), 14, 16);
}
else if (game.roomx == 107 && game.roomy == 101)
{
map.warpto(105, 119, obj.getplayer(), 5, 26);
}
else if (game.roomx == 105 && game.roomy == 118)
{
map.warpto(101, 111, obj.getplayer(), 34, 6);
}
else if (game.roomx == 101 && game.roomy == 111)
{
//There are lots of warp tokens in this room, so we have to distinguish!
switch(game.teleportxpos)
{
case 1:
map.warpto(108, 108, obj.getplayer(), 4, 27);
break;
case 2:
map.warpto(101, 111, obj.getplayer(), 12, 27);
break;
case 3:
map.warpto(119, 111, obj.getplayer(), 31, 7);
break;
case 4:
map.warpto(114, 117, obj.getplayer(), 19, 16);
break;
}
}
else if (game.roomx == 108 && game.roomy == 106)
{
map.warpto(119, 111, obj.getplayer(), 4, 27);
}
else if (game.roomx == 100 && game.roomy == 111)
{
map.warpto(101, 111, obj.getplayer(), 24, 6);
}
else if (game.roomx == 119 && game.roomy == 107)
{
//Secret lab, to super gravitron
map.warpto(119, 108, obj.getplayer(), 19, 10);
}
if (game.teleport == false)
{
game.flashlight = 6;
game.screenshake = 25;
}
}
}
if (screen_transition)
{
map.twoframedelayfix();
}
}
//Update colour cycling for final level
if (map.finalmode && map.final_colormode)
{
map.final_aniframedelay--;
if(map.final_aniframedelay==0)
{
graphics.foregrounddrawn=false;
}
if (map.final_aniframedelay <= 0) {
map.final_aniframedelay = 2;
map.final_aniframe++;
if (map.final_aniframe >= 4)
map.final_aniframe = 0;
}
}
if (game.roomchange)
{
//We've changed room? Let's bring our companion along!
game.roomchange = false;
int i = obj.getplayer();
if (game.companion > 0 && INBOUNDS_VEC(i, obj.entities))
{
//ok, we'll presume our companion has been destroyed in the room change. So:
switch(game.companion)
{
case 6:
{
obj.createentity(obj.entities[i].xp, 121.0f, 15.0f,1); //Y=121, the floor in that particular place!
int j = obj.getcompanion();
if (INBOUNDS_VEC(j, obj.entities))
{
obj.entities[j].vx = obj.entities[i].vx;
obj.entities[j].dir = obj.entities[i].dir;
}
break;
}
case 7:
if (game.roomy <= 105) //don't jump after him!
{
if (game.roomx == 110)
{
obj.createentity(320, 86, 16, 1); //Y=86, the ROOF in that particular place!
}
else
{
obj.createentity(obj.entities[i].xp, 86.0f, 16.0f, 1); //Y=86, the ROOF in that particular place!
}
int j = obj.getcompanion();
if (INBOUNDS_VEC(j, obj.entities))
{
obj.entities[j].vx = obj.entities[i].vx;
obj.entities[j].dir = obj.entities[i].dir;
}
}
break;
case 8:
if (game.roomy >= 104) //don't jump after him!
{
if (game.roomx == 102)
{
obj.createentity(310, 177, 17, 1);
int j = obj.getcompanion();
if (INBOUNDS_VEC(j, obj.entities))
{
obj.entities[j].vx = obj.entities[i].vx;
obj.entities[j].dir = obj.entities[i].dir;
}
}
else
{
obj.createentity(obj.entities[i].xp, 177.0f, 17.0f, 1);
int j = obj.getcompanion();
if (INBOUNDS_VEC(j, obj.entities))
{
obj.entities[j].vx = obj.entities[i].vx;
obj.entities[j].dir = obj.entities[i].dir;
}
}
}
break;
case 9:
if (!map.towermode) //don't go back into the tower!
{
if (game.roomx == 110 && obj.entities[i].xp<20)
{
obj.createentity(100, 185, 18, 15, 0, 1);
}
else
{
obj.createentity(obj.entities[i].xp, 185.0f, 18.0f, 15, 0, 1);
}
int j = obj.getcompanion();
if (INBOUNDS_VEC(j, obj.entities))
{
obj.entities[j].vx = obj.entities[i].vx;
obj.entities[j].dir = obj.entities[i].dir;
}
}
break;
case 10:
//intermission 2, choose colour based on lastsaved
if (game.roomy == 51)
{
if (!obj.flags[59])
{
obj.createentity(225.0f, 169.0f, 18, graphics.crewcolour(game.lastsaved), 0, 10);
int j = obj.getcompanion();
if (INBOUNDS_VEC(j, obj.entities))
{
obj.entities[j].vx = obj.entities[i].vx;
obj.entities[j].dir = obj.entities[i].dir;
}
}
}
else if (game.roomy >= 52)
{
if (obj.flags[59])
{
obj.createentity(160.0f, 177.0f, 18, graphics.crewcolour(game.lastsaved), 0, 18, 1);
int j = obj.getcompanion();
if (INBOUNDS_VEC(j, obj.entities))
{
obj.entities[j].vx = obj.entities[i].vx;
obj.entities[j].dir = obj.entities[i].dir;
}
}
else
{
obj.flags[59] = true;
obj.createentity(obj.entities[i].xp, -20.0f, 18.0f, graphics.crewcolour(game.lastsaved), 0, 10, 0);
int j = obj.getcompanion();
if (INBOUNDS_VEC(j, obj.entities))
{
obj.entities[j].vx = obj.entities[i].vx;
obj.entities[j].dir = obj.entities[i].dir;
}
}
}
break;
case 11:
//Intermission 1: We're using the SuperCrewMate instead!
if(game.roomx-41==game.scmprogress)
{
switch(game.scmprogress)
{
case 0:
obj.createentity(76, 161, 24, graphics.crewcolour(game.lastsaved), 2);
break;
case 1:
obj.createentity(10, 169, 24, graphics.crewcolour(game.lastsaved), 2);
break;
case 2:
obj.createentity(10, 177, 24, graphics.crewcolour(game.lastsaved), 2);
break;
case 3:
if (game.scmmoveme)
{
obj.createentity(obj.entities[obj.getplayer()].xp, 185, 24, graphics.crewcolour(game.lastsaved), 2);
game.scmmoveme = false;
}
else
{
obj.createentity(10, 177, 24, graphics.crewcolour(game.lastsaved), 2);
}
break;
case 4:
obj.createentity(10, 185, 24, graphics.crewcolour(game.lastsaved), 2);
break;
case 5:
obj.createentity(10, 185, 24, graphics.crewcolour(game.lastsaved), 2);
break;
case 6:
obj.createentity(10, 185, 24, graphics.crewcolour(game.lastsaved), 2);
break;
case 7:
obj.createentity(10, 41, 24, graphics.crewcolour(game.lastsaved), 2);
break;
case 8:
obj.createentity(10, 169, 24, graphics.crewcolour(game.lastsaved), 2);
break;
case 9:
obj.createentity(10, 169, 24, graphics.crewcolour(game.lastsaved), 2);
break;
case 10:
obj.createentity(10, 129, 24, graphics.crewcolour(game.lastsaved), 2);
break;
case 11:
obj.createentity(10, 129, 24, graphics.crewcolour(game.lastsaved), 2);
break;
case 12:
obj.createentity(10, 65, 24, graphics.crewcolour(game.lastsaved), 2);
break;
case 13:
obj.createentity(10, 177, 24, graphics.crewcolour(game.lastsaved));
break;
}
}
if (game.scmmoveme)
{
int scm = obj.getscm();
int player = obj.getplayer();
if (INBOUNDS_VEC(scm, obj.entities) && INBOUNDS_VEC(player, obj.entities))
{
obj.entities[scm].xp = obj.entities[player].xp;
}
game.scmmoveme = false;
}
break;
}
}
}
game.activeactivity = obj.checkactivity();
game.oldreadytotele = game.readytotele;
if (game.activetele && !game.advancetext && game.hascontrol && !script.running && !game.intimetrial)
{
int i = obj.getplayer();
SDL_Rect temprect = SDL_Rect();
if (INBOUNDS_VEC(i, obj.entities))
{
temprect.x = obj.entities[i].xp + obj.entities[i].cx;
temprect.y = obj.entities[i].yp + obj.entities[i].cy;
temprect.w = obj.entities[i].w;
temprect.h = obj.entities[i].h;
}
if (help.intersects(game.teleblock, temprect))
{
game.readytotele += 25;
if (game.readytotele >= 255) game.readytotele = 255;
}
else
{
game.readytotele -= 50;
if (game.readytotele < 0) game.readytotele = 0;
}
}
else
{
if (game.readytotele > 0)
{
game.readytotele -= 50;
if (game.readytotele < 0) game.readytotele = 0;
}
}
if (game.teleport_to_new_area)
script.teleport();
#if !defined(NO_CUSTOM_LEVELS)
if (game.shouldreturntoeditor)
{
game.returntoeditor();
}
#endif
game.prev_act_fade = game.act_fade;
if (INBOUNDS_VEC(game.activeactivity, obj.blocks) && game.hascontrol && !script.running)
{
if (game.act_fade < 5)
{
game.act_fade = 5;
}
if (game.act_fade < 10)
{
game.act_fade++;
}
}
else if (game.act_fade > 5)
{
game.act_fade--;
}
if (obj.trophytext > 0)
{
obj.trophytext--;
}
graphics.updatetextboxes();
if (!game.colourblindmode)
{
if (map.towermode)
{
graphics.updatetowerbackground(graphics.towerbg);
}
else
{
graphics.updatebackground(map.background);
}
}
if (!game.blackout)
{
//Update line colours!
if (graphics.linedelay <= 0)
{
graphics.linestate++;
if (graphics.linestate >= 10) graphics.linestate = 0;
graphics.linedelay = 2;
}
else
{
graphics.linedelay--;
}
}
graphics.trinketcolset = false;
for (int i = obj.entities.size() - 1; i >= 0; i--)
{
if (obj.entities[i].invis)
{
continue;
}
obj.entities[i].updatecolour();
}
if (map.finalmode)
{
map.glitchname = map.getglitchname(game.roomx, game.roomy);
}
#if !defined(NO_CUSTOM_LEVELS)
ed.oldreturneditoralpha = ed.returneditoralpha;
if (map.custommode && !map.custommodeforreal && ed.returneditoralpha > 0)
{
ed.returneditoralpha -= 15;
}
// Editor ghosts!
if (game.ghostsenabled)
{
if (map.custommode && !map.custommodeforreal)
{
if (game.gametimer % 3 == 0)
{
int i = obj.getplayer();
GhostInfo ghost;
ghost.rx = game.roomx-100;
ghost.ry = game.roomy-100;
if (INBOUNDS_VEC(i, obj.entities))
{
ghost.x = obj.entities[i].xp;
ghost.y = obj.entities[i].yp;
ghost.col = obj.entities[i].colour;
ghost.realcol = obj.entities[i].realcol;
ghost.frame = obj.entities[i].drawframe;
}
ed.ghosts.push_back(ghost);
}
if (ed.ghosts.size() > 100)
{
ed.ghosts.erase(ed.ghosts.begin());
}
}
}
#endif
}