Path: blob/master/RSDKv5/RSDK/Scene/Legacy/v4/CollisionLegacyv4.cpp
1174 views
1int32 RSDK::Legacy::v4::collisionLeft = 0;2int32 RSDK::Legacy::v4::collisionTop = 0;3int32 RSDK::Legacy::v4::collisionRight = 0;4int32 RSDK::Legacy::v4::collisionBottom = 0;56int32 RSDK::Legacy::v4::collisionTolerance = 0;78RSDK::Legacy::v4::CollisionSensor RSDK::Legacy::v4::sensors[7];910#if !RETRO_USE_ORIGINAL_CODE11int32 RSDK::Legacy::v4::AddDebugHitbox(uint8 type, Entity *entity, int32 left, int32 top, int32 right, int32 bottom)12{13int32 i = 0;14for (; i < debugHitboxCount; ++i) {15if (debugHitboxList[i].hitbox.left == left && debugHitboxList[i].hitbox.top == top && debugHitboxList[i].hitbox.right == right16&& debugHitboxList[i].hitbox.bottom == bottom && debugHitboxList[i].pos.x == entity->xpos && debugHitboxList[i].pos.y == entity->ypos17&& debugHitboxList[i].entity == entity) {18return i;19}20}2122if (i < DEBUG_HITBOX_COUNT) {23debugHitboxList[i].type = type;24debugHitboxList[i].entity = entity;25debugHitboxList[i].collision = 0;26debugHitboxList[i].hitbox.left = left;27debugHitboxList[i].hitbox.top = top;28debugHitboxList[i].hitbox.right = right;29debugHitboxList[i].hitbox.bottom = bottom;30debugHitboxList[i].pos.x = entity ? entity->xpos : 0;31debugHitboxList[i].pos.y = entity ? entity->ypos : 0;3233int32 id = debugHitboxCount;34debugHitboxCount++;35return id;36}3738return -1;39}40#endif4142RSDK::Legacy::Hitbox *RSDK::Legacy::v4::GetHitbox(Entity *entity)43{44AnimationFile *thisAnim = objectScriptList[entity->type].animFile;4546return &hitboxList[thisAnim->hitboxListOffset47+ animFrames[animationList[thisAnim->aniListOffset + entity->animation].frameListOffset + entity->frame].hitboxID];48}4950void RSDK::Legacy::v4::FindFloorPosition(Entity *player, CollisionSensor *sensor, int32 startY)51{52int32 c = 0;53int32 angle = sensor->angle;54int32 tsm1 = (TILE_SIZE - 1);55for (int32 i = 0; i < TILE_SIZE * 3; i += TILE_SIZE) {56if (!sensor->collided) {57int32 XPos = sensor->xpos >> 16;58int32 chunkX = XPos >> 7;59int32 tileX = (XPos & 0x7F) >> 4;60int32 YPos = (sensor->ypos >> 16) - TILE_SIZE + i;61int32 chunkY = YPos >> 7;62int32 tileY = (YPos & 0x7F) >> 4;63if (XPos > -1 && YPos > -1) {64int32 tile = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;65tile += tileX + (tileY << 3);66int32 tileIndex = tiles128x128.tileIndex[tile];67if (tiles128x128.collisionFlags[player->collisionPlane][tile] != SOLID_LRB68&& tiles128x128.collisionFlags[player->collisionPlane][tile] != SOLID_NONE) {69switch (tiles128x128.direction[tile]) {70case FLIP_NONE: {71c = (XPos & tsm1) + (tileIndex << 4);72if (collisionMasks[player->collisionPlane].floorMasks[c] >= 0x40)73break;7475sensor->ypos = collisionMasks[player->collisionPlane].floorMasks[c] + (chunkY << 7) + (tileY << 4);76sensor->collided = true;77sensor->angle = collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF;78break;79}80case FLIP_X: {81c = tsm1 - (XPos & tsm1) + (tileIndex << 4);82if (collisionMasks[player->collisionPlane].floorMasks[c] >= 0x40)83break;8485sensor->ypos = collisionMasks[player->collisionPlane].floorMasks[c] + (chunkY << 7) + (tileY << 4);86sensor->collided = true;87sensor->angle = 0x100 - (collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF);88break;89}90case FLIP_Y: {91c = (XPos & 15) + (tileIndex << 4);92if (collisionMasks[player->collisionPlane].roofMasks[c] <= -0x40)93break;9495sensor->ypos = tsm1 - collisionMasks[player->collisionPlane].roofMasks[c] + (chunkY << 7) + (tileY << 4);96sensor->collided = true;97sensor->angle = (uint8)(0x180 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF000000) >> 24));98break;99}100case FLIP_XY: {101c = tsm1 - (XPos & tsm1) + (tileIndex << 4);102if (collisionMasks[player->collisionPlane].roofMasks[c] <= -0x40)103break;104105sensor->ypos = tsm1 - collisionMasks[player->collisionPlane].roofMasks[c] + (chunkY << 7) + (tileY << 4);106sensor->collided = true;107sensor->angle = 0x100 - (uint8)(0x180 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF000000) >> 24));108break;109}110}111}112113if (sensor->collided) {114if (sensor->angle < 0)115sensor->angle += 0x100;116117if (sensor->angle >= 0x100)118sensor->angle -= 0x100;119120if ((abs(sensor->angle - angle) > 0x20) && (abs(sensor->angle - 0x100 - angle) > 0x20)121&& (abs(sensor->angle + 0x100 - angle) > 0x20)) {122sensor->ypos = startY << 16;123sensor->collided = false;124sensor->angle = angle;125i = TILE_SIZE * 3;126}127else if (sensor->ypos - startY > collisionTolerance || sensor->ypos - startY < -collisionTolerance) {128sensor->ypos = startY << 16;129sensor->collided = false;130}131}132}133}134}135}136void RSDK::Legacy::v4::FindLWallPosition(Entity *player, CollisionSensor *sensor, int32 startX)137{138int32 c = 0;139int32 angle = sensor->angle;140int32 tsm1 = (TILE_SIZE - 1);141for (int32 i = 0; i < TILE_SIZE * 3; i += TILE_SIZE) {142if (!sensor->collided) {143int32 XPos = (sensor->xpos >> 16) - TILE_SIZE + i;144int32 chunkX = XPos >> 7;145int32 tileX = (XPos & 0x7F) >> 4;146int32 YPos = sensor->ypos >> 16;147int32 chunkY = YPos >> 7;148int32 tileY = (YPos & 0x7F) >> 4;149if (XPos > -1 && YPos > -1) {150int32 tile = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;151tile = tile + tileX + (tileY << 3);152int32 tileIndex = tiles128x128.tileIndex[tile];153if (tiles128x128.collisionFlags[player->collisionPlane][tile] < SOLID_NONE) {154switch (tiles128x128.direction[tile]) {155case FLIP_NONE: {156c = (YPos & tsm1) + (tileIndex << 4);157if (collisionMasks[player->collisionPlane].lWallMasks[c] >= 0x40)158break;159160sensor->xpos = collisionMasks[player->collisionPlane].lWallMasks[c] + (chunkX << 7) + (tileX << 4);161sensor->collided = true;162sensor->angle = ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF00) >> 8);163break;164}165case FLIP_X: {166c = (YPos & tsm1) + (tileIndex << 4);167if (collisionMasks[player->collisionPlane].rWallMasks[c] <= -0x40)168break;169170sensor->xpos = tsm1 - collisionMasks[player->collisionPlane].rWallMasks[c] + (chunkX << 7) + (tileX << 4);171sensor->collided = true;172sensor->angle = 0x100 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF0000) >> 16);173break;174}175case FLIP_Y: {176c = tsm1 - (YPos & tsm1) + (tileIndex << 4);177if (collisionMasks[player->collisionPlane].lWallMasks[c] >= 0x40)178break;179180sensor->xpos = collisionMasks[player->collisionPlane].lWallMasks[c] + (chunkX << 7) + (tileX << 4);181sensor->collided = true;182sensor->angle = (uint8)(0x180 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF00) >> 8));183break;184}185case FLIP_XY: {186c = tsm1 - (YPos & tsm1) + (tileIndex << 4);187if (collisionMasks[player->collisionPlane].rWallMasks[c] <= -0x40)188break;189190sensor->xpos = tsm1 - collisionMasks[player->collisionPlane].rWallMasks[c] + (chunkX << 7) + (tileX << 4);191sensor->collided = true;192sensor->angle = 0x100 - (uint8)(0x180 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF0000) >> 16));193break;194}195}196}197if (sensor->collided) {198if (sensor->angle < 0)199sensor->angle += 0x100;200201if (sensor->angle >= 0x100)202sensor->angle -= 0x100;203204if (abs(angle - sensor->angle) > 0x20) {205sensor->xpos = startX << 16;206sensor->collided = false;207sensor->angle = angle;208i = TILE_SIZE * 3;209}210else if (sensor->xpos - startX > collisionTolerance || sensor->xpos - startX < -collisionTolerance) {211sensor->xpos = startX << 16;212sensor->collided = false;213}214}215}216}217}218}219void RSDK::Legacy::v4::FindRoofPosition(Entity *player, CollisionSensor *sensor, int32 startY)220{221int32 c = 0;222int32 angle = sensor->angle;223int32 tsm1 = (TILE_SIZE - 1);224for (int32 i = 0; i < TILE_SIZE * 3; i += TILE_SIZE) {225if (!sensor->collided) {226int32 XPos = sensor->xpos >> 16;227int32 chunkX = XPos >> 7;228int32 tileX = (XPos & 0x7F) >> 4;229int32 YPos = (sensor->ypos >> 16) + TILE_SIZE - i;230int32 chunkY = YPos >> 7;231int32 tileY = (YPos & 0x7F) >> 4;232if (XPos > -1 && YPos > -1) {233int32 tile = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;234tile = tile + tileX + (tileY << 3);235int32 tileIndex = tiles128x128.tileIndex[tile];236if (tiles128x128.collisionFlags[player->collisionPlane][tile] < SOLID_NONE) {237switch (tiles128x128.direction[tile]) {238case FLIP_NONE: {239c = (XPos & tsm1) + (tileIndex << 4);240if (collisionMasks[player->collisionPlane].roofMasks[c] <= -0x40)241break;242243sensor->ypos = collisionMasks[player->collisionPlane].roofMasks[c] + (chunkY << 7) + (tileY << 4);244sensor->collided = true;245sensor->angle = (collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF000000) >> 24;246break;247}248case FLIP_X: {249c = tsm1 - (XPos & tsm1) + (tileIndex << 4);250if (collisionMasks[player->collisionPlane].roofMasks[c] <= -0x40)251break;252253sensor->ypos = collisionMasks[player->collisionPlane].roofMasks[c] + (chunkY << 7) + (tileY << 4);254sensor->collided = true;255sensor->angle = 0x100 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF000000) >> 24);256break;257}258case FLIP_Y: {259c = (XPos & tsm1) + (tileIndex << 4);260if (collisionMasks[player->collisionPlane].floorMasks[c] >= 0x40)261break;262263sensor->ypos = tsm1 - collisionMasks[player->collisionPlane].floorMasks[c] + (chunkY << 7) + (tileY << 4);264sensor->collided = true;265sensor->angle = (uint8)(0x180 - (collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF));266break;267}268case FLIP_XY: {269c = tsm1 - (XPos & tsm1) + (tileIndex << 4);270if (collisionMasks[player->collisionPlane].floorMasks[c] >= 0x40)271break;272273sensor->ypos = tsm1 - collisionMasks[player->collisionPlane].floorMasks[c] + (chunkY << 7) + (tileY << 4);274sensor->collided = true;275sensor->angle = 0x100 - (uint8)(0x180 - (collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF));276break;277}278}279}280281if (sensor->collided) {282if (sensor->angle < 0)283sensor->angle += 0x100;284285if (sensor->angle >= 0x100)286sensor->angle -= 0x100;287288if (abs(sensor->angle - angle) <= 0x20) {289if (sensor->ypos - startY > collisionTolerance || sensor->ypos - startY < -collisionTolerance) {290sensor->ypos = startY << 16;291sensor->collided = false;292}293}294else {295sensor->ypos = startY << 16;296sensor->collided = false;297sensor->angle = angle;298i = TILE_SIZE * 3;299}300}301}302}303}304}305void RSDK::Legacy::v4::FindRWallPosition(Entity *player, CollisionSensor *sensor, int32 startX)306{307int32 c;308int32 angle = sensor->angle;309int32 tsm1 = (TILE_SIZE - 1);310for (int32 i = 0; i < TILE_SIZE * 3; i += TILE_SIZE) {311if (!sensor->collided) {312int32 XPos = (sensor->xpos >> 16) + TILE_SIZE - i;313int32 chunkX = XPos >> 7;314int32 tileX = (XPos & 0x7F) >> 4;315int32 YPos = sensor->ypos >> 16;316int32 chunkY = YPos >> 7;317int32 tileY = (YPos & 0x7F) >> 4;318if (XPos > -1 && YPos > -1) {319int32 tile = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;320tile = tile + tileX + (tileY << 3);321int32 tileIndex = tiles128x128.tileIndex[tile];322if (tiles128x128.collisionFlags[player->collisionPlane][tile] < SOLID_NONE) {323switch (tiles128x128.direction[tile]) {324case FLIP_NONE: {325c = (YPos & tsm1) + (tileIndex << 4);326if (collisionMasks[player->collisionPlane].rWallMasks[c] <= -0x40)327break;328329sensor->xpos = collisionMasks[player->collisionPlane].rWallMasks[c] + (chunkX << 7) + (tileX << 4);330sensor->collided = true;331sensor->angle = (uint8)((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF0000) >> 16);332break;333}334case FLIP_X: {335c = (YPos & tsm1) + (tileIndex << 4);336if (collisionMasks[player->collisionPlane].lWallMasks[c] >= 0x40)337break;338339sensor->xpos = tsm1 - collisionMasks[player->collisionPlane].lWallMasks[c] + (chunkX << 7) + (tileX << 4);340sensor->collided = true;341sensor->angle = 0x100 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF00) >> 8);342break;343}344case FLIP_Y: {345c = tsm1 - (YPos & tsm1) + (tileIndex << 4);346if (collisionMasks[player->collisionPlane].rWallMasks[c] <= -0x40)347break;348349sensor->xpos = collisionMasks[player->collisionPlane].rWallMasks[c] + (chunkX << 7) + (tileX << 4);350sensor->collided = true;351sensor->angle = (uint8)(0x180 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF0000) >> 16));352break;353}354case FLIP_XY: {355c = tsm1 - (YPos & tsm1) + (tileIndex << 4);356if (collisionMasks[player->collisionPlane].lWallMasks[c] >= 0x40)357break;358359sensor->xpos = tsm1 - collisionMasks[player->collisionPlane].lWallMasks[c] + (chunkX << 7) + (tileX << 4);360sensor->collided = true;361sensor->angle = 0x100 - (uint8)(0x180 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF00) >> 8));362break;363}364}365}366if (sensor->collided) {367if (sensor->angle < 0)368sensor->angle += 0x100;369370if (sensor->angle >= 0x100)371sensor->angle -= 0x100;372373if (abs(sensor->angle - angle) > 0x20) {374sensor->xpos = startX << 16;375sensor->collided = false;376sensor->angle = angle;377i = TILE_SIZE * 3;378}379else if (sensor->xpos - startX > collisionTolerance || sensor->xpos - startX < -collisionTolerance) {380sensor->xpos = startX << 16;381sensor->collided = false;382}383}384}385}386}387}388389void RSDK::Legacy::v4::FloorCollision(Entity *player, CollisionSensor *sensor)390{391int32 c;392int32 startY = sensor->ypos >> 16;393int32 tsm1 = (TILE_SIZE - 1);394for (int32 i = 0; i < TILE_SIZE * 3; i += TILE_SIZE) {395if (!sensor->collided) {396int32 XPos = sensor->xpos >> 16;397int32 chunkX = XPos >> 7;398int32 tileX = (XPos & 0x7F) >> 4;399int32 YPos = (sensor->ypos >> 16) - TILE_SIZE + i;400int32 chunkY = YPos >> 7;401int32 tileY = (YPos & 0x7F) >> 4;402if (XPos > -1 && YPos > -1) {403int32 tile = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;404tile += tileX + (tileY << 3);405int32 tileIndex = tiles128x128.tileIndex[tile];406if (tiles128x128.collisionFlags[player->collisionPlane][tile] != SOLID_LRB407&& tiles128x128.collisionFlags[player->collisionPlane][tile] != SOLID_NONE) {408switch (tiles128x128.direction[tile]) {409case FLIP_NONE: {410c = (XPos & tsm1) + (tileIndex << 4);411if ((YPos & tsm1) <= collisionMasks[player->collisionPlane].floorMasks[c] - TILE_SIZE + i412|| collisionMasks[player->collisionPlane].floorMasks[c] >= tsm1)413break;414415sensor->ypos = collisionMasks[player->collisionPlane].floorMasks[c] + (chunkY << 7) + (tileY << 4);416sensor->collided = true;417sensor->angle = collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF;418break;419}420case FLIP_X: {421c = tsm1 - (XPos & tsm1) + (tileIndex << 4);422if ((YPos & tsm1) <= collisionMasks[player->collisionPlane].floorMasks[c] - TILE_SIZE + i423|| collisionMasks[player->collisionPlane].floorMasks[c] >= tsm1)424break;425426sensor->ypos = collisionMasks[player->collisionPlane].floorMasks[c] + (chunkY << 7) + (tileY << 4);427sensor->collided = true;428sensor->angle = 0x100 - (collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF);429break;430}431case FLIP_Y: {432c = (XPos & tsm1) + (tileIndex << 4);433if ((YPos & tsm1) <= tsm1 - collisionMasks[player->collisionPlane].roofMasks[c] - TILE_SIZE + i)434break;435436sensor->ypos = tsm1 - collisionMasks[player->collisionPlane].roofMasks[c] + (chunkY << 7) + (tileY << 4);437sensor->collided = true;438uint8 cAngle = (collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF000000) >> 24;439sensor->angle = (uint8)(0x180 - cAngle);440break;441}442case FLIP_XY: {443c = tsm1 - (XPos & tsm1) + (tileIndex << 4);444if ((YPos & tsm1) <= tsm1 - collisionMasks[player->collisionPlane].roofMasks[c] - TILE_SIZE + i)445break;446447sensor->ypos = tsm1 - collisionMasks[player->collisionPlane].roofMasks[c] + (chunkY << 7) + (tileY << 4);448sensor->collided = true;449sensor->angle = 0x100 - (uint8)(0x180 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF000000) >> 24));450break;451}452}453}454455if (sensor->collided) {456if (sensor->angle < 0)457sensor->angle += 0x100;458459if (sensor->angle >= 0x100)460sensor->angle -= 0x100;461462if (sensor->ypos - startY > (TILE_SIZE - 2)) {463sensor->ypos = startY << 16;464sensor->collided = false;465}466else if (sensor->ypos - startY < -(TILE_SIZE + 1)) {467sensor->ypos = startY << 16;468sensor->collided = false;469}470}471}472}473}474}475void RSDK::Legacy::v4::LWallCollision(Entity *player, CollisionSensor *sensor)476{477int32 c;478int32 startX = sensor->xpos >> 16;479int32 tsm1 = (TILE_SIZE - 1);480for (int32 i = 0; i < TILE_SIZE * 3; i += TILE_SIZE) {481if (!sensor->collided) {482int32 XPos = (sensor->xpos >> 16) - TILE_SIZE + i;483int32 chunkX = XPos >> 7;484int32 tileX = (XPos & 0x7F) >> 4;485int32 YPos = sensor->ypos >> 16;486int32 chunkY = YPos >> 7;487int32 tileY = (YPos & 0x7F) >> 4;488if (XPos > -1 && YPos > -1) {489int32 tile = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;490tile += tileX + (tileY << 3);491int32 tileIndex = tiles128x128.tileIndex[tile];492if (tiles128x128.collisionFlags[player->collisionPlane][tile] != SOLID_TOP493&& tiles128x128.collisionFlags[player->collisionPlane][tile] < SOLID_NONE) {494switch (tiles128x128.direction[tile]) {495case FLIP_NONE: {496c = (YPos & tsm1) + (tileIndex << 4);497if ((XPos & tsm1) <= collisionMasks[player->collisionPlane].lWallMasks[c] - TILE_SIZE + i)498break;499500sensor->xpos = collisionMasks[player->collisionPlane].lWallMasks[c] + (chunkX << 7) + (tileX << 4);501sensor->collided = true;502break;503}504case FLIP_X: {505c = (YPos & tsm1) + (tileIndex << 4);506if ((XPos & tsm1) <= tsm1 - collisionMasks[player->collisionPlane].rWallMasks[c] - TILE_SIZE + i)507break;508509sensor->xpos = tsm1 - collisionMasks[player->collisionPlane].rWallMasks[c] + (chunkX << 7) + (tileX << 4);510sensor->collided = true;511break;512}513case FLIP_Y: {514c = tsm1 - (YPos & tsm1) + (tileIndex << 4);515if ((XPos & tsm1) <= collisionMasks[player->collisionPlane].lWallMasks[c] - TILE_SIZE + i)516break;517518sensor->xpos = collisionMasks[player->collisionPlane].lWallMasks[c] + (chunkX << 7) + (tileX << 4);519sensor->collided = true;520break;521}522case FLIP_XY: {523c = tsm1 - (YPos & tsm1) + (tileIndex << 4);524if ((XPos & tsm1) <= tsm1 - collisionMasks[player->collisionPlane].rWallMasks[c] - TILE_SIZE + i)525break;526527sensor->xpos = tsm1 - collisionMasks[player->collisionPlane].rWallMasks[c] + (chunkX << 7) + (tileX << 4);528sensor->collided = true;529break;530}531}532}533534if (sensor->collided) {535if (sensor->xpos - startX > tsm1) {536sensor->xpos = startX << 16;537sensor->collided = false;538}539else if (sensor->xpos - startX < -tsm1) {540sensor->xpos = startX << 16;541sensor->collided = false;542}543}544}545}546}547}548void RSDK::Legacy::v4::RoofCollision(Entity *player, CollisionSensor *sensor)549{550int32 c;551int32 startY = sensor->ypos >> 16;552int32 tsm1 = (TILE_SIZE - 1);553for (int32 i = 0; i < TILE_SIZE * 3; i += TILE_SIZE) {554if (!sensor->collided) {555int32 XPos = sensor->xpos >> 16;556int32 chunkX = XPos >> 7;557int32 tileX = (XPos & 0x7F) >> 4;558int32 YPos = (sensor->ypos >> 16) + TILE_SIZE - i;559int32 chunkY = YPos >> 7;560int32 tileY = (YPos & 0x7F) >> 4;561if (XPos > -1 && YPos > -1) {562int32 tile = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;563tile += tileX + (tileY << 3);564int32 tileIndex = tiles128x128.tileIndex[tile];565if (tiles128x128.collisionFlags[player->collisionPlane][tile] != SOLID_TOP566&& tiles128x128.collisionFlags[player->collisionPlane][tile] < SOLID_NONE) {567switch (tiles128x128.direction[tile]) {568case FLIP_NONE: {569c = (XPos & tsm1) + (tileIndex << 4);570if ((YPos & tsm1) >= collisionMasks[player->collisionPlane].roofMasks[c] + TILE_SIZE - i)571break;572573sensor->ypos = collisionMasks[player->collisionPlane].roofMasks[c] + (chunkY << 7) + (tileY << 4);574sensor->collided = true;575sensor->angle = ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF000000) >> 24);576break;577}578case FLIP_X: {579c = tsm1 - (XPos & tsm1) + (tileIndex << 4);580if ((YPos & tsm1) >= collisionMasks[player->collisionPlane].roofMasks[c] + TILE_SIZE - i)581break;582583sensor->ypos = collisionMasks[player->collisionPlane].roofMasks[c] + (chunkY << 7) + (tileY << 4);584sensor->collided = true;585sensor->angle = 0x100 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF000000) >> 24);586break;587}588case FLIP_Y: {589c = (XPos & tsm1) + (tileIndex << 4);590if ((YPos & tsm1) >= tsm1 - collisionMasks[player->collisionPlane].floorMasks[c] + TILE_SIZE - i)591break;592593sensor->ypos = tsm1 - collisionMasks[player->collisionPlane].floorMasks[c] + (chunkY << 7) + (tileY << 4);594sensor->collided = true;595sensor->angle = 0x180 - (collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF);596break;597}598case FLIP_XY: {599c = tsm1 - (XPos & tsm1) + (tileIndex << 4);600if ((YPos & tsm1) >= tsm1 - collisionMasks[player->collisionPlane].floorMasks[c] + TILE_SIZE - i)601break;602603sensor->ypos = tsm1 - collisionMasks[player->collisionPlane].floorMasks[c] + (chunkY << 7) + (tileY << 4);604sensor->collided = true;605sensor->angle = 0x100 - (uint8)(0x180 - (collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF));606break;607}608}609}610611if (sensor->collided) {612if (sensor->angle < 0)613sensor->angle += 0x100;614615if (sensor->angle >= 0x100)616sensor->angle -= 0x100;617618if (sensor->ypos - startY > (tsm1 - 1)) {619sensor->ypos = startY << 16;620sensor->collided = false;621}622else if (sensor->ypos - startY < -(tsm1 - 1)) {623sensor->ypos = startY << 16;624sensor->collided = false;625}626}627}628}629}630}631void RSDK::Legacy::v4::RWallCollision(Entity *player, CollisionSensor *sensor)632{633int32 c;634int32 startX = sensor->xpos >> 16;635int32 tsm1 = (TILE_SIZE - 1);636for (int32 i = 0; i < TILE_SIZE * 3; i += TILE_SIZE) {637if (!sensor->collided) {638int32 XPos = (sensor->xpos >> 16) + TILE_SIZE - i;639int32 chunkX = XPos >> 7;640int32 tileX = (XPos & 0x7F) >> 4;641int32 YPos = sensor->ypos >> 16;642int32 chunkY = YPos >> 7;643int32 tileY = (YPos & 0x7F) >> 4;644if (XPos > -1 && YPos > -1) {645int32 tile = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;646tile += tileX + (tileY << 3);647int32 tileIndex = tiles128x128.tileIndex[tile];648if (tiles128x128.collisionFlags[player->collisionPlane][tile] != SOLID_TOP649&& tiles128x128.collisionFlags[player->collisionPlane][tile] < SOLID_NONE) {650switch (tiles128x128.direction[tile]) {651case FLIP_NONE: {652c = (YPos & tsm1) + (tileIndex << 4);653if ((XPos & tsm1) >= collisionMasks[player->collisionPlane].rWallMasks[c] + TILE_SIZE - i)654break;655656sensor->xpos = collisionMasks[player->collisionPlane].rWallMasks[c] + (chunkX << 7) + (tileX << 4);657sensor->collided = true;658break;659}660case FLIP_X: {661c = (YPos & tsm1) + (tileIndex << 4);662if ((XPos & tsm1) >= tsm1 - collisionMasks[player->collisionPlane].lWallMasks[c] + TILE_SIZE - i)663break;664665sensor->xpos = tsm1 - collisionMasks[player->collisionPlane].lWallMasks[c] + (chunkX << 7) + (tileX << 4);666sensor->collided = true;667break;668}669case FLIP_Y: {670c = tsm1 - (YPos & tsm1) + (tileIndex << 4);671if ((XPos & tsm1) >= collisionMasks[player->collisionPlane].rWallMasks[c] + TILE_SIZE - i)672break;673674sensor->xpos = collisionMasks[player->collisionPlane].rWallMasks[c] + (chunkX << 7) + (tileX << 4);675sensor->collided = true;676break;677}678case FLIP_XY: {679c = tsm1 - (YPos & tsm1) + (tileIndex << 4);680if ((XPos & tsm1) >= tsm1 - collisionMasks[player->collisionPlane].lWallMasks[c] + TILE_SIZE - i)681break;682683sensor->xpos = tsm1 - collisionMasks[player->collisionPlane].lWallMasks[c] + (chunkX << 7) + (tileX << 4);684sensor->collided = true;685break;686}687}688}689690if (sensor->collided) {691if (sensor->xpos - startX > tsm1) {692sensor->xpos = startX << 16;693sensor->collided = false;694}695else if (sensor->xpos - startX < -tsm1) {696sensor->xpos = startX << 16;697sensor->collided = false;698}699}700}701}702}703}704705void RSDK::Legacy::v4::ProcessAirCollision(Entity *entity)706{707Hitbox *playerHitbox = GetHitbox(entity);708collisionLeft = playerHitbox->left[0];709collisionTop = playerHitbox->top[0];710collisionRight = playerHitbox->right[0];711collisionBottom = playerHitbox->bottom[0];712713uint8 movingDown = 0;714uint8 movingUp = 0;715uint8 movingLeft = 0;716uint8 movingRight = 0;717718if (entity->xvel < 0) {719movingRight = 0;720}721else {722movingRight = 1;723sensors[0].ypos = entity->ypos + 0x40000;724sensors[0].collided = false;725sensors[0].xpos = entity->xpos + (collisionRight << 16);726}727if (entity->xvel > 0) {728movingLeft = 0;729}730else {731movingLeft = 1;732sensors[1].ypos = entity->ypos + 0x40000;733sensors[1].collided = false;734sensors[1].xpos = entity->xpos + ((collisionLeft - 1) << 16);735}736sensors[2].xpos = entity->xpos + (playerHitbox->left[1] << 16);737sensors[3].xpos = entity->xpos + (playerHitbox->right[1] << 16);738sensors[2].collided = false;739sensors[3].collided = false;740sensors[4].xpos = sensors[2].xpos;741sensors[5].xpos = sensors[3].xpos;742sensors[4].collided = false;743sensors[5].collided = false;744if (entity->yvel < 0) {745movingDown = 0;746}747else {748movingDown = 1;749sensors[2].ypos = entity->ypos + (collisionBottom << 16);750sensors[3].ypos = entity->ypos + (collisionBottom << 16);751}752753if (abs(entity->xvel) > 0x10000 || entity->yvel < 0) {754movingUp = 1;755sensors[4].ypos = entity->ypos + ((collisionTop - 1) << 16);756sensors[5].ypos = entity->ypos + ((collisionTop - 1) << 16);757}758759int32 cnt = (abs(entity->xvel) <= abs(entity->yvel) ? (abs(entity->yvel) >> 19) + 1 : (abs(entity->xvel) >> 19) + 1);760int32 XVel = entity->xvel / cnt;761int32 YVel = entity->yvel / cnt;762int32 XVel2 = entity->xvel - XVel * (cnt - 1);763int32 YVel2 = entity->yvel - YVel * (cnt - 1);764while (cnt > 0) {765if (cnt < 2) {766XVel = XVel2;767YVel = YVel2;768}769cnt--;770771if (movingRight == 1) {772sensors[0].xpos += XVel;773sensors[0].ypos += YVel;774LWallCollision(entity, &sensors[0]);775if (sensors[0].collided) {776movingRight = 2;777}778else if (entity->xvel < 0x20000) {779sensors[0].ypos -= 0x80000;780LWallCollision(entity, &sensors[0]);781if (sensors[0].collided)782movingRight = 2;783sensors[0].ypos += 0x80000;784}785}786787if (movingLeft == 1) {788sensors[1].xpos += XVel;789sensors[1].ypos += YVel;790RWallCollision(entity, &sensors[1]);791if (sensors[1].collided) {792movingLeft = 2;793}794else if (entity->xvel > -0x20000) {795sensors[1].ypos -= 0x80000;796RWallCollision(entity, &sensors[1]);797if (sensors[1].collided)798movingLeft = 2;799sensors[1].ypos += 0x80000;800}801}802803if (movingRight == 2) {804entity->xvel = 0;805entity->speed = 0;806entity->xpos = (sensors[0].xpos - collisionRight) << 16;807sensors[2].xpos = entity->xpos + ((collisionLeft + 1) << 16);808sensors[3].xpos = entity->xpos + ((collisionRight - 2) << 16);809sensors[4].xpos = sensors[2].xpos;810sensors[5].xpos = sensors[3].xpos;811XVel = 0;812XVel2 = 0;813movingRight = 3;814}815816if (movingLeft == 2) {817entity->xvel = 0;818entity->speed = 0;819entity->xpos = (sensors[1].xpos - collisionLeft + 1) << 16;820sensors[2].xpos = entity->xpos + ((collisionLeft + 1) << 16);821sensors[3].xpos = entity->xpos + ((collisionRight - 2) << 16);822sensors[4].xpos = sensors[2].xpos;823sensors[5].xpos = sensors[3].xpos;824XVel = 0;825XVel2 = 0;826movingLeft = 3;827}828829if (movingDown == 1) {830for (int32 i = 2; i < 4; i++) {831if (!sensors[i].collided) {832sensors[i].xpos += XVel;833sensors[i].ypos += YVel;834FloorCollision(entity, &sensors[i]);835}836}837if (sensors[2].collided || sensors[3].collided) {838movingDown = 2;839cnt = 0;840}841}842843if (movingUp == 1) {844for (int32 i = 4; i < 6; i++) {845if (!sensors[i].collided) {846sensors[i].xpos += XVel;847sensors[i].ypos += YVel;848RoofCollision(entity, &sensors[i]);849}850}851if (sensors[4].collided || sensors[5].collided) {852movingUp = 2;853cnt = 0;854}855}856}857858if (movingRight < 2 && movingLeft < 2)859entity->xpos = entity->xpos + entity->xvel;860861if (movingUp < 2 && movingDown < 2) {862entity->ypos = entity->ypos + entity->yvel;863return;864}865866if (movingDown == 2) {867entity->gravity = 0;868if (sensors[2].collided && sensors[3].collided) {869if (sensors[2].ypos >= sensors[3].ypos) {870entity->ypos = (sensors[3].ypos - collisionBottom) << 16;871entity->angle = sensors[3].angle;872}873else {874entity->ypos = (sensors[2].ypos - collisionBottom) << 16;875entity->angle = sensors[2].angle;876}877}878else if (sensors[2].collided == 1) {879entity->ypos = (sensors[2].ypos - collisionBottom) << 16;880entity->angle = sensors[2].angle;881}882else if (sensors[3].collided == 1) {883entity->ypos = (sensors[3].ypos - collisionBottom) << 16;884entity->angle = sensors[3].angle;885}886if (entity->angle > 0xA0 && entity->angle < 0xE0 && entity->collisionMode != CMODE_LWALL) {887entity->collisionMode = CMODE_LWALL;888entity->xpos -= 0x40000;889}890if (entity->angle > 0x20 && entity->angle < 0x60 && entity->collisionMode != CMODE_RWALL) {891entity->collisionMode = CMODE_RWALL;892entity->xpos += 0x40000;893}894if (entity->angle < 0x20 || entity->angle > 0xE0) {895entity->controlLock = 0;896}897entity->rotation = entity->angle << 1;898899int32 speed = 0;900if (entity->down) {901if (entity->angle < 128) {902if (entity->angle < 16) {903speed = entity->xvel;904}905else if (entity->angle >= 32) {906speed = (abs(entity->xvel) <= abs(entity->yvel) ? entity->yvel + entity->yvel / 12 : entity->xvel);907}908else {909speed = (abs(entity->xvel) <= abs(entity->yvel >> 1) ? (entity->yvel + entity->yvel / 12) >> 1 : entity->xvel);910}911}912else if (entity->angle > 240) {913speed = entity->xvel;914}915else if (entity->angle <= 224) {916speed = (abs(entity->xvel) <= abs(entity->yvel) ? -(entity->yvel + entity->yvel / 12) : entity->xvel);917}918else {919speed = (abs(entity->xvel) <= abs(entity->yvel >> 1) ? -((entity->yvel + entity->yvel / 12) >> 1) : entity->xvel);920}921}922else if (entity->angle < 0x80) {923if (entity->angle < 0x10) {924speed = entity->xvel;925}926else if (entity->angle >= 0x20) {927speed = (abs(entity->xvel) <= abs(entity->yvel) ? entity->yvel : entity->xvel);928}929else {930speed = (abs(entity->xvel) <= abs(entity->yvel >> 1) ? entity->yvel >> 1 : entity->xvel);931}932}933else if (entity->angle > 0xF0) {934speed = entity->xvel;935}936else if (entity->angle <= 0xE0) {937speed = (abs(entity->xvel) <= abs(entity->yvel) ? -entity->yvel : entity->xvel);938}939else {940speed = (abs(entity->xvel) <= abs(entity->yvel >> 1) ? -(entity->yvel >> 1) : entity->xvel);941}942943if (speed < -0x180000)944speed = -0x180000;945if (speed > 0x180000)946speed = 0x180000;947entity->speed = speed;948entity->yvel = 0;949scriptEng.checkResult = 1;950}951952if (movingUp == 2) {953int32 sensorAngle = 0;954if (sensors[4].collided && sensors[5].collided) {955if (sensors[4].ypos <= sensors[5].ypos) {956entity->ypos = (sensors[5].ypos - collisionTop + 1) << 16;957sensorAngle = sensors[5].angle;958}959else {960entity->ypos = (sensors[4].ypos - collisionTop + 1) << 16;961sensorAngle = sensors[4].angle;962}963}964else if (sensors[4].collided) {965entity->ypos = (sensors[4].ypos - collisionTop + 1) << 16;966sensorAngle = sensors[4].angle;967}968else if (sensors[5].collided) {969entity->ypos = (sensors[5].ypos - collisionTop + 1) << 16;970sensorAngle = sensors[5].angle;971}972sensorAngle &= 0xFF;973974int32 angle = ArcTanLookup(entity->xvel, entity->yvel);975if (sensorAngle > 0x40 && sensorAngle < 0x62 && angle > 0xA0 && angle < 0xC2) {976entity->gravity = 0;977entity->angle = sensorAngle;978entity->rotation = entity->angle << 1;979entity->collisionMode = CMODE_RWALL;980entity->xpos += 0x40000;981entity->ypos -= 0x20000;982if (entity->angle <= 0x60)983entity->speed = entity->yvel;984else985entity->speed = entity->yvel >> 1;986}987if (sensorAngle > 0x9E && sensorAngle < 0xC0 && angle > 0xBE && angle < 0xE0) {988entity->gravity = 0;989entity->angle = sensorAngle;990entity->rotation = entity->angle << 1;991entity->collisionMode = CMODE_LWALL;992entity->xpos -= 0x40000;993entity->ypos -= 0x20000;994if (entity->angle >= 0xA0)995entity->speed = -entity->yvel;996else997entity->speed = -entity->yvel >> 1;998}999if (entity->yvel < 0)1000entity->yvel = 0;1001scriptEng.checkResult = 2;1002}1003}1004void RSDK::Legacy::v4::ProcessPathGrip(Entity *entity)1005{1006int32 cosValue256;1007int32 sinValue256;1008sensors[4].xpos = entity->xpos;1009sensors[4].ypos = entity->ypos;1010for (int32 i = 0; i < 7; ++i) {1011sensors[i].angle = entity->angle;1012sensors[i].collided = false;1013}1014SetPathGripSensors(entity);1015int32 absSpeed = abs(entity->speed);1016int32 checkDist = absSpeed >> 18;1017absSpeed &= 0x3FFFF;1018uint8 cMode = entity->collisionMode;10191020while (checkDist > -1) {1021if (checkDist >= 1) {1022cosValue256 = cos256LookupTable[entity->angle] << 10;1023sinValue256 = sin256LookupTable[entity->angle] << 10;1024checkDist--;1025}1026else {1027cosValue256 = absSpeed * cos256LookupTable[entity->angle] >> 8;1028sinValue256 = absSpeed * sin256LookupTable[entity->angle] >> 8;1029checkDist = -1;1030}10311032if (entity->speed < 0) {1033cosValue256 = -cosValue256;1034sinValue256 = -sinValue256;1035}10361037sensors[0].collided = false;1038sensors[1].collided = false;1039sensors[2].collided = false;1040sensors[5].collided = false;1041sensors[6].collided = false;1042sensors[4].xpos += cosValue256;1043sensors[4].ypos += sinValue256;1044int32 tileDistance = -1;10451046switch (entity->collisionMode) {1047case CMODE_FLOOR: {1048sensors[3].xpos += cosValue256;1049sensors[3].ypos += sinValue256;10501051if (entity->speed > 0) {1052LWallCollision(entity, &sensors[3]);1053if (sensors[3].collided) {1054sensors[2].xpos = (sensors[3].xpos - 2) << 16;1055}1056}10571058if (entity->speed < 0) {1059RWallCollision(entity, &sensors[3]);1060if (sensors[3].collided) {1061sensors[0].xpos = (sensors[3].xpos + 2) << 16;1062}1063}10641065if (sensors[3].collided) {1066cosValue256 = 0;1067checkDist = -1;1068}10691070for (int32 i = 0; i < 3; i++) {1071sensors[i].xpos += cosValue256;1072sensors[i].ypos += sinValue256;1073FindFloorPosition(entity, &sensors[i], sensors[i].ypos >> 16);1074}10751076for (int32 i = 5; i < 7; i++) {1077sensors[i].xpos += cosValue256;1078sensors[i].ypos += sinValue256;1079FindFloorPosition(entity, &sensors[i], sensors[i].ypos >> 16);1080}10811082tileDistance = -1;1083for (int32 i = 0; i < 3; i++) {1084if (tileDistance > -1) {1085if (sensors[i].collided) {1086if (sensors[i].ypos < sensors[tileDistance].ypos)1087tileDistance = i;10881089if (sensors[i].ypos == sensors[tileDistance].ypos && (sensors[i].angle < 0x08 || sensors[i].angle > 0xF8))1090tileDistance = i;1091}1092}1093else if (sensors[i].collided)1094tileDistance = i;1095}10961097if (tileDistance <= -1) {1098checkDist = -1;1099}1100else {1101sensors[0].ypos = sensors[tileDistance].ypos << 16;1102sensors[0].angle = sensors[tileDistance].angle;1103sensors[1].ypos = sensors[0].ypos;1104sensors[1].angle = sensors[0].angle;1105sensors[2].ypos = sensors[0].ypos;1106sensors[2].angle = sensors[0].angle;1107sensors[3].ypos = sensors[0].ypos - 0x40000;1108sensors[3].angle = sensors[0].angle;1109sensors[4].xpos = sensors[1].xpos;1110sensors[4].ypos = sensors[0].ypos - (collisionBottom << 16);1111}11121113if (sensors[0].angle < 0xDE && sensors[0].angle > 0x80)1114entity->collisionMode = CMODE_LWALL;1115if (sensors[0].angle > 0x22 && sensors[0].angle < 0x80)1116entity->collisionMode = CMODE_RWALL;1117break;1118}1119case CMODE_LWALL: {1120sensors[3].xpos += cosValue256;1121sensors[3].ypos += sinValue256;11221123if (entity->speed > 0)1124RoofCollision(entity, &sensors[3]);11251126if (entity->speed < 0)1127FloorCollision(entity, &sensors[3]);11281129if (sensors[3].collided) {1130sinValue256 = 0;1131checkDist = -1;1132}1133for (int32 i = 0; i < 3; i++) {1134sensors[i].xpos += cosValue256;1135sensors[i].ypos += sinValue256;1136FindLWallPosition(entity, &sensors[i], sensors[i].xpos >> 16);1137}11381139tileDistance = -1;1140for (int32 i = 0; i < 3; i++) {1141if (tileDistance > -1) {1142if (sensors[i].xpos < sensors[tileDistance].xpos && sensors[i].collided) {1143tileDistance = i;1144}1145}1146else if (sensors[i].collided) {1147tileDistance = i;1148}1149}11501151if (tileDistance <= -1) {1152checkDist = -1;1153}1154else {1155sensors[0].xpos = sensors[tileDistance].xpos << 16;1156sensors[0].angle = sensors[tileDistance].angle;1157sensors[1].xpos = sensors[0].xpos;1158sensors[1].angle = sensors[0].angle;1159sensors[2].xpos = sensors[0].xpos;1160sensors[2].angle = sensors[0].angle;1161sensors[4].ypos = sensors[1].ypos;1162sensors[4].xpos = sensors[1].xpos - (collisionRight << 16);1163}11641165if (sensors[0].angle > 0xE2)1166entity->collisionMode = CMODE_FLOOR;1167if (sensors[0].angle < 0x9E)1168entity->collisionMode = CMODE_ROOF;1169break;1170break;1171}1172case CMODE_ROOF: {1173sensors[3].xpos += cosValue256;1174sensors[3].ypos += sinValue256;11751176if (entity->speed > 0)1177RWallCollision(entity, &sensors[3]);11781179if (entity->speed < 0)1180LWallCollision(entity, &sensors[3]);11811182if (sensors[3].collided) {1183cosValue256 = 0;1184checkDist = -1;1185}1186for (int32 i = 0; i < 3; i++) {1187sensors[i].xpos += cosValue256;1188sensors[i].ypos += sinValue256;1189FindRoofPosition(entity, &sensors[i], sensors[i].ypos >> 16);1190}11911192tileDistance = -1;1193for (int32 i = 0; i < 3; i++) {1194if (tileDistance > -1) {1195if (sensors[i].ypos > sensors[tileDistance].ypos && sensors[i].collided) {1196tileDistance = i;1197}1198}1199else if (sensors[i].collided) {1200tileDistance = i;1201}1202}12031204if (tileDistance <= -1) {1205checkDist = -1;1206}1207else {1208sensors[0].ypos = sensors[tileDistance].ypos << 16;1209sensors[0].angle = sensors[tileDistance].angle;1210sensors[1].ypos = sensors[0].ypos;1211sensors[1].angle = sensors[0].angle;1212sensors[2].ypos = sensors[0].ypos;1213sensors[2].angle = sensors[0].angle;1214sensors[3].ypos = sensors[0].ypos + 0x40000;1215sensors[3].angle = sensors[0].angle;1216sensors[4].xpos = sensors[1].xpos;1217sensors[4].ypos = sensors[0].ypos - ((collisionTop - 1) << 16);1218}12191220if (sensors[0].angle > 0xA2)1221entity->collisionMode = CMODE_LWALL;1222if (sensors[0].angle < 0x5E)1223entity->collisionMode = CMODE_RWALL;1224break;1225}1226case CMODE_RWALL: {1227sensors[3].xpos += cosValue256;1228sensors[3].ypos += sinValue256;12291230if (entity->speed > 0)1231FloorCollision(entity, &sensors[3]);12321233if (entity->speed < 0)1234RoofCollision(entity, &sensors[3]);12351236if (sensors[3].collided) {1237sinValue256 = 0;1238checkDist = -1;1239}1240for (int32 i = 0; i < 3; i++) {1241sensors[i].xpos += cosValue256;1242sensors[i].ypos += sinValue256;1243FindRWallPosition(entity, &sensors[i], sensors[i].xpos >> 16);1244}12451246tileDistance = -1;1247for (int32 i = 0; i < 3; i++) {1248if (tileDistance > -1) {1249if (sensors[i].xpos > sensors[tileDistance].xpos && sensors[i].collided) {1250tileDistance = i;1251}1252}1253else if (sensors[i].collided) {1254tileDistance = i;1255}1256}12571258if (tileDistance <= -1) {1259checkDist = -1;1260}1261else {1262sensors[0].xpos = sensors[tileDistance].xpos << 16;1263sensors[0].angle = sensors[tileDistance].angle;1264sensors[1].xpos = sensors[0].xpos;1265sensors[1].angle = sensors[0].angle;1266sensors[2].xpos = sensors[0].xpos;1267sensors[2].angle = sensors[0].angle;1268sensors[4].ypos = sensors[1].ypos;1269sensors[4].xpos = sensors[1].xpos - ((collisionLeft - 1) << 16);1270}12711272if (sensors[0].angle < 0x1E)1273entity->collisionMode = CMODE_FLOOR;1274if (sensors[0].angle > 0x62)1275entity->collisionMode = CMODE_ROOF;1276break;1277}1278}1279if (tileDistance != -1)1280entity->angle = sensors[0].angle;12811282if (!sensors[3].collided)1283SetPathGripSensors(entity);1284else1285checkDist = -2;1286}12871288switch (cMode) {1289case CMODE_FLOOR: {1290if (sensors[0].collided || sensors[1].collided || sensors[2].collided) {1291entity->angle = sensors[0].angle;1292entity->rotation = entity->angle << 1;1293entity->floorSensors[0] = sensors[0].collided;1294entity->floorSensors[1] = sensors[1].collided;1295entity->floorSensors[2] = sensors[2].collided;1296entity->floorSensors[3] = sensors[5].collided;1297entity->floorSensors[4] = sensors[6].collided;12981299if (!sensors[3].collided) {1300entity->pushing = 0;1301entity->xpos = sensors[4].xpos;1302}1303else {1304if (entity->speed > 0)1305entity->xpos = (sensors[3].xpos - collisionRight) << 16;13061307if (entity->speed < 0)1308entity->xpos = (sensors[3].xpos - collisionLeft + 1) << 16;13091310entity->speed = 0;1311if ((entity->left || entity->right) && entity->pushing < 2)1312entity->pushing++;1313}1314entity->ypos = sensors[4].ypos;1315}1316else {1317entity->gravity = 1;1318entity->collisionMode = CMODE_FLOOR;1319entity->xvel = cos256LookupTable[entity->angle] * entity->speed >> 8;1320entity->yvel = sin256LookupTable[entity->angle] * entity->speed >> 8;1321if (entity->yvel < -0x100000)1322entity->yvel = -0x100000;13231324if (entity->yvel > 0x100000)1325entity->yvel = 0x100000;13261327entity->speed = entity->xvel;1328entity->angle = 0;1329if (!sensors[3].collided) {1330entity->pushing = 0;1331entity->xpos += entity->xvel;1332}1333else {1334if (entity->speed > 0)1335entity->xpos = (sensors[3].xpos - collisionRight) << 16;1336if (entity->speed < 0)1337entity->xpos = (sensors[3].xpos - collisionLeft + 1) << 16;13381339entity->speed = 0;1340if ((entity->left || entity->right) && entity->pushing < 2)1341entity->pushing++;1342}1343entity->ypos += entity->yvel;1344}1345break;1346}1347case CMODE_LWALL: {1348if (!sensors[0].collided && !sensors[1].collided && !sensors[2].collided) {1349entity->gravity = 1;1350entity->collisionMode = CMODE_FLOOR;1351entity->xvel = cos256LookupTable[entity->angle] * entity->speed >> 8;1352entity->yvel = sin256LookupTable[entity->angle] * entity->speed >> 8;1353if (entity->yvel < -0x100000) {1354entity->yvel = -0x100000;1355}1356if (entity->yvel > 0x100000) {1357entity->yvel = 0x100000;1358}1359entity->speed = entity->xvel;1360entity->angle = 0;1361}1362else if (entity->speed >= 0x28000 || entity->speed <= -0x28000 || entity->controlLock != 0) {1363entity->angle = sensors[0].angle;1364entity->rotation = entity->angle << 1;1365}1366else {1367entity->gravity = 1;1368entity->angle = 0;1369entity->collisionMode = CMODE_FLOOR;1370entity->speed = entity->xvel;1371entity->controlLock = 30;1372}1373if (!sensors[3].collided) {1374entity->ypos = sensors[4].ypos;1375}1376else {1377if (entity->speed > 0)1378entity->ypos = (sensors[3].ypos - collisionTop) << 16;13791380if (entity->speed < 0)1381entity->ypos = (sensors[3].ypos - collisionBottom) << 16;13821383entity->speed = 0;1384}1385entity->xpos = sensors[4].xpos;1386break;1387}1388case CMODE_ROOF: {1389if (!sensors[0].collided && !sensors[1].collided && !sensors[2].collided) {1390entity->gravity = 1;1391entity->collisionMode = CMODE_FLOOR;1392entity->xvel = cos256LookupTable[entity->angle] * entity->speed >> 8;1393entity->yvel = sin256LookupTable[entity->angle] * entity->speed >> 8;1394entity->floorSensors[0] = false;1395entity->floorSensors[1] = false;1396entity->floorSensors[2] = false;1397if (entity->yvel < -0x100000)1398entity->yvel = -0x100000;13991400if (entity->yvel > 0x100000)1401entity->yvel = 0x100000;14021403entity->angle = 0;1404entity->speed = entity->xvel;1405if (!sensors[3].collided) {1406entity->xpos = entity->xpos + entity->xvel;1407}1408else {1409if (entity->speed > 0)1410entity->xpos = (sensors[3].xpos - collisionRight) << 16;14111412if (entity->speed < 0)1413entity->xpos = (sensors[3].xpos - collisionLeft + 1) << 16;14141415entity->speed = 0;1416}1417}1418else if (entity->speed <= -0x28000 || entity->speed >= 0x28000) {1419entity->angle = sensors[0].angle;1420entity->rotation = entity->angle << 1;1421if (!sensors[3].collided) {1422entity->xpos = sensors[4].xpos;1423}1424else {1425if (entity->speed < 0)1426entity->xpos = (sensors[3].xpos - collisionRight) << 16;14271428if (entity->speed > 0)1429entity->xpos = (sensors[3].xpos - collisionLeft + 1) << 16;1430entity->speed = 0;1431}1432}1433else {1434entity->gravity = 1;1435entity->angle = 0;1436entity->collisionMode = CMODE_FLOOR;1437entity->speed = entity->xvel;1438entity->floorSensors[0] = false;1439entity->floorSensors[1] = false;1440entity->floorSensors[2] = false;1441if (!sensors[3].collided) {1442entity->xpos = entity->xpos + entity->xvel;1443}1444else {1445if (entity->speed > 0)1446entity->xpos = (sensors[3].xpos - collisionRight) << 16;14471448if (entity->speed < 0)1449entity->xpos = (sensors[3].xpos - collisionLeft + 1) << 16;1450entity->speed = 0;1451}1452}1453entity->ypos = sensors[4].ypos;1454break;1455}1456case CMODE_RWALL: {1457if (!sensors[0].collided && !sensors[1].collided && !sensors[2].collided) {1458entity->gravity = 1;1459entity->collisionMode = CMODE_FLOOR;1460entity->xvel = cos256LookupTable[entity->angle] * entity->speed >> 8;1461entity->yvel = sin256LookupTable[entity->angle] * entity->speed >> 8;1462if (entity->yvel < -0x100000)1463entity->yvel = -0x100000;14641465if (entity->yvel > 0x100000)1466entity->yvel = 0x100000;14671468entity->speed = entity->xvel;1469entity->angle = 0;1470}1471else if (entity->speed <= -0x28000 || entity->speed >= 0x28000 || entity->controlLock != 0) {1472entity->angle = sensors[0].angle;1473entity->rotation = entity->angle << 1;1474}1475else {1476entity->gravity = 1;1477entity->angle = 0;1478entity->collisionMode = CMODE_FLOOR;1479entity->speed = entity->xvel;1480entity->controlLock = 30;1481}1482if (!sensors[3].collided) {1483entity->ypos = sensors[4].ypos;1484}1485else {1486if (entity->speed > 0)1487entity->ypos = (sensors[3].ypos - collisionBottom) << 16;14881489if (entity->speed < 0)1490entity->ypos = (sensors[3].ypos - collisionTop + 1) << 16;14911492entity->speed = 0;1493}1494entity->xpos = sensors[4].xpos;1495break;1496}1497default: break;1498}1499}15001501void RSDK::Legacy::v4::SetPathGripSensors(Entity *player)1502{1503Hitbox *playerHitbox = GetHitbox(player);15041505switch (player->collisionMode) {1506case CMODE_FLOOR: {1507collisionLeft = playerHitbox->left[0];1508collisionTop = playerHitbox->top[0];1509collisionRight = playerHitbox->right[0];1510collisionBottom = playerHitbox->bottom[0];1511sensors[0].ypos = sensors[4].ypos + (collisionBottom << 16);1512sensors[1].ypos = sensors[0].ypos;1513sensors[2].ypos = sensors[0].ypos;1514sensors[3].ypos = sensors[4].ypos + 0x40000;1515sensors[5].ypos = sensors[0].ypos;1516sensors[6].ypos = sensors[0].ypos;15171518sensors[0].xpos = sensors[4].xpos + ((playerHitbox->left[1] - 1) << 16);1519sensors[1].xpos = sensors[4].xpos;1520sensors[2].xpos = sensors[4].xpos + (playerHitbox->right[1] << 16);1521sensors[5].xpos = sensors[4].xpos + (playerHitbox->left[1] << 15);1522sensors[6].xpos = sensors[4].xpos + (playerHitbox->right[1] << 15);15231524if (player->speed > 0) {1525sensors[3].xpos = sensors[4].xpos + ((collisionRight + 1) << 16);1526}1527else {1528sensors[3].xpos = sensors[4].xpos + ((collisionLeft - 1) << 16);1529}1530return;1531}1532case CMODE_LWALL: {1533collisionLeft = playerHitbox->left[2];1534collisionTop = playerHitbox->top[2];1535collisionRight = playerHitbox->right[2];1536collisionBottom = playerHitbox->bottom[2];1537sensors[0].xpos = sensors[4].xpos + (collisionRight << 16);1538sensors[1].xpos = sensors[0].xpos;1539sensors[2].xpos = sensors[0].xpos;1540sensors[3].xpos = sensors[4].xpos + 0x40000;1541sensors[0].ypos = sensors[4].ypos + ((playerHitbox->top[3] - 1) << 16);1542sensors[1].ypos = sensors[4].ypos;1543sensors[2].ypos = sensors[4].ypos + (playerHitbox->bottom[3] << 16);1544if (player->speed > 0) {1545sensors[3].ypos = sensors[4].ypos + (collisionTop << 16);1546}1547else {1548sensors[3].ypos = sensors[4].ypos + ((collisionBottom - 1) << 16);1549}1550return;1551}1552case CMODE_ROOF: {1553collisionLeft = playerHitbox->left[4];1554collisionTop = playerHitbox->top[4];1555collisionRight = playerHitbox->right[4];1556collisionBottom = playerHitbox->bottom[4];1557sensors[0].ypos = sensors[4].ypos + ((collisionTop - 1) << 16);1558sensors[1].ypos = sensors[0].ypos;1559sensors[2].ypos = sensors[0].ypos;1560sensors[3].ypos = sensors[4].ypos - 0x40000;1561sensors[0].xpos = sensors[4].xpos + ((playerHitbox->left[5] - 1) << 16);1562sensors[1].xpos = sensors[4].xpos;1563sensors[2].xpos = sensors[4].xpos + (playerHitbox->right[5] << 16);1564if (player->speed < 0) {1565sensors[3].xpos = sensors[4].xpos + ((collisionRight + 1) << 16);1566}1567else {1568sensors[3].xpos = sensors[4].xpos + ((collisionLeft - 1) << 16);1569}1570return;1571}1572case CMODE_RWALL: {1573collisionLeft = playerHitbox->left[6];1574collisionTop = playerHitbox->top[6];1575collisionRight = playerHitbox->right[6];1576collisionBottom = playerHitbox->bottom[6];1577sensors[0].xpos = sensors[4].xpos + ((collisionLeft - 1) << 16);1578sensors[1].xpos = sensors[0].xpos;1579sensors[2].xpos = sensors[0].xpos;1580sensors[3].xpos = sensors[4].xpos - 0x40000;1581sensors[0].ypos = sensors[4].ypos + ((playerHitbox->top[7] - 1) << 16);1582sensors[1].ypos = sensors[4].ypos;1583sensors[2].ypos = sensors[4].ypos + (playerHitbox->bottom[7] << 16);1584if (player->speed > 0) {1585sensors[3].ypos = sensors[4].ypos + (collisionBottom << 16);1586}1587else {1588sensors[3].ypos = sensors[4].ypos + ((collisionTop - 1) << 16);1589}1590return;1591}1592default: return;1593}1594}15951596void RSDK::Legacy::v4::ProcessTileCollisions(Entity *player)1597{1598player->floorSensors[0] = false;1599player->floorSensors[1] = false;1600player->floorSensors[2] = false;1601player->floorSensors[3] = false;1602player->floorSensors[4] = false;16031604scriptEng.checkResult = false;16051606collisionTolerance = 15;1607if (player->speed < 0x60000)1608collisionTolerance = player->angle == 0 ? 8 : 15;16091610if (player->gravity == 1)1611ProcessAirCollision(player);1612else1613ProcessPathGrip(player);1614}16151616void RSDK::Legacy::v4::ObjectFloorCollision(int32 xOffset, int32 yOffset, int32 cPath)1617{1618scriptEng.checkResult = false;1619Entity *entity = &objectEntityList[objectEntityPos];1620int32 c = 0;1621int32 XPos = (entity->xpos >> 16) + xOffset;1622int32 YPos = (entity->ypos >> 16) + yOffset;1623if (XPos > 0 && XPos < stageLayouts[0].xsize << 7 && YPos > 0 && YPos < stageLayouts[0].ysize << 7) {1624int32 chunkX = XPos >> 7;1625int32 tileX = (XPos & 0x7F) >> 4;1626int32 chunkY = YPos >> 7;1627int32 tileY = (YPos & 0x7F) >> 4;1628int32 chunk = (stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6) + tileX + (tileY << 3);1629int32 tileIndex = tiles128x128.tileIndex[chunk];1630if (tiles128x128.collisionFlags[cPath][chunk] != SOLID_LRB && tiles128x128.collisionFlags[cPath][chunk] != SOLID_NONE) {1631switch (tiles128x128.direction[chunk]) {1632case 0: {1633c = (XPos & 15) + (tileIndex << 4);1634if ((YPos & 15) <= collisionMasks[cPath].floorMasks[c]) {1635break;1636}1637YPos = collisionMasks[cPath].floorMasks[c] + (chunkY << 7) + (tileY << 4);1638scriptEng.checkResult = true;1639break;1640}1641case 1: {1642c = 15 - (XPos & 15) + (tileIndex << 4);1643if ((YPos & 15) <= collisionMasks[cPath].floorMasks[c]) {1644break;1645}1646YPos = collisionMasks[cPath].floorMasks[c] + (chunkY << 7) + (tileY << 4);1647scriptEng.checkResult = true;1648break;1649}1650case 2: {1651c = (XPos & 15) + (tileIndex << 4);1652if ((YPos & 15) <= 15 - collisionMasks[cPath].roofMasks[c]) {1653break;1654}1655YPos = 15 - collisionMasks[cPath].roofMasks[c] + (chunkY << 7) + (tileY << 4);1656scriptEng.checkResult = true;1657break;1658}1659case 3: {1660c = 15 - (XPos & 15) + (tileIndex << 4);1661if ((YPos & 15) <= 15 - collisionMasks[cPath].roofMasks[c]) {1662break;1663}1664YPos = 15 - collisionMasks[cPath].roofMasks[c] + (chunkY << 7) + (tileY << 4);1665scriptEng.checkResult = true;1666break;1667}1668}1669}1670if (scriptEng.checkResult) {1671entity->ypos = (YPos - yOffset) << 16;1672}1673}1674}1675void RSDK::Legacy::v4::ObjectLWallCollision(int32 xOffset, int32 yOffset, int32 cPath)1676{1677int32 c;1678scriptEng.checkResult = false;1679Entity *entity = &objectEntityList[objectEntityPos];1680int32 XPos = (entity->xpos >> 16) + xOffset;1681int32 YPos = (entity->ypos >> 16) + yOffset;1682if (XPos > 0 && XPos < stageLayouts[0].xsize << 7 && YPos > 0 && YPos < stageLayouts[0].ysize << 7) {1683int32 chunkX = XPos >> 7;1684int32 tileX = (XPos & 0x7F) >> 4;1685int32 chunkY = YPos >> 7;1686int32 tileY = (YPos & 0x7F) >> 4;1687int32 chunk = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;1688chunk = chunk + tileX + (tileY << 3);1689int32 tileIndex = tiles128x128.tileIndex[chunk];1690if (tiles128x128.collisionFlags[cPath][chunk] != SOLID_TOP && tiles128x128.collisionFlags[cPath][chunk] < SOLID_NONE) {1691switch (tiles128x128.direction[chunk]) {1692case 0: {1693c = (YPos & 15) + (tileIndex << 4);1694if ((XPos & 15) <= collisionMasks[cPath].lWallMasks[c]) {1695break;1696}1697XPos = collisionMasks[cPath].lWallMasks[c] + (chunkX << 7) + (tileX << 4);1698scriptEng.checkResult = true;1699break;1700}1701case 1: {1702c = (YPos & 15) + (tileIndex << 4);1703if ((XPos & 15) <= 15 - collisionMasks[cPath].rWallMasks[c]) {1704break;1705}1706XPos = 15 - collisionMasks[cPath].rWallMasks[c] + (chunkX << 7) + (tileX << 4);1707scriptEng.checkResult = true;1708break;1709}1710case 2: {1711c = 15 - (YPos & 15) + (tileIndex << 4);1712if ((XPos & 15) <= collisionMasks[cPath].lWallMasks[c]) {1713break;1714}1715XPos = collisionMasks[cPath].lWallMasks[c] + (chunkX << 7) + (tileX << 4);1716scriptEng.checkResult = true;1717break;1718}1719case 3: {1720c = 15 - (YPos & 15) + (tileIndex << 4);1721if ((XPos & 15) <= 15 - collisionMasks[cPath].rWallMasks[c]) {1722break;1723}1724XPos = 15 - collisionMasks[cPath].rWallMasks[c] + (chunkX << 7) + (tileX << 4);1725scriptEng.checkResult = true;1726break;1727}1728}1729}1730if (scriptEng.checkResult) {1731entity->xpos = (XPos - xOffset) << 16;1732}1733}1734}1735void RSDK::Legacy::v4::ObjectRoofCollision(int32 xOffset, int32 yOffset, int32 cPath)1736{1737int32 c;1738scriptEng.checkResult = false;1739Entity *entity = &objectEntityList[objectEntityPos];1740int32 XPos = (entity->xpos >> 16) + xOffset;1741int32 YPos = (entity->ypos >> 16) + yOffset;1742if (XPos > 0 && XPos < stageLayouts[0].xsize << 7 && YPos > 0 && YPos < stageLayouts[0].ysize << 7) {1743int32 chunkX = XPos >> 7;1744int32 tileX = (XPos & 0x7F) >> 4;1745int32 chunkY = YPos >> 7;1746int32 tileY = (YPos & 0x7F) >> 4;1747int32 chunk = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;1748chunk = chunk + tileX + (tileY << 3);1749int32 tileIndex = tiles128x128.tileIndex[chunk];1750if (tiles128x128.collisionFlags[cPath][chunk] != SOLID_TOP && tiles128x128.collisionFlags[cPath][chunk] < SOLID_NONE) {1751switch (tiles128x128.direction[chunk]) {1752case 0: {1753c = (XPos & 15) + (tileIndex << 4);1754if ((YPos & 15) >= collisionMasks[cPath].roofMasks[c]) {1755break;1756}1757YPos = collisionMasks[cPath].roofMasks[c] + (chunkY << 7) + (tileY << 4);1758scriptEng.checkResult = true;1759break;1760}1761case 1: {1762c = 15 - (XPos & 15) + (tileIndex << 4);1763if ((YPos & 15) >= collisionMasks[cPath].roofMasks[c]) {1764break;1765}1766YPos = collisionMasks[cPath].roofMasks[c] + (chunkY << 7) + (tileY << 4);1767scriptEng.checkResult = true;1768break;1769}1770case 2: {1771c = (XPos & 15) + (tileIndex << 4);1772if ((YPos & 15) >= 15 - collisionMasks[cPath].floorMasks[c]) {1773break;1774}1775YPos = 15 - collisionMasks[cPath].floorMasks[c] + (chunkY << 7) + (tileY << 4);1776scriptEng.checkResult = true;1777break;1778}1779case 3: {1780c = 15 - (XPos & 15) + (tileIndex << 4);1781if ((YPos & 15) >= 15 - collisionMasks[cPath].floorMasks[c]) {1782break;1783}1784YPos = 15 - collisionMasks[cPath].floorMasks[c] + (chunkY << 7) + (tileY << 4);1785scriptEng.checkResult = true;1786break;1787}1788}1789}1790if (scriptEng.checkResult) {1791entity->ypos = (YPos - yOffset) << 16;1792}1793}1794}1795void RSDK::Legacy::v4::ObjectRWallCollision(int32 xOffset, int32 yOffset, int32 cPath)1796{1797int32 c;1798scriptEng.checkResult = false;1799Entity *entity = &objectEntityList[objectEntityPos];1800int32 XPos = (entity->xpos >> 16) + xOffset;1801int32 YPos = (entity->ypos >> 16) + yOffset;1802if (XPos > 0 && XPos < stageLayouts[0].xsize << 7 && YPos > 0 && YPos < stageLayouts[0].ysize << 7) {1803int32 chunkX = XPos >> 7;1804int32 tileX = (XPos & 0x7F) >> 4;1805int32 chunkY = YPos >> 7;1806int32 tileY = (YPos & 0x7F) >> 4;1807int32 chunk = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;1808chunk = chunk + tileX + (tileY << 3);1809int32 tileIndex = tiles128x128.tileIndex[chunk];1810if (tiles128x128.collisionFlags[cPath][chunk] != SOLID_TOP && tiles128x128.collisionFlags[cPath][chunk] < SOLID_NONE) {1811switch (tiles128x128.direction[chunk]) {1812case 0: {1813c = (YPos & 15) + (tileIndex << 4);1814if ((XPos & 15) >= collisionMasks[cPath].rWallMasks[c]) {1815break;1816}1817XPos = collisionMasks[cPath].rWallMasks[c] + (chunkX << 7) + (tileX << 4);1818scriptEng.checkResult = true;1819break;1820}1821case 1: {1822c = (YPos & 15) + (tileIndex << 4);1823if ((XPos & 15) >= 15 - collisionMasks[cPath].lWallMasks[c]) {1824break;1825}1826XPos = 15 - collisionMasks[cPath].lWallMasks[c] + (chunkX << 7) + (tileX << 4);1827scriptEng.checkResult = true;1828break;1829}1830case 2: {1831c = 15 - (YPos & 15) + (tileIndex << 4);1832if ((XPos & 15) >= collisionMasks[cPath].rWallMasks[c]) {1833break;1834}1835XPos = collisionMasks[cPath].rWallMasks[c] + (chunkX << 7) + (tileX << 4);1836scriptEng.checkResult = true;1837break;1838}1839case 3: {1840c = 15 - (YPos & 15) + (tileIndex << 4);1841if ((XPos & 15) >= 15 - collisionMasks[cPath].lWallMasks[c]) {1842break;1843}1844XPos = 15 - collisionMasks[cPath].lWallMasks[c] + (chunkX << 7) + (tileX << 4);1845scriptEng.checkResult = true;1846break;1847}1848}1849}1850if (scriptEng.checkResult) {1851entity->xpos = (XPos - xOffset) << 16;1852}1853}1854}18551856void RSDK::Legacy::v4::ObjectFloorGrip(int32 xOffset, int32 yOffset, int32 cPath)1857{1858int32 c;1859scriptEng.checkResult = false;1860Entity *entity = &objectEntityList[objectEntityPos];1861int32 XPos = (entity->xpos >> 16) + xOffset;1862int32 YPos = (entity->ypos >> 16) + yOffset;1863int32 chunkX = YPos;1864YPos = YPos - 16;1865for (int32 i = 3; i > 0; i--) {1866if (XPos > 0 && XPos < stageLayouts[0].xsize << 7 && YPos > 0 && YPos < stageLayouts[0].ysize << 7 && !scriptEng.checkResult) {1867int32 chunkX = XPos >> 7;1868int32 tileX = (XPos & 0x7F) >> 4;1869int32 chunkY = YPos >> 7;1870int32 tileY = (YPos & 0x7F) >> 4;1871int32 chunk = (stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6) + tileX + (tileY << 3);1872int32 tileIndex = tiles128x128.tileIndex[chunk];1873if (tiles128x128.collisionFlags[cPath][chunk] != SOLID_LRB && tiles128x128.collisionFlags[cPath][chunk] != SOLID_NONE) {1874switch (tiles128x128.direction[chunk]) {1875case 0: {1876c = (XPos & 15) + (tileIndex << 4);1877if (collisionMasks[cPath].floorMasks[c] >= 64) {1878break;1879}1880entity->ypos = collisionMasks[cPath].floorMasks[c] + (chunkY << 7) + (tileY << 4);1881scriptEng.checkResult = true;1882break;1883}1884case 1: {1885c = 15 - (XPos & 15) + (tileIndex << 4);1886if (collisionMasks[cPath].floorMasks[c] >= 64) {1887break;1888}1889entity->ypos = collisionMasks[cPath].floorMasks[c] + (chunkY << 7) + (tileY << 4);1890scriptEng.checkResult = true;1891break;1892}1893case 2: {1894c = (XPos & 15) + (tileIndex << 4);1895if (collisionMasks[cPath].roofMasks[c] <= -64) {1896break;1897}1898entity->ypos = 15 - collisionMasks[cPath].roofMasks[c] + (chunkY << 7) + (tileY << 4);1899scriptEng.checkResult = true;1900break;1901}1902case 3: {1903c = 15 - (XPos & 15) + (tileIndex << 4);1904if (collisionMasks[cPath].roofMasks[c] <= -64) {1905break;1906}1907entity->ypos = 15 - collisionMasks[cPath].roofMasks[c] + (chunkY << 7) + (tileY << 4);1908scriptEng.checkResult = true;1909break;1910}1911}1912}1913}1914YPos += 16;1915}19161917if (scriptEng.checkResult) {1918if (abs(entity->ypos - chunkX) < 16) {1919entity->ypos = (entity->ypos - yOffset) << 16;1920return;1921}1922entity->ypos = (chunkX - yOffset) << 16;1923scriptEng.checkResult = false;1924}1925}1926void RSDK::Legacy::v4::ObjectLWallGrip(int32 xOffset, int32 yOffset, int32 cPath)1927{1928int32 c;1929scriptEng.checkResult = false;1930Entity *entity = &objectEntityList[objectEntityPos];1931int32 XPos = (entity->xpos >> 16) + xOffset;1932int32 YPos = (entity->ypos >> 16) + yOffset;1933int32 startX = XPos;1934XPos = XPos - 16;1935for (int32 i = 3; i > 0; i--) {1936if (XPos > 0 && XPos < stageLayouts[0].xsize << 7 && YPos > 0 && YPos < stageLayouts[0].ysize << 7 && !scriptEng.checkResult) {1937int32 chunkX = XPos >> 7;1938int32 tileX = (XPos & 0x7F) >> 4;1939int32 chunkY = YPos >> 7;1940int32 tileY = (YPos & 0x7F) >> 4;1941int32 chunk = (stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6) + tileX + (tileY << 3);1942int32 tileIndex = tiles128x128.tileIndex[chunk];1943if (tiles128x128.collisionFlags[cPath][chunk] < SOLID_NONE) {1944switch (tiles128x128.direction[chunk]) {1945case 0: {1946c = (YPos & 15) + (tileIndex << 4);1947if (collisionMasks[cPath].lWallMasks[c] >= 64) {1948break;1949}1950entity->xpos = collisionMasks[cPath].lWallMasks[c] + (chunkX << 7) + (tileX << 4);1951scriptEng.checkResult = true;1952break;1953}1954case 1: {1955c = (YPos & 15) + (tileIndex << 4);1956if (collisionMasks[cPath].rWallMasks[c] <= -64) {1957break;1958}1959entity->xpos = 15 - collisionMasks[cPath].rWallMasks[c] + (chunkX << 7) + (tileX << 4);1960scriptEng.checkResult = true;1961break;1962}1963case 2: {1964c = 15 - (YPos & 15) + (tileIndex << 4);1965if (collisionMasks[cPath].lWallMasks[c] >= 64) {1966break;1967}1968entity->xpos = collisionMasks[cPath].lWallMasks[c] + (chunkX << 7) + (tileX << 4);1969scriptEng.checkResult = true;1970break;1971}1972case 3: {1973c = 15 - (YPos & 15) + (tileIndex << 4);1974if (collisionMasks[cPath].rWallMasks[c] <= -64) {1975break;1976}1977entity->xpos = 15 - collisionMasks[cPath].rWallMasks[c] + (chunkX << 7) + (tileX << 4);1978scriptEng.checkResult = true;1979break;1980}1981}1982}1983}1984XPos += 16;1985}1986if (scriptEng.checkResult) {1987if (abs(entity->xpos - startX) < 16) {1988entity->xpos = (entity->xpos - xOffset) << 16;1989return;1990}1991entity->xpos = (startX - xOffset) << 16;1992scriptEng.checkResult = false;1993}1994}1995void RSDK::Legacy::v4::ObjectRoofGrip(int32 xOffset, int32 yOffset, int32 cPath)1996{1997int32 c;1998scriptEng.checkResult = false;1999Entity *entity = &objectEntityList[objectEntityPos];2000int32 XPos = (entity->xpos >> 16) + xOffset;2001int32 YPos = (entity->ypos >> 16) + yOffset;2002int32 startY = YPos;2003YPos = YPos + 16;2004for (int32 i = 3; i > 0; i--) {2005if (XPos > 0 && XPos < stageLayouts[0].xsize << 7 && YPos > 0 && YPos < stageLayouts[0].ysize << 7 && !scriptEng.checkResult) {2006int32 chunkX = XPos >> 7;2007int32 tileX = (XPos & 0x7F) >> 4;2008int32 chunkY = YPos >> 7;2009int32 tileY = (YPos & 0x7F) >> 4;2010int32 chunk = (stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6) + tileX + (tileY << 3);2011int32 tileIndex = tiles128x128.tileIndex[chunk];2012if (tiles128x128.collisionFlags[cPath][chunk] < SOLID_NONE) {2013switch (tiles128x128.direction[chunk]) {2014case 0: {2015c = (XPos & 15) + (tileIndex << 4);2016if (collisionMasks[cPath].roofMasks[c] <= -64) {2017break;2018}2019entity->ypos = collisionMasks[cPath].roofMasks[c] + (chunkY << 7) + (tileY << 4);2020scriptEng.checkResult = true;2021break;2022}2023case 1: {2024c = 15 - (XPos & 15) + (tileIndex << 4);2025if (collisionMasks[cPath].roofMasks[c] <= -64) {2026break;2027}2028entity->ypos = collisionMasks[cPath].roofMasks[c] + (chunkY << 7) + (tileY << 4);2029scriptEng.checkResult = true;2030break;2031}2032case 2: {2033c = (XPos & 15) + (tileIndex << 4);2034if (collisionMasks[cPath].floorMasks[c] >= 64) {2035break;2036}2037entity->ypos = 15 - collisionMasks[cPath].floorMasks[c] + (chunkY << 7) + (tileY << 4);2038scriptEng.checkResult = true;2039break;2040}2041case 3: {2042c = 15 - (XPos & 15) + (tileIndex << 4);2043if (collisionMasks[cPath].floorMasks[c] >= 64) {2044break;2045}2046entity->ypos = 15 - collisionMasks[cPath].floorMasks[c] + (chunkY << 7) + (tileY << 4);2047scriptEng.checkResult = true;2048break;2049}2050}2051}2052}2053YPos -= 16;2054}2055if (scriptEng.checkResult) {2056if (abs(entity->ypos - startY) < 16) {2057entity->ypos = (entity->ypos - yOffset) << 16;2058return;2059}2060entity->ypos = (startY - yOffset) << 16;2061scriptEng.checkResult = false;2062}2063}2064void RSDK::Legacy::v4::ObjectRWallGrip(int32 xOffset, int32 yOffset, int32 cPath)2065{2066int32 c;2067scriptEng.checkResult = false;2068Entity *entity = &objectEntityList[objectEntityPos];2069int32 XPos = (entity->xpos >> 16) + xOffset;2070int32 YPos = (entity->ypos >> 16) + yOffset;2071int32 startX = XPos;2072XPos = XPos + 16;2073for (int32 i = 3; i > 0; i--) {2074if (XPos > 0 && XPos < stageLayouts[0].xsize << 7 && YPos > 0 && YPos < stageLayouts[0].ysize << 7 && !scriptEng.checkResult) {2075int32 chunkX = XPos >> 7;2076int32 tileX = (XPos & 0x7F) >> 4;2077int32 chunkY = YPos >> 7;2078int32 tileY = (YPos & 0x7F) >> 4;2079int32 chunk = (stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6) + tileX + (tileY << 3);2080int32 tileIndex = tiles128x128.tileIndex[chunk];2081if (tiles128x128.collisionFlags[cPath][chunk] < SOLID_NONE) {2082switch (tiles128x128.direction[chunk]) {2083case 0: {2084c = (YPos & 15) + (tileIndex << 4);2085if (collisionMasks[cPath].rWallMasks[c] <= -64) {2086break;2087}2088entity->xpos = collisionMasks[cPath].rWallMasks[c] + (chunkX << 7) + (tileX << 4);2089scriptEng.checkResult = true;2090break;2091}2092case 1: {2093c = (YPos & 15) + (tileIndex << 4);2094if (collisionMasks[cPath].lWallMasks[c] >= 64) {2095break;2096}2097entity->xpos = 15 - collisionMasks[cPath].lWallMasks[c] + (chunkX << 7) + (tileX << 4);2098scriptEng.checkResult = true;2099break;2100}2101case 2: {2102c = 15 - (YPos & 15) + (tileIndex << 4);2103if (collisionMasks[cPath].rWallMasks[c] <= -64) {2104break;2105}2106entity->xpos = collisionMasks[cPath].rWallMasks[c] + (chunkX << 7) + (tileX << 4);2107scriptEng.checkResult = true;2108break;2109}2110case 3: {2111c = 15 - (YPos & 15) + (tileIndex << 4);2112if (collisionMasks[cPath].lWallMasks[c] >= 64) {2113break;2114}2115entity->xpos = 15 - collisionMasks[cPath].lWallMasks[c] + (chunkX << 7) + (tileX << 4);2116scriptEng.checkResult = true;2117break;2118}2119}2120}2121}2122XPos -= 16;2123}2124if (scriptEng.checkResult) {2125if (abs(entity->xpos - startX) < 16) {2126entity->xpos = (entity->xpos - xOffset) << 16;2127return;2128}2129entity->xpos = (startX - xOffset) << 16;2130scriptEng.checkResult = false;2131}2132}21332134void RSDK::Legacy::v4::ObjectLEntityGrip(int32 xOffset, int32 yOffset, int32 cPath) {2135scriptEng.checkResult = false;2136Entity *entity = &objectEntityList[objectEntityPos];2137int32 mBlockID = entity->values[44];2138int32 XPos = (entity->xpos >> 16) + xOffset - 16;2139int32 YPos = (entity->ypos >> 16) + yOffset;2140int32 check = 0;2141if (mBlockID > 0 && objectTypeGroupList[mBlockID].listSize > 0) {2142TypeGroupList *mBlockGroupList = &objectTypeGroupList[mBlockID];2143for (int32 i = 0; i < objectTypeGroupList[mBlockID].listSize; i++) {2144short entRef = mBlockGroupList->entityRefs[i];2145Entity *otherEntity = &objectEntityList[entRef];2146int32 XPos2 = otherEntity->xpos >> 16;2147int32 YPos2 = otherEntity->ypos >> 16;2148if (((((XPos2 - 16) <= XPos) && (XPos <= (XPos2 + 16))) && ((YPos2 - 16) <= YPos)) && (YPos <= (YPos2 + 16))) {2149entity->xpos = otherEntity->xpos - (xOffset << 16) - 0x100000;2150if (otherEntity->values[0] == 0) {2151check = 2;2152scriptEng.checkResult = check;2153}2154else {2155scriptEng.checkResult = check;2156if (check != 2) {2157check = 1;2158scriptEng.checkResult = check;2159}2160}2161}2162if ((((XPos2 - 16) <= (XPos + 16) && ((XPos + 16) <= (XPos2 + 16))) && (YPos2 - 16) <= YPos) && (YPos <= (YPos2 + 16))) {2163entity->xpos = otherEntity->xpos - (xOffset << 16) - 0x100000;2164if (otherEntity->values[0] == 0) {2165check = 2;2166scriptEng.checkResult = check;2167}2168else {2169scriptEng.checkResult = check;2170if (check != 2) {2171scriptEng.checkResult = check;2172}2173}2174}21752176if (((XPos2 <= (XPos + 32)) && ((XPos + 32) <= (XPos2 + 16))) && (((YPos2 - 16) <= YPos && YPos <= (YPos2 + 16)))) {2177entity->xpos = otherEntity->xpos - (xOffset << 16) - 0x100000;2178if (otherEntity->values[0] == 0) {2179check = 2;2180scriptEng.checkResult = check;2181}2182else {2183scriptEng.checkResult = check;2184if (check != 2) {2185check = 1;2186scriptEng.checkResult = check;2187}2188}2189}21902191if (check != 0) {2192return;2193}2194}2195}2196ObjectLWallGrip(xOffset, yOffset, cPath);2197}21982199void RSDK::Legacy::v4::ObjectREntityGrip(int32 xOffset, int32 yOffset, int32 cPath)2200{2201scriptEng.checkResult = false;2202Entity *entity = &objectEntityList[objectEntityPos];2203int32 mBlockID = entity->values[44];2204int32 XPos = (entity->xpos >> 16) + xOffset + 16;2205int32 YPos = (entity->ypos >> 16) + yOffset;2206int32 check = 0;2207if (mBlockID > 0 && objectTypeGroupList[mBlockID].listSize > 0) {2208TypeGroupList *mBlockGroupList = &objectTypeGroupList[mBlockID];2209for (int32 i = 0; i < objectTypeGroupList[mBlockID].listSize; i++) {2210short entRef = mBlockGroupList->entityRefs[i];2211Entity *otherEntity = &objectEntityList[entRef];2212int32 XPos2 = otherEntity->xpos >> 16;2213int32 YPos2 = otherEntity->ypos >> 16;2214if (((((XPos2 - 16) <= XPos) && (XPos <= (XPos2 + 16))) && ((YPos2 - 16) <= YPos)) && (YPos <= (YPos2 + 16))) {2215entity->xpos = otherEntity->xpos + ((16 - xOffset) << 16);2216if (otherEntity->values[0] == 0) {2217check = 2;2218scriptEng.checkResult = check;2219}2220else {2221scriptEng.checkResult = check;2222if (check != 2) {2223check = 1;2224scriptEng.checkResult = check;2225}2226}2227}2228if ((((XPos2 - 16) <= (XPos + 16) && ((XPos - 16) <= (XPos2 + 16))) && (YPos2 - 16) <= YPos) && (YPos <= (YPos2 + 16))) {2229entity->xpos = otherEntity->xpos + ((16 - xOffset) << 16);2230if (otherEntity->values[0] == 0) {2231check = 2;2232scriptEng.checkResult = check;2233}2234else {2235scriptEng.checkResult = check;2236if (check != 2) {2237scriptEng.checkResult = check;2238}2239}2240}22412242if (((XPos2 <= (XPos - 32)) && ((XPos - 32) <= (XPos2 + 16))) && (((YPos2 - 16) <= YPos && YPos <= (YPos2 + 16)))) {2243entity->xpos = otherEntity->xpos + ((16 - xOffset) << 16);2244if (otherEntity->values[0] == 0) {2245check = 2;2246scriptEng.checkResult = check;2247}2248else {2249scriptEng.checkResult = check;2250if (check != 2) {2251check = 1;2252scriptEng.checkResult = check;2253}2254}2255}22562257if (check != 0) {2258return;2259}2260}2261}2262ObjectRWallGrip(xOffset, yOffset, cPath);2263}22642265void RSDK::Legacy::v4::TouchCollision(Entity *thisEntity, int32 thisLeft, int32 thisTop, int32 thisRight, int32 thisBottom, Entity *otherEntity,2266int32 otherLeft, int32 otherTop, int32 otherRight, int32 otherBottom)2267{2268Hitbox *thisHitbox = GetHitbox(thisEntity);2269Hitbox *otherHitbox = GetHitbox(otherEntity);22702271if (thisLeft == C_BOX)2272thisLeft = thisHitbox->left[0];22732274if (thisTop == C_BOX)2275thisTop = thisHitbox->top[0];22762277if (thisRight == C_BOX)2278thisRight = thisHitbox->right[0];22792280if (thisBottom == C_BOX)2281thisBottom = thisHitbox->bottom[0];22822283if (otherLeft == C_BOX)2284otherLeft = otherHitbox->left[0];22852286if (otherTop == C_BOX)2287otherTop = otherHitbox->top[0];22882289if (otherRight == C_BOX)2290otherRight = otherHitbox->right[0];22912292if (otherBottom == C_BOX)2293otherBottom = otherHitbox->bottom[0];22942295#if !RETRO_USE_ORIGINAL_CODE2296int32 thisHitboxID = 0;2297int32 otherHitboxID = 0;2298if (showHitboxes) {2299thisHitboxID = AddDebugHitbox(H_TYPE_TOUCH, thisEntity, thisLeft, thisTop, thisRight, thisBottom);2300otherHitboxID = AddDebugHitbox(H_TYPE_TOUCH, otherEntity, otherLeft, otherTop, otherRight, otherBottom);2301}2302#endif23032304thisLeft += thisEntity->xpos >> 16;2305thisTop += thisEntity->ypos >> 16;2306thisRight += thisEntity->xpos >> 16;2307thisBottom += thisEntity->ypos >> 16;23082309otherLeft += otherEntity->xpos >> 16;2310otherTop += otherEntity->ypos >> 16;2311otherRight += otherEntity->xpos >> 16;2312otherBottom += otherEntity->ypos >> 16;23132314scriptEng.checkResult = otherRight > thisLeft && otherLeft < thisRight && otherBottom > thisTop && otherTop < thisBottom;23152316#if !RETRO_USE_ORIGINAL_CODE2317if (showHitboxes) {2318if (thisHitboxID >= 0 && scriptEng.checkResult)2319debugHitboxList[thisHitboxID].collision |= 1;2320if (otherHitboxID >= 0 && scriptEng.checkResult)2321debugHitboxList[otherHitboxID].collision |= 1;2322}2323#endif2324}2325void RSDK::Legacy::v4::BoxCollision(Entity *thisEntity, int32 thisLeft, int32 thisTop, int32 thisRight, int32 thisBottom, Entity *otherEntity,2326int32 otherLeft, int32 otherTop, int32 otherRight, int32 otherBottom)2327{2328Hitbox *thisHitbox = GetHitbox(thisEntity);2329Hitbox *otherHitbox = GetHitbox(otherEntity);23302331if (thisLeft == C_BOX)2332thisLeft = thisHitbox->left[0];23332334if (thisTop == C_BOX)2335thisTop = thisHitbox->top[0];23362337if (thisRight == C_BOX)2338thisRight = thisHitbox->right[0];23392340if (thisBottom == C_BOX)2341thisBottom = thisHitbox->bottom[0];23422343if (otherLeft == C_BOX)2344otherLeft = otherHitbox->left[0];23452346if (otherTop == C_BOX)2347otherTop = otherHitbox->top[0];23482349if (otherRight == C_BOX)2350otherRight = otherHitbox->right[0];23512352if (otherBottom == C_BOX)2353otherBottom = otherHitbox->bottom[0];23542355#if !RETRO_USE_ORIGINAL_CODE2356int32 thisHitboxID = 0;2357int32 otherHitboxID = 0;2358if (showHitboxes) {2359thisHitboxID = AddDebugHitbox(H_TYPE_BOX, thisEntity, thisLeft, thisTop, thisRight, thisBottom);2360otherHitboxID = AddDebugHitbox(H_TYPE_BOX, otherEntity, otherLeft, otherTop, otherRight, otherBottom);2361}2362#endif23632364thisLeft += thisEntity->xpos >> 16;2365thisTop += thisEntity->ypos >> 16;2366thisRight += thisEntity->xpos >> 16;2367thisBottom += thisEntity->ypos >> 16;23682369thisLeft <<= 16;2370thisTop <<= 16;2371thisRight <<= 16;2372thisBottom <<= 16;23732374otherLeft <<= 16;2375otherTop <<= 16;2376otherRight <<= 16;2377otherBottom <<= 16;23782379scriptEng.checkResult = 0;23802381int32 rx = otherEntity->xpos >> 16 << 16;2382int32 ry = otherEntity->ypos >> 16 << 16;23832384int32 xDif = otherEntity->xpos - thisRight;2385if (thisEntity->xpos > otherEntity->xpos)2386xDif = thisLeft - otherEntity->xpos;2387int32 yDif = thisTop - otherEntity->ypos;2388if (thisEntity->ypos <= otherEntity->ypos)2389yDif = otherEntity->ypos - thisBottom;23902391if (xDif <= yDif && abs(otherEntity->xvel) >> 1 <= abs(otherEntity->yvel)) {2392sensors[0].collided = false;2393sensors[1].collided = false;2394sensors[2].collided = false;2395sensors[3].collided = false;2396sensors[4].collided = false;2397sensors[0].xpos = rx + otherLeft + 0x20000;2398sensors[1].xpos = rx;2399sensors[2].xpos = rx + otherRight - 0x20000;2400sensors[3].xpos = (sensors[0].xpos + rx) >> 1;2401sensors[4].xpos = (sensors[2].xpos + rx) >> 1;24022403sensors[0].ypos = ry + otherBottom;24042405if (otherEntity->yvel >= 0) {2406for (int32 i = 0; i < 5; ++i) {2407if (thisLeft < sensors[i].xpos && thisRight > sensors[i].xpos && thisTop <= sensors[0].ypos2408&& thisTop > otherEntity->ypos - otherEntity->yvel) {2409sensors[i].collided = true;2410otherEntity->floorSensors[i] = true;2411}2412}2413}24142415if (sensors[0].collided || sensors[1].collided || sensors[2].collided) {2416if (!otherEntity->gravity && (otherEntity->collisionMode == CMODE_RWALL || otherEntity->collisionMode == CMODE_LWALL)) {2417otherEntity->xvel = 0;2418otherEntity->speed = 0;2419}2420otherEntity->ypos = thisTop - otherBottom;2421otherEntity->gravity = 0;2422otherEntity->yvel = 0;2423otherEntity->angle = 0;2424otherEntity->rotation = 0;2425otherEntity->controlLock = 0;2426scriptEng.checkResult = 1;2427}2428else {2429sensors[0].collided = false;2430sensors[1].collided = false;2431sensors[0].xpos = rx + otherLeft + 0x20000;2432sensors[1].xpos = rx + otherRight - 0x20000;24332434sensors[0].ypos = ry + otherTop;24352436for (int32 i = 0; i < 2; ++i) {2437if (thisLeft < sensors[1].xpos && thisRight > sensors[0].xpos && thisBottom > sensors[0].ypos2438&& thisBottom < otherEntity->ypos - otherEntity->yvel) {2439sensors[i].collided = true;2440}2441}24422443if (sensors[1].collided || sensors[0].collided) {2444if (otherEntity->gravity == 1)2445otherEntity->ypos = thisBottom - otherTop;24462447if (otherEntity->yvel <= 0)2448otherEntity->yvel = 0;2449scriptEng.checkResult = 4;2450}2451else {2452sensors[0].collided = false;2453sensors[1].collided = false;2454sensors[0].xpos = rx + otherRight;24552456sensors[0].ypos = ry + otherTop + 0x20000;2457sensors[1].ypos = ry + otherBottom - 0x20000;2458for (int32 i = 0; i < 2; ++i) {2459if (thisLeft <= sensors[0].xpos && thisLeft > otherEntity->xpos - otherEntity->xvel && thisTop < sensors[1].ypos2460&& thisBottom > sensors[0].ypos) {2461sensors[i].collided = true;2462}2463}24642465if (sensors[1].collided || sensors[0].collided) {2466otherEntity->xpos = thisLeft - otherRight;2467if (otherEntity->xvel > 0) {2468if (!otherEntity->direction)2469otherEntity->pushing = 2;24702471otherEntity->xvel = 0;2472if (otherEntity->collisionMode || !otherEntity->left)2473otherEntity->speed = 0;2474else2475otherEntity->speed = -0x8000;2476}2477scriptEng.checkResult = 2;2478}2479else {2480sensors[0].collided = false;2481sensors[1].collided = false;2482sensors[0].xpos = rx + otherLeft;24832484sensors[0].ypos = ry + otherTop + 0x20000;2485sensors[1].ypos = ry + otherBottom - 0x20000;2486for (int32 i = 0; i < 2; ++i) {2487if (thisRight > sensors[0].xpos && thisRight < otherEntity->xpos - otherEntity->xvel && thisTop < sensors[1].ypos2488&& thisBottom > sensors[0].ypos) {2489sensors[i].collided = true;2490}2491}24922493if (sensors[1].collided || sensors[0].collided) {2494otherEntity->xpos = thisRight - otherLeft;2495if (otherEntity->xvel < 0) {2496if (otherEntity->direction == FLIP_X)2497otherEntity->pushing = 2;24982499if (otherEntity->xvel < -0x10000)2500otherEntity->xpos += 0x8000;25012502otherEntity->xvel = 0;2503if (otherEntity->collisionMode || !otherEntity->right)2504otherEntity->speed = 0;2505else2506otherEntity->speed = 0x8000;2507}2508scriptEng.checkResult = 3;2509}2510}2511}2512}2513}2514else {2515sensors[0].collided = false;2516sensors[1].collided = false;2517sensors[0].xpos = rx + otherRight;25182519sensors[0].ypos = ry + otherTop + 0x20000;2520sensors[1].ypos = ry + otherBottom - 0x20000;2521for (int32 i = 0; i < 2; ++i) {2522if (thisLeft <= sensors[0].xpos && thisLeft > otherEntity->xpos - otherEntity->xvel && thisTop < sensors[1].ypos2523&& thisBottom > sensors[0].ypos) {2524sensors[i].collided = true;2525}2526}2527if (sensors[1].collided || sensors[0].collided) {2528otherEntity->xpos = thisLeft - otherRight;2529if (otherEntity->xvel > 0) {2530if (!otherEntity->direction)2531otherEntity->pushing = 2;25322533otherEntity->xvel = 0;2534if (otherEntity->collisionMode || !otherEntity->left)2535otherEntity->speed = 0;2536else2537otherEntity->speed = -0x8000;2538}2539scriptEng.checkResult = 2;2540}2541else {2542sensors[0].collided = false;2543sensors[1].collided = false;2544sensors[0].xpos = rx + otherLeft;25452546sensors[0].ypos = ry + otherTop + 0x20000;2547sensors[1].ypos = ry + otherBottom - 0x20000;2548for (int32 i = 0; i < 2; ++i) {2549if (thisRight > sensors[0].xpos && thisRight < otherEntity->xpos - otherEntity->xvel && thisTop < sensors[1].ypos2550&& thisBottom > sensors[0].ypos) {2551sensors[i].collided = true;2552}2553}25542555if (sensors[0].collided || sensors[1].collided) {2556otherEntity->xpos = thisRight - otherLeft;2557if (otherEntity->xvel < 0) {2558if (otherEntity->direction == FLIP_X)2559otherEntity->pushing = 2;25602561if (otherEntity->xvel < -0x10000)2562otherEntity->xpos += 0x8000;25632564otherEntity->xvel = 0;2565if (otherEntity->collisionMode || !otherEntity->right)2566otherEntity->speed = 0;2567else2568otherEntity->speed = 0x8000;2569}2570scriptEng.checkResult = 3;2571}2572else {2573sensors[0].collided = false;2574sensors[1].collided = false;2575sensors[2].collided = false;2576sensors[3].collided = false;2577sensors[4].collided = false;2578sensors[0].xpos = rx + otherLeft + 0x20000;2579sensors[1].xpos = rx;2580sensors[2].xpos = rx + otherRight - 0x20000;2581sensors[3].xpos = (sensors[0].xpos + rx) >> 1;2582sensors[4].xpos = (sensors[2].xpos + rx) >> 1;25832584sensors[0].ypos = ry + otherBottom;2585if (otherEntity->yvel >= 0) {2586for (int32 i = 0; i < 5; ++i) {2587if (thisLeft < sensors[i].xpos && thisRight > sensors[i].xpos && thisTop <= sensors[0].ypos2588&& thisTop > otherEntity->ypos - otherEntity->yvel) {2589sensors[i].collided = true;2590otherEntity->floorSensors[i] = true;2591}2592}2593}2594if (sensors[2].collided || sensors[1].collided || sensors[0].collided) {2595if (!otherEntity->gravity && (otherEntity->collisionMode == CMODE_RWALL || otherEntity->collisionMode == CMODE_LWALL)) {2596otherEntity->xvel = 0;2597otherEntity->speed = 0;2598}2599otherEntity->ypos = thisTop - otherBottom;2600otherEntity->gravity = 0;2601otherEntity->yvel = 0;2602otherEntity->angle = 0;2603otherEntity->rotation = 0;2604otherEntity->controlLock = 0;2605scriptEng.checkResult = 1;2606}2607else {2608sensors[0].collided = false;2609sensors[1].collided = false;2610sensors[0].xpos = rx + otherLeft + 0x20000;2611sensors[1].xpos = rx + otherRight - 0x20000;2612sensors[0].ypos = ry + otherTop;26132614for (int32 i = 0; i < 2; ++i) {2615if (thisLeft < sensors[1].xpos && thisRight > sensors[0].xpos && thisBottom > sensors[0].ypos2616&& thisBottom < otherEntity->ypos - otherEntity->yvel) {2617sensors[i].collided = true;2618}2619}26202621if (sensors[1].collided || sensors[0].collided) {2622if (otherEntity->gravity == 1)2623otherEntity->ypos = thisBottom - otherTop;26242625if (otherEntity->yvel <= 0)2626otherEntity->yvel = 0;2627scriptEng.checkResult = 4;2628}2629}2630}2631}2632}26332634#if !RETRO_USE_ORIGINAL_CODE2635if (showHitboxes) {2636if (thisHitboxID >= 0 && scriptEng.checkResult)2637debugHitboxList[thisHitboxID].collision |= 1 << (scriptEng.checkResult - 1);2638if (otherHitboxID >= 0 && scriptEng.checkResult)2639debugHitboxList[otherHitboxID].collision |= 1 << (4 - scriptEng.checkResult);2640}2641#endif2642}2643void RSDK::Legacy::v4::BoxCollision2(Entity *thisEntity, int32 thisLeft, int32 thisTop, int32 thisRight, int32 thisBottom, Entity *otherEntity,2644int32 otherLeft, int32 otherTop, int32 otherRight, int32 otherBottom)2645{2646Hitbox *thisHitbox = GetHitbox(thisEntity);2647Hitbox *otherHitbox = GetHitbox(otherEntity);26482649if (thisLeft == C_BOX)2650thisLeft = thisHitbox->left[0];26512652if (thisTop == C_BOX)2653thisTop = thisHitbox->top[0];26542655if (thisRight == C_BOX)2656thisRight = thisHitbox->right[0];26572658if (thisBottom == C_BOX)2659thisBottom = thisHitbox->bottom[0];26602661if (otherLeft == C_BOX)2662otherLeft = otherHitbox->left[0];26632664if (otherTop == C_BOX)2665otherTop = otherHitbox->top[0];26662667if (otherRight == C_BOX)2668otherRight = otherHitbox->right[0];26692670if (otherBottom == C_BOX)2671otherBottom = otherHitbox->bottom[0];26722673#if !RETRO_USE_ORIGINAL_CODE2674int32 thisHitboxID = 0;2675int32 otherHitboxID = 0;2676if (showHitboxes) {2677thisHitboxID = AddDebugHitbox(H_TYPE_BOX, thisEntity, thisLeft, thisTop, thisRight, thisBottom);2678otherHitboxID = AddDebugHitbox(H_TYPE_BOX, otherEntity, otherLeft, otherTop, otherRight, otherBottom);2679}2680#endif26812682thisLeft += thisEntity->xpos >> 16;2683thisTop += thisEntity->ypos >> 16;2684thisRight += thisEntity->xpos >> 16;2685thisBottom += thisEntity->ypos >> 16;26862687thisLeft <<= 16;2688thisTop <<= 16;2689thisRight <<= 16;2690thisBottom <<= 16;26912692otherLeft <<= 16;2693otherTop <<= 16;2694otherRight <<= 16;2695otherBottom <<= 16;26962697scriptEng.checkResult = 0;26982699int32 rx = otherEntity->xpos >> 16 << 16;2700int32 ry = otherEntity->ypos >> 16 << 16;27012702int32 xDif = thisLeft - rx;2703if (thisEntity->xpos <= rx)2704xDif = rx - thisRight;2705int32 yDif = thisTop - ry;2706if (thisEntity->ypos <= ry)2707yDif = ry - thisBottom;27082709if (xDif <= yDif) {2710sensors[0].collided = false;2711sensors[1].collided = false;2712sensors[2].collided = false;2713sensors[0].xpos = rx + otherLeft + 0x20000;2714sensors[1].xpos = rx;2715sensors[2].xpos = rx + otherRight - 0x20000;27162717sensors[0].ypos = ry + otherBottom;27182719if (otherEntity->yvel >= 0) {2720// this should prolly be using all 5 sensors, but this was unused in S2 so it was prolly forgotten about2721for (int32 i = 0; i < 3; ++i) {2722if (thisLeft < sensors[i].xpos && thisRight > sensors[i].xpos && thisTop <= sensors[0].ypos && thisEntity->ypos > sensors[0].ypos) {2723sensors[i].collided = true;2724otherEntity->floorSensors[i] = true;2725}2726}2727}27282729if (sensors[0].collided || sensors[1].collided || sensors[2].collided) {2730if (!otherEntity->gravity && (otherEntity->collisionMode == CMODE_RWALL || otherEntity->collisionMode == CMODE_LWALL)) {2731otherEntity->xvel = 0;2732otherEntity->speed = 0;2733}2734otherEntity->ypos = thisTop - otherBottom;2735otherEntity->gravity = 0;2736otherEntity->yvel = 0;2737otherEntity->angle = 0;2738otherEntity->rotation = 0;2739otherEntity->controlLock = 0;2740scriptEng.checkResult = 1;2741}2742else {2743sensors[0].collided = false;2744sensors[1].collided = false;2745sensors[0].xpos = rx + otherLeft + 0x20000;2746sensors[1].xpos = rx + otherRight - 0x20000;27472748sensors[0].ypos = ry + otherTop;27492750for (int32 i = 0; i < 2; ++i) {2751if (thisLeft < sensors[1].xpos && thisRight > sensors[0].xpos && thisBottom > sensors[0].ypos && thisEntity->ypos < sensors[0].ypos) {2752sensors[i].collided = true;2753}2754}27552756if (sensors[1].collided || sensors[0].collided) {2757if (!otherEntity->gravity && (otherEntity->collisionMode == CMODE_RWALL || otherEntity->collisionMode == CMODE_LWALL)) {2758otherEntity->xvel = 0;2759otherEntity->speed = 0;2760}27612762otherEntity->ypos = thisBottom - otherTop;2763if (otherEntity->yvel < 0)2764otherEntity->yvel = 0;2765scriptEng.checkResult = 4;2766}2767else {2768sensors[0].collided = false;2769sensors[1].collided = false;2770sensors[0].xpos = rx + otherRight;27712772sensors[0].ypos = ry + otherTop + 0x20000;2773sensors[1].ypos = ry + otherBottom - 0x20000;2774for (int32 i = 0; i < 2; ++i) {2775if (thisLeft <= sensors[0].xpos && thisEntity->xpos > sensors[0].xpos && thisTop < sensors[1].ypos2776&& thisBottom > sensors[0].ypos) {2777sensors[i].collided = true;2778}2779}27802781if (sensors[1].collided || sensors[0].collided) {2782otherEntity->xpos = thisLeft - otherRight;2783if (otherEntity->xvel > 0) {2784if (!otherEntity->direction)2785otherEntity->pushing = 2;27862787otherEntity->xvel = 0;2788otherEntity->speed = 0;2789}2790scriptEng.checkResult = 2;2791}2792else {2793sensors[0].collided = false;2794sensors[1].collided = false;2795sensors[0].xpos = rx + otherLeft;27962797sensors[0].ypos = ry + otherTop + 0x20000;2798sensors[1].ypos = ry + otherBottom - 0x20000;2799for (int32 i = 0; i < 2; ++i) {2800if (thisRight > sensors[0].xpos && thisEntity->xpos < sensors[0].xpos && thisTop < sensors[1].ypos2801&& thisBottom > sensors[0].ypos) {2802sensors[i].collided = true;2803}2804}28052806if (sensors[1].collided || sensors[0].collided) {2807otherEntity->xpos = thisRight - otherLeft;2808if (otherEntity->xvel < 0) {2809if (otherEntity->direction == FLIP_X)2810otherEntity->pushing = 2;28112812if (otherEntity->xvel < -0x10000)2813otherEntity->xpos += 0x8000;28142815otherEntity->xvel = 0;2816otherEntity->speed = 0;2817}2818scriptEng.checkResult = 3;2819}2820}2821}2822}2823}2824else {2825sensors[0].collided = false;2826sensors[1].collided = false;2827sensors[0].xpos = rx + otherRight;28282829sensors[0].ypos = ry + otherTop + 0x20000;2830sensors[1].ypos = ry + otherBottom - 0x20000;2831for (int32 i = 0; i < 2; ++i) {2832if (thisLeft <= sensors[0].xpos && thisEntity->xpos > sensors[0].xpos && thisTop < sensors[1].ypos && thisBottom > sensors[0].ypos) {2833sensors[i].collided = true;2834}2835}2836if (sensors[1].collided || sensors[0].collided) {2837otherEntity->xpos = thisLeft - otherRight;2838if (otherEntity->xvel > 0) {2839if (!otherEntity->direction)2840otherEntity->pushing = 2;28412842otherEntity->xvel = 0;2843otherEntity->speed = 0;2844}2845scriptEng.checkResult = 2;2846}2847else {2848sensors[0].collided = false;2849sensors[1].collided = false;2850sensors[0].xpos = rx + otherLeft;28512852sensors[0].ypos = ry + otherTop + 0x20000;2853sensors[1].ypos = ry + otherBottom - 0x20000;2854for (int32 i = 0; i < 2; ++i) {2855if (thisRight > sensors[0].xpos && thisEntity->xpos < sensors[0].xpos && thisTop < sensors[1].ypos && thisBottom > sensors[0].ypos) {2856sensors[i].collided = true;2857}2858}28592860if (sensors[0].collided || sensors[1].collided) {2861otherEntity->xpos = thisRight - otherLeft;2862if (otherEntity->xvel < 0) {2863if (otherEntity->direction == FLIP_X)2864otherEntity->pushing = 2;28652866if (otherEntity->xvel < -0x10000)2867otherEntity->xpos += 0x8000;28682869otherEntity->xvel = 0;2870otherEntity->speed = 0;2871}2872scriptEng.checkResult = 3;2873}2874else {2875sensors[0].collided = false;2876sensors[1].collided = false;2877sensors[2].collided = false;2878sensors[0].xpos = rx + otherLeft + 0x20000;2879sensors[1].xpos = rx;2880sensors[2].xpos = rx + otherRight - 0x20000;28812882sensors[0].ypos = ry + otherBottom;2883if (otherEntity->yvel >= 0) {2884for (int32 i = 0; i < 3; ++i) {2885if (thisLeft < sensors[i].xpos && thisRight > sensors[i].xpos && thisTop <= sensors[0].ypos2886&& thisEntity->ypos > sensors[0].ypos) {2887sensors[i].collided = true;2888otherEntity->floorSensors[i] = true;2889}2890}2891}28922893if (sensors[0].collided || sensors[1].collided || sensors[2].collided) {2894if (!otherEntity->gravity && (otherEntity->collisionMode == CMODE_RWALL || otherEntity->collisionMode == CMODE_LWALL)) {2895otherEntity->xvel = 0;2896otherEntity->speed = 0;2897}2898otherEntity->ypos = thisTop - otherBottom;2899otherEntity->gravity = 0;2900otherEntity->yvel = 0;2901otherEntity->angle = 0;2902otherEntity->rotation = 0;2903otherEntity->controlLock = 0;2904scriptEng.checkResult = 1;2905}2906else {2907sensors[0].collided = false;2908sensors[1].collided = false;2909sensors[0].xpos = rx + otherLeft + 0x20000;2910sensors[1].xpos = rx + otherRight - 0x20000;29112912sensors[0].ypos = ry + otherTop;29132914for (int32 i = 0; i < 2; ++i) {2915if (thisLeft < sensors[1].xpos && thisRight > sensors[0].xpos && thisBottom > sensors[0].ypos2916&& thisEntity->ypos < sensors[0].ypos) {2917sensors[i].collided = true;2918}2919}29202921if (sensors[1].collided || sensors[0].collided) {2922if (!otherEntity->gravity && (otherEntity->collisionMode == CMODE_RWALL || otherEntity->collisionMode == CMODE_LWALL)) {2923otherEntity->xvel = 0;2924otherEntity->speed = 0;2925}29262927otherEntity->ypos = thisBottom - otherTop;29282929if (otherEntity->yvel < 0)2930otherEntity->yvel = 0;2931scriptEng.checkResult = 4;2932}2933}2934}2935}2936}29372938#if !RETRO_USE_ORIGINAL_CODE2939if (showHitboxes) {2940if (thisHitboxID >= 0 && scriptEng.checkResult)2941debugHitboxList[thisHitboxID].collision |= 1 << (scriptEng.checkResult - 1);2942if (otherHitboxID >= 0 && scriptEng.checkResult)2943debugHitboxList[otherHitboxID].collision |= 1 << (4 - scriptEng.checkResult);2944}2945#endif2946}2947void RSDK::Legacy::v4::PlatformCollision(Entity *thisEntity, int32 thisLeft, int32 thisTop, int32 thisRight, int32 thisBottom, Entity *otherEntity,2948int32 otherLeft, int32 otherTop, int32 otherRight, int32 otherBottom)2949{2950scriptEng.checkResult = false;29512952Hitbox *thisHitbox = GetHitbox(thisEntity);2953Hitbox *otherHitbox = GetHitbox(otherEntity);29542955if (thisLeft == C_BOX)2956thisLeft = thisHitbox->left[0];29572958if (thisTop == C_BOX)2959thisTop = thisHitbox->top[0];29602961if (thisRight == C_BOX)2962thisRight = thisHitbox->right[0];29632964if (thisBottom == C_BOX)2965thisBottom = thisHitbox->bottom[0];29662967if (otherLeft == C_BOX)2968otherLeft = otherHitbox->left[0];29692970if (otherTop == C_BOX)2971otherTop = otherHitbox->top[0];29722973if (otherRight == C_BOX)2974otherRight = otherHitbox->right[0];29752976if (otherBottom == C_BOX)2977otherBottom = otherHitbox->bottom[0];29782979#if !RETRO_USE_ORIGINAL_CODE2980int32 thisHitboxID = 0;2981int32 otherHitboxID = 0;2982if (showHitboxes) {2983thisHitboxID = AddDebugHitbox(H_TYPE_PLAT, thisEntity, thisLeft, thisTop, thisRight, thisBottom);2984otherHitboxID = AddDebugHitbox(H_TYPE_PLAT, otherEntity, otherLeft, otherTop, otherRight, otherBottom);2985}2986#endif29872988thisLeft += thisEntity->xpos >> 16;2989thisTop += thisEntity->ypos >> 16;2990thisRight += thisEntity->xpos >> 16;2991thisBottom += thisEntity->ypos >> 16;29922993thisLeft <<= 16;2994thisTop <<= 16;2995thisRight <<= 16;2996thisBottom <<= 16;29972998sensors[0].collided = false;2999sensors[1].collided = false;3000sensors[2].collided = false;30013002int32 rx = otherEntity->xpos >> 16 << 16;3003int32 ry = otherEntity->ypos >> 16 << 16;30043005sensors[0].xpos = rx + (otherLeft << 16);3006sensors[1].xpos = rx;3007sensors[2].xpos = rx + (otherRight << 16);3008sensors[3].xpos = (rx + sensors[0].xpos) >> 1;3009sensors[4].xpos = (sensors[2].xpos + rx) >> 1;30103011sensors[0].ypos = (otherBottom << 16) + ry;30123013for (int32 i = 0; i < 5; ++i) {3014if (thisLeft < sensors[i].xpos && thisRight > sensors[i].xpos && thisTop - 1 <= sensors[0].ypos && thisBottom > sensors[0].ypos3015&& otherEntity->yvel >= 0) {3016sensors[i].collided = true;3017otherEntity->floorSensors[i] = true;3018}3019}30203021if (sensors[0].collided || sensors[1].collided || sensors[2].collided) {3022if (!otherEntity->gravity && (otherEntity->collisionMode == CMODE_RWALL || otherEntity->collisionMode == CMODE_LWALL)) {3023otherEntity->xvel = 0;3024otherEntity->speed = 0;3025}3026otherEntity->ypos = thisTop - (otherBottom << 16);3027otherEntity->gravity = 0;3028otherEntity->yvel = 0;3029otherEntity->angle = 0;3030otherEntity->rotation = 0;3031otherEntity->controlLock = 0;3032scriptEng.checkResult = true;3033}30343035#if !RETRO_USE_ORIGINAL_CODE3036if (showHitboxes) {3037if (thisHitboxID >= 0 && scriptEng.checkResult)3038debugHitboxList[thisHitboxID].collision |= 1 << 0;3039if (otherHitboxID >= 0 && scriptEng.checkResult)3040debugHitboxList[otherHitboxID].collision |= 1 << 3;3041}3042#endif3043}304430453046