Path: blob/main/RSDKv4/Collision.cpp
817 views
#include "RetroEngine.hpp"12int collisionLeft = 0;3int collisionTop = 0;4int collisionRight = 0;5int collisionBottom = 0;67int collisionTolerance = 0;89CollisionSensor sensors[RETRO_REV00 ? 6 : 7];1011#if !RETRO_USE_ORIGINAL_CODE12byte showHitboxes = 0;1314int debugHitboxCount = 0;15DebugHitboxInfo debugHitboxList[DEBUG_HITBOX_COUNT];1617int AddDebugHitbox(byte type, Entity *entity, int left, int top, int right, int bottom)18{19int i = 0;20for (; i < debugHitboxCount; ++i) {21if (debugHitboxList[i].left == left && debugHitboxList[i].top == top && debugHitboxList[i].right == right22&& debugHitboxList[i].bottom == bottom23&& (entity && debugHitboxList[i].xpos == entity->xpos && debugHitboxList[i].ypos == entity->ypos24&& debugHitboxList[i].entity == entity)) {25return i;26}27}2829if (i < DEBUG_HITBOX_COUNT) {30debugHitboxList[i].type = type;31debugHitboxList[i].entity = entity;32debugHitboxList[i].collision = 0;33debugHitboxList[i].left = left;34debugHitboxList[i].top = top;35debugHitboxList[i].right = right;36debugHitboxList[i].bottom = bottom;37debugHitboxList[i].xpos = entity ? entity->xpos : 0;38debugHitboxList[i].ypos = entity ? entity->ypos : 0;3940int id = debugHitboxCount;41debugHitboxCount++;42return id;43}4445return -1;46}47#endif4849inline Hitbox *GetHitbox(Entity *entity)50{51AnimationFile *thisAnim = objectScriptList[entity->type].animFile;52return &hitboxList[thisAnim->hitboxListOffset53+ animFrames[animationList[thisAnim->aniListOffset + entity->animation].frameListOffset + entity->frame].hitboxID];54}5556void FindFloorPosition(Entity *player, CollisionSensor *sensor, int startY)57{58int c = 0;59int angle = sensor->angle;60int tsm1 = (TILE_SIZE - 1);61for (int i = 0; i < TILE_SIZE * 3; i += TILE_SIZE) {62if (!sensor->collided) {63int XPos = sensor->xpos >> 16;64int chunkX = XPos >> 7;65int tileX = (XPos & 0x7F) >> 4;66int YPos = (sensor->ypos >> 16) - TILE_SIZE + i;67int chunkY = YPos >> 7;68int tileY = (YPos & 0x7F) >> 4;69if (XPos > -1 && YPos > -1) {70int tile = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;71tile += tileX + (tileY << 3);72int tileIndex = tiles128x128.tileIndex[tile];73if (tiles128x128.collisionFlags[player->collisionPlane][tile] != SOLID_LRB74&& tiles128x128.collisionFlags[player->collisionPlane][tile] != SOLID_NONE) {75switch (tiles128x128.direction[tile]) {76case FLIP_NONE: {77c = (XPos & tsm1) + (tileIndex << 4);78if (collisionMasks[player->collisionPlane].floorMasks[c] >= 0x40)79break;8081sensor->ypos = collisionMasks[player->collisionPlane].floorMasks[c] + (chunkY << 7) + (tileY << 4);82sensor->collided = true;83sensor->angle = collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF;84break;85}86case FLIP_X: {87c = tsm1 - (XPos & tsm1) + (tileIndex << 4);88if (collisionMasks[player->collisionPlane].floorMasks[c] >= 0x40)89break;9091sensor->ypos = collisionMasks[player->collisionPlane].floorMasks[c] + (chunkY << 7) + (tileY << 4);92sensor->collided = true;93sensor->angle = 0x100 - (collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF);94break;95}96case FLIP_Y: {97c = (XPos & 15) + (tileIndex << 4);98if (collisionMasks[player->collisionPlane].roofMasks[c] <= -0x40)99break;100101sensor->ypos = tsm1 - collisionMasks[player->collisionPlane].roofMasks[c] + (chunkY << 7) + (tileY << 4);102sensor->collided = true;103sensor->angle = (byte)(0x180 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF000000) >> 24));104break;105}106case FLIP_XY: {107c = tsm1 - (XPos & tsm1) + (tileIndex << 4);108if (collisionMasks[player->collisionPlane].roofMasks[c] <= -0x40)109break;110111sensor->ypos = tsm1 - collisionMasks[player->collisionPlane].roofMasks[c] + (chunkY << 7) + (tileY << 4);112sensor->collided = true;113sensor->angle = 0x100 - (byte)(0x180 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF000000) >> 24));114break;115}116}117}118119if (sensor->collided) {120if (sensor->angle < 0)121sensor->angle += 0x100;122123if (sensor->angle >= 0x100)124sensor->angle -= 0x100;125126if ((abs(sensor->angle - angle) > 0x20) && (abs(sensor->angle - 0x100 - angle) > 0x20)127&& (abs(sensor->angle + 0x100 - angle) > 0x20)) {128sensor->ypos = startY << 16;129sensor->collided = false;130sensor->angle = angle;131i = TILE_SIZE * 3;132}133else if (sensor->ypos - startY > collisionTolerance || sensor->ypos - startY < -collisionTolerance) {134sensor->ypos = startY << 16;135sensor->collided = false;136}137}138}139}140}141}142void FindLWallPosition(Entity *player, CollisionSensor *sensor, int startX)143{144int c = 0;145int angle = sensor->angle;146int tsm1 = (TILE_SIZE - 1);147for (int i = 0; i < TILE_SIZE * 3; i += TILE_SIZE) {148if (!sensor->collided) {149int XPos = (sensor->xpos >> 16) - TILE_SIZE + i;150int chunkX = XPos >> 7;151int tileX = (XPos & 0x7F) >> 4;152int YPos = sensor->ypos >> 16;153int chunkY = YPos >> 7;154int tileY = (YPos & 0x7F) >> 4;155if (XPos > -1 && YPos > -1) {156int tile = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;157tile = tile + tileX + (tileY << 3);158int tileIndex = tiles128x128.tileIndex[tile];159if (tiles128x128.collisionFlags[player->collisionPlane][tile] < SOLID_NONE) {160switch (tiles128x128.direction[tile]) {161case FLIP_NONE: {162c = (YPos & tsm1) + (tileIndex << 4);163if (collisionMasks[player->collisionPlane].lWallMasks[c] >= 0x40)164break;165166sensor->xpos = collisionMasks[player->collisionPlane].lWallMasks[c] + (chunkX << 7) + (tileX << 4);167sensor->collided = true;168sensor->angle = ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF00) >> 8);169break;170}171case FLIP_X: {172c = (YPos & tsm1) + (tileIndex << 4);173if (collisionMasks[player->collisionPlane].rWallMasks[c] <= -0x40)174break;175176sensor->xpos = tsm1 - collisionMasks[player->collisionPlane].rWallMasks[c] + (chunkX << 7) + (tileX << 4);177sensor->collided = true;178sensor->angle = 0x100 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF0000) >> 16);179break;180}181case FLIP_Y: {182c = tsm1 - (YPos & tsm1) + (tileIndex << 4);183if (collisionMasks[player->collisionPlane].lWallMasks[c] >= 0x40)184break;185186sensor->xpos = collisionMasks[player->collisionPlane].lWallMasks[c] + (chunkX << 7) + (tileX << 4);187sensor->collided = true;188sensor->angle = (byte)(0x180 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF00) >> 8));189break;190}191case FLIP_XY: {192c = tsm1 - (YPos & tsm1) + (tileIndex << 4);193if (collisionMasks[player->collisionPlane].rWallMasks[c] <= -0x40)194break;195196sensor->xpos = tsm1 - collisionMasks[player->collisionPlane].rWallMasks[c] + (chunkX << 7) + (tileX << 4);197sensor->collided = true;198sensor->angle = 0x100 - (byte)(0x180 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF0000) >> 16));199break;200}201}202}203if (sensor->collided) {204if (sensor->angle < 0)205sensor->angle += 0x100;206207if (sensor->angle >= 0x100)208sensor->angle -= 0x100;209210if (abs(angle - sensor->angle) > 0x20) {211sensor->xpos = startX << 16;212sensor->collided = false;213sensor->angle = angle;214i = TILE_SIZE * 3;215}216else if (sensor->xpos - startX > collisionTolerance || sensor->xpos - startX < -collisionTolerance) {217sensor->xpos = startX << 16;218sensor->collided = false;219}220}221}222}223}224}225void FindRoofPosition(Entity *player, CollisionSensor *sensor, int startY)226{227int c = 0;228int angle = sensor->angle;229int tsm1 = (TILE_SIZE - 1);230for (int i = 0; i < TILE_SIZE * 3; i += TILE_SIZE) {231if (!sensor->collided) {232int XPos = sensor->xpos >> 16;233int chunkX = XPos >> 7;234int tileX = (XPos & 0x7F) >> 4;235int YPos = (sensor->ypos >> 16) + TILE_SIZE - i;236int chunkY = YPos >> 7;237int tileY = (YPos & 0x7F) >> 4;238if (XPos > -1 && YPos > -1) {239int tile = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;240tile = tile + tileX + (tileY << 3);241int tileIndex = tiles128x128.tileIndex[tile];242if (tiles128x128.collisionFlags[player->collisionPlane][tile] < SOLID_NONE) {243switch (tiles128x128.direction[tile]) {244case FLIP_NONE: {245c = (XPos & tsm1) + (tileIndex << 4);246if (collisionMasks[player->collisionPlane].roofMasks[c] <= -0x40)247break;248249sensor->ypos = collisionMasks[player->collisionPlane].roofMasks[c] + (chunkY << 7) + (tileY << 4);250sensor->collided = true;251sensor->angle = (collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF000000) >> 24;252break;253}254case FLIP_X: {255c = tsm1 - (XPos & tsm1) + (tileIndex << 4);256if (collisionMasks[player->collisionPlane].roofMasks[c] <= -0x40)257break;258259sensor->ypos = collisionMasks[player->collisionPlane].roofMasks[c] + (chunkY << 7) + (tileY << 4);260sensor->collided = true;261sensor->angle = 0x100 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF000000) >> 24);262break;263}264case FLIP_Y: {265c = (XPos & tsm1) + (tileIndex << 4);266if (collisionMasks[player->collisionPlane].floorMasks[c] >= 0x40)267break;268269sensor->ypos = tsm1 - collisionMasks[player->collisionPlane].floorMasks[c] + (chunkY << 7) + (tileY << 4);270sensor->collided = true;271sensor->angle = (byte)(0x180 - (collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF));272break;273}274case FLIP_XY: {275c = tsm1 - (XPos & tsm1) + (tileIndex << 4);276if (collisionMasks[player->collisionPlane].floorMasks[c] >= 0x40)277break;278279sensor->ypos = tsm1 - collisionMasks[player->collisionPlane].floorMasks[c] + (chunkY << 7) + (tileY << 4);280sensor->collided = true;281sensor->angle = 0x100 - (byte)(0x180 - (collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF));282break;283}284}285}286287if (sensor->collided) {288if (sensor->angle < 0)289sensor->angle += 0x100;290291if (sensor->angle >= 0x100)292sensor->angle -= 0x100;293294if (abs(sensor->angle - angle) <= 0x20) {295if (sensor->ypos - startY > collisionTolerance || sensor->ypos - startY < -collisionTolerance) {296sensor->ypos = startY << 16;297sensor->collided = false;298}299}300else {301sensor->ypos = startY << 16;302sensor->collided = false;303sensor->angle = angle;304i = TILE_SIZE * 3;305}306}307}308}309}310}311void FindRWallPosition(Entity *player, CollisionSensor *sensor, int startX)312{313int c;314int angle = sensor->angle;315int tsm1 = (TILE_SIZE - 1);316for (int i = 0; i < TILE_SIZE * 3; i += TILE_SIZE) {317if (!sensor->collided) {318int XPos = (sensor->xpos >> 16) + TILE_SIZE - i;319int chunkX = XPos >> 7;320int tileX = (XPos & 0x7F) >> 4;321int YPos = sensor->ypos >> 16;322int chunkY = YPos >> 7;323int tileY = (YPos & 0x7F) >> 4;324if (XPos > -1 && YPos > -1) {325int tile = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;326tile = tile + tileX + (tileY << 3);327int tileIndex = tiles128x128.tileIndex[tile];328if (tiles128x128.collisionFlags[player->collisionPlane][tile] < SOLID_NONE) {329switch (tiles128x128.direction[tile]) {330case FLIP_NONE: {331c = (YPos & tsm1) + (tileIndex << 4);332if (collisionMasks[player->collisionPlane].rWallMasks[c] <= -0x40)333break;334335sensor->xpos = collisionMasks[player->collisionPlane].rWallMasks[c] + (chunkX << 7) + (tileX << 4);336sensor->collided = true;337sensor->angle = (byte)((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF0000) >> 16);338break;339}340case FLIP_X: {341c = (YPos & tsm1) + (tileIndex << 4);342if (collisionMasks[player->collisionPlane].lWallMasks[c] >= 0x40)343break;344345sensor->xpos = tsm1 - collisionMasks[player->collisionPlane].lWallMasks[c] + (chunkX << 7) + (tileX << 4);346sensor->collided = true;347sensor->angle = 0x100 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF00) >> 8);348break;349}350case FLIP_Y: {351c = tsm1 - (YPos & tsm1) + (tileIndex << 4);352if (collisionMasks[player->collisionPlane].rWallMasks[c] <= -0x40)353break;354355sensor->xpos = collisionMasks[player->collisionPlane].rWallMasks[c] + (chunkX << 7) + (tileX << 4);356sensor->collided = true;357sensor->angle = (byte)(0x180 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF0000) >> 16));358break;359}360case FLIP_XY: {361c = tsm1 - (YPos & tsm1) + (tileIndex << 4);362if (collisionMasks[player->collisionPlane].lWallMasks[c] >= 0x40)363break;364365sensor->xpos = tsm1 - collisionMasks[player->collisionPlane].lWallMasks[c] + (chunkX << 7) + (tileX << 4);366sensor->collided = true;367sensor->angle = 0x100 - (byte)(0x180 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF00) >> 8));368break;369}370}371}372if (sensor->collided) {373if (sensor->angle < 0)374sensor->angle += 0x100;375376if (sensor->angle >= 0x100)377sensor->angle -= 0x100;378379if (abs(sensor->angle - angle) > 0x20) {380sensor->xpos = startX << 16;381sensor->collided = false;382sensor->angle = angle;383i = TILE_SIZE * 3;384}385else if (sensor->xpos - startX > collisionTolerance || sensor->xpos - startX < -collisionTolerance) {386sensor->xpos = startX << 16;387sensor->collided = false;388}389}390}391}392}393}394395void FloorCollision(Entity *player, CollisionSensor *sensor)396{397int c;398int startY = sensor->ypos >> 16;399int tsm1 = (TILE_SIZE - 1);400for (int i = 0; i < TILE_SIZE * 3; i += TILE_SIZE) {401if (!sensor->collided) {402int XPos = sensor->xpos >> 16;403int chunkX = XPos >> 7;404int tileX = (XPos & 0x7F) >> 4;405int YPos = (sensor->ypos >> 16) - TILE_SIZE + i;406int chunkY = YPos >> 7;407int tileY = (YPos & 0x7F) >> 4;408if (XPos > -1 && YPos > -1) {409int tile = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;410tile += tileX + (tileY << 3);411int tileIndex = tiles128x128.tileIndex[tile];412if (tiles128x128.collisionFlags[player->collisionPlane][tile] != SOLID_LRB413&& tiles128x128.collisionFlags[player->collisionPlane][tile] != SOLID_NONE) {414switch (tiles128x128.direction[tile]) {415case FLIP_NONE: {416c = (XPos & tsm1) + (tileIndex << 4);417if ((YPos & tsm1) <= collisionMasks[player->collisionPlane].floorMasks[c] - TILE_SIZE + i418|| collisionMasks[player->collisionPlane].floorMasks[c] >= tsm1)419break;420421sensor->ypos = collisionMasks[player->collisionPlane].floorMasks[c] + (chunkY << 7) + (tileY << 4);422sensor->collided = true;423sensor->angle = collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF;424break;425}426case FLIP_X: {427c = tsm1 - (XPos & tsm1) + (tileIndex << 4);428if ((YPos & tsm1) <= collisionMasks[player->collisionPlane].floorMasks[c] - TILE_SIZE + i429|| collisionMasks[player->collisionPlane].floorMasks[c] >= tsm1)430break;431432sensor->ypos = collisionMasks[player->collisionPlane].floorMasks[c] + (chunkY << 7) + (tileY << 4);433sensor->collided = true;434sensor->angle = 0x100 - (collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF);435break;436}437case FLIP_Y: {438c = (XPos & tsm1) + (tileIndex << 4);439if ((YPos & tsm1) <= tsm1 - collisionMasks[player->collisionPlane].roofMasks[c] - TILE_SIZE + i)440break;441442sensor->ypos = tsm1 - collisionMasks[player->collisionPlane].roofMasks[c] + (chunkY << 7) + (tileY << 4);443sensor->collided = true;444byte cAngle = (collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF000000) >> 24;445sensor->angle = (byte)(0x180 - cAngle);446break;447}448case FLIP_XY: {449c = tsm1 - (XPos & tsm1) + (tileIndex << 4);450if ((YPos & tsm1) <= tsm1 - collisionMasks[player->collisionPlane].roofMasks[c] - TILE_SIZE + i)451break;452453sensor->ypos = tsm1 - collisionMasks[player->collisionPlane].roofMasks[c] + (chunkY << 7) + (tileY << 4);454sensor->collided = true;455sensor->angle = 0x100 - (byte)(0x180 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF000000) >> 24));456break;457}458}459}460461if (sensor->collided) {462if (sensor->angle < 0)463sensor->angle += 0x100;464465if (sensor->angle >= 0x100)466sensor->angle -= 0x100;467468if (sensor->ypos - startY > (TILE_SIZE - 2)) {469sensor->ypos = startY << 16;470sensor->collided = false;471}472else if (sensor->ypos - startY < -(TILE_SIZE + 1)) {473sensor->ypos = startY << 16;474sensor->collided = false;475}476}477}478}479}480}481void LWallCollision(Entity *player, CollisionSensor *sensor)482{483int c;484int startX = sensor->xpos >> 16;485int tsm1 = (TILE_SIZE - 1);486for (int i = 0; i < TILE_SIZE * 3; i += TILE_SIZE) {487if (!sensor->collided) {488int XPos = (sensor->xpos >> 16) - TILE_SIZE + i;489int chunkX = XPos >> 7;490int tileX = (XPos & 0x7F) >> 4;491int YPos = sensor->ypos >> 16;492int chunkY = YPos >> 7;493int tileY = (YPos & 0x7F) >> 4;494if (XPos > -1 && YPos > -1) {495int tile = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;496tile += tileX + (tileY << 3);497int tileIndex = tiles128x128.tileIndex[tile];498if (tiles128x128.collisionFlags[player->collisionPlane][tile] != SOLID_TOP499&& tiles128x128.collisionFlags[player->collisionPlane][tile] < SOLID_NONE) {500switch (tiles128x128.direction[tile]) {501case FLIP_NONE: {502c = (YPos & tsm1) + (tileIndex << 4);503if ((XPos & tsm1) <= collisionMasks[player->collisionPlane].lWallMasks[c] - TILE_SIZE + i)504break;505506sensor->xpos = collisionMasks[player->collisionPlane].lWallMasks[c] + (chunkX << 7) + (tileX << 4);507sensor->collided = true;508break;509}510case FLIP_X: {511c = (YPos & tsm1) + (tileIndex << 4);512if ((XPos & tsm1) <= tsm1 - collisionMasks[player->collisionPlane].rWallMasks[c] - TILE_SIZE + i)513break;514515sensor->xpos = tsm1 - collisionMasks[player->collisionPlane].rWallMasks[c] + (chunkX << 7) + (tileX << 4);516sensor->collided = true;517break;518}519case FLIP_Y: {520c = tsm1 - (YPos & tsm1) + (tileIndex << 4);521if ((XPos & tsm1) <= collisionMasks[player->collisionPlane].lWallMasks[c] - TILE_SIZE + i)522break;523524sensor->xpos = collisionMasks[player->collisionPlane].lWallMasks[c] + (chunkX << 7) + (tileX << 4);525sensor->collided = true;526break;527}528case FLIP_XY: {529c = tsm1 - (YPos & tsm1) + (tileIndex << 4);530if ((XPos & tsm1) <= tsm1 - collisionMasks[player->collisionPlane].rWallMasks[c] - TILE_SIZE + i)531break;532533sensor->xpos = tsm1 - collisionMasks[player->collisionPlane].rWallMasks[c] + (chunkX << 7) + (tileX << 4);534sensor->collided = true;535break;536}537}538}539540if (sensor->collided) {541if (sensor->xpos - startX > tsm1) {542sensor->xpos = startX << 16;543sensor->collided = false;544}545else if (sensor->xpos - startX < -tsm1) {546sensor->xpos = startX << 16;547sensor->collided = false;548}549}550}551}552}553}554void RoofCollision(Entity *player, CollisionSensor *sensor)555{556int c;557int startY = sensor->ypos >> 16;558int tsm1 = (TILE_SIZE - 1);559for (int i = 0; i < TILE_SIZE * 3; i += TILE_SIZE) {560if (!sensor->collided) {561int XPos = sensor->xpos >> 16;562int chunkX = XPos >> 7;563int tileX = (XPos & 0x7F) >> 4;564int YPos = (sensor->ypos >> 16) + TILE_SIZE - i;565int chunkY = YPos >> 7;566int tileY = (YPos & 0x7F) >> 4;567if (XPos > -1 && YPos > -1) {568int tile = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;569tile += tileX + (tileY << 3);570int tileIndex = tiles128x128.tileIndex[tile];571if (tiles128x128.collisionFlags[player->collisionPlane][tile] != SOLID_TOP572&& tiles128x128.collisionFlags[player->collisionPlane][tile] < SOLID_NONE) {573switch (tiles128x128.direction[tile]) {574case FLIP_NONE: {575c = (XPos & tsm1) + (tileIndex << 4);576if ((YPos & tsm1) >= collisionMasks[player->collisionPlane].roofMasks[c] + TILE_SIZE - i)577break;578579sensor->ypos = collisionMasks[player->collisionPlane].roofMasks[c] + (chunkY << 7) + (tileY << 4);580sensor->collided = true;581sensor->angle = ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF000000) >> 24);582break;583}584case FLIP_X: {585c = tsm1 - (XPos & tsm1) + (tileIndex << 4);586if ((YPos & tsm1) >= collisionMasks[player->collisionPlane].roofMasks[c] + TILE_SIZE - i)587break;588589sensor->ypos = collisionMasks[player->collisionPlane].roofMasks[c] + (chunkY << 7) + (tileY << 4);590sensor->collided = true;591sensor->angle = 0x100 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF000000) >> 24);592break;593}594case FLIP_Y: {595c = (XPos & tsm1) + (tileIndex << 4);596if ((YPos & tsm1) >= tsm1 - collisionMasks[player->collisionPlane].floorMasks[c] + TILE_SIZE - i)597break;598599sensor->ypos = tsm1 - collisionMasks[player->collisionPlane].floorMasks[c] + (chunkY << 7) + (tileY << 4);600sensor->collided = true;601sensor->angle = 0x180 - (collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF);602break;603}604case FLIP_XY: {605c = tsm1 - (XPos & tsm1) + (tileIndex << 4);606if ((YPos & tsm1) >= tsm1 - collisionMasks[player->collisionPlane].floorMasks[c] + TILE_SIZE - i)607break;608609sensor->ypos = tsm1 - collisionMasks[player->collisionPlane].floorMasks[c] + (chunkY << 7) + (tileY << 4);610sensor->collided = true;611sensor->angle = 0x100 - (byte)(0x180 - (collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF));612break;613}614}615}616617if (sensor->collided) {618if (sensor->angle < 0)619sensor->angle += 0x100;620621if (sensor->angle >= 0x100)622sensor->angle -= 0x100;623624if (sensor->ypos - startY > (tsm1 - 1)) {625sensor->ypos = startY << 16;626sensor->collided = false;627}628else if (sensor->ypos - startY < -(tsm1 - 1)) {629sensor->ypos = startY << 16;630sensor->collided = false;631}632}633}634}635}636}637void RWallCollision(Entity *player, CollisionSensor *sensor)638{639int c;640int startX = sensor->xpos >> 16;641int tsm1 = (TILE_SIZE - 1);642for (int i = 0; i < TILE_SIZE * 3; i += TILE_SIZE) {643if (!sensor->collided) {644int XPos = (sensor->xpos >> 16) + TILE_SIZE - i;645int chunkX = XPos >> 7;646int tileX = (XPos & 0x7F) >> 4;647int YPos = sensor->ypos >> 16;648int chunkY = YPos >> 7;649int tileY = (YPos & 0x7F) >> 4;650if (XPos > -1 && YPos > -1) {651int tile = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;652tile += tileX + (tileY << 3);653int tileIndex = tiles128x128.tileIndex[tile];654if (tiles128x128.collisionFlags[player->collisionPlane][tile] != SOLID_TOP655&& tiles128x128.collisionFlags[player->collisionPlane][tile] < SOLID_NONE) {656switch (tiles128x128.direction[tile]) {657case FLIP_NONE: {658c = (YPos & tsm1) + (tileIndex << 4);659if ((XPos & tsm1) >= collisionMasks[player->collisionPlane].rWallMasks[c] + TILE_SIZE - i)660break;661662sensor->xpos = collisionMasks[player->collisionPlane].rWallMasks[c] + (chunkX << 7) + (tileX << 4);663sensor->collided = true;664break;665}666case FLIP_X: {667c = (YPos & tsm1) + (tileIndex << 4);668if ((XPos & tsm1) >= tsm1 - collisionMasks[player->collisionPlane].lWallMasks[c] + TILE_SIZE - i)669break;670671sensor->xpos = tsm1 - collisionMasks[player->collisionPlane].lWallMasks[c] + (chunkX << 7) + (tileX << 4);672sensor->collided = true;673break;674}675case FLIP_Y: {676c = tsm1 - (YPos & tsm1) + (tileIndex << 4);677if ((XPos & tsm1) >= collisionMasks[player->collisionPlane].rWallMasks[c] + TILE_SIZE - i)678break;679680sensor->xpos = collisionMasks[player->collisionPlane].rWallMasks[c] + (chunkX << 7) + (tileX << 4);681sensor->collided = true;682break;683}684case FLIP_XY: {685c = tsm1 - (YPos & tsm1) + (tileIndex << 4);686if ((XPos & tsm1) >= tsm1 - collisionMasks[player->collisionPlane].lWallMasks[c] + TILE_SIZE - i)687break;688689sensor->xpos = tsm1 - collisionMasks[player->collisionPlane].lWallMasks[c] + (chunkX << 7) + (tileX << 4);690sensor->collided = true;691break;692}693}694}695696if (sensor->collided) {697if (sensor->xpos - startX > tsm1) {698sensor->xpos = startX << 16;699sensor->collided = false;700}701else if (sensor->xpos - startX < -tsm1) {702sensor->xpos = startX << 16;703sensor->collided = false;704}705}706}707}708}709}710711void ProcessAirCollision(Entity *entity)712{713Hitbox *playerHitbox = GetHitbox(entity);714collisionLeft = playerHitbox->left[0];715collisionTop = playerHitbox->top[0];716collisionRight = playerHitbox->right[0];717collisionBottom = playerHitbox->bottom[0];718719byte movingDown = 0;720byte movingUp = 0;721byte movingLeft = 0;722byte movingRight = 0;723724if (entity->xvel < 0) {725movingRight = 0;726}727else {728movingRight = 1;729sensors[0].ypos = entity->ypos + 0x40000;730sensors[0].collided = false;731sensors[0].xpos = entity->xpos + (collisionRight << 16);732}733if (entity->xvel > 0) {734movingLeft = 0;735}736else {737movingLeft = 1;738sensors[1].ypos = entity->ypos + 0x40000;739sensors[1].collided = false;740sensors[1].xpos = entity->xpos + ((collisionLeft - 1) << 16);741}742sensors[2].xpos = entity->xpos + (playerHitbox->left[1] << 16);743sensors[3].xpos = entity->xpos + (playerHitbox->right[1] << 16);744sensors[2].collided = false;745sensors[3].collided = false;746sensors[4].xpos = sensors[2].xpos;747sensors[5].xpos = sensors[3].xpos;748sensors[4].collided = false;749sensors[5].collided = false;750if (entity->yvel < 0) {751movingDown = 0;752}753else {754movingDown = 1;755sensors[2].ypos = entity->ypos + (collisionBottom << 16);756sensors[3].ypos = entity->ypos + (collisionBottom << 16);757}758759if (abs(entity->xvel) > 0x10000 || entity->yvel < 0) {760movingUp = 1;761sensors[4].ypos = entity->ypos + ((collisionTop - 1) << 16);762sensors[5].ypos = entity->ypos + ((collisionTop - 1) << 16);763}764765int cnt = (abs(entity->xvel) <= abs(entity->yvel) ? (abs(entity->yvel) >> 19) + 1 : (abs(entity->xvel) >> 19) + 1);766int XVel = entity->xvel / cnt;767int YVel = entity->yvel / cnt;768int XVel2 = entity->xvel - XVel * (cnt - 1);769int YVel2 = entity->yvel - YVel * (cnt - 1);770while (cnt > 0) {771if (cnt < 2) {772XVel = XVel2;773YVel = YVel2;774}775cnt--;776777if (movingRight == 1) {778sensors[0].xpos += XVel;779sensors[0].ypos += YVel;780LWallCollision(entity, &sensors[0]);781if (sensors[0].collided) {782movingRight = 2;783}784else if (entity->xvel < 0x20000) {785sensors[0].ypos -= 0x80000;786LWallCollision(entity, &sensors[0]);787if (sensors[0].collided)788movingRight = 2;789sensors[0].ypos += 0x80000;790}791}792793if (movingLeft == 1) {794sensors[1].xpos += XVel;795sensors[1].ypos += YVel;796RWallCollision(entity, &sensors[1]);797if (sensors[1].collided) {798movingLeft = 2;799}800else if (entity->xvel > -0x20000) {801sensors[1].ypos -= 0x80000;802RWallCollision(entity, &sensors[1]);803if (sensors[1].collided)804movingLeft = 2;805sensors[1].ypos += 0x80000;806}807}808809if (movingRight == 2) {810entity->xvel = 0;811entity->speed = 0;812entity->xpos = (sensors[0].xpos - collisionRight) << 16;813sensors[2].xpos = entity->xpos + ((collisionLeft + 1) << 16);814sensors[3].xpos = entity->xpos + ((collisionRight - 2) << 16);815sensors[4].xpos = sensors[2].xpos;816sensors[5].xpos = sensors[3].xpos;817XVel = 0;818XVel2 = 0;819movingRight = 3;820}821822if (movingLeft == 2) {823entity->xvel = 0;824entity->speed = 0;825entity->xpos = (sensors[1].xpos - collisionLeft + 1) << 16;826sensors[2].xpos = entity->xpos + ((collisionLeft + 1) << 16);827sensors[3].xpos = entity->xpos + ((collisionRight - 2) << 16);828sensors[4].xpos = sensors[2].xpos;829sensors[5].xpos = sensors[3].xpos;830XVel = 0;831XVel2 = 0;832movingLeft = 3;833}834835if (movingDown == 1) {836for (int i = 2; i < 4; i++) {837if (!sensors[i].collided) {838sensors[i].xpos += XVel;839sensors[i].ypos += YVel;840FloorCollision(entity, &sensors[i]);841}842}843if (sensors[2].collided || sensors[3].collided) {844movingDown = 2;845cnt = 0;846}847}848849if (movingUp == 1) {850for (int i = 4; i < 6; i++) {851if (!sensors[i].collided) {852sensors[i].xpos += XVel;853sensors[i].ypos += YVel;854RoofCollision(entity, &sensors[i]);855}856}857if (sensors[4].collided || sensors[5].collided) {858movingUp = 2;859cnt = 0;860}861}862}863864if (movingRight < 2 && movingLeft < 2)865entity->xpos = entity->xpos + entity->xvel;866867if (movingUp < 2 && movingDown < 2) {868entity->ypos = entity->ypos + entity->yvel;869return;870}871872if (movingDown == 2) {873entity->gravity = 0;874if (sensors[2].collided && sensors[3].collided) {875if (sensors[2].ypos >= sensors[3].ypos) {876entity->ypos = (sensors[3].ypos - collisionBottom) << 16;877entity->angle = sensors[3].angle;878}879else {880entity->ypos = (sensors[2].ypos - collisionBottom) << 16;881entity->angle = sensors[2].angle;882}883}884else if (sensors[2].collided == 1) {885entity->ypos = (sensors[2].ypos - collisionBottom) << 16;886entity->angle = sensors[2].angle;887}888else if (sensors[3].collided == 1) {889entity->ypos = (sensors[3].ypos - collisionBottom) << 16;890entity->angle = sensors[3].angle;891}892if (entity->angle > 0xA0 && entity->angle < 0xE0 && entity->collisionMode != CMODE_LWALL) {893entity->collisionMode = CMODE_LWALL;894entity->xpos -= 0x40000;895}896if (entity->angle > 0x20 && entity->angle < 0x60 && entity->collisionMode != CMODE_RWALL) {897entity->collisionMode = CMODE_RWALL;898entity->xpos += 0x40000;899}900if (entity->angle < 0x20 || entity->angle > 0xE0) {901entity->controlLock = 0;902}903entity->rotation = entity->angle << 1;904905int speed = 0;906if (entity->down) {907if (entity->angle < 128) {908if (entity->angle < 16) {909speed = entity->xvel;910}911else if (entity->angle >= 32) {912speed = (abs(entity->xvel) <= abs(entity->yvel) ? entity->yvel + entity->yvel / 12 : entity->xvel);913}914else {915speed = (abs(entity->xvel) <= abs(entity->yvel >> 1) ? (entity->yvel + entity->yvel / 12) >> 1 : entity->xvel);916}917}918else if (entity->angle > 240) {919speed = entity->xvel;920}921else if (entity->angle <= 224) {922speed = (abs(entity->xvel) <= abs(entity->yvel) ? -(entity->yvel + entity->yvel / 12) : entity->xvel);923}924else {925speed = (abs(entity->xvel) <= abs(entity->yvel >> 1) ? -((entity->yvel + entity->yvel / 12) >> 1) : entity->xvel);926}927}928else if (entity->angle < 0x80) {929if (entity->angle < 0x10) {930speed = entity->xvel;931}932else if (entity->angle >= 0x20) {933speed = (abs(entity->xvel) <= abs(entity->yvel) ? entity->yvel : entity->xvel);934}935else {936speed = (abs(entity->xvel) <= abs(entity->yvel >> 1) ? entity->yvel >> 1 : entity->xvel);937}938}939else if (entity->angle > 0xF0) {940speed = entity->xvel;941}942else if (entity->angle <= 0xE0) {943speed = (abs(entity->xvel) <= abs(entity->yvel) ? -entity->yvel : entity->xvel);944}945else {946speed = (abs(entity->xvel) <= abs(entity->yvel >> 1) ? -(entity->yvel >> 1) : entity->xvel);947}948949if (speed < -0x180000)950speed = -0x180000;951if (speed > 0x180000)952speed = 0x180000;953entity->speed = speed;954entity->yvel = 0;955scriptEng.checkResult = 1;956}957958if (movingUp == 2) {959int sensorAngle = 0;960if (sensors[4].collided && sensors[5].collided) {961if (sensors[4].ypos <= sensors[5].ypos) {962entity->ypos = (sensors[5].ypos - collisionTop + 1) << 16;963sensorAngle = sensors[5].angle;964}965else {966entity->ypos = (sensors[4].ypos - collisionTop + 1) << 16;967sensorAngle = sensors[4].angle;968}969}970else if (sensors[4].collided) {971entity->ypos = (sensors[4].ypos - collisionTop + 1) << 16;972sensorAngle = sensors[4].angle;973}974else if (sensors[5].collided) {975entity->ypos = (sensors[5].ypos - collisionTop + 1) << 16;976sensorAngle = sensors[5].angle;977}978sensorAngle &= 0xFF;979980int angle = ArcTanLookup(entity->xvel, entity->yvel);981if (sensorAngle > 0x40 && sensorAngle < 0x62 && angle > 0xA0 && angle < 0xC2) {982entity->gravity = 0;983entity->angle = sensorAngle;984entity->rotation = entity->angle << 1;985entity->collisionMode = CMODE_RWALL;986entity->xpos += 0x40000;987entity->ypos -= 0x20000;988if (entity->angle <= 0x60)989entity->speed = entity->yvel;990else991entity->speed = entity->yvel >> 1;992}993if (sensorAngle > 0x9E && sensorAngle < 0xC0 && angle > 0xBE && angle < 0xE0) {994entity->gravity = 0;995entity->angle = sensorAngle;996entity->rotation = entity->angle << 1;997entity->collisionMode = CMODE_LWALL;998entity->xpos -= 0x40000;999entity->ypos -= 0x20000;1000if (entity->angle >= 0xA0)1001entity->speed = -entity->yvel;1002else1003entity->speed = -entity->yvel >> 1;1004}1005if (entity->yvel < 0)1006entity->yvel = 0;1007scriptEng.checkResult = 2;1008}1009}1010void ProcessPathGrip(Entity *entity)1011{1012int cosValue256;1013int sinValue256;1014sensors[4].xpos = entity->xpos;1015sensors[4].ypos = entity->ypos;1016for (int i = 0; i < (RETRO_REV00 ? 6 : 7); ++i) {1017sensors[i].angle = entity->angle;1018sensors[i].collided = false;1019}1020SetPathGripSensors(entity);1021int absSpeed = abs(entity->speed);1022int checkDist = absSpeed >> 18;1023absSpeed &= 0x3FFFF;1024byte cMode = entity->collisionMode;10251026while (checkDist > -1) {1027if (checkDist >= 1) {1028cosValue256 = cos256LookupTable[entity->angle] << 10;1029sinValue256 = sin256LookupTable[entity->angle] << 10;1030checkDist--;1031}1032else {1033cosValue256 = absSpeed * cos256LookupTable[entity->angle] >> 8;1034sinValue256 = absSpeed * sin256LookupTable[entity->angle] >> 8;1035checkDist = -1;1036}10371038if (entity->speed < 0) {1039cosValue256 = -cosValue256;1040sinValue256 = -sinValue256;1041}10421043sensors[0].collided = false;1044sensors[1].collided = false;1045sensors[2].collided = false;1046#if !RETRO_REV001047sensors[5].collided = false;1048sensors[6].collided = false;1049#endif1050sensors[4].xpos += cosValue256;1051sensors[4].ypos += sinValue256;1052int tileDistance = -1;10531054switch (entity->collisionMode) {1055case CMODE_FLOOR: {1056sensors[3].xpos += cosValue256;1057sensors[3].ypos += sinValue256;10581059if (entity->speed > 0) {1060LWallCollision(entity, &sensors[3]);1061if (sensors[3].collided) {1062sensors[2].xpos = (sensors[3].xpos - 2) << 16;1063}1064}10651066if (entity->speed < 0) {1067RWallCollision(entity, &sensors[3]);1068if (sensors[3].collided) {1069sensors[0].xpos = (sensors[3].xpos + 2) << 16;1070}1071}10721073if (sensors[3].collided) {1074cosValue256 = 0;1075checkDist = -1;1076}10771078for (int i = 0; i < 3; i++) {1079sensors[i].xpos += cosValue256;1080sensors[i].ypos += sinValue256;1081FindFloorPosition(entity, &sensors[i], sensors[i].ypos >> 16);1082}10831084#if !RETRO_REV001085for (int i = 5; i < 7; i++) {1086sensors[i].xpos += cosValue256;1087sensors[i].ypos += sinValue256;1088FindFloorPosition(entity, &sensors[i], sensors[i].ypos >> 16);1089}1090#endif10911092tileDistance = -1;1093for (int i = 0; i < 3; i++) {1094if (tileDistance > -1) {1095if (sensors[i].collided) {1096if (sensors[i].ypos < sensors[tileDistance].ypos)1097tileDistance = i;10981099if (sensors[i].ypos == sensors[tileDistance].ypos && (sensors[i].angle < 0x08 || sensors[i].angle > 0xF8))1100tileDistance = i;1101}1102}1103else if (sensors[i].collided)1104tileDistance = i;1105}11061107if (tileDistance <= -1) {1108checkDist = -1;1109}1110else {1111sensors[0].ypos = sensors[tileDistance].ypos << 16;1112sensors[0].angle = sensors[tileDistance].angle;1113sensors[1].ypos = sensors[0].ypos;1114sensors[1].angle = sensors[0].angle;1115sensors[2].ypos = sensors[0].ypos;1116sensors[2].angle = sensors[0].angle;1117sensors[3].ypos = sensors[0].ypos - 0x40000;1118sensors[3].angle = sensors[0].angle;1119sensors[4].xpos = sensors[1].xpos;1120sensors[4].ypos = sensors[0].ypos - (collisionBottom << 16);1121}11221123if (sensors[0].angle < 0xDE && sensors[0].angle > 0x80)1124entity->collisionMode = CMODE_LWALL;1125if (sensors[0].angle > 0x22 && sensors[0].angle < 0x80)1126entity->collisionMode = CMODE_RWALL;1127break;1128}1129case CMODE_LWALL: {1130sensors[3].xpos += cosValue256;1131sensors[3].ypos += sinValue256;11321133if (entity->speed > 0)1134RoofCollision(entity, &sensors[3]);11351136if (entity->speed < 0)1137FloorCollision(entity, &sensors[3]);11381139if (sensors[3].collided) {1140sinValue256 = 0;1141checkDist = -1;1142}1143for (int i = 0; i < 3; i++) {1144sensors[i].xpos += cosValue256;1145sensors[i].ypos += sinValue256;1146FindLWallPosition(entity, &sensors[i], sensors[i].xpos >> 16);1147}11481149tileDistance = -1;1150for (int i = 0; i < 3; i++) {1151if (tileDistance > -1) {1152if (sensors[i].xpos < sensors[tileDistance].xpos && sensors[i].collided) {1153tileDistance = i;1154}1155}1156else if (sensors[i].collided) {1157tileDistance = i;1158}1159}11601161if (tileDistance <= -1) {1162checkDist = -1;1163}1164else {1165sensors[0].xpos = sensors[tileDistance].xpos << 16;1166sensors[0].angle = sensors[tileDistance].angle;1167sensors[1].xpos = sensors[0].xpos;1168sensors[1].angle = sensors[0].angle;1169sensors[2].xpos = sensors[0].xpos;1170sensors[2].angle = sensors[0].angle;1171sensors[4].ypos = sensors[1].ypos;1172sensors[4].xpos = sensors[1].xpos - (collisionRight << 16);1173}11741175if (sensors[0].angle > 0xE2)1176entity->collisionMode = CMODE_FLOOR;1177if (sensors[0].angle < 0x9E)1178entity->collisionMode = CMODE_ROOF;1179break;1180break;1181}1182case CMODE_ROOF: {1183sensors[3].xpos += cosValue256;1184sensors[3].ypos += sinValue256;11851186if (entity->speed > 0)1187RWallCollision(entity, &sensors[3]);11881189if (entity->speed < 0)1190LWallCollision(entity, &sensors[3]);11911192if (sensors[3].collided) {1193cosValue256 = 0;1194checkDist = -1;1195}1196for (int i = 0; i < 3; i++) {1197sensors[i].xpos += cosValue256;1198sensors[i].ypos += sinValue256;1199FindRoofPosition(entity, &sensors[i], sensors[i].ypos >> 16);1200}12011202tileDistance = -1;1203for (int i = 0; i < 3; i++) {1204if (tileDistance > -1) {1205if (sensors[i].ypos > sensors[tileDistance].ypos && sensors[i].collided) {1206tileDistance = i;1207}1208}1209else if (sensors[i].collided) {1210tileDistance = i;1211}1212}12131214if (tileDistance <= -1) {1215checkDist = -1;1216}1217else {1218sensors[0].ypos = sensors[tileDistance].ypos << 16;1219sensors[0].angle = sensors[tileDistance].angle;1220sensors[1].ypos = sensors[0].ypos;1221sensors[1].angle = sensors[0].angle;1222sensors[2].ypos = sensors[0].ypos;1223sensors[2].angle = sensors[0].angle;1224sensors[3].ypos = sensors[0].ypos + 0x40000;1225sensors[3].angle = sensors[0].angle;1226sensors[4].xpos = sensors[1].xpos;1227sensors[4].ypos = sensors[0].ypos - ((collisionTop - 1) << 16);1228}12291230if (sensors[0].angle > 0xA2)1231entity->collisionMode = CMODE_LWALL;1232if (sensors[0].angle < 0x5E)1233entity->collisionMode = CMODE_RWALL;1234break;1235}1236case CMODE_RWALL: {1237sensors[3].xpos += cosValue256;1238sensors[3].ypos += sinValue256;12391240if (entity->speed > 0)1241FloorCollision(entity, &sensors[3]);12421243if (entity->speed < 0)1244RoofCollision(entity, &sensors[3]);12451246if (sensors[3].collided) {1247sinValue256 = 0;1248checkDist = -1;1249}1250for (int i = 0; i < 3; i++) {1251sensors[i].xpos += cosValue256;1252sensors[i].ypos += sinValue256;1253FindRWallPosition(entity, &sensors[i], sensors[i].xpos >> 16);1254}12551256tileDistance = -1;1257for (int i = 0; i < 3; i++) {1258if (tileDistance > -1) {1259if (sensors[i].xpos > sensors[tileDistance].xpos && sensors[i].collided) {1260tileDistance = i;1261}1262}1263else if (sensors[i].collided) {1264tileDistance = i;1265}1266}12671268if (tileDistance <= -1) {1269checkDist = -1;1270}1271else {1272sensors[0].xpos = sensors[tileDistance].xpos << 16;1273sensors[0].angle = sensors[tileDistance].angle;1274sensors[1].xpos = sensors[0].xpos;1275sensors[1].angle = sensors[0].angle;1276sensors[2].xpos = sensors[0].xpos;1277sensors[2].angle = sensors[0].angle;1278sensors[4].ypos = sensors[1].ypos;1279sensors[4].xpos = sensors[1].xpos - ((collisionLeft - 1) << 16);1280}12811282if (sensors[0].angle < 0x1E)1283entity->collisionMode = CMODE_FLOOR;1284if (sensors[0].angle > 0x62)1285entity->collisionMode = CMODE_ROOF;1286break;1287}1288}1289if (tileDistance != -1)1290entity->angle = sensors[0].angle;12911292if (!sensors[3].collided)1293SetPathGripSensors(entity);1294else1295checkDist = -2;1296}12971298switch (cMode) {1299case CMODE_FLOOR: {1300if (sensors[0].collided || sensors[1].collided || sensors[2].collided) {1301entity->angle = sensors[0].angle;1302entity->rotation = entity->angle << 1;1303entity->floorSensors[0] = sensors[0].collided;1304entity->floorSensors[1] = sensors[1].collided;1305entity->floorSensors[2] = sensors[2].collided;1306#if !RETRO_REV001307entity->floorSensors[3] = sensors[5].collided;1308entity->floorSensors[4] = sensors[6].collided;1309#endif1310if (!sensors[3].collided) {1311entity->pushing = 0;1312entity->xpos = sensors[4].xpos;1313}1314else {1315if (entity->speed > 0)1316entity->xpos = (sensors[3].xpos - collisionRight) << 16;13171318if (entity->speed < 0)1319entity->xpos = (sensors[3].xpos - collisionLeft + 1) << 16;13201321entity->speed = 0;1322if ((entity->left || entity->right) && entity->pushing < 2)1323entity->pushing++;1324}1325entity->ypos = sensors[4].ypos;1326}1327else {1328entity->gravity = 1;1329entity->collisionMode = CMODE_FLOOR;1330entity->xvel = cos256LookupTable[entity->angle] * entity->speed >> 8;1331entity->yvel = sin256LookupTable[entity->angle] * entity->speed >> 8;1332if (entity->yvel < -0x100000)1333entity->yvel = -0x100000;13341335if (entity->yvel > 0x100000)1336entity->yvel = 0x100000;13371338entity->speed = entity->xvel;1339entity->angle = 0;1340if (!sensors[3].collided) {1341entity->pushing = 0;1342entity->xpos += entity->xvel;1343}1344else {1345if (entity->speed > 0)1346entity->xpos = (sensors[3].xpos - collisionRight) << 16;1347if (entity->speed < 0)1348entity->xpos = (sensors[3].xpos - collisionLeft + 1) << 16;13491350entity->speed = 0;1351if ((entity->left || entity->right) && entity->pushing < 2)1352entity->pushing++;1353}1354entity->ypos += entity->yvel;1355}1356break;1357}1358case CMODE_LWALL: {1359if (!sensors[0].collided && !sensors[1].collided && !sensors[2].collided) {1360entity->gravity = 1;1361entity->collisionMode = CMODE_FLOOR;1362entity->xvel = cos256LookupTable[entity->angle] * entity->speed >> 8;1363entity->yvel = sin256LookupTable[entity->angle] * entity->speed >> 8;1364if (entity->yvel < -0x100000) {1365entity->yvel = -0x100000;1366}1367if (entity->yvel > 0x100000) {1368entity->yvel = 0x100000;1369}1370entity->speed = entity->xvel;1371entity->angle = 0;1372}1373else if (entity->speed >= 0x28000 || entity->speed <= -0x28000 || entity->controlLock != 0) {1374entity->angle = sensors[0].angle;1375entity->rotation = entity->angle << 1;1376}1377else {1378entity->gravity = 1;1379entity->angle = 0;1380entity->collisionMode = CMODE_FLOOR;1381entity->speed = entity->xvel;1382entity->controlLock = 30;1383}1384if (!sensors[3].collided) {1385entity->ypos = sensors[4].ypos;1386}1387else {1388if (entity->speed > 0)1389entity->ypos = (sensors[3].ypos - collisionTop) << 16;13901391if (entity->speed < 0)1392entity->ypos = (sensors[3].ypos - collisionBottom) << 16;13931394entity->speed = 0;1395}1396entity->xpos = sensors[4].xpos;1397break;1398}1399case CMODE_ROOF: {1400if (!sensors[0].collided && !sensors[1].collided && !sensors[2].collided) {1401entity->gravity = 1;1402entity->collisionMode = CMODE_FLOOR;1403entity->xvel = cos256LookupTable[entity->angle] * entity->speed >> 8;1404entity->yvel = sin256LookupTable[entity->angle] * entity->speed >> 8;1405entity->floorSensors[0] = false;1406entity->floorSensors[1] = false;1407entity->floorSensors[2] = false;1408if (entity->yvel < -0x100000)1409entity->yvel = -0x100000;14101411if (entity->yvel > 0x100000)1412entity->yvel = 0x100000;14131414entity->angle = 0;1415entity->speed = entity->xvel;1416if (!sensors[3].collided) {1417entity->xpos = entity->xpos + entity->xvel;1418}1419else {1420if (entity->speed > 0)1421entity->xpos = (sensors[3].xpos - collisionRight) << 16;14221423if (entity->speed < 0)1424entity->xpos = (sensors[3].xpos - collisionLeft + 1) << 16;14251426entity->speed = 0;1427}1428}1429else if (entity->speed <= -0x28000 || entity->speed >= 0x28000) {1430entity->angle = sensors[0].angle;1431entity->rotation = entity->angle << 1;1432if (!sensors[3].collided) {1433entity->xpos = sensors[4].xpos;1434}1435else {1436if (entity->speed < 0)1437entity->xpos = (sensors[3].xpos - collisionRight) << 16;14381439if (entity->speed > 0)1440entity->xpos = (sensors[3].xpos - collisionLeft + 1) << 16;1441entity->speed = 0;1442}1443}1444else {1445entity->gravity = 1;1446entity->angle = 0;1447entity->collisionMode = CMODE_FLOOR;1448entity->speed = entity->xvel;1449entity->floorSensors[0] = false;1450entity->floorSensors[1] = false;1451entity->floorSensors[2] = false;1452if (!sensors[3].collided) {1453entity->xpos = entity->xpos + entity->xvel;1454}1455else {1456if (entity->speed > 0)1457entity->xpos = (sensors[3].xpos - collisionRight) << 16;14581459if (entity->speed < 0)1460entity->xpos = (sensors[3].xpos - collisionLeft + 1) << 16;1461entity->speed = 0;1462}1463}1464entity->ypos = sensors[4].ypos;1465break;1466}1467case CMODE_RWALL: {1468if (!sensors[0].collided && !sensors[1].collided && !sensors[2].collided) {1469entity->gravity = 1;1470entity->collisionMode = CMODE_FLOOR;1471entity->xvel = cos256LookupTable[entity->angle] * entity->speed >> 8;1472entity->yvel = sin256LookupTable[entity->angle] * entity->speed >> 8;1473if (entity->yvel < -0x100000)1474entity->yvel = -0x100000;14751476if (entity->yvel > 0x100000)1477entity->yvel = 0x100000;14781479entity->speed = entity->xvel;1480entity->angle = 0;1481}1482else if (entity->speed <= -0x28000 || entity->speed >= 0x28000 || entity->controlLock != 0) {1483entity->angle = sensors[0].angle;1484entity->rotation = entity->angle << 1;1485}1486else {1487entity->gravity = 1;1488entity->angle = 0;1489entity->collisionMode = CMODE_FLOOR;1490entity->speed = entity->xvel;1491entity->controlLock = 30;1492}1493if (!sensors[3].collided) {1494entity->ypos = sensors[4].ypos;1495}1496else {1497if (entity->speed > 0)1498entity->ypos = (sensors[3].ypos - collisionBottom) << 16;14991500if (entity->speed < 0)1501entity->ypos = (sensors[3].ypos - collisionTop + 1) << 16;15021503entity->speed = 0;1504}1505entity->xpos = sensors[4].xpos;1506break;1507}1508default: break;1509}1510}15111512void SetPathGripSensors(Entity *player)1513{1514Hitbox *playerHitbox = GetHitbox(player);15151516switch (player->collisionMode) {1517case CMODE_FLOOR: {1518collisionLeft = playerHitbox->left[0];1519collisionTop = playerHitbox->top[0];1520collisionRight = playerHitbox->right[0];1521collisionBottom = playerHitbox->bottom[0];1522sensors[0].ypos = sensors[4].ypos + (collisionBottom << 16);1523sensors[1].ypos = sensors[0].ypos;1524sensors[2].ypos = sensors[0].ypos;1525sensors[3].ypos = sensors[4].ypos + 0x40000;1526#if !RETRO_REV001527sensors[5].ypos = sensors[0].ypos;1528sensors[6].ypos = sensors[0].ypos;1529#endif15301531sensors[0].xpos = sensors[4].xpos + ((playerHitbox->left[1] - 1) << 16);1532sensors[1].xpos = sensors[4].xpos;1533sensors[2].xpos = sensors[4].xpos + (playerHitbox->right[1] << 16);1534#if !RETRO_REV001535sensors[5].xpos = sensors[4].xpos + (playerHitbox->left[1] << 15);1536sensors[6].xpos = sensors[4].xpos + (playerHitbox->right[1] << 15);1537#endif1538if (player->speed > 0) {1539sensors[3].xpos = sensors[4].xpos + ((collisionRight + 1) << 16);1540}1541else {1542sensors[3].xpos = sensors[4].xpos + ((collisionLeft - 1) << 16);1543}1544return;1545}1546case CMODE_LWALL: {1547collisionLeft = playerHitbox->left[2];1548collisionTop = playerHitbox->top[2];1549collisionRight = playerHitbox->right[2];1550collisionBottom = playerHitbox->bottom[2];1551sensors[0].xpos = sensors[4].xpos + (collisionRight << 16);1552sensors[1].xpos = sensors[0].xpos;1553sensors[2].xpos = sensors[0].xpos;1554sensors[3].xpos = sensors[4].xpos + 0x40000;1555sensors[0].ypos = sensors[4].ypos + ((playerHitbox->top[3] - 1) << 16);1556sensors[1].ypos = sensors[4].ypos;1557sensors[2].ypos = sensors[4].ypos + (playerHitbox->bottom[3] << 16);1558if (player->speed > 0) {1559sensors[3].ypos = sensors[4].ypos + (collisionTop << 16);1560}1561else {1562sensors[3].ypos = sensors[4].ypos + ((collisionBottom - 1) << 16);1563}1564return;1565}1566case CMODE_ROOF: {1567collisionLeft = playerHitbox->left[4];1568collisionTop = playerHitbox->top[4];1569collisionRight = playerHitbox->right[4];1570collisionBottom = playerHitbox->bottom[4];1571sensors[0].ypos = sensors[4].ypos + ((collisionTop - 1) << 16);1572sensors[1].ypos = sensors[0].ypos;1573sensors[2].ypos = sensors[0].ypos;1574sensors[3].ypos = sensors[4].ypos - 0x40000;1575sensors[0].xpos = sensors[4].xpos + ((playerHitbox->left[5] - 1) << 16);1576sensors[1].xpos = sensors[4].xpos;1577sensors[2].xpos = sensors[4].xpos + (playerHitbox->right[5] << 16);1578if (player->speed < 0) {1579sensors[3].xpos = sensors[4].xpos + ((collisionRight + 1) << 16);1580}1581else {1582sensors[3].xpos = sensors[4].xpos + ((collisionLeft - 1) << 16);1583}1584return;1585}1586case CMODE_RWALL: {1587collisionLeft = playerHitbox->left[6];1588collisionTop = playerHitbox->top[6];1589collisionRight = playerHitbox->right[6];1590collisionBottom = playerHitbox->bottom[6];1591sensors[0].xpos = sensors[4].xpos + ((collisionLeft - 1) << 16);1592sensors[1].xpos = sensors[0].xpos;1593sensors[2].xpos = sensors[0].xpos;1594sensors[3].xpos = sensors[4].xpos - 0x40000;1595sensors[0].ypos = sensors[4].ypos + ((playerHitbox->top[7] - 1) << 16);1596sensors[1].ypos = sensors[4].ypos;1597sensors[2].ypos = sensors[4].ypos + (playerHitbox->bottom[7] << 16);1598if (player->speed > 0) {1599sensors[3].ypos = sensors[4].ypos + (collisionBottom << 16);1600}1601else {1602sensors[3].ypos = sensors[4].ypos + ((collisionTop - 1) << 16);1603}1604return;1605}1606default: return;1607}1608}16091610void ProcessTileCollisions(Entity *player)1611{1612player->floorSensors[0] = false;1613player->floorSensors[1] = false;1614player->floorSensors[2] = false;1615#if !RETRO_REV001616player->floorSensors[3] = false;1617player->floorSensors[4] = false;1618#endif1619scriptEng.checkResult = false;16201621collisionTolerance = 15;1622if (player->speed < 0x60000)1623collisionTolerance = (sbyte)player->angle == 0 ? 8 : 15;16241625if (player->gravity == 1)1626ProcessAirCollision(player);1627else1628ProcessPathGrip(player);1629}16301631void ObjectFloorCollision(int xOffset, int yOffset, int cPath)1632{1633scriptEng.checkResult = false;1634Entity *entity = &objectEntityList[objectEntityPos];1635int c = 0;1636int XPos = (entity->xpos >> 16) + xOffset;1637int YPos = (entity->ypos >> 16) + yOffset;1638if (XPos > 0 && XPos < stageLayouts[0].xsize << 7 && YPos > 0 && YPos < stageLayouts[0].ysize << 7) {1639int chunkX = XPos >> 7;1640int tileX = (XPos & 0x7F) >> 4;1641int chunkY = YPos >> 7;1642int tileY = (YPos & 0x7F) >> 4;1643int chunk = (stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6) + tileX + (tileY << 3);1644int tileIndex = tiles128x128.tileIndex[chunk];1645if (tiles128x128.collisionFlags[cPath][chunk] != SOLID_LRB && tiles128x128.collisionFlags[cPath][chunk] != SOLID_NONE) {1646switch (tiles128x128.direction[chunk]) {1647case 0: {1648c = (XPos & 15) + (tileIndex << 4);1649if ((YPos & 15) <= collisionMasks[cPath].floorMasks[c]) {1650break;1651}1652YPos = collisionMasks[cPath].floorMasks[c] + (chunkY << 7) + (tileY << 4);1653scriptEng.checkResult = true;1654break;1655}1656case 1: {1657c = 15 - (XPos & 15) + (tileIndex << 4);1658if ((YPos & 15) <= collisionMasks[cPath].floorMasks[c]) {1659break;1660}1661YPos = collisionMasks[cPath].floorMasks[c] + (chunkY << 7) + (tileY << 4);1662scriptEng.checkResult = true;1663break;1664}1665case 2: {1666c = (XPos & 15) + (tileIndex << 4);1667if ((YPos & 15) <= 15 - collisionMasks[cPath].roofMasks[c]) {1668break;1669}1670YPos = 15 - collisionMasks[cPath].roofMasks[c] + (chunkY << 7) + (tileY << 4);1671scriptEng.checkResult = true;1672break;1673}1674case 3: {1675c = 15 - (XPos & 15) + (tileIndex << 4);1676if ((YPos & 15) <= 15 - collisionMasks[cPath].roofMasks[c]) {1677break;1678}1679YPos = 15 - collisionMasks[cPath].roofMasks[c] + (chunkY << 7) + (tileY << 4);1680scriptEng.checkResult = true;1681break;1682}1683}1684}1685if (scriptEng.checkResult) {1686entity->ypos = (YPos - yOffset) << 16;1687}1688}1689}1690void ObjectLWallCollision(int xOffset, int yOffset, int cPath)1691{1692int c;1693scriptEng.checkResult = false;1694Entity *entity = &objectEntityList[objectEntityPos];1695int XPos = (entity->xpos >> 16) + xOffset;1696int YPos = (entity->ypos >> 16) + yOffset;1697if (XPos > 0 && XPos < stageLayouts[0].xsize << 7 && YPos > 0 && YPos < stageLayouts[0].ysize << 7) {1698int chunkX = XPos >> 7;1699int tileX = (XPos & 0x7F) >> 4;1700int chunkY = YPos >> 7;1701int tileY = (YPos & 0x7F) >> 4;1702int chunk = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;1703chunk = chunk + tileX + (tileY << 3);1704int tileIndex = tiles128x128.tileIndex[chunk];1705if (tiles128x128.collisionFlags[cPath][chunk] != SOLID_TOP && tiles128x128.collisionFlags[cPath][chunk] < SOLID_NONE) {1706switch (tiles128x128.direction[chunk]) {1707case 0: {1708c = (YPos & 15) + (tileIndex << 4);1709if ((XPos & 15) <= collisionMasks[cPath].lWallMasks[c]) {1710break;1711}1712XPos = collisionMasks[cPath].lWallMasks[c] + (chunkX << 7) + (tileX << 4);1713scriptEng.checkResult = true;1714break;1715}1716case 1: {1717c = (YPos & 15) + (tileIndex << 4);1718if ((XPos & 15) <= 15 - collisionMasks[cPath].rWallMasks[c]) {1719break;1720}1721XPos = 15 - collisionMasks[cPath].rWallMasks[c] + (chunkX << 7) + (tileX << 4);1722scriptEng.checkResult = true;1723break;1724}1725case 2: {1726c = 15 - (YPos & 15) + (tileIndex << 4);1727if ((XPos & 15) <= collisionMasks[cPath].lWallMasks[c]) {1728break;1729}1730XPos = collisionMasks[cPath].lWallMasks[c] + (chunkX << 7) + (tileX << 4);1731scriptEng.checkResult = true;1732break;1733}1734case 3: {1735c = 15 - (YPos & 15) + (tileIndex << 4);1736if ((XPos & 15) <= 15 - collisionMasks[cPath].rWallMasks[c]) {1737break;1738}1739XPos = 15 - collisionMasks[cPath].rWallMasks[c] + (chunkX << 7) + (tileX << 4);1740scriptEng.checkResult = true;1741break;1742}1743}1744}1745if (scriptEng.checkResult) {1746entity->xpos = (XPos - xOffset) << 16;1747}1748}1749}1750void ObjectRoofCollision(int xOffset, int yOffset, int cPath)1751{1752int c;1753scriptEng.checkResult = false;1754Entity *entity = &objectEntityList[objectEntityPos];1755int XPos = (entity->xpos >> 16) + xOffset;1756int YPos = (entity->ypos >> 16) + yOffset;1757if (XPos > 0 && XPos < stageLayouts[0].xsize << 7 && YPos > 0 && YPos < stageLayouts[0].ysize << 7) {1758int chunkX = XPos >> 7;1759int tileX = (XPos & 0x7F) >> 4;1760int chunkY = YPos >> 7;1761int tileY = (YPos & 0x7F) >> 4;1762int chunk = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;1763chunk = chunk + tileX + (tileY << 3);1764int tileIndex = tiles128x128.tileIndex[chunk];1765if (tiles128x128.collisionFlags[cPath][chunk] != SOLID_TOP && tiles128x128.collisionFlags[cPath][chunk] < SOLID_NONE) {1766switch (tiles128x128.direction[chunk]) {1767case 0: {1768c = (XPos & 15) + (tileIndex << 4);1769if ((YPos & 15) >= collisionMasks[cPath].roofMasks[c]) {1770break;1771}1772YPos = collisionMasks[cPath].roofMasks[c] + (chunkY << 7) + (tileY << 4);1773scriptEng.checkResult = true;1774break;1775}1776case 1: {1777c = 15 - (XPos & 15) + (tileIndex << 4);1778if ((YPos & 15) >= collisionMasks[cPath].roofMasks[c]) {1779break;1780}1781YPos = collisionMasks[cPath].roofMasks[c] + (chunkY << 7) + (tileY << 4);1782scriptEng.checkResult = true;1783break;1784}1785case 2: {1786c = (XPos & 15) + (tileIndex << 4);1787if ((YPos & 15) >= 15 - collisionMasks[cPath].floorMasks[c]) {1788break;1789}1790YPos = 15 - collisionMasks[cPath].floorMasks[c] + (chunkY << 7) + (tileY << 4);1791scriptEng.checkResult = true;1792break;1793}1794case 3: {1795c = 15 - (XPos & 15) + (tileIndex << 4);1796if ((YPos & 15) >= 15 - collisionMasks[cPath].floorMasks[c]) {1797break;1798}1799YPos = 15 - collisionMasks[cPath].floorMasks[c] + (chunkY << 7) + (tileY << 4);1800scriptEng.checkResult = true;1801break;1802}1803}1804}1805if (scriptEng.checkResult) {1806entity->ypos = (YPos - yOffset) << 16;1807}1808}1809}1810void ObjectRWallCollision(int xOffset, int yOffset, int cPath)1811{1812int c;1813scriptEng.checkResult = false;1814Entity *entity = &objectEntityList[objectEntityPos];1815int XPos = (entity->xpos >> 16) + xOffset;1816int YPos = (entity->ypos >> 16) + yOffset;1817if (XPos > 0 && XPos < stageLayouts[0].xsize << 7 && YPos > 0 && YPos < stageLayouts[0].ysize << 7) {1818int chunkX = XPos >> 7;1819int tileX = (XPos & 0x7F) >> 4;1820int chunkY = YPos >> 7;1821int tileY = (YPos & 0x7F) >> 4;1822int chunk = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;1823chunk = chunk + tileX + (tileY << 3);1824int tileIndex = tiles128x128.tileIndex[chunk];1825if (tiles128x128.collisionFlags[cPath][chunk] != SOLID_TOP && tiles128x128.collisionFlags[cPath][chunk] < SOLID_NONE) {1826switch (tiles128x128.direction[chunk]) {1827case 0: {1828c = (YPos & 15) + (tileIndex << 4);1829if ((XPos & 15) >= collisionMasks[cPath].rWallMasks[c]) {1830break;1831}1832XPos = collisionMasks[cPath].rWallMasks[c] + (chunkX << 7) + (tileX << 4);1833scriptEng.checkResult = true;1834break;1835}1836case 1: {1837c = (YPos & 15) + (tileIndex << 4);1838if ((XPos & 15) >= 15 - collisionMasks[cPath].lWallMasks[c]) {1839break;1840}1841XPos = 15 - collisionMasks[cPath].lWallMasks[c] + (chunkX << 7) + (tileX << 4);1842scriptEng.checkResult = true;1843break;1844}1845case 2: {1846c = 15 - (YPos & 15) + (tileIndex << 4);1847if ((XPos & 15) >= collisionMasks[cPath].rWallMasks[c]) {1848break;1849}1850XPos = collisionMasks[cPath].rWallMasks[c] + (chunkX << 7) + (tileX << 4);1851scriptEng.checkResult = true;1852break;1853}1854case 3: {1855c = 15 - (YPos & 15) + (tileIndex << 4);1856if ((XPos & 15) >= 15 - collisionMasks[cPath].lWallMasks[c]) {1857break;1858}1859XPos = 15 - collisionMasks[cPath].lWallMasks[c] + (chunkX << 7) + (tileX << 4);1860scriptEng.checkResult = true;1861break;1862}1863}1864}1865if (scriptEng.checkResult) {1866entity->xpos = (XPos - xOffset) << 16;1867}1868}1869}18701871void ObjectFloorGrip(int xOffset, int yOffset, int cPath)1872{1873int c;1874scriptEng.checkResult = false;1875Entity *entity = &objectEntityList[objectEntityPos];1876int XPos = (entity->xpos >> 16) + xOffset;1877int YPos = (entity->ypos >> 16) + yOffset;1878int chunkX = YPos;1879YPos = YPos - 16;1880for (int i = 3; i > 0; i--) {1881if (XPos > 0 && XPos < stageLayouts[0].xsize << 7 && YPos > 0 && YPos < stageLayouts[0].ysize << 7 && !scriptEng.checkResult) {1882int chunkX = XPos >> 7;1883int tileX = (XPos & 0x7F) >> 4;1884int chunkY = YPos >> 7;1885int tileY = (YPos & 0x7F) >> 4;1886int chunk = (stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6) + tileX + (tileY << 3);1887int tileIndex = tiles128x128.tileIndex[chunk];1888if (tiles128x128.collisionFlags[cPath][chunk] != SOLID_LRB && tiles128x128.collisionFlags[cPath][chunk] != SOLID_NONE) {1889switch (tiles128x128.direction[chunk]) {1890case 0: {1891c = (XPos & 15) + (tileIndex << 4);1892if (collisionMasks[cPath].floorMasks[c] >= 64) {1893break;1894}1895entity->ypos = collisionMasks[cPath].floorMasks[c] + (chunkY << 7) + (tileY << 4);1896scriptEng.checkResult = true;1897break;1898}1899case 1: {1900c = 15 - (XPos & 15) + (tileIndex << 4);1901if (collisionMasks[cPath].floorMasks[c] >= 64) {1902break;1903}1904entity->ypos = collisionMasks[cPath].floorMasks[c] + (chunkY << 7) + (tileY << 4);1905scriptEng.checkResult = true;1906break;1907}1908case 2: {1909c = (XPos & 15) + (tileIndex << 4);1910if (collisionMasks[cPath].roofMasks[c] <= -64) {1911break;1912}1913entity->ypos = 15 - collisionMasks[cPath].roofMasks[c] + (chunkY << 7) + (tileY << 4);1914scriptEng.checkResult = true;1915break;1916}1917case 3: {1918c = 15 - (XPos & 15) + (tileIndex << 4);1919if (collisionMasks[cPath].roofMasks[c] <= -64) {1920break;1921}1922entity->ypos = 15 - collisionMasks[cPath].roofMasks[c] + (chunkY << 7) + (tileY << 4);1923scriptEng.checkResult = true;1924break;1925}1926}1927}1928}1929YPos += 16;1930}19311932if (scriptEng.checkResult) {1933if (abs(entity->ypos - chunkX) < 16) {1934entity->ypos = (entity->ypos - yOffset) << 16;1935return;1936}1937entity->ypos = (chunkX - yOffset) << 16;1938scriptEng.checkResult = false;1939}1940}1941void ObjectLWallGrip(int xOffset, int yOffset, int cPath)1942{1943int c;1944scriptEng.checkResult = false;1945Entity *entity = &objectEntityList[objectEntityPos];1946int XPos = (entity->xpos >> 16) + xOffset;1947int YPos = (entity->ypos >> 16) + yOffset;1948int startX = XPos;1949XPos = XPos - 16;1950for (int i = 3; i > 0; i--) {1951if (XPos > 0 && XPos < stageLayouts[0].xsize << 7 && YPos > 0 && YPos < stageLayouts[0].ysize << 7 && !scriptEng.checkResult) {1952int chunkX = XPos >> 7;1953int tileX = (XPos & 0x7F) >> 4;1954int chunkY = YPos >> 7;1955int tileY = (YPos & 0x7F) >> 4;1956int chunk = (stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6) + tileX + (tileY << 3);1957int tileIndex = tiles128x128.tileIndex[chunk];1958if (tiles128x128.collisionFlags[cPath][chunk] < SOLID_NONE) {1959switch (tiles128x128.direction[chunk]) {1960case 0: {1961c = (YPos & 15) + (tileIndex << 4);1962if (collisionMasks[cPath].lWallMasks[c] >= 64) {1963break;1964}1965entity->xpos = collisionMasks[cPath].lWallMasks[c] + (chunkX << 7) + (tileX << 4);1966scriptEng.checkResult = true;1967break;1968}1969case 1: {1970c = (YPos & 15) + (tileIndex << 4);1971if (collisionMasks[cPath].rWallMasks[c] <= -64) {1972break;1973}1974entity->xpos = 15 - collisionMasks[cPath].rWallMasks[c] + (chunkX << 7) + (tileX << 4);1975scriptEng.checkResult = true;1976break;1977}1978case 2: {1979c = 15 - (YPos & 15) + (tileIndex << 4);1980if (collisionMasks[cPath].lWallMasks[c] >= 64) {1981break;1982}1983entity->xpos = collisionMasks[cPath].lWallMasks[c] + (chunkX << 7) + (tileX << 4);1984scriptEng.checkResult = true;1985break;1986}1987case 3: {1988c = 15 - (YPos & 15) + (tileIndex << 4);1989if (collisionMasks[cPath].rWallMasks[c] <= -64) {1990break;1991}1992entity->xpos = 15 - collisionMasks[cPath].rWallMasks[c] + (chunkX << 7) + (tileX << 4);1993scriptEng.checkResult = true;1994break;1995}1996}1997}1998}1999XPos += 16;2000}2001if (scriptEng.checkResult) {2002if (abs(entity->xpos - startX) < 16) {2003entity->xpos = (entity->xpos - xOffset) << 16;2004return;2005}2006entity->xpos = (startX - xOffset) << 16;2007scriptEng.checkResult = false;2008}2009}2010void ObjectRoofGrip(int xOffset, int yOffset, int cPath)2011{2012int c;2013scriptEng.checkResult = false;2014Entity *entity = &objectEntityList[objectEntityPos];2015int XPos = (entity->xpos >> 16) + xOffset;2016int YPos = (entity->ypos >> 16) + yOffset;2017int startY = YPos;2018YPos = YPos + 16;2019for (int i = 3; i > 0; i--) {2020if (XPos > 0 && XPos < stageLayouts[0].xsize << 7 && YPos > 0 && YPos < stageLayouts[0].ysize << 7 && !scriptEng.checkResult) {2021int chunkX = XPos >> 7;2022int tileX = (XPos & 0x7F) >> 4;2023int chunkY = YPos >> 7;2024int tileY = (YPos & 0x7F) >> 4;2025int chunk = (stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6) + tileX + (tileY << 3);2026int tileIndex = tiles128x128.tileIndex[chunk];2027if (tiles128x128.collisionFlags[cPath][chunk] < SOLID_NONE) {2028switch (tiles128x128.direction[chunk]) {2029case 0: {2030c = (XPos & 15) + (tileIndex << 4);2031if (collisionMasks[cPath].roofMasks[c] <= -64) {2032break;2033}2034entity->ypos = collisionMasks[cPath].roofMasks[c] + (chunkY << 7) + (tileY << 4);2035scriptEng.checkResult = true;2036break;2037}2038case 1: {2039c = 15 - (XPos & 15) + (tileIndex << 4);2040if (collisionMasks[cPath].roofMasks[c] <= -64) {2041break;2042}2043entity->ypos = collisionMasks[cPath].roofMasks[c] + (chunkY << 7) + (tileY << 4);2044scriptEng.checkResult = true;2045break;2046}2047case 2: {2048c = (XPos & 15) + (tileIndex << 4);2049if (collisionMasks[cPath].floorMasks[c] >= 64) {2050break;2051}2052entity->ypos = 15 - collisionMasks[cPath].floorMasks[c] + (chunkY << 7) + (tileY << 4);2053scriptEng.checkResult = true;2054break;2055}2056case 3: {2057c = 15 - (XPos & 15) + (tileIndex << 4);2058if (collisionMasks[cPath].floorMasks[c] >= 64) {2059break;2060}2061entity->ypos = 15 - collisionMasks[cPath].floorMasks[c] + (chunkY << 7) + (tileY << 4);2062scriptEng.checkResult = true;2063break;2064}2065}2066}2067}2068YPos -= 16;2069}2070if (scriptEng.checkResult) {2071if (abs(entity->ypos - startY) < 16) {2072entity->ypos = (entity->ypos - yOffset) << 16;2073return;2074}2075entity->ypos = (startY - yOffset) << 16;2076scriptEng.checkResult = false;2077}2078}2079void ObjectRWallGrip(int xOffset, int yOffset, int cPath)2080{2081int c;2082scriptEng.checkResult = false;2083Entity *entity = &objectEntityList[objectEntityPos];2084int XPos = (entity->xpos >> 16) + xOffset;2085int YPos = (entity->ypos >> 16) + yOffset;2086int startX = XPos;2087XPos = XPos + 16;2088for (int i = 3; i > 0; i--) {2089if (XPos > 0 && XPos < stageLayouts[0].xsize << 7 && YPos > 0 && YPos < stageLayouts[0].ysize << 7 && !scriptEng.checkResult) {2090int chunkX = XPos >> 7;2091int tileX = (XPos & 0x7F) >> 4;2092int chunkY = YPos >> 7;2093int tileY = (YPos & 0x7F) >> 4;2094int chunk = (stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6) + tileX + (tileY << 3);2095int tileIndex = tiles128x128.tileIndex[chunk];2096if (tiles128x128.collisionFlags[cPath][chunk] < SOLID_NONE) {2097switch (tiles128x128.direction[chunk]) {2098case 0: {2099c = (YPos & 15) + (tileIndex << 4);2100if (collisionMasks[cPath].rWallMasks[c] <= -64) {2101break;2102}2103entity->xpos = collisionMasks[cPath].rWallMasks[c] + (chunkX << 7) + (tileX << 4);2104scriptEng.checkResult = true;2105break;2106}2107case 1: {2108c = (YPos & 15) + (tileIndex << 4);2109if (collisionMasks[cPath].lWallMasks[c] >= 64) {2110break;2111}2112entity->xpos = 15 - collisionMasks[cPath].lWallMasks[c] + (chunkX << 7) + (tileX << 4);2113scriptEng.checkResult = true;2114break;2115}2116case 2: {2117c = 15 - (YPos & 15) + (tileIndex << 4);2118if (collisionMasks[cPath].rWallMasks[c] <= -64) {2119break;2120}2121entity->xpos = collisionMasks[cPath].rWallMasks[c] + (chunkX << 7) + (tileX << 4);2122scriptEng.checkResult = true;2123break;2124}2125case 3: {2126c = 15 - (YPos & 15) + (tileIndex << 4);2127if (collisionMasks[cPath].lWallMasks[c] >= 64) {2128break;2129}2130entity->xpos = 15 - collisionMasks[cPath].lWallMasks[c] + (chunkX << 7) + (tileX << 4);2131scriptEng.checkResult = true;2132break;2133}2134}2135}2136}2137XPos -= 16;2138}2139if (scriptEng.checkResult) {2140if (abs(entity->xpos - startX) < 16) {2141entity->xpos = (entity->xpos - xOffset) << 16;2142return;2143}2144entity->xpos = (startX - xOffset) << 16;2145scriptEng.checkResult = false;2146}2147}2148#if RETRO_REV032149void ObjectLEntityGrip(int xOffset, int yOffset, int cPath)2150{2151scriptEng.checkResult = false;2152Entity *entity = &objectEntityList[objectEntityPos];2153int mBlockID = entity->values[44];2154int XPos = (entity->xpos >> 16) + xOffset - 16;2155int YPos = (entity->ypos >> 16) + yOffset;2156int check = 0;2157if (mBlockID > 0 && objectTypeGroupList[mBlockID].listSize > 0) {2158TypeGroupList *mBlockGroupList = &objectTypeGroupList[mBlockID];2159for (int i = 0; i < objectTypeGroupList[mBlockID].listSize; i++) {2160short entRef = mBlockGroupList->entityRefs[i];2161Entity *otherEntity = &objectEntityList[entRef];2162int XPos2 = otherEntity->xpos >> 16;2163int YPos2 = otherEntity->ypos >> 16;2164if (((((XPos2 - 16) <= XPos) && (XPos <= (XPos2 + 16))) && ((YPos2 - 16) <= YPos)) && (YPos <= (YPos2 + 16))) {2165entity->xpos = otherEntity->xpos - (xOffset << 16) - 0x100000;2166if (otherEntity->values[0] == 0) {2167check = 2;2168scriptEng.checkResult = check;2169}2170else {2171scriptEng.checkResult = check;2172if (check != 2) {2173check = 1;2174scriptEng.checkResult = check;2175}2176}2177}2178if ((((XPos2 - 16) <= (XPos + 16) && ((XPos + 16) <= (XPos2 + 16))) && (YPos2 - 16) <= YPos) && (YPos <= (YPos2 + 16))) {2179entity->xpos = otherEntity->xpos - (xOffset << 16) - 0x100000;2180if (otherEntity->values[0] == 0) {2181check = 2;2182scriptEng.checkResult = check;2183}2184else {2185scriptEng.checkResult = check;2186if (check != 2) {2187scriptEng.checkResult = check;2188}2189}2190}21912192if (((XPos2 <= (XPos + 32)) && ((XPos + 32) <= (XPos2 + 16))) && (((YPos2 - 16) <= YPos && YPos <= (YPos2 + 16)))) {2193entity->xpos = otherEntity->xpos - (xOffset << 16) - 0x100000;2194if (otherEntity->values[0] == 0) {2195check = 2;2196scriptEng.checkResult = check;2197}2198else {2199scriptEng.checkResult = check;2200if (check != 2) {2201check = 1;2202scriptEng.checkResult = check;2203}2204}2205}22062207if (check != 0) {2208return;2209}2210}2211}2212ObjectLWallGrip(xOffset, yOffset, cPath);2213}2214void ObjectREntityGrip(int xOffset, int yOffset, int cPath)2215{2216scriptEng.checkResult = false;2217Entity *entity = &objectEntityList[objectEntityPos];2218int mBlockID = entity->values[44];2219int XPos = (entity->xpos >> 16) + xOffset + 16;2220int YPos = (entity->ypos >> 16) + yOffset;2221int check = 0;2222if (mBlockID > 0 && objectTypeGroupList[mBlockID].listSize > 0) {2223TypeGroupList *mBlockGroupList = &objectTypeGroupList[mBlockID];2224for (int i = 0; i < objectTypeGroupList[mBlockID].listSize; i++) {2225short entRef = mBlockGroupList->entityRefs[i];2226Entity *otherEntity = &objectEntityList[entRef];2227int XPos2 = otherEntity->xpos >> 16;2228int YPos2 = otherEntity->ypos >> 16;2229if (((((XPos2 - 16) <= XPos) && (XPos <= (XPos2 + 16))) && ((YPos2 - 16) <= YPos)) && (YPos <= (YPos2 + 16))) {2230entity->xpos = otherEntity->xpos + ((16 - xOffset) << 16);2231if (otherEntity->values[0] == 0) {2232check = 2;2233scriptEng.checkResult = check;2234}2235else {2236scriptEng.checkResult = check;2237if (check != 2) {2238check = 1;2239scriptEng.checkResult = check;2240}2241}2242}2243if ((((XPos2 - 16) <= (XPos + 16) && ((XPos - 16) <= (XPos2 + 16))) && (YPos2 - 16) <= YPos) && (YPos <= (YPos2 + 16))) {2244entity->xpos = otherEntity->xpos + ((16 - xOffset) << 16);2245if (otherEntity->values[0] == 0) {2246check = 2;2247scriptEng.checkResult = check;2248}2249else {2250scriptEng.checkResult = check;2251if (check != 2) {2252scriptEng.checkResult = check;2253}2254}2255}22562257if (((XPos2 <= (XPos - 32)) && ((XPos - 32) <= (XPos2 + 16))) && (((YPos2 - 16) <= YPos && YPos <= (YPos2 + 16)))) {2258entity->xpos = otherEntity->xpos + ((16 - xOffset) << 16);2259if (otherEntity->values[0] == 0) {2260check = 2;2261scriptEng.checkResult = check;2262}2263else {2264scriptEng.checkResult = check;2265if (check != 2) {2266check = 1;2267scriptEng.checkResult = check;2268}2269}2270}22712272if (check != 0) {2273return;2274}2275}2276}2277ObjectRWallGrip(xOffset, yOffset, cPath);2278}2279#endif2280void TouchCollision(Entity *thisEntity, int thisLeft, int thisTop, int thisRight, int thisBottom, Entity *otherEntity, int otherLeft, int otherTop,2281int otherRight, int otherBottom)2282{2283Hitbox *thisHitbox = GetHitbox(thisEntity);2284Hitbox *otherHitbox = GetHitbox(otherEntity);22852286if (thisLeft == C_BOX)2287thisLeft = thisHitbox->left[0];22882289if (thisTop == C_BOX)2290thisTop = thisHitbox->top[0];22912292if (thisRight == C_BOX)2293thisRight = thisHitbox->right[0];22942295if (thisBottom == C_BOX)2296thisBottom = thisHitbox->bottom[0];22972298if (otherLeft == C_BOX)2299otherLeft = otherHitbox->left[0];23002301if (otherTop == C_BOX)2302otherTop = otherHitbox->top[0];23032304if (otherRight == C_BOX)2305otherRight = otherHitbox->right[0];23062307if (otherBottom == C_BOX)2308otherBottom = otherHitbox->bottom[0];23092310#if !RETRO_USE_ORIGINAL_CODE2311int thisHitboxID = 0;2312int otherHitboxID = 0;2313if (showHitboxes) {2314thisHitboxID = AddDebugHitbox(H_TYPE_TOUCH, thisEntity, thisLeft, thisTop, thisRight, thisBottom);2315otherHitboxID = AddDebugHitbox(H_TYPE_TOUCH, otherEntity, otherLeft, otherTop, otherRight, otherBottom);2316}2317#endif23182319thisLeft += thisEntity->xpos >> 16;2320thisTop += thisEntity->ypos >> 16;2321thisRight += thisEntity->xpos >> 16;2322thisBottom += thisEntity->ypos >> 16;23232324otherLeft += otherEntity->xpos >> 16;2325otherTop += otherEntity->ypos >> 16;2326otherRight += otherEntity->xpos >> 16;2327otherBottom += otherEntity->ypos >> 16;23282329scriptEng.checkResult = otherRight > thisLeft && otherLeft < thisRight && otherBottom > thisTop && otherTop < thisBottom;23302331#if !RETRO_USE_ORIGINAL_CODE2332if (showHitboxes) {2333if (thisHitboxID >= 0 && scriptEng.checkResult)2334debugHitboxList[thisHitboxID].collision |= 1;2335if (otherHitboxID >= 0 && scriptEng.checkResult)2336debugHitboxList[otherHitboxID].collision |= 1;2337}2338#endif2339}2340void BoxCollision(Entity *thisEntity, int thisLeft, int thisTop, int thisRight, int thisBottom, Entity *otherEntity, int otherLeft, int otherTop,2341int otherRight, int otherBottom)2342{2343Hitbox *thisHitbox = GetHitbox(thisEntity);2344Hitbox *otherHitbox = GetHitbox(otherEntity);23452346if (thisLeft == C_BOX)2347thisLeft = thisHitbox->left[0];23482349if (thisTop == C_BOX)2350thisTop = thisHitbox->top[0];23512352if (thisRight == C_BOX)2353thisRight = thisHitbox->right[0];23542355if (thisBottom == C_BOX)2356thisBottom = thisHitbox->bottom[0];23572358if (otherLeft == C_BOX)2359otherLeft = otherHitbox->left[0];23602361if (otherTop == C_BOX)2362otherTop = otherHitbox->top[0];23632364if (otherRight == C_BOX)2365otherRight = otherHitbox->right[0];23662367if (otherBottom == C_BOX)2368otherBottom = otherHitbox->bottom[0];23692370#if !RETRO_USE_ORIGINAL_CODE2371int thisHitboxID = 0;2372int otherHitboxID = 0;2373if (showHitboxes) {2374thisHitboxID = AddDebugHitbox(H_TYPE_BOX, thisEntity, thisLeft, thisTop, thisRight, thisBottom);2375otherHitboxID = AddDebugHitbox(H_TYPE_BOX, otherEntity, otherLeft, otherTop, otherRight, otherBottom);2376}2377#endif23782379thisLeft += thisEntity->xpos >> 16;2380thisTop += thisEntity->ypos >> 16;2381thisRight += thisEntity->xpos >> 16;2382thisBottom += thisEntity->ypos >> 16;23832384thisLeft <<= 16;2385thisTop <<= 16;2386thisRight <<= 16;2387thisBottom <<= 16;23882389otherLeft <<= 16;2390otherTop <<= 16;2391otherRight <<= 16;2392otherBottom <<= 16;23932394scriptEng.checkResult = 0;23952396int rx = otherEntity->xpos >> 16 << 16;2397int ry = otherEntity->ypos >> 16 << 16;23982399int xDif = otherEntity->xpos - thisRight;2400if (thisEntity->xpos > otherEntity->xpos)2401xDif = thisLeft - otherEntity->xpos;2402int yDif = thisTop - otherEntity->ypos;2403if (thisEntity->ypos <= otherEntity->ypos)2404yDif = otherEntity->ypos - thisBottom;24052406if (xDif <= yDif && abs(otherEntity->xvel) >> 1 <= abs(otherEntity->yvel)) {2407sensors[0].collided = false;2408sensors[1].collided = false;2409sensors[2].collided = false;2410sensors[3].collided = false;2411sensors[4].collided = false;2412sensors[0].xpos = rx + otherLeft + 0x20000;2413sensors[1].xpos = rx;2414sensors[2].xpos = rx + otherRight - 0x20000;2415sensors[3].xpos = (sensors[0].xpos + rx) >> 1;2416sensors[4].xpos = (sensors[2].xpos + rx) >> 1;24172418sensors[0].ypos = ry + otherBottom;24192420if (otherEntity->yvel >= 0) {2421for (int i = 0; i < (RETRO_REV00 ? 3 : 5); ++i) {2422if (thisLeft < sensors[i].xpos && thisRight > sensors[i].xpos && thisTop <= sensors[0].ypos2423&& thisTop > otherEntity->ypos - otherEntity->yvel) {2424sensors[i].collided = true;2425otherEntity->floorSensors[i] = true;2426}2427}2428}24292430if (sensors[0].collided || sensors[1].collided || sensors[2].collided) {2431if (!otherEntity->gravity && (otherEntity->collisionMode == CMODE_RWALL || otherEntity->collisionMode == CMODE_LWALL)) {2432otherEntity->xvel = 0;2433otherEntity->speed = 0;2434}2435otherEntity->ypos = thisTop - otherBottom;2436otherEntity->gravity = 0;2437otherEntity->yvel = 0;2438otherEntity->angle = 0;2439otherEntity->rotation = 0;2440otherEntity->controlLock = 0;2441scriptEng.checkResult = 1;2442}2443else {2444sensors[0].collided = false;2445sensors[1].collided = false;2446sensors[0].xpos = rx + otherLeft + 0x20000;2447sensors[1].xpos = rx + otherRight - 0x20000;24482449sensors[0].ypos = ry + otherTop;24502451for (int i = 0; i < 2; ++i) {2452if (thisLeft < sensors[1].xpos && thisRight > sensors[0].xpos && thisBottom > sensors[0].ypos2453&& thisBottom < otherEntity->ypos - otherEntity->yvel) {2454sensors[i].collided = true;2455}2456}24572458if (sensors[1].collided || sensors[0].collided) {2459if (otherEntity->gravity == 1)2460otherEntity->ypos = thisBottom - otherTop;24612462if (otherEntity->yvel <= 0)2463otherEntity->yvel = 0;2464scriptEng.checkResult = 4;2465}2466else {2467sensors[0].collided = false;2468sensors[1].collided = false;2469sensors[0].xpos = rx + otherRight;24702471sensors[0].ypos = ry + otherTop + 0x20000;2472sensors[1].ypos = ry + otherBottom - 0x20000;2473for (int i = 0; i < 2; ++i) {2474if (thisLeft <= sensors[0].xpos && thisLeft > otherEntity->xpos - otherEntity->xvel && thisTop < sensors[1].ypos2475&& thisBottom > sensors[0].ypos) {2476sensors[i].collided = true;2477}2478}24792480if (sensors[1].collided || sensors[0].collided) {2481otherEntity->xpos = thisLeft - otherRight;2482if (otherEntity->xvel > 0) {2483if (!otherEntity->direction)2484otherEntity->pushing = 2;24852486otherEntity->xvel = 0;2487if (otherEntity->collisionMode || !otherEntity->left)2488otherEntity->speed = 0;2489else2490otherEntity->speed = -0x8000;2491}2492scriptEng.checkResult = 2;2493}2494else {2495sensors[0].collided = false;2496sensors[1].collided = false;2497sensors[0].xpos = rx + otherLeft;24982499sensors[0].ypos = ry + otherTop + 0x20000;2500sensors[1].ypos = ry + otherBottom - 0x20000;2501for (int i = 0; i < 2; ++i) {2502if (thisRight > sensors[0].xpos && thisRight < otherEntity->xpos - otherEntity->xvel && thisTop < sensors[1].ypos2503&& thisBottom > sensors[0].ypos) {2504sensors[i].collided = true;2505}2506}25072508if (sensors[1].collided || sensors[0].collided) {2509otherEntity->xpos = thisRight - otherLeft;2510if (otherEntity->xvel < 0) {2511if (otherEntity->direction == FLIP_X)2512otherEntity->pushing = 2;25132514if (otherEntity->xvel < -0x10000)2515otherEntity->xpos += 0x8000;25162517otherEntity->xvel = 0;2518if (otherEntity->collisionMode || !otherEntity->right)2519otherEntity->speed = 0;2520else2521otherEntity->speed = 0x8000;2522}2523scriptEng.checkResult = 3;2524}2525}2526}2527}2528}2529else {2530sensors[0].collided = false;2531sensors[1].collided = false;2532sensors[0].xpos = rx + otherRight;25332534sensors[0].ypos = ry + otherTop + 0x20000;2535sensors[1].ypos = ry + otherBottom - 0x20000;2536for (int i = 0; i < 2; ++i) {2537if (thisLeft <= sensors[0].xpos && thisLeft > otherEntity->xpos - otherEntity->xvel && thisTop < sensors[1].ypos2538&& thisBottom > sensors[0].ypos) {2539sensors[i].collided = true;2540}2541}2542if (sensors[1].collided || sensors[0].collided) {2543otherEntity->xpos = thisLeft - otherRight;2544if (otherEntity->xvel > 0) {2545if (!otherEntity->direction)2546otherEntity->pushing = 2;25472548otherEntity->xvel = 0;2549if (otherEntity->collisionMode || !otherEntity->left)2550otherEntity->speed = 0;2551else2552otherEntity->speed = -0x8000;2553}2554scriptEng.checkResult = 2;2555}2556else {2557sensors[0].collided = false;2558sensors[1].collided = false;2559sensors[0].xpos = rx + otherLeft;25602561sensors[0].ypos = ry + otherTop + 0x20000;2562sensors[1].ypos = ry + otherBottom - 0x20000;2563for (int i = 0; i < 2; ++i) {2564if (thisRight > sensors[0].xpos && thisRight < otherEntity->xpos - otherEntity->xvel && thisTop < sensors[1].ypos2565&& thisBottom > sensors[0].ypos) {2566sensors[i].collided = true;2567}2568}25692570if (sensors[0].collided || sensors[1].collided) {2571otherEntity->xpos = thisRight - otherLeft;2572if (otherEntity->xvel < 0) {2573if (otherEntity->direction == FLIP_X)2574otherEntity->pushing = 2;25752576if (otherEntity->xvel < -0x10000)2577otherEntity->xpos += 0x8000;25782579otherEntity->xvel = 0;2580if (otherEntity->collisionMode || !otherEntity->right)2581otherEntity->speed = 0;2582else2583otherEntity->speed = 0x8000;2584}2585scriptEng.checkResult = 3;2586}2587else {2588sensors[0].collided = false;2589sensors[1].collided = false;2590sensors[2].collided = false;2591sensors[3].collided = false;2592sensors[4].collided = false;2593sensors[0].xpos = rx + otherLeft + 0x20000;2594sensors[1].xpos = rx;2595sensors[2].xpos = rx + otherRight - 0x20000;2596sensors[3].xpos = (sensors[0].xpos + rx) >> 1;2597sensors[4].xpos = (sensors[2].xpos + rx) >> 1;25982599sensors[0].ypos = ry + otherBottom;2600if (otherEntity->yvel >= 0) {2601for (int i = 0; i < (RETRO_REV00 ? 3 : 5); ++i) {2602if (thisLeft < sensors[i].xpos && thisRight > sensors[i].xpos && thisTop <= sensors[0].ypos2603&& thisTop > otherEntity->ypos - otherEntity->yvel) {2604sensors[i].collided = true;2605otherEntity->floorSensors[i] = true;2606}2607}2608}2609if (sensors[2].collided || sensors[1].collided || sensors[0].collided) {2610if (!otherEntity->gravity && (otherEntity->collisionMode == CMODE_RWALL || otherEntity->collisionMode == CMODE_LWALL)) {2611otherEntity->xvel = 0;2612otherEntity->speed = 0;2613}2614otherEntity->ypos = thisTop - otherBottom;2615otherEntity->gravity = 0;2616otherEntity->yvel = 0;2617otherEntity->angle = 0;2618otherEntity->rotation = 0;2619otherEntity->controlLock = 0;2620scriptEng.checkResult = 1;2621}2622else {2623sensors[0].collided = false;2624sensors[1].collided = false;2625sensors[0].xpos = rx + otherLeft + 0x20000;2626sensors[1].xpos = rx + otherRight - 0x20000;2627sensors[0].ypos = ry + otherTop;26282629for (int i = 0; i < 2; ++i) {2630if (thisLeft < sensors[1].xpos && thisRight > sensors[0].xpos && thisBottom > sensors[0].ypos2631&& thisBottom < otherEntity->ypos - otherEntity->yvel) {2632sensors[i].collided = true;2633}2634}26352636if (sensors[1].collided || sensors[0].collided) {2637if (otherEntity->gravity == 1)2638otherEntity->ypos = thisBottom - otherTop;26392640if (otherEntity->yvel <= 0)2641otherEntity->yvel = 0;2642scriptEng.checkResult = 4;2643}2644}2645}2646}2647}26482649#if !RETRO_USE_ORIGINAL_CODE2650if (showHitboxes) {2651if (thisHitboxID >= 0 && scriptEng.checkResult)2652debugHitboxList[thisHitboxID].collision |= 1 << (scriptEng.checkResult - 1);2653if (otherHitboxID >= 0 && scriptEng.checkResult)2654debugHitboxList[otherHitboxID].collision |= 1 << (4 - scriptEng.checkResult);2655}2656#endif2657}2658void BoxCollision2(Entity *thisEntity, int thisLeft, int thisTop, int thisRight, int thisBottom, Entity *otherEntity, int otherLeft, int otherTop,2659int otherRight, int otherBottom)2660{2661Hitbox *thisHitbox = GetHitbox(thisEntity);2662Hitbox *otherHitbox = GetHitbox(otherEntity);26632664if (thisLeft == C_BOX)2665thisLeft = thisHitbox->left[0];26662667if (thisTop == C_BOX)2668thisTop = thisHitbox->top[0];26692670if (thisRight == C_BOX)2671thisRight = thisHitbox->right[0];26722673if (thisBottom == C_BOX)2674thisBottom = thisHitbox->bottom[0];26752676if (otherLeft == C_BOX)2677otherLeft = otherHitbox->left[0];26782679if (otherTop == C_BOX)2680otherTop = otherHitbox->top[0];26812682if (otherRight == C_BOX)2683otherRight = otherHitbox->right[0];26842685if (otherBottom == C_BOX)2686otherBottom = otherHitbox->bottom[0];26872688#if !RETRO_USE_ORIGINAL_CODE2689int thisHitboxID = 0;2690int otherHitboxID = 0;2691if (showHitboxes) {2692thisHitboxID = AddDebugHitbox(H_TYPE_BOX, thisEntity, thisLeft, thisTop, thisRight, thisBottom);2693otherHitboxID = AddDebugHitbox(H_TYPE_BOX, otherEntity, otherLeft, otherTop, otherRight, otherBottom);2694}2695#endif26962697thisLeft += thisEntity->xpos >> 16;2698thisTop += thisEntity->ypos >> 16;2699thisRight += thisEntity->xpos >> 16;2700thisBottom += thisEntity->ypos >> 16;27012702thisLeft <<= 16;2703thisTop <<= 16;2704thisRight <<= 16;2705thisBottom <<= 16;27062707otherLeft <<= 16;2708otherTop <<= 16;2709otherRight <<= 16;2710otherBottom <<= 16;27112712scriptEng.checkResult = 0;27132714int rx = otherEntity->xpos >> 16 << 16;2715int ry = otherEntity->ypos >> 16 << 16;27162717int xDif = thisLeft - rx;2718if (thisEntity->xpos <= rx)2719xDif = rx - thisRight;2720int yDif = thisTop - ry;2721if (thisEntity->ypos <= ry)2722yDif = ry - thisBottom;27232724if (xDif <= yDif) {2725sensors[0].collided = false;2726sensors[1].collided = false;2727sensors[2].collided = false;2728sensors[0].xpos = rx + otherLeft + 0x20000;2729sensors[1].xpos = rx;2730sensors[2].xpos = rx + otherRight - 0x20000;27312732sensors[0].ypos = ry + otherBottom;27332734if (otherEntity->yvel >= 0) {2735// this should prolly be using all 5 sensors, but this was barely used in S2 so it was prolly forgotten about2736for (int i = 0; i < 3; ++i) {2737if (thisLeft < sensors[i].xpos && thisRight > sensors[i].xpos && thisTop <= sensors[0].ypos && thisEntity->ypos > sensors[0].ypos) {2738sensors[i].collided = true;2739otherEntity->floorSensors[i] = true;2740}2741}2742}27432744if (sensors[0].collided || sensors[1].collided || sensors[2].collided) {2745if (!otherEntity->gravity && (otherEntity->collisionMode == CMODE_RWALL || otherEntity->collisionMode == CMODE_LWALL)) {2746otherEntity->xvel = 0;2747otherEntity->speed = 0;2748}2749otherEntity->ypos = thisTop - otherBottom;2750otherEntity->gravity = 0;2751otherEntity->yvel = 0;2752otherEntity->angle = 0;2753otherEntity->rotation = 0;2754otherEntity->controlLock = 0;2755scriptEng.checkResult = 1;2756}2757else {2758sensors[0].collided = false;2759sensors[1].collided = false;2760sensors[0].xpos = rx + otherLeft + 0x20000;2761sensors[1].xpos = rx + otherRight - 0x20000;27622763sensors[0].ypos = ry + otherTop;27642765for (int i = 0; i < 2; ++i) {2766if (thisLeft < sensors[1].xpos && thisRight > sensors[0].xpos && thisBottom > sensors[0].ypos && thisEntity->ypos < sensors[0].ypos) {2767sensors[i].collided = true;2768}2769}27702771if (sensors[1].collided || sensors[0].collided) {2772if (!otherEntity->gravity && (otherEntity->collisionMode == CMODE_RWALL || otherEntity->collisionMode == CMODE_LWALL)) {2773otherEntity->xvel = 0;2774otherEntity->speed = 0;2775}27762777otherEntity->ypos = thisBottom - otherTop;2778if (otherEntity->yvel < 0)2779otherEntity->yvel = 0;2780scriptEng.checkResult = 4;2781}2782else {2783sensors[0].collided = false;2784sensors[1].collided = false;2785sensors[0].xpos = rx + otherRight;27862787sensors[0].ypos = ry + otherTop + 0x20000;2788sensors[1].ypos = ry + otherBottom - 0x20000;2789for (int i = 0; i < 2; ++i) {2790if (thisLeft <= sensors[0].xpos && thisEntity->xpos > sensors[0].xpos && thisTop < sensors[1].ypos2791&& thisBottom > sensors[0].ypos) {2792sensors[i].collided = true;2793}2794}27952796if (sensors[1].collided || sensors[0].collided) {2797otherEntity->xpos = thisLeft - otherRight;2798if (otherEntity->xvel > 0) {2799if (!otherEntity->direction)2800otherEntity->pushing = 2;28012802otherEntity->xvel = 0;2803otherEntity->speed = 0;2804}2805scriptEng.checkResult = 2;2806}2807else {2808sensors[0].collided = false;2809sensors[1].collided = false;2810sensors[0].xpos = rx + otherLeft;28112812sensors[0].ypos = ry + otherTop + 0x20000;2813sensors[1].ypos = ry + otherBottom - 0x20000;2814for (int i = 0; i < 2; ++i) {2815if (thisRight > sensors[0].xpos && thisEntity->xpos < sensors[0].xpos && thisTop < sensors[1].ypos2816&& thisBottom > sensors[0].ypos) {2817sensors[i].collided = true;2818}2819}28202821if (sensors[1].collided || sensors[0].collided) {2822otherEntity->xpos = thisRight - otherLeft;2823if (otherEntity->xvel < 0) {2824if (otherEntity->direction == FLIP_X)2825otherEntity->pushing = 2;28262827if (otherEntity->xvel < -0x10000)2828otherEntity->xpos += 0x8000;28292830otherEntity->xvel = 0;2831otherEntity->speed = 0;2832}2833scriptEng.checkResult = 3;2834}2835}2836}2837}2838}2839else {2840sensors[0].collided = false;2841sensors[1].collided = false;2842sensors[0].xpos = rx + otherRight;28432844sensors[0].ypos = ry + otherTop + 0x20000;2845sensors[1].ypos = ry + otherBottom - 0x20000;2846for (int i = 0; i < 2; ++i) {2847if (thisLeft <= sensors[0].xpos && thisEntity->xpos > sensors[0].xpos && thisTop < sensors[1].ypos && thisBottom > sensors[0].ypos) {2848sensors[i].collided = true;2849}2850}2851if (sensors[1].collided || sensors[0].collided) {2852otherEntity->xpos = thisLeft - otherRight;2853if (otherEntity->xvel > 0) {2854if (!otherEntity->direction)2855otherEntity->pushing = 2;28562857otherEntity->xvel = 0;2858otherEntity->speed = 0;2859}2860scriptEng.checkResult = 2;2861}2862else {2863sensors[0].collided = false;2864sensors[1].collided = false;2865sensors[0].xpos = rx + otherLeft;28662867sensors[0].ypos = ry + otherTop + 0x20000;2868sensors[1].ypos = ry + otherBottom - 0x20000;2869for (int i = 0; i < 2; ++i) {2870if (thisRight > sensors[0].xpos && thisEntity->xpos < sensors[0].xpos && thisTop < sensors[1].ypos && thisBottom > sensors[0].ypos) {2871sensors[i].collided = true;2872}2873}28742875if (sensors[0].collided || sensors[1].collided) {2876otherEntity->xpos = thisRight - otherLeft;2877if (otherEntity->xvel < 0) {2878if (otherEntity->direction == FLIP_X)2879otherEntity->pushing = 2;28802881if (otherEntity->xvel < -0x10000)2882otherEntity->xpos += 0x8000;28832884otherEntity->xvel = 0;2885otherEntity->speed = 0;2886}2887scriptEng.checkResult = 3;2888}2889else {2890sensors[0].collided = false;2891sensors[1].collided = false;2892sensors[2].collided = false;2893sensors[0].xpos = rx + otherLeft + 0x20000;2894sensors[1].xpos = rx;2895sensors[2].xpos = rx + otherRight - 0x20000;28962897sensors[0].ypos = ry + otherBottom;2898if (otherEntity->yvel >= 0) {2899for (int i = 0; i < 3; ++i) {2900if (thisLeft < sensors[i].xpos && thisRight > sensors[i].xpos && thisTop <= sensors[0].ypos2901&& thisEntity->ypos > sensors[0].ypos) {2902sensors[i].collided = true;2903otherEntity->floorSensors[i] = true;2904}2905}2906}29072908if (sensors[0].collided || sensors[1].collided || sensors[2].collided) {2909if (!otherEntity->gravity && (otherEntity->collisionMode == CMODE_RWALL || otherEntity->collisionMode == CMODE_LWALL)) {2910otherEntity->xvel = 0;2911otherEntity->speed = 0;2912}2913otherEntity->ypos = thisTop - otherBottom;2914otherEntity->gravity = 0;2915otherEntity->yvel = 0;2916otherEntity->angle = 0;2917otherEntity->rotation = 0;2918otherEntity->controlLock = 0;2919scriptEng.checkResult = 1;2920}2921else {2922sensors[0].collided = false;2923sensors[1].collided = false;2924sensors[0].xpos = rx + otherLeft + 0x20000;2925sensors[1].xpos = rx + otherRight - 0x20000;29262927sensors[0].ypos = ry + otherTop;29282929for (int i = 0; i < 2; ++i) {2930if (thisLeft < sensors[1].xpos && thisRight > sensors[0].xpos && thisBottom > sensors[0].ypos2931&& thisEntity->ypos < sensors[0].ypos) {2932sensors[i].collided = true;2933}2934}29352936if (sensors[1].collided || sensors[0].collided) {2937if (!otherEntity->gravity && (otherEntity->collisionMode == CMODE_RWALL || otherEntity->collisionMode == CMODE_LWALL)) {2938otherEntity->xvel = 0;2939otherEntity->speed = 0;2940}29412942otherEntity->ypos = thisBottom - otherTop;29432944if (otherEntity->yvel < 0)2945otherEntity->yvel = 0;2946scriptEng.checkResult = 4;2947}2948}2949}2950}2951}29522953#if !RETRO_USE_ORIGINAL_CODE2954if (showHitboxes) {2955if (thisHitboxID >= 0 && scriptEng.checkResult)2956debugHitboxList[thisHitboxID].collision |= 1 << (scriptEng.checkResult - 1);2957if (otherHitboxID >= 0 && scriptEng.checkResult)2958debugHitboxList[otherHitboxID].collision |= 1 << (4 - scriptEng.checkResult);2959}2960#endif2961}2962void PlatformCollision(Entity *thisEntity, int thisLeft, int thisTop, int thisRight, int thisBottom, Entity *otherEntity, int otherLeft, int otherTop,2963int otherRight, int otherBottom)2964{2965scriptEng.checkResult = false;29662967Hitbox *thisHitbox = GetHitbox(thisEntity);2968Hitbox *otherHitbox = GetHitbox(otherEntity);29692970if (thisLeft == C_BOX)2971thisLeft = thisHitbox->left[0];29722973if (thisTop == C_BOX)2974thisTop = thisHitbox->top[0];29752976if (thisRight == C_BOX)2977thisRight = thisHitbox->right[0];29782979if (thisBottom == C_BOX)2980thisBottom = thisHitbox->bottom[0];29812982if (otherLeft == C_BOX)2983otherLeft = otherHitbox->left[0];29842985if (otherTop == C_BOX)2986otherTop = otherHitbox->top[0];29872988if (otherRight == C_BOX)2989otherRight = otherHitbox->right[0];29902991if (otherBottom == C_BOX)2992otherBottom = otherHitbox->bottom[0];29932994#if !RETRO_USE_ORIGINAL_CODE2995int thisHitboxID = 0;2996int otherHitboxID = 0;2997if (showHitboxes) {2998thisHitboxID = AddDebugHitbox(H_TYPE_PLAT, thisEntity, thisLeft, thisTop, thisRight, thisBottom);2999otherHitboxID = AddDebugHitbox(H_TYPE_PLAT, otherEntity, otherLeft, otherTop, otherRight, otherBottom);3000}3001#endif30023003thisLeft += thisEntity->xpos >> 16;3004thisTop += thisEntity->ypos >> 16;3005thisRight += thisEntity->xpos >> 16;3006thisBottom += thisEntity->ypos >> 16;30073008thisLeft <<= 16;3009thisTop <<= 16;3010thisRight <<= 16;3011thisBottom <<= 16;30123013sensors[0].collided = false;3014sensors[1].collided = false;3015sensors[2].collided = false;30163017int rx = otherEntity->xpos >> 16 << 16;3018int ry = otherEntity->ypos >> 16 << 16;30193020sensors[0].xpos = rx + (otherLeft << 16);3021sensors[1].xpos = rx;3022sensors[2].xpos = rx + (otherRight << 16);3023sensors[3].xpos = (rx + sensors[0].xpos) >> 1;3024sensors[4].xpos = (sensors[2].xpos + rx) >> 1;30253026sensors[0].ypos = (otherBottom << 16) + ry;30273028for (int i = 0; i < (RETRO_REV00 ? 3 : 5); ++i) {3029if (thisLeft < sensors[i].xpos && thisRight > sensors[i].xpos && thisTop - 1 <= sensors[0].ypos && thisBottom > sensors[0].ypos3030&& otherEntity->yvel >= 0) {3031sensors[i].collided = true;3032otherEntity->floorSensors[i] = true;3033}3034}30353036if (sensors[0].collided || sensors[1].collided || sensors[2].collided) {3037if (!otherEntity->gravity && (otherEntity->collisionMode == CMODE_RWALL || otherEntity->collisionMode == CMODE_LWALL)) {3038otherEntity->xvel = 0;3039otherEntity->speed = 0;3040}3041otherEntity->ypos = thisTop - (otherBottom << 16);3042otherEntity->gravity = 0;3043otherEntity->yvel = 0;3044otherEntity->angle = 0;3045otherEntity->rotation = 0;3046otherEntity->controlLock = 0;3047scriptEng.checkResult = true;3048}30493050#if !RETRO_USE_ORIGINAL_CODE3051if (showHitboxes) {3052if (thisHitboxID >= 0 && scriptEng.checkResult)3053debugHitboxList[thisHitboxID].collision |= 1 << 0;3054if (otherHitboxID >= 0 && scriptEng.checkResult)3055debugHitboxList[otherHitboxID].collision |= 1 << 3;3056}3057#endif3058}305930603061