Path: blob/master/RSDKv5/RSDK/Scene/Collision.cpp
1163 views
#include "RSDK/Core/RetroEngine.hpp"12using namespace RSDK;34#if RETRO_REV0U5#include "Legacy/CollisionLegacy.cpp"6#endif78#if RETRO_REV0U9// Not sure why its 8.0 in v5U, it's 4.0 in v5 and v4, the "fix" is here since 8.0 causes issues with chibi due to his lil hitbox10#if RETRO_USE_ORIGINAL_CODE11#define COLLISION_OFFSET (TO_FIXED(8))12#else13#define COLLISION_OFFSET (TO_FIXED(4))14#endif15#else16#define COLLISION_OFFSET (TO_FIXED(4))17#endif1819int32 RSDK::collisionTolerance = 0;20#if RETRO_REV0U21bool32 RSDK::useCollisionOffset = false;22#else23int32 RSDK::collisionOffset = 0;24#endif25int32 RSDK::collisionMaskAir = 0;2627Hitbox RSDK::collisionOuter = { 0, 0, 0, 0 };28Hitbox RSDK::collisionInner = { 0, 0, 0, 0 };2930Entity *RSDK::collisionEntity = NULL;3132CollisionSensor RSDK::sensors[6];3334#if RETRO_REV0U35#if RETRO_USE_ORIGINAL_CODE36// not sure why it's 24 here... it was 14 in all prev RSDK versions, maybe a mistake???37int32 RSDK::collisionMinimumDistance = TO_FIXED(24);38#else39int32 RSDK::collisionMinimumDistance = TO_FIXED(14);40#endif4142uint8 RSDK::lowCollisionTolerance = 8;43uint8 RSDK::highCollisionTolerance = 14;4445uint8 RSDK::floorAngleTolerance = 0x20;46uint8 RSDK::wallAngleTolerance = 0x20;47uint8 RSDK::roofAngleTolerance = 0x20;48#else49#define collisionMinimumDistance (14)5051#define lowCollisionTolerance (8)52#define highCollisionTolerance (15)5354#define floorAngleTolerance (0x20)55#define wallAngleTolerance (0x20)56#define roofAngleTolerance (0x20)57#endif5859#if !RETRO_USE_ORIGINAL_CODE60bool32 RSDK::showHitboxes = false;6162int32 RSDK::debugHitboxCount = 0;63DebugHitboxInfo RSDK::debugHitboxList[DEBUG_HITBOX_COUNT];6465int32 RSDK::AddDebugHitbox(uint8 type, uint8 dir, Entity *entity, Hitbox *hitbox)66{67int32 i = 0;68for (; i < debugHitboxCount; ++i) {69if (debugHitboxList[i].hitbox.left == hitbox->left && debugHitboxList[i].hitbox.top == hitbox->top70&& debugHitboxList[i].hitbox.right == hitbox->right && debugHitboxList[i].hitbox.bottom == hitbox->bottom71&& debugHitboxList[i].pos.x == entity->position.x && debugHitboxList[i].pos.y == entity->position.y72&& debugHitboxList[i].entity == entity) {73return i;74}75}7677if (i < DEBUG_HITBOX_COUNT) {78debugHitboxList[i].type = type;79debugHitboxList[i].entity = entity;80debugHitboxList[i].collision = 0;81debugHitboxList[i].hitbox.left = hitbox->left;82debugHitboxList[i].hitbox.top = hitbox->top;83debugHitboxList[i].hitbox.right = hitbox->right;84debugHitboxList[i].hitbox.bottom = hitbox->bottom;85debugHitboxList[i].pos.x = entity->position.x;86debugHitboxList[i].pos.y = entity->position.y;8788if ((dir & FLIP_X) == FLIP_X) {89int32 store = -debugHitboxList[i].hitbox.left;90debugHitboxList[i].hitbox.left = -debugHitboxList[i].hitbox.right;91debugHitboxList[i].hitbox.right = store;92}93if ((dir & FLIP_Y) == FLIP_Y) {94int32 store = -debugHitboxList[i].hitbox.top;95debugHitboxList[i].hitbox.top = -debugHitboxList[i].hitbox.bottom;96debugHitboxList[i].hitbox.bottom = store;97}9899int32 id = debugHitboxCount;100debugHitboxCount++;101return id;102}103104return -1;105}106#endif107108#if RETRO_REV0U || RETRO_USE_MOD_LOADER109void RSDK::CopyCollisionMask(uint16 dst, uint16 src, uint8 cPlane, uint8 cMode)110{111CollisionMask *srcMask = NULL;112CollisionMask *dstMask = NULL;113114switch (cMode) {115default: break;116117case CMODE_FLOOR:118srcMask = &collisionMasks[cPlane][src & 0x3FF];119dstMask = &collisionMasks[cPlane][dst & 0x3FF];120tileInfo[cPlane][dst & 0x3FF].floorAngle = tileInfo[cPlane][src & 0x3FF].floorAngle;121memcpy(dstMask->floorMasks, srcMask->floorMasks, sizeof(uint8) * TILE_SIZE);122123srcMask = &collisionMasks[cPlane][(src & 0x3FF) * FLIP_X];124dstMask = &collisionMasks[cPlane][(dst & 0x3FF) * FLIP_X];125tileInfo[cPlane][(dst & 0x3FF) * FLIP_X].floorAngle = tileInfo[cPlane][(src & 0x3FF) * FLIP_X].floorAngle;126memcpy(dstMask->floorMasks, srcMask->floorMasks, sizeof(uint8) * TILE_SIZE);127128srcMask = &collisionMasks[cPlane][(src & 0x3FF) * FLIP_Y];129dstMask = &collisionMasks[cPlane][(dst & 0x3FF) * FLIP_Y];130tileInfo[cPlane][(dst & 0x3FF) * FLIP_Y].floorAngle = tileInfo[cPlane][(src & 0x3FF) * FLIP_Y].floorAngle;131memcpy(dstMask->floorMasks, srcMask->floorMasks, sizeof(uint8) * TILE_SIZE);132133srcMask = &collisionMasks[cPlane][(src & 0x3FF) * FLIP_XY];134dstMask = &collisionMasks[cPlane][(dst & 0x3FF) * FLIP_XY];135tileInfo[cPlane][(dst & 0x3FF) * FLIP_XY].floorAngle = tileInfo[cPlane][(src & 0x3FF) * FLIP_XY].floorAngle;136memcpy(dstMask->floorMasks, srcMask->floorMasks, sizeof(uint8) * TILE_SIZE);137break;138139case CMODE_LWALL:140srcMask = &collisionMasks[cPlane][src & 0x3FF];141dstMask = &collisionMasks[cPlane][dst & 0x3FF];142tileInfo[cPlane][dst & 0x3FF].lWallAngle = tileInfo[cPlane][src & 0x3FF].lWallAngle;143memcpy(dstMask->lWallMasks, srcMask->lWallMasks, sizeof(uint8) * TILE_SIZE);144145srcMask = &collisionMasks[cPlane][(src & 0x3FF) * FLIP_X];146dstMask = &collisionMasks[cPlane][(dst & 0x3FF) * FLIP_X];147tileInfo[cPlane][(dst & 0x3FF) * FLIP_X].lWallAngle = tileInfo[cPlane][(src & 0x3FF) * FLIP_X].lWallAngle;148memcpy(dstMask->lWallMasks, srcMask->lWallMasks, sizeof(uint8) * TILE_SIZE);149150srcMask = &collisionMasks[cPlane][(src & 0x3FF) * FLIP_Y];151dstMask = &collisionMasks[cPlane][(dst & 0x3FF) * FLIP_Y];152tileInfo[cPlane][(dst & 0x3FF) * FLIP_Y].lWallAngle = tileInfo[cPlane][(src & 0x3FF) * FLIP_Y].lWallAngle;153memcpy(dstMask->lWallMasks, srcMask->lWallMasks, sizeof(uint8) * TILE_SIZE);154155srcMask = &collisionMasks[cPlane][(src & 0x3FF) * FLIP_XY];156dstMask = &collisionMasks[cPlane][(dst & 0x3FF) * FLIP_XY];157tileInfo[cPlane][(dst & 0x3FF) * FLIP_XY].lWallAngle = tileInfo[cPlane][(src & 0x3FF) * FLIP_XY].lWallAngle;158memcpy(dstMask->lWallMasks, srcMask->lWallMasks, sizeof(uint8) * TILE_SIZE);159break;160161case CMODE_ROOF:162srcMask = &collisionMasks[cPlane][src & 0x3FF];163dstMask = &collisionMasks[cPlane][dst & 0x3FF];164tileInfo[cPlane][dst & 0x3FF].roofAngle = tileInfo[cPlane][src & 0x3FF].roofAngle;165memcpy(dstMask->roofMasks, srcMask->roofMasks, sizeof(uint8) * TILE_SIZE);166167srcMask = &collisionMasks[cPlane][(src & 0x3FF) * FLIP_X];168dstMask = &collisionMasks[cPlane][(dst & 0x3FF) * FLIP_X];169tileInfo[cPlane][(dst & 0x3FF) * FLIP_X].roofAngle = tileInfo[cPlane][(src & 0x3FF) * FLIP_X].roofAngle;170memcpy(dstMask->roofMasks, srcMask->roofMasks, sizeof(uint8) * TILE_SIZE);171172srcMask = &collisionMasks[cPlane][(src & 0x3FF) * FLIP_Y];173dstMask = &collisionMasks[cPlane][(dst & 0x3FF) * FLIP_Y];174tileInfo[cPlane][(dst & 0x3FF) * FLIP_Y].roofAngle = tileInfo[cPlane][(src & 0x3FF) * FLIP_Y].roofAngle;175memcpy(dstMask->roofMasks, srcMask->roofMasks, sizeof(uint8) * TILE_SIZE);176177srcMask = &collisionMasks[cPlane][(src & 0x3FF) * FLIP_XY];178dstMask = &collisionMasks[cPlane][(dst & 0x3FF) * FLIP_XY];179tileInfo[cPlane][(dst & 0x3FF) * FLIP_XY].roofAngle = tileInfo[cPlane][(src & 0x3FF) * FLIP_XY].roofAngle;180memcpy(dstMask->roofMasks, srcMask->roofMasks, sizeof(uint8) * TILE_SIZE);181break;182183case CMODE_RWALL:184srcMask = &collisionMasks[cPlane][src & 0x3FF];185dstMask = &collisionMasks[cPlane][dst & 0x3FF];186tileInfo[cPlane][dst & 0x3FF].rWallAngle = tileInfo[cPlane][src & 0x3FF].rWallAngle;187memcpy(dstMask->rWallMasks, srcMask->rWallMasks, sizeof(uint8) * TILE_SIZE);188189srcMask = &collisionMasks[cPlane][(src & 0x3FF) * FLIP_X];190dstMask = &collisionMasks[cPlane][(dst & 0x3FF) * FLIP_X];191tileInfo[cPlane][(dst & 0x3FF) * FLIP_X].rWallAngle = tileInfo[cPlane][(src & 0x3FF) * FLIP_X].rWallAngle;192memcpy(dstMask->rWallMasks, srcMask->rWallMasks, sizeof(uint8) * TILE_SIZE);193194srcMask = &collisionMasks[cPlane][(src & 0x3FF) * FLIP_Y];195dstMask = &collisionMasks[cPlane][(dst & 0x3FF) * FLIP_Y];196tileInfo[cPlane][(dst & 0x3FF) * FLIP_Y].rWallAngle = tileInfo[cPlane][(src & 0x3FF) * FLIP_Y].rWallAngle;197memcpy(dstMask->rWallMasks, srcMask->rWallMasks, sizeof(uint8) * TILE_SIZE);198199srcMask = &collisionMasks[cPlane][(src & 0x3FF) * FLIP_XY];200dstMask = &collisionMasks[cPlane][(dst & 0x3FF) * FLIP_XY];201tileInfo[cPlane][(dst & 0x3FF) * FLIP_XY].rWallAngle = tileInfo[cPlane][(src & 0x3FF) * FLIP_XY].rWallAngle;202memcpy(dstMask->rWallMasks, srcMask->rWallMasks, sizeof(uint8) * TILE_SIZE);203break;204}205}206#endif207208bool32 RSDK::CheckObjectCollisionTouch(Entity *thisEntity, Hitbox *thisHitbox, Entity *otherEntity, Hitbox *otherHitbox)209{210int32 store = 0;211if (!thisEntity || !otherEntity || !thisHitbox || !otherHitbox)212return false;213214if ((thisEntity->direction & FLIP_X) == FLIP_X) {215store = -thisHitbox->left;216thisHitbox->left = -thisHitbox->right;217thisHitbox->right = store;218219store = -otherHitbox->left;220otherHitbox->left = -otherHitbox->right;221otherHitbox->right = store;222}223if ((thisEntity->direction & FLIP_Y) == FLIP_Y) {224store = -thisHitbox->top;225thisHitbox->top = -thisHitbox->bottom;226thisHitbox->bottom = store;227228store = -otherHitbox->top;229otherHitbox->top = -otherHitbox->bottom;230otherHitbox->bottom = store;231}232233int32 thisIX = FROM_FIXED(thisEntity->position.x);234int32 thisIY = FROM_FIXED(thisEntity->position.y);235int32 otherIX = FROM_FIXED(otherEntity->position.x);236int32 otherIY = FROM_FIXED(otherEntity->position.y);237238bool32 collided = thisIX + thisHitbox->left < otherIX + otherHitbox->right && thisIX + thisHitbox->right > otherIX + otherHitbox->left239&& thisIY + thisHitbox->top < otherIY + otherHitbox->bottom && thisIY + thisHitbox->bottom > otherIY + otherHitbox->top;240241if ((thisEntity->direction & FLIP_X) == FLIP_X) {242store = -thisHitbox->left;243thisHitbox->left = -thisHitbox->right;244thisHitbox->right = store;245246store = -otherHitbox->left;247otherHitbox->left = -otherHitbox->right;248otherHitbox->right = store;249}250if ((thisEntity->direction & FLIP_Y) == FLIP_Y) {251store = -thisHitbox->top;252thisHitbox->top = -thisHitbox->bottom;253thisHitbox->bottom = store;254255store = -otherHitbox->top;256otherHitbox->top = -otherHitbox->bottom;257otherHitbox->bottom = store;258}259260#if !RETRO_USE_ORIGINAL_CODE261if (showHitboxes) {262int32 thisHitboxID = RSDK::AddDebugHitbox(H_TYPE_TOUCH, thisEntity->direction, thisEntity, thisHitbox);263int32 otherHitboxID = RSDK::AddDebugHitbox(H_TYPE_TOUCH, otherEntity->direction, otherEntity, otherHitbox);264265if (thisHitboxID >= 0 && collided)266debugHitboxList[thisHitboxID].collision |= 1 << (collided - 1);267if (otherHitboxID >= 0 && collided)268debugHitboxList[otherHitboxID].collision |= 1 << (collided - 1);269}270#endif271272return collided;273}274275uint8 RSDK::CheckObjectCollisionBox(Entity *thisEntity, Hitbox *thisHitbox, Entity *otherEntity, Hitbox *otherHitbox, bool32 setValues)276{277if (!thisEntity || !otherEntity || !thisHitbox || !otherHitbox)278return C_NONE;279280int32 collisionSideH = C_NONE;281int32 collisionSideV = C_NONE;282283int32 collideX = otherEntity->position.x;284int32 collideY = otherEntity->position.y;285286if ((thisEntity->direction & FLIP_X) == FLIP_X) {287int32 store = -thisHitbox->left;288thisHitbox->left = -thisHitbox->right;289thisHitbox->right = store;290291store = -otherHitbox->left;292otherHitbox->left = -otherHitbox->right;293otherHitbox->right = store;294}295296if ((thisEntity->direction & FLIP_Y) == FLIP_Y) {297int32 store = -thisHitbox->top;298thisHitbox->top = -thisHitbox->bottom;299thisHitbox->bottom = store;300301store = -otherHitbox->top;302otherHitbox->top = -otherHitbox->bottom;303otherHitbox->bottom = store;304}305306int32 thisIX = FROM_FIXED(thisEntity->position.x);307int32 thisIY = FROM_FIXED(thisEntity->position.y);308int32 otherIX = FROM_FIXED(otherEntity->position.x);309int32 otherIY = FROM_FIXED(otherEntity->position.y);310311otherHitbox->top++;312otherHitbox->bottom--;313314if (otherIX <= (thisHitbox->right + thisHitbox->left + 2 * thisIX) >> 1) {315if (otherIX + otherHitbox->right >= thisIX + thisHitbox->left && thisIY + thisHitbox->top < otherIY + otherHitbox->bottom316&& thisIY + thisHitbox->bottom > otherIY + otherHitbox->top) {317collisionSideH = C_LEFT;318collideX = thisEntity->position.x + TO_FIXED(thisHitbox->left - otherHitbox->right);319}320}321else {322if (otherIX + otherHitbox->left < thisIX + thisHitbox->right && thisIY + thisHitbox->top < otherIY + otherHitbox->bottom323&& thisIY + thisHitbox->bottom > otherIY + otherHitbox->top) {324collisionSideH = C_RIGHT;325collideX = thisEntity->position.x + TO_FIXED(thisHitbox->right - otherHitbox->left);326}327}328329otherHitbox->left++;330otherHitbox->top--;331otherHitbox->right--;332otherHitbox->bottom++;333334if (otherIY < (thisHitbox->top + thisHitbox->bottom + 2 * thisIY) >> 1) {335if (otherIY + otherHitbox->bottom >= thisIY + thisHitbox->top && thisIX + thisHitbox->left < otherIX + otherHitbox->right336&& thisIX + thisHitbox->right > otherIX + otherHitbox->left) {337collisionSideV = C_TOP;338collideY = thisEntity->position.y + TO_FIXED(thisHitbox->top - otherHitbox->bottom);339}340}341else {342if (otherIY + otherHitbox->top < thisIY + thisHitbox->bottom && thisIX + thisHitbox->left < otherIX + otherHitbox->right) {343if (otherIX + otherHitbox->left < thisIX + thisHitbox->right) {344collisionSideV = C_BOTTOM;345collideY = thisEntity->position.y + TO_FIXED(thisHitbox->bottom - otherHitbox->top);346}347}348}349350otherHitbox->left--;351otherHitbox->right++;352353if ((thisEntity->direction & FLIP_X) == FLIP_X) {354int32 store = -thisHitbox->left;355thisHitbox->left = -thisHitbox->right;356thisHitbox->right = store;357358store = -otherHitbox->left;359otherHitbox->left = -otherHitbox->right;360otherHitbox->right = store;361}362363if ((thisEntity->direction & FLIP_Y) == FLIP_Y) {364int32 store = -thisHitbox->top;365thisHitbox->top = -thisHitbox->bottom;366thisHitbox->bottom = store;367368store = -otherHitbox->top;369otherHitbox->top = -otherHitbox->bottom;370otherHitbox->bottom = store;371}372373uint8 side = C_NONE;374375int32 cx = FROM_FIXED(collideX - otherEntity->position.x);376int32 cy = FROM_FIXED(collideY - otherEntity->position.y);377if ((cx * cx >= cy * cy && (collisionSideV || !collisionSideH)) || (!collisionSideH && collisionSideV)) {378side = collisionSideV;379}380else {381side = collisionSideH;382}383384if (setValues) {385int32 velX = 0;386switch (side) {387default:388case C_NONE: break;389390case C_TOP:391otherEntity->position.y = collideY;392393if (otherEntity->velocity.y > 0)394otherEntity->velocity.y = 0;395396#if RETRO_REV0U397if (otherEntity->tileCollisions != TILECOLLISION_UP) {398#endif399if (!otherEntity->onGround && otherEntity->velocity.y >= 0) {400otherEntity->groundVel = otherEntity->velocity.x;401otherEntity->angle = 0x00;402otherEntity->onGround = true;403}404#if RETRO_REV0U405}406#endif407break;408409case C_LEFT:410otherEntity->position.x = collideX;411412velX = otherEntity->velocity.x;413if (otherEntity->onGround) {414if (otherEntity->collisionMode == CMODE_ROOF)415velX = -otherEntity->groundVel;416else417velX = otherEntity->groundVel;418}419420if (velX > 0) {421otherEntity->velocity.x = 0;422otherEntity->groundVel = 0;423}424break;425426case C_RIGHT:427otherEntity->position.x = collideX;428429velX = otherEntity->velocity.x;430if (otherEntity->onGround) {431if (otherEntity->collisionMode == CMODE_ROOF)432velX = -otherEntity->groundVel;433else434velX = otherEntity->groundVel;435}436437if (velX < 0) {438otherEntity->velocity.x = 0;439otherEntity->groundVel = 0;440}441break;442443case C_BOTTOM:444otherEntity->position.y = collideY;445446if (otherEntity->velocity.y < 0)447otherEntity->velocity.y = 0;448449#if RETRO_REV0U450if (otherEntity->tileCollisions == TILECOLLISION_UP) {451if (!otherEntity->onGround && otherEntity->velocity.y <= 0) {452otherEntity->angle = 0x80;453otherEntity->groundVel = -otherEntity->velocity.x;454otherEntity->onGround = true;455}456}457#endif458break;459}460}461else {462#if !RETRO_REV0U463switch (side) {464default:465case C_NONE: break;466case C_TOP: otherEntity->position.y = collideY; break;467case C_LEFT: otherEntity->position.x = collideX; break;468case C_RIGHT: otherEntity->position.x = collideX; break;469case C_BOTTOM: otherEntity->position.y = collideY; break;470}471#endif472}473474#if !RETRO_USE_ORIGINAL_CODE475if (showHitboxes) {476int32 thisHitboxID = RSDK::AddDebugHitbox(H_TYPE_BOX, thisEntity->direction, thisEntity, thisHitbox);477int32 otherHitboxID = RSDK::AddDebugHitbox(H_TYPE_BOX, otherEntity->direction, otherEntity, otherHitbox);478479if (thisHitboxID >= 0 && side)480debugHitboxList[thisHitboxID].collision |= 1 << (side - 1);481if (otherHitboxID >= 0 && side)482debugHitboxList[otherHitboxID].collision |= 1 << (4 - side);483}484#endif485return side;486}487488bool32 RSDK::CheckObjectCollisionPlatform(Entity *thisEntity, Hitbox *thisHitbox, Entity *otherEntity, Hitbox *otherHitbox, bool32 setValues)489{490int32 store = 0;491bool32 collided = false;492493if (!thisEntity || !otherEntity || !thisHitbox || !otherHitbox)494return false;495496if ((thisEntity->direction & FLIP_X) == FLIP_X) {497store = -thisHitbox->left;498thisHitbox->left = -thisHitbox->right;499thisHitbox->right = store;500501store = -otherHitbox->left;502otherHitbox->left = -otherHitbox->right;503otherHitbox->right = store;504}505if ((thisEntity->direction & FLIP_Y) == FLIP_Y) {506store = -thisHitbox->top;507thisHitbox->top = -thisHitbox->bottom;508thisHitbox->bottom = store;509510store = -otherHitbox->top;511otherHitbox->top = -otherHitbox->bottom;512otherHitbox->bottom = store;513}514515int32 thisIX = FROM_FIXED(thisEntity->position.x);516int32 thisIY = FROM_FIXED(thisEntity->position.y);517int32 otherIX = FROM_FIXED(otherEntity->position.x);518int32 otherIY = FROM_FIXED(otherEntity->position.y);519520int32 otherMoveY = FROM_FIXED(otherEntity->position.y - otherEntity->velocity.y);521522#if RETRO_REV0U523if (otherEntity->tileCollisions == TILECOLLISION_UP) {524if (otherIY - otherHitbox->bottom >= thisIY + thisHitbox->top && otherMoveY - otherHitbox->bottom <= thisIY + thisHitbox->bottom525&& thisIX + thisHitbox->left < otherIX + otherHitbox->right && thisIX + thisHitbox->right > otherIX + otherHitbox->left526&& otherEntity->velocity.y <= 0) {527528otherEntity->position.y = thisEntity->position.y + TO_FIXED(thisHitbox->bottom + otherHitbox->bottom);529530if (setValues) {531otherEntity->velocity.y = 0;532533if (!otherEntity->onGround) {534otherEntity->groundVel = -otherEntity->velocity.x;535otherEntity->angle = 0x80;536otherEntity->onGround = true;537}538}539540collided = true;541}542}543else {544#endif545if (otherIY + otherHitbox->bottom >= thisIY + thisHitbox->top && otherMoveY + otherHitbox->bottom <= thisIY + thisHitbox->bottom546&& thisIX + thisHitbox->left < otherIX + otherHitbox->right && thisIX + thisHitbox->right > otherIX + otherHitbox->left547&& otherEntity->velocity.y >= 0) {548549otherEntity->position.y = thisEntity->position.y + TO_FIXED(thisHitbox->top - otherHitbox->bottom);550551if (setValues) {552otherEntity->velocity.y = 0;553554if (!otherEntity->onGround) {555otherEntity->groundVel = otherEntity->velocity.x;556otherEntity->angle = 0x00;557otherEntity->onGround = true;558}559}560561collided = true;562}563#if RETRO_REV0U564}565#endif566567if ((thisEntity->direction & FLIP_X) == FLIP_X) {568store = -thisHitbox->left;569thisHitbox->left = -thisHitbox->right;570thisHitbox->right = store;571572store = -otherHitbox->left;573otherHitbox->left = -otherHitbox->right;574otherHitbox->right = store;575}576577if ((thisEntity->direction & FLIP_Y) == FLIP_Y) {578store = -thisHitbox->top;579thisHitbox->top = -thisHitbox->bottom;580thisHitbox->bottom = store;581582store = -otherHitbox->top;583otherHitbox->top = -otherHitbox->bottom;584otherHitbox->bottom = store;585}586587#if !RETRO_USE_ORIGINAL_CODE588if (showHitboxes) {589int32 thisHitboxID = RSDK::AddDebugHitbox(H_TYPE_PLAT, thisEntity->direction, thisEntity, thisHitbox);590int32 otherHitboxID = RSDK::AddDebugHitbox(H_TYPE_PLAT, otherEntity->direction, otherEntity, otherHitbox);591#if RETRO_REV0U592if (otherEntity->tileCollisions == TILECOLLISION_UP) {593594if (thisHitboxID >= 0 && collided)595debugHitboxList[thisHitboxID].collision |= 1 << 3;596if (otherHitboxID >= 0 && collided)597debugHitboxList[otherHitboxID].collision |= 1 << 0;598}599else {600#endif601if (thisHitboxID >= 0 && collided)602debugHitboxList[thisHitboxID].collision |= 1 << 0;603if (otherHitboxID >= 0 && collided)604debugHitboxList[otherHitboxID].collision |= 1 << 3;605#if RETRO_REV0U606}607#endif608}609#endif610611return collided;612}613614bool32 RSDK::ObjectTileCollision(Entity *entity, uint16 cLayers, uint8 cMode, uint8 cPlane, int32 xOffset, int32 yOffset, bool32 setPos)615{616int32 layerID = 1;617bool32 collided = false;618int32 posX = FROM_FIXED(xOffset + entity->position.x);619int32 posY = FROM_FIXED(yOffset + entity->position.y);620621int32 solid = 0;622switch (cMode) {623default: return false;624625case CMODE_FLOOR:626solid = cPlane ? (1 << 14) : (1 << 12);627628for (int32 l = 0; l < LAYER_COUNT; ++l, layerID <<= 1) {629if (cLayers & layerID) {630TileLayer *layer = &tileLayers[l];631int32 colX = posX - layer->position.x;632int32 colY = posY - layer->position.y;633int32 cy = (colY & -TILE_SIZE) - TILE_SIZE;634if (colX >= 0 && colX < TILE_SIZE * layer->xsize) {635for (int32 i = 0; i < 3; ++i) {636if (cy >= 0 && cy < TILE_SIZE * layer->ysize) {637uint16 tile = layer->layout[(colX / TILE_SIZE) + ((cy / TILE_SIZE) << layer->widthShift)];638if (tile < 0xFFFF && tile & solid) {639int32 ty = cy + collisionMasks[cPlane][tile & 0xFFF].floorMasks[colX & 0xF];640if (colY >= ty && abs(colY - ty) <= 14) {641collided = true;642colY = ty;643i = 3;644}645}646}647cy += TILE_SIZE;648}649}650posX = layer->position.x + colX;651posY = layer->position.y + colY;652}653}654655if (setPos && collided)656entity->position.y = TO_FIXED(posY) - yOffset;657return collided;658659case CMODE_LWALL:660solid = cPlane ? (1 << 15) : (1 << 13);661662for (int32 l = 0; l < LAYER_COUNT; ++l, layerID <<= 1) {663if (cLayers & layerID) {664TileLayer *layer = &tileLayers[l];665int32 colX = posX - layer->position.x;666int32 colY = posY - layer->position.y;667int32 cx = (colX & -TILE_SIZE) - TILE_SIZE;668if (colY >= 0 && colY < TILE_SIZE * layer->ysize) {669for (int32 i = 0; i < 3; ++i) {670if (cx >= 0 && cx < TILE_SIZE * layer->xsize) {671uint16 tile = layer->layout[(cx >> 4) + ((colY / TILE_SIZE) << layer->widthShift)];672if (tile < 0xFFFF && tile & solid) {673int32 tx = cx + collisionMasks[cPlane][tile & 0xFFF].lWallMasks[colY & 0xF];674if (colX >= tx && abs(colX - tx) <= 14) {675collided = true;676colX = tx;677i = 3;678}679}680}681cx += TILE_SIZE;682}683}684posX = layer->position.x + colX;685posY = layer->position.y + colY;686}687}688689if (setPos && collided)690entity->position.x = TO_FIXED(posX) - xOffset;691return collided;692693case CMODE_ROOF:694solid = cPlane ? (1 << 15) : (1 << 13);695696for (int32 l = 0; l < LAYER_COUNT; ++l, layerID <<= 1) {697if (cLayers & layerID) {698TileLayer *layer = &tileLayers[l];699int32 colX = posX - layer->position.x;700int32 colY = posY - layer->position.y;701int32 cy = (colY & -TILE_SIZE) + TILE_SIZE;702if (colX >= 0 && colX < TILE_SIZE * layer->xsize) {703for (int32 i = 0; i < 3; ++i) {704if (cy >= 0 && cy < TILE_SIZE * layer->ysize) {705uint16 tile = layer->layout[(colX >> 4) + ((cy / TILE_SIZE) << layer->widthShift)];706if (tile < 0xFFFF && tile & solid) {707int32 ty = cy + collisionMasks[cPlane][tile & 0xFFF].roofMasks[colX & 0xF];708if (colY <= ty && abs(colY - ty) <= 14) {709collided = true;710colY = ty;711i = 3;712}713}714}715cy -= TILE_SIZE;716}717}718posX = layer->position.x + colX;719posY = layer->position.y + colY;720}721}722723if (setPos && collided)724entity->position.y = TO_FIXED(posY) - yOffset;725return collided;726727case CMODE_RWALL:728solid = cPlane ? (1 << 15) : (1 << 13);729730for (int32 l = 0; l < LAYER_COUNT; ++l, layerID <<= 1) {731if (cLayers & layerID) {732TileLayer *layer = &tileLayers[l];733int32 colX = posX - layer->position.x;734int32 colY = posY - layer->position.y;735int32 cx = (colX & -TILE_SIZE) + TILE_SIZE;736if (colY >= 0 && colY < TILE_SIZE * layer->ysize) {737for (int32 i = 0; i < 3; ++i) {738if (cx >= 0 && cx < TILE_SIZE * layer->xsize) {739uint16 tile = layer->layout[(cx >> 4) + ((colY / TILE_SIZE) << layer->widthShift)];740if (tile < 0xFFFF && tile & solid) {741int32 tx = cx + collisionMasks[cPlane][tile & 0xFFF].rWallMasks[colY & 0xF];742if (colX <= tx && abs(colX - tx) <= 14) {743collided = true;744colX = tx;745i = 3;746}747}748}749cx -= TILE_SIZE;750}751}752posX = layer->position.x + colX;753posY = layer->position.y + colY;754}755}756757if (setPos && collided)758entity->position.x = TO_FIXED(posX) - xOffset;759return collided;760}761}762bool32 RSDK::ObjectTileGrip(Entity *entity, uint16 cLayers, uint8 cMode, uint8 cPlane, int32 xOffset, int32 yOffset, int32 tolerance)763{764int32 layerID = 1;765bool32 collided = false;766int32 posX = FROM_FIXED(xOffset + entity->position.x);767int32 posY = FROM_FIXED(yOffset + entity->position.y);768769int32 solid = 0;770switch (cMode) {771default: return false;772773case CMODE_FLOOR:774solid = cPlane ? (1 << 14) : (1 << 12);775776for (int32 l = 0; l < LAYER_COUNT; ++l, layerID <<= 1) {777if (cLayers & layerID) {778TileLayer *layer = &tileLayers[l];779int32 colX = posX - layer->position.x;780int32 colY = posY - layer->position.y;781int32 cy = (colY & -TILE_SIZE) - TILE_SIZE;782if (colX >= 0 && colX < TILE_SIZE * layer->xsize) {783for (int32 i = 0; i < 3; ++i) {784if (cy >= 0 && cy < TILE_SIZE * layer->ysize) {785uint16 tile = layer->layout[(colX >> 4) + ((cy / TILE_SIZE) << layer->widthShift)];786if (tile < 0xFFFF && tile & solid) {787int32 mask = collisionMasks[cPlane][tile & 0xFFF].floorMasks[colX & 0xF];788int32 ty = cy + mask;789if (mask < 0xFF) {790if (abs(colY - ty) <= tolerance) {791collided = true;792colY = ty;793}794i = 3;795}796}797}798cy += TILE_SIZE;799}800}801posX = layer->position.x + colX;802posY = layer->position.y + colY;803}804}805806if (collided)807entity->position.y = TO_FIXED(posY) - yOffset;808return collided;809810case CMODE_LWALL:811solid = cPlane ? (1 << 15) : (1 << 13);812813for (int32 l = 0; l < LAYER_COUNT; ++l, layerID <<= 1) {814if (cLayers & layerID) {815TileLayer *layer = &tileLayers[l];816int32 colX = posX - layer->position.x;817int32 colY = posY - layer->position.y;818int32 cx = (colX & -TILE_SIZE) - TILE_SIZE;819if (colY >= 0 && colY < TILE_SIZE * layer->ysize) {820for (int32 i = 0; i < 3; ++i) {821if (cx >= 0 && cx < TILE_SIZE * layer->xsize) {822uint16 tile = layer->layout[(cx >> 4) + ((colY / TILE_SIZE) << layer->widthShift)];823if (tile < 0xFFFF && tile & solid) {824int32 mask = collisionMasks[cPlane][tile & 0xFFF].lWallMasks[colY & 0xF];825int32 tx = cx + mask;826if (mask < 0xFF) {827if (abs(colX - tx) <= tolerance) {828collided = true;829colX = tx;830}831i = 3;832}833}834}835cx += TILE_SIZE;836}837}838posX = layer->position.x + colX;839posY = layer->position.y + colY;840}841}842843if (collided)844entity->position.x = TO_FIXED(posX) - xOffset;845return collided;846847case CMODE_ROOF:848solid = cPlane ? (1 << 15) : (1 << 13);849850for (int32 l = 0; l < LAYER_COUNT; ++l, layerID <<= 1) {851if (cLayers & layerID) {852TileLayer *layer = &tileLayers[l];853int32 colX = posX - layer->position.x;854int32 colY = posY - layer->position.y;855int32 cy = (colY & -TILE_SIZE) + TILE_SIZE;856if (colX >= 0 && colX < TILE_SIZE * layer->xsize) {857for (int32 i = 0; i < 3; ++i) {858if (cy >= 0 && cy < TILE_SIZE * layer->ysize) {859uint16 tile = layer->layout[(colX >> 4) + ((cy / TILE_SIZE) << layer->widthShift)];860if (tile < 0xFFFF && tile & solid) {861int32 mask = collisionMasks[cPlane][tile & 0xFFF].roofMasks[colX & 0xF];862int32 ty = cy + mask;863if (mask < 0xFF) {864if (abs(colY - ty) <= tolerance) {865collided = true;866colY = ty;867}868i = 3;869}870}871}872cy -= TILE_SIZE;873}874}875posX = layer->position.x + colX;876posY = layer->position.y + colY;877}878}879880if (collided)881entity->position.y = TO_FIXED(posY) - yOffset;882return collided;883884case CMODE_RWALL:885solid = cPlane ? (1 << 15) : (1 << 13);886887for (int32 l = 0; l < LAYER_COUNT; ++l, layerID <<= 1) {888if (cLayers & layerID) {889TileLayer *layer = &tileLayers[l];890int32 colX = posX - layer->position.x;891int32 colY = posY - layer->position.y;892int32 cx = (colX & -TILE_SIZE) + TILE_SIZE;893if (colY >= 0 && colY < TILE_SIZE * layer->ysize) {894for (int32 i = 0; i < 3; ++i) {895if (cx >= 0 && cx < TILE_SIZE * layer->xsize) {896uint16 tile = layer->layout[(cx >> 4) + ((colY / TILE_SIZE) << layer->widthShift)];897if (tile < 0xFFFF && tile & solid) {898int32 mask = collisionMasks[cPlane][tile & 0xFFF].rWallMasks[colY & 0xF];899int32 tx = cx + mask;900if (mask < 0xFF) {901if (abs(colX - tx) <= tolerance) {902collided = true;903colX = tx;904}905i = 3;906}907}908}909cx -= TILE_SIZE;910}911}912posX = layer->position.x + colX;913posY = layer->position.y + colY;914}915}916917if (collided)918entity->position.x = TO_FIXED(posX) - xOffset;919return collided;920}921}922923void RSDK::ProcessObjectMovement(Entity *entity, Hitbox *outerBox, Hitbox *innerBox)924{925if (entity && outerBox && innerBox) {926if (entity->tileCollisions) {927entity->angle &= 0xFF;928929collisionTolerance = highCollisionTolerance;930if (abs(entity->groundVel) < TO_FIXED(6) && entity->angle == 0)931collisionTolerance = lowCollisionTolerance;932933collisionOuter.left = outerBox->left;934collisionOuter.top = outerBox->top;935collisionOuter.right = outerBox->right;936collisionOuter.bottom = outerBox->bottom;937938collisionInner.left = innerBox->left;939collisionInner.top = innerBox->top;940collisionInner.right = innerBox->right;941collisionInner.bottom = innerBox->bottom;942943collisionEntity = entity;944945#if RETRO_REV0U946collisionMaskAir = collisionOuter.bottom >= 14 ? 19 : 17;947948if (entity->onGround) {949// true = normal, false = flipped950if (entity->tileCollisions == TILECOLLISION_DOWN)951useCollisionOffset = entity->angle == 0x00;952else953useCollisionOffset = entity->angle == 0x80;954955#if !RETRO_USE_ORIGINAL_CODE956// fixes some clipping issues as chibi sonic (& using small hitboxes)957// shouldn't effect anything else :)958if (collisionOuter.bottom < 14)959useCollisionOffset = false;960#endif961962ProcessPathGrip();963}964else {965useCollisionOffset = false;966// true = normal, false = flipped967if (entity->tileCollisions == TILECOLLISION_DOWN)968ProcessAirCollision_Down();969else970ProcessAirCollision_Up();971}972#else973if (collisionOuter.bottom >= 14) {974collisionOffset = COLLISION_OFFSET;975collisionMaskAir = 19;976}977else {978collisionOffset = 0;979collisionTolerance = 15;980collisionMaskAir = 17;981}982983if (entity->onGround)984ProcessPathGrip();985else986ProcessAirCollision_Down();987#endif988989if (entity->onGround) {990entity->velocity.x = entity->groundVel * cos256LookupTable[entity->angle & 0xFF] >> 8;991entity->velocity.y = entity->groundVel * sin256LookupTable[entity->angle & 0xFF] >> 8;992}993else {994entity->groundVel = entity->velocity.x;995}996}997else {998entity->position.x += entity->velocity.x;999entity->position.y += entity->velocity.y;1000}1001}1002}10031004void RSDK::ProcessAirCollision_Down()1005{1006uint8 movingDown = 0;1007uint8 movingUp = 0;1008uint8 movingLeft = 0;1009uint8 movingRight = 0;10101011int32 offset = 0;1012#if RETRO_REV0U1013offset = useCollisionOffset ? COLLISION_OFFSET : 0;1014#else1015offset = collisionOffset;1016#endif10171018if (collisionEntity->velocity.x >= 0) {1019movingRight = 1;1020sensors[0].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.right);1021sensors[0].position.y = collisionEntity->position.y + offset;1022}10231024if (collisionEntity->velocity.x <= 0) {1025movingLeft = 1;1026sensors[1].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.left) - TO_FIXED(1);1027sensors[1].position.y = collisionEntity->position.y + offset;1028}10291030// Bug Details:1031// using collision outer here results in a few slopes having some wonky collision if you jump at the on the wrong angles1032// v4 and prior uses inner box here instead, which works fine as far as I can tell...1033// Fix (I think, it may break something else?):1034// uncomment the 2 lines below and remove the two below that to get v4-like behaviour1035// sensors[2].pos.x = collisionEntity->position.x + TO_FIXED(collisionInner.left);1036// sensors[3].pos.x = collisionEntity->position.x + TO_FIXED(collisionInner.right);1037sensors[2].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.left) + TO_FIXED(1);1038sensors[3].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.right) - TO_FIXED(2);1039sensors[4].position.x = sensors[2].position.x;1040sensors[5].position.x = sensors[3].position.x;10411042sensors[0].collided = false;1043sensors[1].collided = false;1044sensors[2].collided = false;1045sensors[3].collided = false;1046sensors[4].collided = false;1047sensors[5].collided = false;1048if (collisionEntity->velocity.y >= 0) {1049movingDown = 1;1050sensors[2].position.y = collisionEntity->position.y + TO_FIXED(collisionOuter.bottom);1051sensors[3].position.y = collisionEntity->position.y + TO_FIXED(collisionOuter.bottom);1052}10531054if (abs(collisionEntity->velocity.x) > TO_FIXED(1) || collisionEntity->velocity.y < 0) {1055movingUp = 1;1056sensors[4].position.y = collisionEntity->position.y + TO_FIXED(collisionOuter.top) - TO_FIXED(1);1057sensors[5].position.y = collisionEntity->position.y + TO_FIXED(collisionOuter.top) - TO_FIXED(1);1058}10591060int32 cnt = (abs(collisionEntity->velocity.x) <= abs(collisionEntity->velocity.y) ? ((abs(collisionEntity->velocity.y) >> collisionMaskAir) + 1)1061: (abs(collisionEntity->velocity.x) >> collisionMaskAir) + 1);1062int32 velX = collisionEntity->velocity.x / cnt;1063int32 velY = collisionEntity->velocity.y / cnt;1064int32 velX2 = collisionEntity->velocity.x - velX * (cnt - 1);1065int32 velY2 = collisionEntity->velocity.y - velY * (cnt - 1);1066while (cnt > 0) {1067if (cnt < 2) {1068velX = velX2;1069velY = velY2;1070}1071cnt--;10721073if (movingRight == 1) {1074sensors[0].position.x += velX;1075sensors[0].position.y += velY;1076LWallCollision(&sensors[0]);10771078if (sensors[0].collided) {1079movingRight = 2;1080}1081#if !RETRO_REV0U1082else if (collisionEntity->velocity.x < TO_FIXED(2) && collisionOffset > 0) {1083sensors[0].position.y -= collisionOffset << 1;1084LWallCollision(&sensors[0]);10851086if (sensors[0].collided)1087movingRight = 2;1088sensors[0].position.y += collisionOffset << 1;1089}1090#endif1091}10921093if (movingLeft == 1) {1094sensors[1].position.x += velX;1095sensors[1].position.y += velY;1096RWallCollision(&sensors[1]);10971098if (sensors[1].collided) {1099movingLeft = 2;1100}1101#if !RETRO_REV0U1102else if (collisionEntity->velocity.x > -TO_FIXED(2) && collisionOffset > 0) {1103sensors[1].position.y -= collisionOffset << 1;1104RWallCollision(&sensors[1]);11051106if (sensors[1].collided)1107movingLeft = 2;1108sensors[1].position.y += collisionOffset << 1;1109}1110#endif1111}11121113if (movingRight == 2) {1114collisionEntity->velocity.x = 0;1115collisionEntity->groundVel = 0;1116collisionEntity->position.x = sensors[0].position.x - TO_FIXED(collisionOuter.right);11171118sensors[2].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.left) + TO_FIXED(1);1119sensors[3].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.right) - TO_FIXED(2);1120sensors[4].position.x = sensors[2].position.x;1121sensors[5].position.x = sensors[3].position.x;11221123velX = 0;1124velX2 = 0;1125movingRight = 3;1126}11271128if (movingLeft == 2) {1129collisionEntity->velocity.x = 0;1130collisionEntity->groundVel = 0;1131collisionEntity->position.x = sensors[1].position.x - TO_FIXED(collisionOuter.left) + TO_FIXED(1);11321133sensors[2].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.left) + TO_FIXED(1);1134sensors[3].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.right) - TO_FIXED(2);1135sensors[4].position.x = sensors[2].position.x;1136sensors[5].position.x = sensors[3].position.x;11371138velX = 0;1139velX2 = 0;1140movingLeft = 3;1141}11421143if (movingDown == 1) {1144for (int32 i = 2; i < 4; i++) {1145if (!sensors[i].collided) {1146sensors[i].position.x += velX;1147sensors[i].position.y += velY;1148FloorCollision(&sensors[i]);1149}1150}11511152if (sensors[2].collided || sensors[3].collided) {1153movingDown = 2;1154cnt = 0;1155}1156}11571158if (movingUp == 1) {1159for (int32 i = 4; i < 6; i++) {1160if (!sensors[i].collided) {1161sensors[i].position.x += velX;1162sensors[i].position.y += velY;1163RoofCollision(&sensors[i]);1164}1165}11661167if (sensors[4].collided || sensors[5].collided) {1168movingUp = 2;1169cnt = 0;1170}1171}1172}11731174if (movingRight < 2 && movingLeft < 2)1175collisionEntity->position.x += collisionEntity->velocity.x;11761177if (movingUp < 2 && movingDown < 2) {1178collisionEntity->position.y += collisionEntity->velocity.y;1179return;1180}11811182if (movingDown == 2) {1183collisionEntity->onGround = true;11841185if (sensors[2].collided && sensors[3].collided) {1186if (sensors[2].position.y >= sensors[3].position.y) {1187collisionEntity->position.y = sensors[3].position.y - TO_FIXED(collisionOuter.bottom);1188collisionEntity->angle = sensors[3].angle;1189}1190else {1191collisionEntity->position.y = sensors[2].position.y - TO_FIXED(collisionOuter.bottom);1192collisionEntity->angle = sensors[2].angle;1193}1194}1195else if (sensors[2].collided) {1196collisionEntity->position.y = sensors[2].position.y - TO_FIXED(collisionOuter.bottom);1197collisionEntity->angle = sensors[2].angle;1198}1199else if (sensors[3].collided) {1200collisionEntity->position.y = sensors[3].position.y - TO_FIXED(collisionOuter.bottom);1201collisionEntity->angle = sensors[3].angle;1202}12031204if (collisionEntity->angle > 0xA0 && collisionEntity->angle < 0xDE && collisionEntity->collisionMode != CMODE_LWALL) {1205collisionEntity->collisionMode = CMODE_LWALL;1206collisionEntity->position.x -= TO_FIXED(4);1207}12081209if (collisionEntity->angle > 0x22 && collisionEntity->angle < 0x60 && collisionEntity->collisionMode != CMODE_RWALL) {1210collisionEntity->collisionMode = CMODE_RWALL;1211collisionEntity->position.x += TO_FIXED(4);1212}12131214int32 speed = 0;1215if (collisionEntity->angle < 0x80) {1216if (collisionEntity->angle < 0x10) {1217speed = collisionEntity->velocity.x;1218}1219else if (collisionEntity->angle >= 0x20) {1220speed = (abs(collisionEntity->velocity.x) <= abs(collisionEntity->velocity.y) ? collisionEntity->velocity.y1221: collisionEntity->velocity.x);1222}1223else {1224speed = (abs(collisionEntity->velocity.x) <= abs(collisionEntity->velocity.y >> 1) ? (collisionEntity->velocity.y >> 1)1225: collisionEntity->velocity.x);1226}1227}1228else if (collisionEntity->angle > 0xF0) {1229speed = collisionEntity->velocity.x;1230}1231else if (collisionEntity->angle <= 0xE0) {1232speed =1233(abs(collisionEntity->velocity.x) <= abs(collisionEntity->velocity.y) ? -collisionEntity->velocity.y : collisionEntity->velocity.x);1234}1235else {1236speed = (abs(collisionEntity->velocity.x) <= abs(collisionEntity->velocity.y >> 1) ? -(collisionEntity->velocity.y >> 1)1237: collisionEntity->velocity.x);1238}12391240if (speed < -TO_FIXED(24))1241speed = -TO_FIXED(24);12421243if (speed > TO_FIXED(24))1244speed = TO_FIXED(24);12451246collisionEntity->groundVel = speed;1247collisionEntity->velocity.x = speed;1248collisionEntity->velocity.y = 0;1249}12501251if (movingUp == 2) {1252int32 sensorAngle = 0;12531254if (sensors[4].collided && sensors[5].collided) {1255if (sensors[4].position.y <= sensors[5].position.y) {1256collisionEntity->position.y = sensors[5].position.y - TO_FIXED(collisionOuter.top) + TO_FIXED(1);1257sensorAngle = sensors[5].angle;1258}1259else {1260collisionEntity->position.y = sensors[4].position.y - TO_FIXED(collisionOuter.top) + TO_FIXED(1);1261sensorAngle = sensors[4].angle;1262}1263}1264else if (sensors[4].collided) {1265collisionEntity->position.y = sensors[4].position.y - TO_FIXED(collisionOuter.top) + TO_FIXED(1);1266sensorAngle = sensors[4].angle;1267}1268else if (sensors[5].collided) {1269collisionEntity->position.y = sensors[5].position.y - TO_FIXED(collisionOuter.top) + TO_FIXED(1);1270sensorAngle = sensors[5].angle;1271}1272sensorAngle &= 0xFF;12731274if (sensorAngle < 0x62) {1275if (collisionEntity->velocity.y < -abs(collisionEntity->velocity.x)) {1276collisionEntity->onGround = true;1277collisionEntity->angle = sensorAngle;1278collisionEntity->collisionMode = CMODE_RWALL;1279collisionEntity->position.x += TO_FIXED(4);1280collisionEntity->position.y -= TO_FIXED(2);12811282collisionEntity->groundVel = collisionEntity->angle <= 0x60 ? collisionEntity->velocity.y : (collisionEntity->velocity.y >> 1);1283}1284}12851286if (sensorAngle > 0x9E && sensorAngle < 0xC1) {1287if (collisionEntity->velocity.y < -abs(collisionEntity->velocity.x)) {1288collisionEntity->onGround = true;1289collisionEntity->angle = sensorAngle;1290collisionEntity->collisionMode = CMODE_LWALL;1291collisionEntity->position.x -= TO_FIXED(4);1292collisionEntity->position.y -= TO_FIXED(2);12931294collisionEntity->groundVel = collisionEntity->angle >= 0xA0 ? -collisionEntity->velocity.y : -(collisionEntity->velocity.y >> 1);1295}1296}12971298if (collisionEntity->velocity.y < 0)1299collisionEntity->velocity.y = 0;1300}1301}1302#if RETRO_REV0U1303void RSDK::ProcessAirCollision_Up()1304{1305uint8 movingDown = 0;1306uint8 movingUp = 0;1307uint8 movingLeft = 0;1308uint8 movingRight = 0;13091310int32 offset = useCollisionOffset ? -COLLISION_OFFSET : 0;13111312if (collisionEntity->velocity.x >= 0) {1313movingRight = 1;1314sensors[0].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.right);1315sensors[0].position.y = collisionEntity->position.y + offset;1316}13171318if (collisionEntity->velocity.x <= 0) {1319movingLeft = 1;1320sensors[1].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.left) - TO_FIXED(1);1321sensors[1].position.y = collisionEntity->position.y + offset;1322}13231324// Bug Details:1325// using collision outer here results in a few slopes having some wonky collision if you jump at the on the wrong angles1326// v4 and prior uses inner box here instead, which works fine as far as I can tell...1327// Fix (I think, it may break something else?):1328// uncomment the 2 lines below and remove the two below that to get v4-like behaviour1329// sensors[2].pos.x = collisionEntity->position.x + TO_FIXED(collisionInner.left);1330// sensors[3].pos.x = collisionEntity->position.x + TO_FIXED(collisionInner.right);1331sensors[2].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.left) + TO_FIXED(1);1332sensors[3].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.right) - TO_FIXED(2);1333sensors[4].position.x = sensors[2].position.x;1334sensors[5].position.x = sensors[3].position.x;13351336sensors[0].collided = false;1337sensors[1].collided = false;1338sensors[2].collided = false;1339sensors[3].collided = false;1340sensors[4].collided = false;1341sensors[5].collided = false;1342if (collisionEntity->velocity.y <= 0) {1343movingDown = 1;1344sensors[4].position.y = collisionEntity->position.y + TO_FIXED(collisionOuter.top) - TO_FIXED(1);1345sensors[5].position.y = collisionEntity->position.y + TO_FIXED(collisionOuter.top) - TO_FIXED(1);1346}13471348if (abs(collisionEntity->velocity.x) > TO_FIXED(1) || collisionEntity->velocity.y > 0) {1349movingUp = 1;1350sensors[2].position.y = collisionEntity->position.y + TO_FIXED(collisionOuter.bottom);1351sensors[3].position.y = collisionEntity->position.y + TO_FIXED(collisionOuter.bottom);1352}13531354int32 cnt = (abs(collisionEntity->velocity.x) <= abs(collisionEntity->velocity.y) ? ((abs(collisionEntity->velocity.y) >> collisionMaskAir) + 1)1355: (abs(collisionEntity->velocity.x) >> collisionMaskAir) + 1);1356int32 velX = collisionEntity->velocity.x / cnt;1357int32 velY = collisionEntity->velocity.y / cnt;1358int32 velX2 = collisionEntity->velocity.x - velX * (cnt - 1);1359int32 velY2 = collisionEntity->velocity.y - velY * (cnt - 1);1360while (cnt > 0) {1361if (cnt < 2) {1362velX = velX2;1363velY = velY2;1364}1365cnt--;13661367if (movingRight == 1) {1368sensors[0].position.x += velX;1369sensors[0].position.y += velY;1370LWallCollision(&sensors[0]);13711372if (sensors[0].collided) {1373movingRight = 2;1374}1375#if !RETRO_REV0U1376else if (collisionEntity->velocity.x < TO_FIXED(2) && collisionOffset > 0) {1377sensors[0].position.y -= collisionOffset << 1;1378LWallCollision(&sensors[0]);13791380if (sensors[0].collided)1381movingRight = 2;1382sensors[0].position.y += collisionOffset << 1;1383}1384#endif1385}13861387if (movingLeft == 1) {1388sensors[1].position.x += velX;1389sensors[1].position.y += velY;1390RWallCollision(&sensors[1]);13911392if (sensors[1].collided) {1393movingLeft = 2;1394}1395#if !RETRO_REV0U1396else if (collisionEntity->velocity.x > -TO_FIXED(2) && collisionOffset > 0) {1397sensors[1].position.y -= collisionOffset << 1;1398RWallCollision(&sensors[1]);13991400if (sensors[1].collided)1401movingLeft = 2;1402sensors[1].position.y += collisionOffset << 1;1403}1404#endif1405}14061407if (movingRight == 2) {1408collisionEntity->velocity.x = 0;1409collisionEntity->groundVel = 0;1410collisionEntity->position.x = sensors[0].position.x - TO_FIXED(collisionOuter.right);14111412sensors[2].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.left) + TO_FIXED(1);1413sensors[3].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.right) - TO_FIXED(2);1414sensors[4].position.x = sensors[2].position.x;1415sensors[5].position.x = sensors[3].position.x;14161417velX = 0;1418velX2 = 0;1419movingRight = 3;1420}14211422if (movingLeft == 2) {1423collisionEntity->velocity.x = 0;1424collisionEntity->groundVel = 0;1425collisionEntity->position.x = sensors[1].position.x - TO_FIXED(collisionOuter.left) + TO_FIXED(1);14261427sensors[2].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.left) + TO_FIXED(1);1428sensors[3].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.right) - TO_FIXED(2);1429sensors[4].position.x = sensors[2].position.x;1430sensors[5].position.x = sensors[3].position.x;14311432velX = 0;1433velX2 = 0;1434movingLeft = 3;1435}14361437if (movingUp == 1) {1438for (int32 i = 2; i < 4; i++) {1439if (!sensors[i].collided) {1440sensors[i].position.x += velX;1441sensors[i].position.y += velY;1442FloorCollision(&sensors[i]);1443}1444}14451446if (sensors[2].collided || sensors[3].collided) {1447movingUp = 2;1448cnt = 0;1449}1450}14511452if (movingDown == 1) {1453for (int32 i = 4; i < 6; i++) {1454if (!sensors[i].collided) {1455sensors[i].position.x += velX;1456sensors[i].position.y += velY;1457RoofCollision(&sensors[i]);1458}1459}14601461if (sensors[4].collided || sensors[5].collided) {1462movingDown = 2;1463cnt = 0;1464}1465}1466}14671468if (movingRight < 2 && movingLeft < 2)1469collisionEntity->position.x += collisionEntity->velocity.x;14701471if (movingUp < 2 && movingDown < 2) {1472collisionEntity->position.y += collisionEntity->velocity.y;1473return;1474}14751476if (movingDown == 2) {1477collisionEntity->onGround = true;14781479if (sensors[4].collided && sensors[5].collided) {1480if (sensors[4].position.y <= sensors[5].position.y) {1481collisionEntity->position.y = sensors[5].position.y - TO_FIXED(collisionOuter.top) + TO_FIXED(1);1482collisionEntity->angle = sensors[5].angle;1483}1484else {1485collisionEntity->position.y = sensors[4].position.y - TO_FIXED(collisionOuter.top) + TO_FIXED(1);1486collisionEntity->angle = sensors[4].angle;1487}1488}1489else if (sensors[4].collided) {1490collisionEntity->position.y = sensors[4].position.y - TO_FIXED(collisionOuter.top) + TO_FIXED(1);1491collisionEntity->angle = sensors[4].angle;1492}1493else if (sensors[5].collided) {1494collisionEntity->position.y = sensors[5].position.y - TO_FIXED(collisionOuter.top) + TO_FIXED(1);1495collisionEntity->angle = sensors[5].angle;1496}14971498if (collisionEntity->angle > 0xA2 && collisionEntity->angle < 0xE0 && collisionEntity->collisionMode != CMODE_LWALL) {1499collisionEntity->collisionMode = CMODE_LWALL;1500collisionEntity->position.x -= TO_FIXED(4);1501}15021503if (collisionEntity->angle > 0x20 && collisionEntity->angle < 0x5E && collisionEntity->collisionMode != CMODE_RWALL) {1504collisionEntity->collisionMode = CMODE_RWALL;1505collisionEntity->position.x += TO_FIXED(4);1506}15071508int32 speed = 0;1509if (collisionEntity->angle >= 0x80) {1510if (collisionEntity->angle < 0x90) {1511speed = -collisionEntity->velocity.x;1512}1513else if (collisionEntity->angle >= 0xA0) {1514speed = (abs(collisionEntity->velocity.x) <= abs(collisionEntity->velocity.y) ? collisionEntity->velocity.y1515: collisionEntity->velocity.x);1516}1517else {1518speed = (abs(collisionEntity->velocity.x) <= abs(collisionEntity->velocity.y >> 1) ? (collisionEntity->velocity.y >> 1)1519: collisionEntity->velocity.x);1520}1521}1522else if (collisionEntity->angle <= 0x70) {1523speed = collisionEntity->velocity.x;1524}1525else if (collisionEntity->angle <= 0x60) {1526speed =1527(abs(collisionEntity->velocity.x) <= abs(collisionEntity->velocity.y) ? -collisionEntity->velocity.y : collisionEntity->velocity.x);1528}1529else {1530speed = (abs(collisionEntity->velocity.x) <= abs(collisionEntity->velocity.y >> 1) ? -(collisionEntity->velocity.y >> 1)1531: collisionEntity->velocity.x);1532}15331534if (speed < -TO_FIXED(24))1535speed = -TO_FIXED(24);15361537if (speed > TO_FIXED(24))1538speed = TO_FIXED(24);15391540collisionEntity->groundVel = speed;1541collisionEntity->velocity.x = speed;1542collisionEntity->velocity.y = 0;1543}15441545if (movingUp == 2) {1546int32 sensorAngle = 0;15471548if (sensors[2].collided && sensors[3].collided) {1549if (sensors[2].position.y >= sensors[3].position.y) {1550collisionEntity->position.y = sensors[3].position.y - TO_FIXED(collisionOuter.bottom);1551sensorAngle = sensors[3].angle;1552}1553else {1554collisionEntity->position.y = sensors[2].position.y - TO_FIXED(collisionOuter.bottom);1555sensorAngle = sensors[2].angle;1556}1557}1558else if (sensors[2].collided) {1559collisionEntity->position.y = sensors[2].position.y - TO_FIXED(collisionOuter.bottom);1560sensorAngle = sensors[2].angle;1561}1562else if (sensors[3].collided) {1563collisionEntity->position.y = sensors[3].position.y - TO_FIXED(collisionOuter.bottom);1564sensorAngle = sensors[3].angle;1565}1566sensorAngle &= 0xFF;15671568if (sensorAngle >= 0x21 && sensorAngle <= 0x40) {1569if (collisionEntity->velocity.y > -abs(collisionEntity->velocity.x)) {1570collisionEntity->onGround = true;1571collisionEntity->angle = sensorAngle;1572collisionEntity->collisionMode = CMODE_RWALL;1573collisionEntity->position.x += TO_FIXED(4);1574collisionEntity->position.y -= TO_FIXED(2);15751576collisionEntity->groundVel = collisionEntity->angle <= 0x20 ? collisionEntity->velocity.y : (collisionEntity->velocity.y >> 1);1577}1578}15791580if (sensorAngle >= 0xC0 && sensorAngle <= 0xE2) {1581if (collisionEntity->velocity.y > -abs(collisionEntity->velocity.x)) {1582collisionEntity->onGround = true;1583collisionEntity->angle = sensorAngle;1584collisionEntity->collisionMode = CMODE_LWALL;1585collisionEntity->position.x -= TO_FIXED(4);1586collisionEntity->position.y -= TO_FIXED(2);15871588collisionEntity->groundVel = collisionEntity->angle <= 0xE0 ? -collisionEntity->velocity.y : -(collisionEntity->velocity.y >> 1);1589}1590}15911592if (collisionEntity->velocity.y > 0)1593collisionEntity->velocity.y = 0;1594}1595}1596#endif1597void RSDK::ProcessPathGrip()1598{1599int32 xVel = 0;1600int32 yVel = 0;16011602sensors[4].position.x = collisionEntity->position.x;1603sensors[4].position.y = collisionEntity->position.y;1604for (int32 i = 0; i < 6; ++i) {1605sensors[i].angle = collisionEntity->angle;1606sensors[i].collided = false;1607}1608SetPathGripSensors(sensors);16091610int32 absSpeed = abs(collisionEntity->groundVel);1611int32 checkDist = absSpeed >> 18;1612absSpeed &= 0x3FFFF;1613while (checkDist > -1) {1614if (checkDist >= 1) {1615xVel = cos256LookupTable[collisionEntity->angle] << 10;1616yVel = sin256LookupTable[collisionEntity->angle] << 10;1617checkDist--;1618}1619else {1620xVel = absSpeed * cos256LookupTable[collisionEntity->angle] >> 8;1621yVel = absSpeed * sin256LookupTable[collisionEntity->angle] >> 8;1622checkDist = -1;1623}16241625if (collisionEntity->groundVel < 0) {1626xVel = -xVel;1627yVel = -yVel;1628}16291630sensors[0].collided = false;1631sensors[1].collided = false;1632sensors[2].collided = false;1633sensors[4].position.x += xVel;1634sensors[4].position.y += yVel;1635int32 tileDistance = -1;16361637switch (collisionEntity->collisionMode) {1638case CMODE_FLOOR: {1639sensors[3].position.x += xVel;1640sensors[3].position.y += yVel;16411642if (collisionEntity->groundVel > 0) {1643LWallCollision(&sensors[3]);1644#if RETRO_REV0U1645if (sensors[3].collided)1646sensors[2].position.x = sensors[3].position.x - TO_FIXED(2);1647#endif1648}16491650if (collisionEntity->groundVel < 0) {1651RWallCollision(&sensors[3]);1652#if RETRO_REV0U1653if (sensors[3].collided)1654sensors[0].position.x = sensors[3].position.x + TO_FIXED(2);1655#endif1656}16571658if (sensors[3].collided) {1659xVel = 0;1660checkDist = -1;1661}16621663for (int32 i = 0; i < 3; i++) {1664sensors[i].position.x += xVel;1665sensors[i].position.y += yVel;1666FindFloorPosition(&sensors[i]);1667}16681669tileDistance = -1;1670for (int32 i = 0; i < 3; i++) {1671if (tileDistance > -1) {1672if (sensors[i].collided) {1673if (sensors[i].position.y < sensors[tileDistance].position.y)1674tileDistance = i;16751676if (sensors[i].position.y == sensors[tileDistance].position.y && (sensors[i].angle < 0x08 || sensors[i].angle > 0xF8))1677tileDistance = i;1678}1679}1680else if (sensors[i].collided)1681tileDistance = i;1682}16831684if (tileDistance <= -1) {1685checkDist = -1;1686}1687else {1688sensors[0].position.y = sensors[tileDistance].position.y;1689sensors[0].angle = sensors[tileDistance].angle;16901691sensors[1].position.y = sensors[0].position.y;1692sensors[1].angle = sensors[0].angle;16931694sensors[2].position.y = sensors[0].position.y;1695sensors[2].angle = sensors[0].angle;16961697sensors[4].position.x = sensors[1].position.x;1698sensors[4].position.y = sensors[0].position.y - TO_FIXED(collisionOuter.bottom);1699}17001701if (sensors[0].angle < 0xDE && sensors[0].angle > 0x80)1702collisionEntity->collisionMode = CMODE_LWALL;1703if (sensors[0].angle > 0x22 && sensors[0].angle < 0x80)1704collisionEntity->collisionMode = CMODE_RWALL;1705break;1706}17071708case CMODE_LWALL: {1709sensors[3].position.x += xVel;1710sensors[3].position.y += yVel;17111712if (collisionEntity->groundVel > 0)1713RoofCollision(&sensors[3]);17141715if (collisionEntity->groundVel < 0)1716FloorCollision(&sensors[3]);17171718if (sensors[3].collided) {1719yVel = 0;1720checkDist = -1;1721}17221723for (int32 i = 0; i < 3; i++) {1724sensors[i].position.x += xVel;1725sensors[i].position.y += yVel;1726FindLWallPosition(&sensors[i]);1727}17281729tileDistance = -1;1730for (int32 i = 0; i < 3; i++) {1731if (tileDistance > -1) {1732if (sensors[i].position.x < sensors[tileDistance].position.x && sensors[i].collided) {1733tileDistance = i;1734}1735}1736else if (sensors[i].collided) {1737tileDistance = i;1738}1739}17401741if (tileDistance <= -1) {1742checkDist = -1;1743}1744else {1745sensors[0].position.x = sensors[tileDistance].position.x;1746sensors[0].angle = sensors[tileDistance].angle;17471748sensors[1].position.x = sensors[0].position.x;1749sensors[1].angle = sensors[0].angle;17501751sensors[2].position.x = sensors[0].position.x;1752sensors[2].angle = sensors[0].angle;17531754sensors[4].position.x = sensors[1].position.x - TO_FIXED(collisionOuter.bottom);1755sensors[4].position.y = sensors[1].position.y;1756}17571758if (sensors[0].angle > 0xE2)1759collisionEntity->collisionMode = CMODE_FLOOR;17601761if (sensors[0].angle < 0x9E)1762collisionEntity->collisionMode = CMODE_ROOF;1763break;1764}17651766case CMODE_ROOF: {1767sensors[3].position.x += xVel;1768sensors[3].position.y += yVel;17691770if (collisionEntity->groundVel > 0) {1771RWallCollision(&sensors[3]);1772#if RETRO_REV0U1773if (sensors[3].collided)1774sensors[2].position.x = sensors[3].position.x + TO_FIXED(2);1775#endif1776}17771778if (collisionEntity->groundVel < 0) {1779LWallCollision(&sensors[3]);1780#if RETRO_REV0U1781if (sensors[3].collided)1782sensors[0].position.x = sensors[3].position.x - TO_FIXED(2);1783#endif1784}17851786if (sensors[3].collided) {1787xVel = 0;1788checkDist = -1;1789}17901791for (int32 i = 0; i < 3; i++) {1792sensors[i].position.x += xVel;1793sensors[i].position.y += yVel;1794FindRoofPosition(&sensors[i]);1795}17961797tileDistance = -1;1798for (int32 i = 0; i < 3; i++) {1799if (tileDistance > -1) {1800if (sensors[i].position.y > sensors[tileDistance].position.y && sensors[i].collided) {1801tileDistance = i;1802}1803}1804else if (sensors[i].collided) {1805tileDistance = i;1806}1807}18081809if (tileDistance <= -1) {1810checkDist = -1;1811}1812else {1813sensors[0].position.y = sensors[tileDistance].position.y;1814sensors[0].angle = sensors[tileDistance].angle;18151816sensors[1].position.y = sensors[0].position.y;1817sensors[1].angle = sensors[0].angle;18181819sensors[2].position.y = sensors[0].position.y;1820sensors[2].angle = sensors[0].angle;18211822sensors[4].position.x = sensors[1].position.x;1823sensors[4].position.y = sensors[0].position.y + TO_FIXED(collisionOuter.bottom) + TO_FIXED(1);1824}18251826if (sensors[0].angle > 0xA2)1827collisionEntity->collisionMode = CMODE_LWALL;1828if (sensors[0].angle < 0x5E)1829collisionEntity->collisionMode = CMODE_RWALL;1830break;1831}18321833case CMODE_RWALL: {1834sensors[3].position.x += xVel;1835sensors[3].position.y += yVel;18361837if (collisionEntity->groundVel > 0)1838FloorCollision(&sensors[3]);18391840if (collisionEntity->groundVel < 0)1841RoofCollision(&sensors[3]);18421843if (sensors[3].collided) {1844yVel = 0;1845checkDist = -1;1846}18471848for (int32 i = 0; i < 3; i++) {1849sensors[i].position.x += xVel;1850sensors[i].position.y += yVel;1851FindRWallPosition(&sensors[i]);1852}18531854tileDistance = -1;1855for (int32 i = 0; i < 3; i++) {1856if (tileDistance > -1) {1857if (sensors[i].position.x > sensors[tileDistance].position.x && sensors[i].collided) {1858tileDistance = i;1859}1860}1861else if (sensors[i].collided) {1862tileDistance = i;1863}1864}18651866if (tileDistance <= -1) {1867checkDist = -1;1868}1869else {1870sensors[0].position.x = sensors[tileDistance].position.x;1871sensors[0].angle = sensors[tileDistance].angle;18721873sensors[1].position.x = sensors[0].position.x;1874sensors[1].angle = sensors[0].angle;18751876sensors[2].position.x = sensors[0].position.x;1877sensors[2].angle = sensors[0].angle;18781879sensors[4].position.x = sensors[1].position.x + TO_FIXED(collisionOuter.bottom) + TO_FIXED(1);1880sensors[4].position.y = sensors[1].position.y;1881}18821883if (sensors[0].angle < 0x1E)1884collisionEntity->collisionMode = CMODE_FLOOR;1885if (sensors[0].angle > 0x62)1886collisionEntity->collisionMode = CMODE_ROOF;1887break;1888}1889}18901891if (tileDistance != -1)1892collisionEntity->angle = sensors[0].angle;18931894if (!sensors[3].collided)1895SetPathGripSensors(sensors);1896else1897checkDist = -2;1898}18991900#if RETRO_REV0U1901int32 newCollisionMode = collisionEntity->tileCollisions == TILECOLLISION_DOWN ? CMODE_FLOOR : CMODE_ROOF;1902int32 newAngle = newCollisionMode << 6;1903#else1904int32 newCollisionMode = CMODE_FLOOR;1905int32 newAngle = newCollisionMode << 6;1906#endif19071908switch (collisionEntity->collisionMode) {1909case CMODE_FLOOR: {1910if (sensors[0].collided || sensors[1].collided || sensors[2].collided) {1911collisionEntity->angle = sensors[0].angle;19121913if (!sensors[3].collided) {1914collisionEntity->position.x = sensors[4].position.x;1915}1916else {1917if (collisionEntity->groundVel > 0)1918collisionEntity->position.x = sensors[3].position.x - TO_FIXED(collisionOuter.right);19191920if (collisionEntity->groundVel < 0)1921collisionEntity->position.x = sensors[3].position.x - TO_FIXED(collisionOuter.left) + TO_FIXED(1);19221923collisionEntity->groundVel = 0;1924collisionEntity->velocity.x = 0;1925}19261927collisionEntity->position.y = sensors[4].position.y;1928}1929else {1930collisionEntity->onGround = false;1931collisionEntity->collisionMode = newCollisionMode;1932collisionEntity->velocity.x = cos256LookupTable[collisionEntity->angle] * collisionEntity->groundVel >> 8;1933collisionEntity->velocity.y = sin256LookupTable[collisionEntity->angle] * collisionEntity->groundVel >> 8;1934if (collisionEntity->velocity.y < -TO_FIXED(16))1935collisionEntity->velocity.y = -TO_FIXED(16);19361937if (collisionEntity->velocity.y > TO_FIXED(16))1938collisionEntity->velocity.y = TO_FIXED(16);19391940collisionEntity->groundVel = collisionEntity->velocity.x;1941collisionEntity->angle = newAngle;1942if (!sensors[3].collided) {1943collisionEntity->position.x += collisionEntity->velocity.x;1944}1945else {1946if (collisionEntity->groundVel > 0)1947collisionEntity->position.x = sensors[3].position.x - TO_FIXED(collisionOuter.right);1948if (collisionEntity->groundVel < 0)1949collisionEntity->position.x = sensors[3].position.x - TO_FIXED(collisionOuter.left) + TO_FIXED(1);19501951collisionEntity->groundVel = 0;1952collisionEntity->velocity.x = 0;1953}19541955collisionEntity->position.y += collisionEntity->velocity.y;1956}1957break;1958}19591960case CMODE_LWALL: {1961if (sensors[0].collided || sensors[1].collided || sensors[2].collided) {1962collisionEntity->angle = sensors[0].angle;1963}1964else {1965collisionEntity->onGround = false;1966collisionEntity->collisionMode = newCollisionMode;1967collisionEntity->velocity.x = cos256LookupTable[collisionEntity->angle] * collisionEntity->groundVel >> 8;1968collisionEntity->velocity.y = sin256LookupTable[collisionEntity->angle] * collisionEntity->groundVel >> 8;19691970if (collisionEntity->velocity.y < -TO_FIXED(16))1971collisionEntity->velocity.y = -TO_FIXED(16);19721973if (collisionEntity->velocity.y > TO_FIXED(16))1974collisionEntity->velocity.y = TO_FIXED(16);19751976collisionEntity->groundVel = collisionEntity->velocity.x;1977collisionEntity->angle = newAngle;1978}19791980if (!sensors[3].collided) {1981collisionEntity->position.x = sensors[4].position.x;1982collisionEntity->position.y = sensors[4].position.y;1983}1984else {1985if (collisionEntity->groundVel > 0)1986collisionEntity->position.y = sensors[3].position.y + TO_FIXED(collisionOuter.right) + TO_FIXED(1);19871988if (collisionEntity->groundVel < 0)1989collisionEntity->position.y = sensors[3].position.y - TO_FIXED(collisionOuter.left);19901991collisionEntity->groundVel = 0;1992collisionEntity->position.x = sensors[4].position.x;1993}1994break;1995}19961997case CMODE_ROOF: {1998if (sensors[0].collided || sensors[1].collided || sensors[2].collided) {1999collisionEntity->angle = sensors[0].angle;20002001if (!sensors[3].collided) {2002collisionEntity->position.x = sensors[4].position.x;2003}2004else {2005if (collisionEntity->groundVel > 0)2006collisionEntity->position.x = sensors[3].position.x + TO_FIXED(collisionOuter.right);20072008if (collisionEntity->groundVel < 0)2009collisionEntity->position.x = sensors[3].position.x + TO_FIXED(collisionOuter.left) - TO_FIXED(1);20102011collisionEntity->groundVel = 0;2012}2013}2014else {2015collisionEntity->onGround = false;2016collisionEntity->collisionMode = newCollisionMode;2017collisionEntity->velocity.x = cos256LookupTable[collisionEntity->angle] * collisionEntity->groundVel >> 8;2018collisionEntity->velocity.y = sin256LookupTable[collisionEntity->angle] * collisionEntity->groundVel >> 8;20192020if (collisionEntity->velocity.y < -TO_FIXED(16))2021collisionEntity->velocity.y = -TO_FIXED(16);20222023if (collisionEntity->velocity.y > TO_FIXED(16))2024collisionEntity->velocity.y = TO_FIXED(16);20252026collisionEntity->angle = newAngle;2027collisionEntity->groundVel = collisionEntity->velocity.x;20282029if (!sensors[3].collided) {2030collisionEntity->position.x += collisionEntity->velocity.x;2031}2032else {2033if (collisionEntity->groundVel > 0)2034collisionEntity->position.x = sensors[3].position.x - TO_FIXED(collisionOuter.right);20352036if (collisionEntity->groundVel < 0)2037collisionEntity->position.x = sensors[3].position.x - TO_FIXED(collisionOuter.left) + TO_FIXED(1);20382039collisionEntity->groundVel = 0;2040}2041}2042collisionEntity->position.y = sensors[4].position.y;2043break;2044}20452046case CMODE_RWALL: {2047if (sensors[0].collided || sensors[1].collided || sensors[2].collided) {2048collisionEntity->angle = sensors[0].angle;2049}2050else {2051collisionEntity->onGround = false;2052collisionEntity->collisionMode = newCollisionMode;2053collisionEntity->velocity.x = cos256LookupTable[collisionEntity->angle] * collisionEntity->groundVel >> 8;2054collisionEntity->velocity.y = sin256LookupTable[collisionEntity->angle] * collisionEntity->groundVel >> 8;20552056if (collisionEntity->velocity.y < -TO_FIXED(16))2057collisionEntity->velocity.y = -TO_FIXED(16);20582059if (collisionEntity->velocity.y > TO_FIXED(16))2060collisionEntity->velocity.y = TO_FIXED(16);20612062collisionEntity->groundVel = collisionEntity->velocity.x;2063collisionEntity->angle = newAngle;2064}20652066if (!sensors[3].collided) {2067collisionEntity->position.x = sensors[4].position.x;2068collisionEntity->position.y = sensors[4].position.y;2069}2070else {2071if (collisionEntity->groundVel > 0)2072collisionEntity->position.y = sensors[3].position.y - TO_FIXED(collisionOuter.right);20732074if (collisionEntity->groundVel < 0)2075collisionEntity->position.y = sensors[3].position.y - TO_FIXED(collisionOuter.left) + TO_FIXED(1);20762077collisionEntity->groundVel = 0;2078collisionEntity->position.x = sensors[4].position.x;2079}2080break;2081}20822083default: break;2084}2085}20862087void RSDK::SetPathGripSensors(CollisionSensor *sensors)2088{2089int32 offset = 0;2090#if RETRO_REV0U2091offset = useCollisionOffset ? COLLISION_OFFSET : 0;2092#else2093offset = collisionOffset;2094#endif20952096switch (collisionEntity->collisionMode) {2097case CMODE_FLOOR:2098sensors[0].position.y = sensors[4].position.y + TO_FIXED(collisionOuter.bottom);2099sensors[1].position.y = sensors[4].position.y + TO_FIXED(collisionOuter.bottom);2100sensors[2].position.y = sensors[4].position.y + TO_FIXED(collisionOuter.bottom);2101sensors[3].position.y = sensors[4].position.y + offset;21022103sensors[0].position.x = sensors[4].position.x + TO_FIXED(collisionInner.left) - TO_FIXED(1);2104sensors[1].position.x = sensors[4].position.x;2105sensors[2].position.x = sensors[4].position.x + TO_FIXED(collisionInner.right);2106if (collisionEntity->groundVel <= 0)2107sensors[3].position.x = sensors[4].position.x + TO_FIXED(collisionOuter.left) - TO_FIXED(1);2108else2109sensors[3].position.x = sensors[4].position.x + TO_FIXED(collisionOuter.right);2110break;21112112case CMODE_LWALL:2113sensors[0].position.x = sensors[4].position.x + TO_FIXED(collisionOuter.bottom);2114sensors[1].position.x = sensors[4].position.x + TO_FIXED(collisionOuter.bottom);2115sensors[2].position.x = sensors[4].position.x + TO_FIXED(collisionOuter.bottom);2116sensors[3].position.x = sensors[4].position.x;21172118sensors[0].position.y = sensors[4].position.y + TO_FIXED(collisionInner.left) - TO_FIXED(1);2119sensors[1].position.y = sensors[4].position.y;2120sensors[2].position.y = sensors[4].position.y + TO_FIXED(collisionInner.right);2121if (collisionEntity->groundVel <= 0)2122sensors[3].position.y = sensors[4].position.y - TO_FIXED(collisionOuter.left);2123else2124sensors[3].position.y = sensors[4].position.y - TO_FIXED(collisionOuter.right) - TO_FIXED(1);2125break;21262127case CMODE_ROOF:2128sensors[0].position.y = sensors[4].position.y - TO_FIXED(collisionOuter.bottom) - TO_FIXED(1);2129sensors[1].position.y = sensors[4].position.y - TO_FIXED(collisionOuter.bottom) - TO_FIXED(1);2130sensors[2].position.y = sensors[4].position.y - TO_FIXED(collisionOuter.bottom) - TO_FIXED(1);2131sensors[3].position.y = sensors[4].position.y - offset;21322133sensors[0].position.x = sensors[4].position.x + TO_FIXED(collisionInner.left) - TO_FIXED(1);2134sensors[1].position.x = sensors[4].position.x;2135sensors[2].position.x = sensors[4].position.x + TO_FIXED(collisionInner.right);2136if (collisionEntity->groundVel <= 0)2137sensors[3].position.x = sensors[4].position.x - TO_FIXED(collisionOuter.left);2138else2139sensors[3].position.x = sensors[4].position.x - TO_FIXED(collisionOuter.right) - TO_FIXED(1);2140break;21412142case CMODE_RWALL:2143sensors[0].position.x = sensors[4].position.x - TO_FIXED(collisionOuter.bottom) - TO_FIXED(1);2144sensors[1].position.x = sensors[4].position.x - TO_FIXED(collisionOuter.bottom) - TO_FIXED(1);2145sensors[2].position.x = sensors[4].position.x - TO_FIXED(collisionOuter.bottom) - TO_FIXED(1);2146sensors[3].position.x = sensors[4].position.x;21472148sensors[0].position.y = sensors[4].position.y + TO_FIXED(collisionInner.left) - TO_FIXED(1);2149sensors[1].position.y = sensors[4].position.y;2150sensors[2].position.y = sensors[4].position.y + TO_FIXED(collisionInner.right);2151if (collisionEntity->groundVel <= 0)2152sensors[3].position.y = sensors[4].position.y + TO_FIXED(collisionOuter.left) - TO_FIXED(1);2153else2154sensors[3].position.y = sensors[4].position.y + TO_FIXED(collisionOuter.right);2155break;21562157default: break;2158}2159}21602161void RSDK::FindFloorPosition(CollisionSensor *sensor)2162{2163int32 posX = FROM_FIXED(sensor->position.x);2164int32 posY = FROM_FIXED(sensor->position.y);21652166int32 solid = 0;2167#if RETRO_REV0U2168if (collisionEntity->tileCollisions == TILECOLLISION_DOWN)2169solid = collisionEntity->collisionPlane ? (1 << 14) : (1 << 12);2170else2171solid = collisionEntity->collisionPlane ? (1 << 15) : (1 << 13);2172#else2173solid = collisionEntity->collisionPlane ? (1 << 14) : (1 << 12);2174#endif21752176int32 startY = posY;21772178for (int32 l = 0, layerID = 1; l < LAYER_COUNT; ++l, layerID <<= 1) {2179if (collisionEntity->collisionLayers & layerID) {2180TileLayer *layer = &tileLayers[l];2181int32 colX = posX - layer->position.x;2182int32 colY = posY - layer->position.y;2183int32 cy = (colY & -TILE_SIZE) - TILE_SIZE;2184if (colX >= 0 && colX < TILE_SIZE * layer->xsize) {2185for (int32 i = 0; i < 3; ++i) {2186if (cy >= 0 && cy < TILE_SIZE * layer->ysize) {2187uint16 tile = layer->layout[(colX / TILE_SIZE) + ((cy / TILE_SIZE) << layer->widthShift)];21882189if (tile < 0xFFFF && tile & solid) {2190int32 mask = collisionMasks[collisionEntity->collisionPlane][tile & 0xFFF].floorMasks[colX & 0xF];2191int32 ty = cy + mask;2192int32 tileAngle = tileInfo[collisionEntity->collisionPlane][tile & 0xFFF].floorAngle;21932194if (mask < 0xFF) {2195if (!sensor->collided || startY >= ty) {2196if (abs(colY - ty) <= collisionTolerance) {2197#if RETRO_REV0U2198#if !RETRO_USE_ORIGINAL_CODE2199if (abs(sensor->angle - tileAngle) <= TILE_SIZE * 2 // * 3 causes some issues in certain tiles2200#else2201if (abs(sensor->angle - tileAngle) <= TILE_SIZE * 32202#endif2203|| abs(sensor->angle - tileAngle + 0x100) <= floorAngleTolerance2204|| abs(sensor->angle - tileAngle - 0x100) <= floorAngleTolerance) {2205#else2206if (abs(sensor->angle - tileAngle) <= 0x20 || abs(sensor->angle - tileAngle + 0x100) <= 0x202207|| abs(sensor->angle - tileAngle - 0x100) <= 0x20) {2208#endif2209sensor->collided = true;2210sensor->angle = tileAngle;2211sensor->position.y = TO_FIXED(ty + layer->position.y);2212startY = ty;2213i = 3;2214}2215}2216}2217}2218}2219}22202221cy += TILE_SIZE;2222}2223}22242225posX = layer->position.x + colX;2226posY = layer->position.y + colY;2227}2228}2229}2230void RSDK::FindLWallPosition(CollisionSensor *sensor)2231{2232int32 posX = FROM_FIXED(sensor->position.x);2233int32 posY = FROM_FIXED(sensor->position.y);22342235int32 solid = collisionEntity->collisionPlane ? ((1 << 14) | (1 << 15)) : ((1 << 12) | (1 << 13));22362237int32 startX = posX;22382239for (int32 l = 0, layerID = 1; l < LAYER_COUNT; ++l, layerID <<= 1) {2240if (collisionEntity->collisionLayers & layerID) {2241TileLayer *layer = &tileLayers[l];2242int32 colX = posX - layer->position.x;2243int32 colY = posY - layer->position.y;2244int32 cx = (colX & -TILE_SIZE) - TILE_SIZE;2245if (colY >= 0 && colY < TILE_SIZE * layer->ysize) {2246for (int32 i = 0; i < 3; ++i) {2247if (cx >= 0 && cx < TILE_SIZE * layer->xsize) {2248uint16 tile = layer->layout[(cx / TILE_SIZE) + ((colY / TILE_SIZE) << layer->widthShift)];22492250if (tile < 0xFFFF && tile & solid) {2251int32 mask = collisionMasks[collisionEntity->collisionPlane][tile & 0xFFF].lWallMasks[colY & 0xF];2252int32 tx = cx + mask;2253int32 tileAngle = tileInfo[collisionEntity->collisionPlane][tile & 0xFFF].lWallAngle;22542255if (mask < 0xFF) {2256if (!sensor->collided || startX >= tx) {2257if (abs(colX - tx) <= collisionTolerance && abs(sensor->angle - tileAngle) <= wallAngleTolerance) {2258sensor->collided = true;2259sensor->angle = tileAngle;2260sensor->position.x = TO_FIXED(tx + layer->position.x);2261startX = tx;2262i = 3;2263}2264}2265}2266}2267}22682269cx += TILE_SIZE;2270}2271}22722273posX = layer->position.x + colX;2274posY = layer->position.y + colY;2275}2276}2277}2278void RSDK::FindRoofPosition(CollisionSensor *sensor)2279{2280int32 posX = FROM_FIXED(sensor->position.x);2281int32 posY = FROM_FIXED(sensor->position.y);22822283int32 solid = 0;2284#if RETRO_REV0U2285if (collisionEntity->tileCollisions == TILECOLLISION_DOWN)2286solid = collisionEntity->collisionPlane ? (1 << 15) : (1 << 13);2287else2288solid = collisionEntity->collisionPlane ? (1 << 14) : (1 << 12);2289#else2290solid = collisionEntity->collisionPlane ? (1 << 15) : (1 << 13);2291#endif22922293int32 startY = posY;22942295for (int32 l = 0, layerID = 1; l < LAYER_COUNT; ++l, layerID <<= 1) {2296if (collisionEntity->collisionLayers & layerID) {2297TileLayer *layer = &tileLayers[l];2298int32 colX = posX - layer->position.x;2299int32 colY = posY - layer->position.y;2300int32 cy = (colY & -TILE_SIZE) + TILE_SIZE;23012302if (colX >= 0 && colX < TILE_SIZE * layer->xsize) {2303for (int32 i = 0; i < 3; ++i) {2304if (cy >= 0 && cy < TILE_SIZE * layer->ysize) {2305uint16 tile = layer->layout[(colX / TILE_SIZE) + ((cy / TILE_SIZE) << layer->widthShift)];23062307if (tile < 0xFFFF && tile & solid) {2308int32 mask = collisionMasks[collisionEntity->collisionPlane][tile & 0xFFF].roofMasks[colX & 0xF];2309int32 ty = cy + mask;2310int32 tileAngle = tileInfo[collisionEntity->collisionPlane][tile & 0xFFF].roofAngle;23112312if (mask < 0xFF) {2313if (!sensor->collided || startY <= ty) {2314if (abs(colY - ty) <= collisionTolerance && abs(sensor->angle - tileAngle) <= roofAngleTolerance) {2315sensor->collided = true;2316sensor->angle = tileAngle;2317sensor->position.y = TO_FIXED(ty + layer->position.y);2318startY = ty;2319i = 3;2320}2321}2322}2323}2324}23252326cy -= TILE_SIZE;2327}2328}23292330posX = layer->position.x + colX;2331posY = layer->position.y + colY;2332}2333}2334}2335void RSDK::FindRWallPosition(CollisionSensor *sensor)2336{2337int32 posX = FROM_FIXED(sensor->position.x);2338int32 posY = FROM_FIXED(sensor->position.y);23392340int32 solid = collisionEntity->collisionPlane ? ((1 << 14) | (1 << 15)) : ((1 << 12) | (1 << 13));23412342int32 startX = posX;23432344for (int32 l = 0, layerID = 1; l < LAYER_COUNT; ++l, layerID <<= 1) {2345if (collisionEntity->collisionLayers & layerID) {2346TileLayer *layer = &tileLayers[l];2347int32 colX = posX - layer->position.x;2348int32 colY = posY - layer->position.y;2349int32 cx = (colX & -TILE_SIZE) + TILE_SIZE;23502351if (colY >= 0 && colY < TILE_SIZE * layer->ysize) {2352for (int32 i = 0; i < 3; ++i) {2353if (cx >= 0 && cx < TILE_SIZE * layer->xsize) {2354uint16 tile = layer->layout[(cx / TILE_SIZE) + ((colY / TILE_SIZE) << layer->widthShift)];23552356if (tile < 0xFFFF && tile & solid) {2357int32 mask = collisionMasks[collisionEntity->collisionPlane][tile & 0xFFF].rWallMasks[colY & 0xF];2358int32 tx = cx + mask;2359int32 tileAngle = tileInfo[collisionEntity->collisionPlane][tile & 0xFFF].rWallAngle;23602361if (mask < 0xFF) {2362if (!sensor->collided || startX <= tx) {2363if (abs(colX - tx) <= collisionTolerance && abs(sensor->angle - tileAngle) <= wallAngleTolerance) {2364sensor->collided = true;2365sensor->angle = tileAngle;2366sensor->position.x = TO_FIXED(tx + layer->position.x);2367startX = tx;2368i = 3;2369}2370}2371}2372}2373}23742375cx -= TILE_SIZE;2376}2377}23782379posX = layer->position.x + colX;2380posY = layer->position.y + colY;2381}2382}2383}23842385void RSDK::FloorCollision(CollisionSensor *sensor)2386{2387int32 posX = FROM_FIXED(sensor->position.x);2388int32 posY = FROM_FIXED(sensor->position.y);23892390int32 solid = 0;2391#if RETRO_REV0U2392if (collisionEntity->tileCollisions == TILECOLLISION_DOWN)2393solid = collisionEntity->collisionPlane ? (1 << 14) : (1 << 12);2394else2395solid = collisionEntity->collisionPlane ? (1 << 15) : (1 << 13);2396#else2397solid = collisionEntity->collisionPlane ? (1 << 14) : (1 << 12);2398#endif23992400#if RETRO_REV0U2401int32 collideAngle = 0;2402int32 collidePos = 0x7FFFFFFF;2403#endif24042405for (int32 l = 0, layerID = 1; l < LAYER_COUNT; ++l, layerID <<= 1) {2406if (collisionEntity->collisionLayers & layerID) {2407TileLayer *layer = &tileLayers[l];2408int32 colX = posX - layer->position.x;2409int32 colY = posY - layer->position.y;2410int32 cy = (colY & -TILE_SIZE) - TILE_SIZE;24112412if (colX >= 0 && colX < TILE_SIZE * layer->xsize) {2413#if RETRO_REV0U2414int32 stepCount = 2;2415#else2416int32 stepCount = 3;2417#endif2418for (int32 i = 0; i < stepCount; ++i) {2419int32 step = TILE_SIZE;24202421if (cy >= 0 && cy < TILE_SIZE * layer->ysize) {2422uint16 tile = layer->layout[(colX / TILE_SIZE) + ((cy / TILE_SIZE) << layer->widthShift)];2423if (tile < 0xFFFF && tile & solid) {2424int32 mask = collisionMasks[collisionEntity->collisionPlane][tile & 0xFFF].floorMasks[colX & 0xF];2425#if RETRO_REV0U2426int32 ty = layer->position.y + cy + mask;2427#else2428int32 ty = cy + mask;2429#endif2430if (mask < 0xFF) {2431#if RETRO_REV0U2432step = -TILE_SIZE;2433if (colY < collidePos) {2434collideAngle = tileInfo[collisionEntity->collisionPlane][tile & 0xFFF].floorAngle;2435collidePos = ty;2436i = stepCount;2437#else2438if (colY >= ty) {2439if (abs(colY - ty) <= collisionMinimumDistance) {2440sensor->collided = true;2441sensor->angle = tileInfo[collisionEntity->collisionPlane][tile & 0xFFF].floorAngle;2442sensor->position.y = TO_FIXED(ty + layer->position.y);2443i = stepCount;2444}2445#endif2446}2447}2448}2449}24502451cy += step;2452}2453}24542455posX = layer->position.x + colX;2456posY = layer->position.y + colY;2457}2458}24592460#if RETRO_REV0U2461if (collidePos != 0x7FFFFFFF) {2462int32 collideDist = sensor->position.y - TO_FIXED(collidePos);2463if (sensor->position.y >= TO_FIXED(collidePos) && collideDist <= collisionMinimumDistance) {2464sensor->angle = collideAngle;2465sensor->position.y = TO_FIXED(collidePos);2466sensor->collided = true;2467}2468}2469#endif2470}2471void RSDK::LWallCollision(CollisionSensor *sensor)2472{2473int32 posX = FROM_FIXED(sensor->position.x);2474int32 posY = FROM_FIXED(sensor->position.y);24752476int32 solid = collisionEntity->collisionPlane ? (1 << 15) : (1 << 13);24772478for (int32 l = 0, layerID = 1; l < LAYER_COUNT; ++l, layerID <<= 1) {2479if (collisionEntity->collisionLayers & layerID) {2480TileLayer *layer = &tileLayers[l];2481int32 colX = posX - layer->position.x;2482int32 colY = posY - layer->position.y;2483int32 cx = (colX & -TILE_SIZE) - TILE_SIZE;24842485if (colY >= 0 && colY < TILE_SIZE * layer->ysize) {2486for (int32 i = 0; i < 3; ++i) {2487if (cx >= 0 && cx < TILE_SIZE * layer->xsize) {2488uint16 tile = layer->layout[(cx / TILE_SIZE) + ((colY / TILE_SIZE) << layer->widthShift)];24892490if (tile < 0xFFFF && tile & solid) {2491int32 mask = collisionMasks[collisionEntity->collisionPlane][tile & 0xFFF].lWallMasks[colY & 0xF];2492int32 tx = cx + mask;2493if (mask < 0xFF && colX >= tx && abs(colX - tx) <= 14) {2494sensor->collided = true;2495sensor->angle = tileInfo[collisionEntity->collisionPlane][tile & 0xFFF].lWallAngle;2496sensor->position.x = TO_FIXED(tx + layer->position.x);2497i = 3;2498}2499}2500}25012502cx += TILE_SIZE;2503}2504}25052506posX = layer->position.x + colX;2507posY = layer->position.y + colY;2508}2509}2510}2511void RSDK::RoofCollision(CollisionSensor *sensor)2512{2513int32 posX = FROM_FIXED(sensor->position.x);2514int32 posY = FROM_FIXED(sensor->position.y);25152516int32 solid = 0;2517#if RETRO_REV0U2518if (collisionEntity->tileCollisions == TILECOLLISION_DOWN)2519solid = collisionEntity->collisionPlane ? (1 << 15) : (1 << 13);2520else2521solid = collisionEntity->collisionPlane ? (1 << 14) : (1 << 12);2522#else2523solid = collisionEntity->collisionPlane ? (1 << 15) : (1 << 13);2524#endif25252526#if RETRO_REV0U2527int32 collideAngle = 0;2528int32 collidePos = -1;2529#endif25302531for (int32 l = 0, layerID = 1; l < LAYER_COUNT; ++l, layerID <<= 1) {2532if (collisionEntity->collisionLayers & layerID) {2533TileLayer *layer = &tileLayers[l];2534int32 colX = posX - layer->position.x;2535int32 colY = posY - layer->position.y;2536int32 cy = (colY & -TILE_SIZE) + TILE_SIZE;25372538if (colX >= 0 && colX < TILE_SIZE * layer->xsize) {2539#if RETRO_REV0U2540int32 stepCount = 2;2541#else2542int32 stepCount = 3;2543#endif2544for (int32 i = 0; i < stepCount; ++i) {2545int32 step = -TILE_SIZE;25462547if (cy >= 0 && cy < TILE_SIZE * layer->ysize) {2548int32 tileX = (colX / TILE_SIZE);2549int32 tileY = (cy / TILE_SIZE);2550uint16 tile = layer->layout[tileX + (tileY << layer->widthShift)];25512552if (tile < 0xFFFF && tile & solid) {2553int32 mask = collisionMasks[collisionEntity->collisionPlane][tile & 0xFFF].roofMasks[colX & 0xF];2554#if RETRO_REV0U2555int32 ty = layer->position.y + cy + mask;2556#else2557int32 ty = cy + mask;2558#endif2559if (mask < 0xFF) {2560#if RETRO_REV0U2561step = TILE_SIZE;2562if (colY > collidePos) {2563collideAngle = tileInfo[collisionEntity->collisionPlane][tile & 0xFFF].roofAngle;2564collidePos = ty;2565i = stepCount;2566#else2567if (colY < ty) {2568if (abs(colY - ty) <= collisionMinimumDistance) {2569sensor->collided = true;2570sensor->angle = tileInfo[collisionEntity->collisionPlane][tile & 0xFFF].roofAngle;2571sensor->position.y = TO_FIXED(ty + layer->position.y);2572i = stepCount;2573}2574#endif2575}2576}2577}2578}25792580cy += step;2581}2582}25832584posX = layer->position.x + colX;2585posY = layer->position.y + colY;2586}2587}25882589#if RETRO_REV0U2590if (collidePos >= 0 && sensor->position.y <= TO_FIXED(collidePos) && sensor->position.y - TO_FIXED(collidePos) >= -collisionMinimumDistance) {2591sensor->angle = collideAngle;2592sensor->position.y = TO_FIXED(collidePos);2593sensor->collided = true;2594}2595#endif2596}2597void RSDK::RWallCollision(CollisionSensor *sensor)2598{2599int32 posX = FROM_FIXED(sensor->position.x);2600int32 posY = FROM_FIXED(sensor->position.y);26012602int32 solid = collisionEntity->collisionPlane ? (1 << 15) : (1 << 13);26032604for (int32 l = 0, layerID = 1; l < LAYER_COUNT; ++l, layerID <<= 1) {2605if (collisionEntity->collisionLayers & layerID) {2606TileLayer *layer = &tileLayers[l];2607int32 colX = posX - layer->position.x;2608int32 colY = posY - layer->position.y;2609int32 cx = (colX & -TILE_SIZE) + TILE_SIZE;26102611if (colY >= 0 && colY < TILE_SIZE * layer->ysize) {2612for (int32 i = 0; i < 3; ++i) {2613if (cx >= 0 && cx < TILE_SIZE * layer->xsize) {2614uint16 tile = layer->layout[(cx / TILE_SIZE) + ((colY / TILE_SIZE) << layer->widthShift)];26152616if (tile < 0xFFFF && tile & solid) {2617int32 mask = collisionMasks[collisionEntity->collisionPlane][tile & 0xFFF].rWallMasks[colY & 0xF];2618int32 tx = cx + mask;2619if (mask < 0xFF && colX <= tx && abs(colX - tx) <= 14) {2620sensor->collided = true;2621sensor->angle = tileInfo[collisionEntity->collisionPlane][tile & 0xFFF].rWallAngle;2622sensor->position.x = TO_FIXED(tx + layer->position.x);2623i = 3;2624}2625}2626}26272628cx -= TILE_SIZE;2629}2630}26312632posX = layer->position.x + colX;2633posY = layer->position.y + colY;2634}2635}2636}263726382639