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--; }
|
2020-04-04 00:55:04 +02:00
|
|
|
#define removeblock_iter(index) { obj.removeblock(index); index--; }
|
2020-04-03 22:07:04 +02:00
|
|
|
|
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);
|
|
|
|
|
2020-03-31 02:46:36 +02:00
|
|
|
void gravcreate(int ypos, int dir, int xoff = 0, int yoff = 0);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-03-31 02:46:36 +02: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);
|
|
|
|
|
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-04-03 22:03:02 +02:00
|
|
|
|
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);
|
|
|
|
|
2020-03-31 02:46:36 +02:00
|
|
|
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 );
|
|
|
|
|
Prevent updating an entity if updateentities() removed it
Otherwise, this would result in the game updating an entity twice, which
isn't good. This is most noticeable in the Gravitron, where many
Gravitron squares are created and destroyed at a time, and it's
especially noticeable during the part near the end of the Gravitron
where the pattern is two Gravitron squares, one at the top and bottom,
and then two Gravitron squares in the middle afterwards. The timing is
just right such that the top one of the two middle ones would be
misaligned with the bottom one of the two when a Gravitron square gets
outside the screen.
To do this, I changed entityclass::updateentities() into a bool, and
made every single caller check its return value. I only needed to do
this for the ones preceding updateentitylogic() and
entitymapcollision(), but I wanted to play it safe and be defensive, so
I did it for the disappearing platform kludge, as well as the
updateentities() within the updateentities() function.
2020-05-05 22:49:12 +02:00
|
|
|
bool updateentities(int i);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-03-31 02:46:36 +02:00
|
|
|
void animateentities(int i);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-04-02 00:32:21 +02: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 checkactivity();
|
|
|
|
|
|
|
|
int getgridpoint(int t);
|
|
|
|
|
|
|
|
bool checkplatform();
|
|
|
|
|
|
|
|
bool checkblocks();
|
|
|
|
|
2020-03-31 02:46:36 +02:00
|
|
|
bool checktowerspikes(int t);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-03-31 02:46:36 +02: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);
|
2020-04-02 21:41:33 +02:00
|
|
|
|
2020-04-02 22:42:50 +02:00
|
|
|
bool entitywarphlinecollide(int t, int l);
|
|
|
|
bool entitywarpvlinecollide(int t, int l);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-04-02 22:42:50 +02:00
|
|
|
void customwarplinecheck(int i);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-03-31 02:46:36 +02:00
|
|
|
float entitycollideplatformroof(int t);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-03-31 02:46:36 +02:00
|
|
|
float entitycollideplatformfloor(int t);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-03-31 02:46:36 +02:00
|
|
|
bool entitycollidefloor(int t);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-03-31 02:46:36 +02:00
|
|
|
bool entitycollideroof(int t);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-03-31 02:46:36 +02:00
|
|
|
bool testwallsx(int t, int tx, int ty);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-04-02 22:42:50 +02: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);
|
|
|
|
|
2020-03-31 02:46:36 +02:00
|
|
|
void updateentitylogic(int t);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
|
2020-03-31 02:46:36 +02:00
|
|
|
void entitymapcollision(int t);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-03-31 02:46:36 +02:00
|
|
|
void movingplatformfix(int t);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-03-31 02:46:36 +02:00
|
|
|
void scmmovingplatformfix(int t);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-03-31 02:46:36 +02:00
|
|
|
void hormovingplatformfix(int t);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-03-31 02:46:36 +02: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;
|
2020-07-03 03:22:19 +02:00
|
|
|
bool flags[100];
|
2020-07-03 04:17:32 +02:00
|
|
|
bool collect[100];
|
|
|
|
bool customcollect[100];
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-01-25 02:26:00 +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;
|
2020-04-30 01:54:36 +02:00
|
|
|
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;
|
2020-07-03 03:10:52 +02:00
|
|
|
bool customcrewmoods[Game::numcrew];
|
2020-01-01 21:29:24 +01:00
|
|
|
};
|
|
|
|
|
2020-02-01 00:53:29 +01:00
|
|
|
extern entityclass obj;
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
#endif /* ENTITY_H */
|