// Returns the combo in the given direction, or -1 if it falls off.
int AdjacentCombo(int location, int dir) {
if (dir == DIR_UP) {
location -= 16;
if (location < 0) {location = -1;}}
else if (dir == DIR_DOWN) {
location += 16;
if (location > 175) {location = -1;}}
else if (dir == DIR_RIGHT) {
location++;
if (location % 16 == 0) {location = -1;}}
else if (dir == DIR_LEFT) {
if (location % 16 == 0) {location = -1;}
else {location--;}}
else {
location = -1;}
return location;}
// Return the long orthogonal direction.
int Dir_LongOrth(int dx, int dy) {
if (Abs(dx) > Abs(dy)) {
if (dx < 0) {return DIR_LEFT;}
else {return DIR_RIGHT;}}
else if (dy != 0) {
if (dy < 0) {return DIR_UP;}
else {return DIR_DOWN;}}
else {
return -1;}}
// Return the short orthogonal direction.
// This should never return the same direction as Dir_LongOrth.
int Dir_ShortOrth(int dx, int dy) {
if (dx == 0 || dy == 0) {return -1;}
else if (Abs(dx) <= Abs(dy)) {
if (dx < 0) {return DIR_LEFT;}
else {return DIR_RIGHT;}}
else {
if (dy < 0) {return DIR_UP;}
else {return DIR_DOWN;}}}
// Return the x component of a direction.
int DirX(int dir) {
if (dir < 2) {return 0;}
else if (dir % 2 == 0) {return -1;}
else {return 1;}}
// Return the y component of a direction.
int DirY(int dir) {
if (dir == DIR_UP) {return -1;}
else if (dir == DIR_DOWN) {return 1;}
else if (dir > 3) {
if (dir & 2) {return 1;}
else {return -1;}}
else {
return 0;}}
// Gets the conveyor direction at location.
int ConveyorDir(int loc) {
int type = Screen->ComboT[loc];
if (type == CT_CVDOWN) {return DIR_DOWN;}
if (type == CT_CVUP) {return DIR_UP;}
if (type == CT_CVRIGHT) {return DIR_RIGHT;}
if (type == CT_CVLEFT) {return DIR_LEFT;}
return -1;}
// Like LinkCollision, but test against the effect width and height instead
// of the tile width and height.
bool LinkCollision2(ffc f) {
int ax = Link->X + Link->HitXOffset;
int ay = Link->Y + Link->HitYOffset;
return RectCollision(f->X, f->Y, f->X+(f->EffectWidth), f->Y+(f->EffectHeight), ax, ay, ax+Link->HitWidth, ay+Link->HitHeight);}
// Change the size of an ffc, keeping the current center.
void FFC_ChangeSize(ffc _ffc, int width, int height) {
_ffc->X += (_ffc->TileWidth - width) * 8;
_ffc->Y += (_ffc->TileHeight - height) * 8;
_ffc->TileWidth = width;
_ffc->TileHeight = height;}
// If there are not any solid quarter-tiles from (x1,y1) to (x2,y2).
bool Path_NoSolid(int x1, int y1, int x2, int y2) {
x1 = Clamp(x1, 0, 255);
y1 = Clamp(y1, 0, 175);
x2 = Clamp(x2, 0, 255);
y2 = Clamp(y2, 0, 175);
int dx = x2 - x1;
int dy = y2 - y1;
int adx = Abs(dx);
int ady = Abs(dy);
// Reassign x/y to a/b.
// a is the long axis, b is the short one.
int a;
float b;
int da; // -1 or 1
float db; // range from -1.0 to 1.0
int ta;
bool long_x;
if (adx > ady) {
long_x = true;
a = x1;
b = y1;
ta = x2;
da = Cond(dx >= 0, 1, -1);
db = dy / adx;}
else {
long_x = false;
a = y1;
b = x1;
ta = y2;
da = Cond(dy >= 0, 1 ,-1);
db = dx / ady;}
// Snap to the center of a quarter-tile.
int dif = 4 - (a % 8);
a += dif;
b += db * da * dif;
da *= 8;
db *= 8;
while (Cond(da > 0, a <= ta, a >= ta)) {
if (Cond(long_x, Screen->isSolid(a, b), Screen->isSolid(b, a))) {
return false;}
a += da;
b += db;}
return true;}
// If two boxes are aligned orthogonally (i.e. one could hit the other with a rook's move).
bool Path_OrthAligned(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2) {
if (x1 + w1 >= x2 && x2 + w2 >= x1) {
return true;}
if (y1 + h1 >= y2 && y2 + h2 >= y1) {
return true;}
return false;}