Path: blob/master/SonicMania/Objects/CPZ/TransportTube.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: TransportTube Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectTransportTube *TransportTube;1011void TransportTube_Update(void)12{13RSDK_THIS(TransportTube);1415StateMachine_Run(self->state);16}1718void TransportTube_LateUpdate(void) {}1920void TransportTube_StaticUpdate(void) {}2122void TransportTube_Draw(void) {}2324void TransportTube_Create(void *data)25{26RSDK_THIS(TransportTube);2728self->drawFX = FX_FLIP;29if (!SceneInfo->inEditor) {30self->active = ACTIVE_BOUNDS;31self->updateRange.x = TO_FIXED(192);32self->updateRange.y = TO_FIXED(192);33TransportTube_SetupDirections(self);3435switch (self->type) {36case TRANSPORTTUBE_CHANGEDIR: self->state = TransportTube_State_ChangeDir; break;37case TRANSPORTTUBE_ENTRY: self->state = TransportTube_State_Entry; break;3839case TRANSPORTTUBE_TOTARGET_NEXT:40case TRANSPORTTUBE_TOTARGET_PREV: self->state = TransportTube_State_ToTargetEntity; break;4142case TRANSPORTTUBE_TOTARGET_NODE: self->state = TransportTube_State_TargetSeqNode; break;43case TRANSPORTTUBE_JUNCTION: self->state = TransportTube_State_ChooseDir; break;44case TRANSPORTTUBE_EXIT: self->state = TransportTube_State_Exit; break;45default: break;46}47}48}4950void TransportTube_StageLoad(void) { TransportTube->sfxTravel = RSDK.GetSfx("Tube/Travel.wav"); }5152void TransportTube_SetupDirections(EntityTransportTube *entity)53{54int32 velocityX[] = { 0, 0, -16, 16, 12, -12, 12, -12 };55int32 velocityY[] = { -16, 16, 0, 0, -12, -12, 12, 12 };5657entity->directionCount = 0;58for (int32 i = 0; i < 8; ++i) {59if (entity->dirMask & (1 << i)) {60entity->dirVelocity[entity->directionCount].x = velocityX[i];61entity->dirVelocity[entity->directionCount].y = velocityY[i];62++entity->directionCount;63}64}65}6667void TransportTube_HandleVelocityChange(int32 velX, int32 velY)68{69RSDK_THIS(TransportTube);7071int32 id = 0;72int32 velStore = 0xFFFF;73for (int32 v = 0; v < self->directionCount; ++v) {74int32 x = abs(velX - self->dirVelocity[v].x);75int32 y = abs(velY - self->dirVelocity[v].y);7677if (x + y < velStore) {78id = v;79velStore = x + y;80}81}8283int32 pos = 0;84for (int32 v = 0; v < self->directionCount; ++v) {85if (v != id)86self->directionIDs[pos++] = v;87}8889int32 dir = self->directionIDs[RSDK.Rand(0, self->directionCount - 1)];90self->velocity.x = TO_FIXED(self->dirVelocity[dir].x);91self->velocity.y = TO_FIXED(self->dirVelocity[dir].y);92}9394void TransportTube_State_ChangeDir(void)95{96RSDK_THIS(TransportTube);9798for (int32 i = 0; i < Player->playerCount; ++i) {99EntityPlayer *player = RSDK_GET_ENTITY(i, Player);100int32 rx = FROM_FIXED(player->position.x - self->position.x);101int32 ry = FROM_FIXED(player->position.y - self->position.y);102103if (self->playerTimers[i]) {104if (rx * rx + ry * ry >= 0xC0)105self->playerTimers[i]--;106}107else if (player->state == Player_State_TransportTube && !TransportTube->nextSlot[i] && rx * rx + ry * ry < 0xC0) {108TransportTube_HandleVelocityChange(rx - FROM_FIXED(player->velocity.x), ry - FROM_FIXED(player->velocity.y));109player->position.x = self->position.x;110player->position.y = self->position.y;111player->velocity = self->velocity;112self->playerTimers[i] = 2;113}114}115}116117void TransportTube_State_Entry(void)118{119RSDK_THIS(TransportTube);120121for (int32 i = 0; i < Player->playerCount; ++i) {122EntityPlayer *player = RSDK_GET_ENTITY(i, Player);123124if (Player_CheckValidState(player)) {125int32 rx = FROM_FIXED(player->position.x - self->position.x);126int32 ry = FROM_FIXED(player->position.y - self->position.y);127if (self->playerTimers[i]) {128if (rx * rx + ry * ry >= 0xC0)129self->playerTimers[i]--;130}131else if (rx * rx + ry * ry < 0xC0) {132player->position.x = self->position.x;133player->position.y = self->position.y;134if (player->state == Player_State_TransportTube) {135player->drawGroup = Zone->playerDrawGroup[0];136player->tileCollisions = TILECOLLISION_DOWN;137player->interaction = true;138player->state = Player_State_Air;139if (player->velocity.x)140player->direction = player->velocity.x <= 0;141self->playerTimers[i] = 2;142}143else {144TransportTube_HandleVelocityChange(rx - FROM_FIXED(player->velocity.x), ry - FROM_FIXED(player->velocity.y));145player->velocity = self->velocity;146RSDK.SetSpriteAnimation(player->aniFrames, ANI_JUMP, &player->animator, false, 0);147player->drawGroup = 1;148player->onGround = false;149player->tileCollisions = TILECOLLISION_NONE;150player->interaction = false;151player->state = Player_State_TransportTube;152player->nextAirState = StateMachine_None;153player->nextGroundState = StateMachine_None;154TransportTube->nextSlot[i] = 0;155RSDK.PlaySfx(TransportTube->sfxTravel, false, 255);156self->playerTimers[i] = 2;157}158}159}160}161}162163void TransportTube_State_ToTargetEntity(void)164{165RSDK_THIS(TransportTube);166167for (int32 i = 0; i < Player->playerCount; ++i) {168EntityPlayer *player = RSDK_GET_ENTITY(i, Player);169int32 rx = FROM_FIXED(player->position.x - self->position.x);170int32 ry = FROM_FIXED(player->position.y - self->position.y);171172if (self->playerTimers[i]) {173if (rx * rx + ry * ry >= 0xC0)174--self->playerTimers[i];175}176else if (player->state == Player_State_TransportTube && rx * rx + ry * ry < 0xC0) {177if (self->players[i]) {178TransportTube->nextSlot[i] = 0;179self->players[i] = NULL;180self->playerTimers[i] = 2;181}182else {183if (self->type == TRANSPORTTUBE_TOTARGET_NEXT)184TransportTube->nextSlot[i] = 1;185else186TransportTube->nextSlot[i] = -1;187188EntityTransportTube *node = RSDK_GET_ENTITY(SceneInfo->entitySlot + TransportTube->nextSlot[i], TransportTube);189int32 angle = RSDK.ATan2(FROM_FIXED(node->position.x - player->position.x), FROM_FIXED(node->position.y - player->position.y));190player->velocity.x = 0xC00 * RSDK.Cos256(angle);191player->velocity.y = 0xC00 * RSDK.Sin256(angle);192node->players[i] = player;193self->playerTimers[i] = 2;194}195}196}197}198199void TransportTube_State_TargetSeqNode(void)200{201RSDK_THIS(TransportTube);202203for (int32 i = 0; i < Player->playerCount; ++i) {204EntityPlayer *player = self->players[i];205if (player) {206if (player->state == Player_State_TransportTube) {207int32 rx = FROM_FIXED(player->position.x - self->position.x);208int32 ry = FROM_FIXED(player->position.y - self->position.y);209if (rx * rx + ry * ry < 0xC0) {210player->position.x = self->position.x;211player->position.y = self->position.y;212213EntityTransportTube *node = RSDK_GET_ENTITY(SceneInfo->entitySlot + TransportTube->nextSlot[i], TransportTube);214int32 angle = RSDK.ATan2(FROM_FIXED(node->position.x - player->position.x), FROM_FIXED(node->position.y - player->position.y));215player->velocity.x = 0xC00 * RSDK.Cos256(angle);216player->velocity.y = 0xC00 * RSDK.Sin256(angle);217self->players[i] = NULL;218node->players[i] = player;219}220}221else {222self->players[i] = NULL;223}224}225}226}227228void TransportTube_State_ChooseDir(void)229{230RSDK_THIS(TransportTube);231232for (int32 i = 0; i < Player->playerCount; ++i) {233EntityPlayer *player = RSDK_GET_ENTITY(i, Player);234int32 rx = FROM_FIXED(player->position.x - self->position.x);235int32 ry = FROM_FIXED(player->position.y - self->position.y);236237if (self->playerTimers[i]) {238if (rx * rx + ry * ry >= 0xC0)239--self->playerTimers[i];240}241else if (player->state == Player_State_TransportTube && rx * rx + ry * ry < 0xC0) {242player->position.x = self->position.x;243player->position.y = self->position.y;244player->velocity.x = 0;245player->velocity.y = 0;246247uint8 moveMask = self->dirMask & ((player->up << 0) | (player->down << 1) | (player->left << 2) | (player->right << 3));248if (moveMask & 1)249player->velocity.y = -0x100000;250else if (moveMask & 2)251player->velocity.y = 0x100000;252else if (moveMask & 4)253player->velocity.x = -0x100000;254else if (moveMask & 8)255player->velocity.x = 0x100000;256257if (player->velocity.x || player->velocity.y) {258self->playerTimers[i] = 2;259RSDK.PlaySfx(TransportTube->sfxTravel, false, 255);260}261}262}263}264265void TransportTube_State_Exit(void)266{267RSDK_THIS(TransportTube);268269for (int32 i = 0; i < Player->playerCount; ++i) {270EntityPlayer *player = RSDK_GET_ENTITY(i, Player);271272if (Player_CheckValidState(player)) {273int32 rx = FROM_FIXED(player->position.x - self->position.x);274int32 ry = FROM_FIXED(player->position.y - self->position.y);275276if (self->playerTimers[i]) {277if (rx * rx + ry * ry >= 0xC0)278self->playerTimers[i]--;279}280else if (rx * rx + ry * ry < 0xC0) {281player->position.x = self->position.x;282player->position.y = self->position.y;283player->drawGroup = Zone->playerDrawGroup[0];284player->tileCollisions = TILECOLLISION_DOWN;285player->interaction = true;286player->state = Player_State_Air;287self->playerTimers[i] = 2;288}289}290}291}292293#if GAME_INCLUDE_EDITOR294void TransportTube_EditorDraw(void)295{296RSDK_THIS(TransportTube);297self->updateRange.x = 0xC00000;298self->updateRange.y = 0xC00000;299300RSDK.SetSpriteAnimation(TransportTube->aniFrames, 0, &self->animator, true, 0);301RSDK.DrawSprite(&self->animator, NULL, false);302303RSDK_DRAWING_OVERLAY(true);304305TransportTube_SetupDirections(self);306for (int32 v = 0; v < self->directionCount; ++v) {307DrawHelpers_DrawArrow(self->position.x, self->position.y, self->position.x + (self->dirVelocity[v].x << 18),308self->position.y + (self->dirVelocity[v].y << 18), 0xFF0000, INK_NONE, 0xFF);309}310311RSDK_DRAWING_OVERLAY(false);312313RSDK.SetSpriteAnimation(TransportTube->aniFrames, self->type == TRANSPORTTUBE_JUNCTION ? 1 : 2, &self->animator, true, 0);314RSDK.DrawSprite(&self->animator, NULL, false);315}316317void TransportTube_EditorLoad(void)318{319TransportTube->aniFrames = RSDK.LoadSpriteAnimation("CPZ/TransportTube.bin", SCOPE_STAGE);320321RSDK_ACTIVE_VAR(TransportTube, type);322RSDK_ENUM_VAR("Change Direction", TRANSPORTTUBE_CHANGEDIR);323RSDK_ENUM_VAR("Entrance", TRANSPORTTUBE_ENTRY);324RSDK_ENUM_VAR("Start Sequence (Next Slot)", TRANSPORTTUBE_TOTARGET_NEXT);325RSDK_ENUM_VAR("Start Sequence (Prev Slot)", TRANSPORTTUBE_TOTARGET_PREV);326RSDK_ENUM_VAR("Sequence Node", TRANSPORTTUBE_TOTARGET_NODE);327RSDK_ENUM_VAR("Junction", TRANSPORTTUBE_JUNCTION);328RSDK_ENUM_VAR("Exit", TRANSPORTTUBE_EXIT);329}330#endif331332void TransportTube_Serialize(void)333{334RSDK_EDITABLE_VAR(TransportTube, VAR_UINT8, type);335RSDK_EDITABLE_VAR(TransportTube, VAR_UINT8, dirMask);336}337338339