1
0
mirror of https://github.com/TerryCavanagh/VVVVVV.git synced 2024-06-02 02:53:32 +02:00
VVVVVV/desktop_version/src/Entity.h

216 lines
4.1 KiB
C
Raw Normal View History

2020-01-01 21:29:24 +01:00
#ifndef ENTITY_H
#define ENTITY_H
#include "Maths.h"
#include "Ent.h"
#include "BlockV.h"
#include <vector>
#include <string>
Prevent removing the player entity Removing the player entity has all sorts of nasty effects, such as softlocking the game because many inputs require there to be a player present, such as opening the quit menu. The most infamous glitch to remove the player entity is the Gravitron Fling, where the game doesn't see a gravity line at a specific y-position in the current room, and when it moves the bottom gravity line it moves the player instead. When the gravity line gets outside the room, it gets destroyed, so if the player gets dragged outside the room, they get destroyed, too. (Don't misinterpret this as saying anytime the player gets dragged outside the room, they get destroyed - it's only the Gravitron logic that destroys them.) Also, there are many places in the code that use entity-getting functions that have a fallback value of 0. If it was possible to remove the player, then it's possible for this fallback value of 0 to index obj.entities out-of-bounds, which is not good. To fix this, entityclass::removeentity() is now a bool that signifies if the entity was successfully removed or not. If the entity given is the player (meaning it first checks if it's rule 0, just so in 99% of cases it'll short-circuit and won't do the next check, which is if entityclass::getplayer() says the indice to be removed is the player), then it'll refuse to remove the entity, and return false. This is a change in behavior where callers might expect entityclass::removeentity() to always succeed, so I changed the removeentity_iter() macro to only decrement if removing the entity succeeded. I also changed entityclass::updateentities() from 'removeentity(i); return true;' to 'return removeentity(i);'.
2020-06-13 21:00:04 +02:00
#define removeentity_iter(index) { if (obj.removeentity(index)) index--; }
#define removeblock_iter(index) { obj.removeblock(index); index--; }
2020-01-01 21:29:24 +01:00
enum
{
BLOCK = 0,
TRIGGER = 1,
DAMAGE = 2,
DIRECTIONAL = 3,
SAFE = 4,
ACTIVITY = 5
};
class entityclass
{
public:
void init();
void resetallflags();
void fatal_top()
{
createblock(DAMAGE, -8, -8, 384, 16);
}
void fatal_bottom()
{
createblock(DAMAGE, -8, 224, 384, 16);
}
void fatal_left()
{
createblock(DAMAGE, -8, -8, 16, 260);
}
void fatal_right()
{
createblock(DAMAGE, 312, -8, 16, 260);
}
int swncolour(int t );
void swnenemiescol(int t);
void gravcreate(int ypos, int dir, int xoff = 0, int yoff = 0);
2020-01-01 21:29:24 +01:00
void generateswnwave(int t);
2020-01-01 21:29:24 +01:00
void createblock(int t, int xp, int yp, int w, int h, int trig = 0, const std::string& script = "");
2020-01-01 21:29:24 +01:00
Prevent removing the player entity Removing the player entity has all sorts of nasty effects, such as softlocking the game because many inputs require there to be a player present, such as opening the quit menu. The most infamous glitch to remove the player entity is the Gravitron Fling, where the game doesn't see a gravity line at a specific y-position in the current room, and when it moves the bottom gravity line it moves the player instead. When the gravity line gets outside the room, it gets destroyed, so if the player gets dragged outside the room, they get destroyed, too. (Don't misinterpret this as saying anytime the player gets dragged outside the room, they get destroyed - it's only the Gravitron logic that destroys them.) Also, there are many places in the code that use entity-getting functions that have a fallback value of 0. If it was possible to remove the player, then it's possible for this fallback value of 0 to index obj.entities out-of-bounds, which is not good. To fix this, entityclass::removeentity() is now a bool that signifies if the entity was successfully removed or not. If the entity given is the player (meaning it first checks if it's rule 0, just so in 99% of cases it'll short-circuit and won't do the next check, which is if entityclass::getplayer() says the indice to be removed is the player), then it'll refuse to remove the entity, and return false. This is a change in behavior where callers might expect entityclass::removeentity() to always succeed, so I changed the removeentity_iter() macro to only decrement if removing the entity succeeded. I also changed entityclass::updateentities() from 'removeentity(i); return true;' to 'return removeentity(i);'.
2020-06-13 21:00:04 +02:00
bool removeentity(int t);
2020-01-01 21:29:24 +01:00
void removeallblocks();
void removeblock(int t);
void removeblockat(int x, int y);
void removetrigger(int t);
void copylinecross(int t);
void revertlinecross(int t, int s);
bool gridmatch(int p1, int p2, int p3, int p4, int p11, int p21, int p31, int p41);
int crewcolour(int t);
void createentity(float xp, float yp, int t, float vx = 0, float vy = 0,
2020-01-01 21:29:24 +01:00
int p1 = 0, int p2 = 0, int p3 = 320, int p4 = 240 );
bool updateentities(int i);
2020-01-01 21:29:24 +01:00
void animateentities(int i);
2020-01-01 21:29:24 +01:00
int getcompanion();
2020-01-01 21:29:24 +01:00
int getplayer();
int getscm();
int getlineat(int t);
int getcrewman(int t);
int getcustomcrewman(int t);
int getteleporter();
void rectset(int xi, int yi, int wi, int hi);
void rect2set(int xi, int yi, int wi, int hi);
bool entitycollide(int a, int b);
bool checkdamage();
bool scmcheckdamage();
void settemprect(int t);
int checktrigger(int* block_idx);
2020-01-01 21:29:24 +01:00
int checkactivity();
int getgridpoint(int t);
bool checkplatform();
bool checkblocks();
bool checktowerspikes(int t);
2020-01-01 21:29:24 +01:00
bool checkwall();
2020-01-01 21:29:24 +01:00
float hplatformat();
int yline(int a, int b);
bool entityhlinecollide(int t, int l);
bool entityvlinecollide(int t, int l);
bool entitywarphlinecollide(int t, int l);
bool entitywarpvlinecollide(int t, int l);
2020-01-01 21:29:24 +01:00
void customwarplinecheck(int i);
2020-01-01 21:29:24 +01:00
float entitycollideplatformroof(int t);
2020-01-01 21:29:24 +01:00
float entitycollideplatformfloor(int t);
2020-01-01 21:29:24 +01:00
bool entitycollidefloor(int t);
2020-01-01 21:29:24 +01:00
bool entitycollideroof(int t);
2020-01-01 21:29:24 +01:00
bool testwallsx(int t, int tx, int ty);
2020-01-01 21:29:24 +01:00
bool testwallsy(int t, float tx, float ty);
2020-01-01 21:29:24 +01:00
void fixfriction(int t, float xfix, float xrate, float yrate);
void applyfriction(int t, float xrate, float yrate);
void updateentitylogic(int t);
2020-01-01 21:29:24 +01:00
void entitymapcollision(int t);
2020-01-01 21:29:24 +01:00
void movingplatformfix(int t);
2020-01-01 21:29:24 +01:00
void scmmovingplatformfix(int t);
2020-01-01 21:29:24 +01:00
void hormovingplatformfix(int t);
2020-01-01 21:29:24 +01:00
void entitycollisioncheck();
2020-01-01 21:29:24 +01:00
std::vector<entclass> entities;
std::vector<entclass> linecrosskludge;
point colpoint1, colpoint2;
int tempx, tempy, tempw, temph, temp, temp2;
//public var tempx:int, tempy:int, tempw:int, temph:int, temp:int, temp2:int;
int tpx1, tpy1, tpx2, tpy2;
SDL_Rect temprect, temprect2;
int x, k;
float dx, dy, dr;
int px, py, linetemp;
int activetrigger;
std::vector<blockclass> blocks;
bool flags[100];
bool collect[100];
bool customcollect[100];
2020-01-01 21:29:24 +01:00
bool skipblocks, skipdirblocks;
2020-01-01 21:29:24 +01:00
int platformtile;
bool vertplatforms, horplatforms;
// :(
bool nearelephant, upsetmode;
int upset;
//Trophy Text
int trophytext, trophytype;
int oldtrophytext;
2020-01-01 21:29:24 +01:00
//Secret lab scripts
int altstates;
//Custom stuff
int customenemy;
int customplatformtile;
bool customwarpmode, customwarpmodevon, customwarpmodehon;
std::string customscript;
bool customcrewmoods[Game::numcrew];
2020-01-01 21:29:24 +01:00
};
extern entityclass obj;
2020-01-01 21:29:24 +01:00
#endif /* ENTITY_H */