Path: blob/master/SonicMania/Objects/SPZ/CableWarp.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: CableWarp Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectCableWarp *CableWarp;1011void CableWarp_Update(void)12{13RSDK_THIS(CableWarp);1415StateMachine_Run(self->state);16}1718void CableWarp_LateUpdate(void) {}1920void CableWarp_StaticUpdate(void) {}2122void CableWarp_Draw(void)23{24RSDK_THIS(CableWarp);2526RSDK.DrawSprite(&self->animator, NULL, false);27}2829void CableWarp_Create(void *data)30{31RSDK_THIS(CableWarp);3233if (!SceneInfo->inEditor) {34if (data)35self->type = VOID_TO_INT(data);3637self->active = ACTIVE_BOUNDS;38self->updateRange.x = 0x400000;39self->updateRange.y = 0x400000;40self->drawGroup = Zone->objectDrawGroup[1];41self->alpha = 0x100;4243switch (self->type) {44case CABLEWARP_ENTRY:45self->visible = true;46RSDK.SetSpriteAnimation(CableWarp->aniFrames, 0, &self->animator, true, 0);47self->state = CableWarp_State_CablePlug;48break;4950case CABLEWARP_EXIT:51self->visible = true;52RSDK.SetSpriteAnimation(CableWarp->aniFrames, 0, &self->animator, true, 2);53self->state = CableWarp_State_CheckPlayerEntry;54break;5556case CABLEWARP_NODE: self->visible = false; break;5758case CABLEWARP_TRANSPORT:59self->visible = false;60self->active = ACTIVE_NORMAL;61RSDK.SetSpriteAnimation(CableWarp->aniFrames, 1, &self->animator, true, 0);62self->state = CableWarp_StateTransport_BeginEnter;63break;6465default: break;66}67}68}6970void CableWarp_StageLoad(void)71{72CableWarp->aniFrames = RSDK.LoadSpriteAnimation("SPZ2/CableWarp.bin", SCOPE_STAGE);7374CableWarp->sfxCharge = RSDK.GetSfx("Stage/ElecCharge.wav");75CableWarp->sfxPulse = RSDK.GetSfx("Stage/ElecPulse.wav");76CableWarp->sfxLedgeBreak = RSDK.GetSfx("Stage/LedgeBreak.wav");7778CableWarp->hitboxPlug.left = -16;79CableWarp->hitboxPlug.top = -16;80CableWarp->hitboxPlug.right = 16;81CableWarp->hitboxPlug.bottom = 32;8283CableWarp->hitboxTransport.left = -16;84CableWarp->hitboxTransport.top = 0;85CableWarp->hitboxTransport.right = 16;86CableWarp->hitboxTransport.bottom = 32;87}8889void CableWarp_State_CablePlug(void)90{91RSDK_THIS(CableWarp);9293foreach_active(Player, player)94{95#if MANIA_USE_PLUS96int32 velY = player->velocity.y;97#endif9899if (Player_CheckCollisionBox(player, self, &CableWarp->hitboxPlug) == C_TOP) {100#if MANIA_USE_PLUS101if (player->animator.animationID == ANI_JUMP || player->state == Player_State_DropDash102|| player->state == Player_State_MightyHammerDrop) {103if (player->state == Player_State_DropDash) {104player->velocity.y = -0x10000;105RSDK.SetSpriteAnimation(player->aniFrames, ANI_JUMP, &player->animator, false, 0);106player->state = Player_State_Air;107}108else if (player->state == Player_State_MightyHammerDrop) {109player->velocity.y = velY;110RSDK.SetSpriteAnimation(player->aniFrames, ANI_JUMP, &player->animator, false, 0);111player->state = Player_State_Air;112}113else {114player->velocity.y = -0x10000;115}116#else117if (player->animator.animationID == ANI_JUMP) {118player->velocity.y = -0x10000;119#endif120player->onGround = false;121122EntityDebris *debris = CREATE_ENTITY(Debris, Debris_State_Fall, self->position.x - 0x80000, self->position.y - 0x80000);123debris->velocity.x = -0x20000;124debris->velocity.y = -0x20000;125debris->gravityStrength = 0x3800;126debris->drawGroup = Zone->playerDrawGroup[1];127RSDK.SetSpriteAnimation(CableWarp->aniFrames, 0, &debris->animator, true, 3);128129debris = CREATE_ENTITY(Debris, Debris_State_Fall, self->position.x + 0x80000, self->position.y - 0x80000);130debris->velocity.x = 0x20000;131debris->velocity.y = -0x20000;132debris->gravityStrength = 0x3800;133debris->drawGroup = Zone->playerDrawGroup[1];134RSDK.SetSpriteAnimation(CableWarp->aniFrames, 0, &debris->animator, true, 4);135RSDK.PlaySfx(CableWarp->sfxLedgeBreak, false, 0xFF);136RSDK.SetSpriteAnimation(CableWarp->aniFrames, 0, &self->animator, true, 1);137self->state = CableWarp_State_CheckPlayerEntry;138139foreach_break;140}141}142}143}144145void CableWarp_State_CheckPlayerEntry(void)146{147RSDK_THIS(CableWarp);148149foreach_active(Player, player)150{151if (Player_CheckCollisionBox(player, self, &CableWarp->hitboxTransport) == C_TOP && !self->type) {152player->state = Player_State_Static;153player->nextAirState = StateMachine_None;154player->nextGroundState = StateMachine_None;155player->tileCollisions = TILECOLLISION_NONE;156player->interaction = false;157player->onGround = false;158player->velocity.x = 0;159player->velocity.y = 0;160RSDK.SetSpriteAnimation(player->aniFrames, ANI_JUMP, &player->animator, false, 0);161162EntityCableWarp *warp = CREATE_ENTITY(CableWarp, INT_TO_VOID(CABLEWARP_TRANSPORT), self->position.x, self->position.y);163warp->isPermanent = true;164warp->player = player;165166warp->slotID = SceneInfo->entitySlot;167if (self->type) {168warp->nextSlot = warp->slotID - 1;169EntityCableWarp *nextNode = RSDK_GET_ENTITY(warp->nextSlot, CableWarp);170if (nextNode->classID != CableWarp->classID || nextNode->type != CABLEWARP_NODE)171warp->nextSlot += 2;172}173else {174warp->nextSlot = warp->slotID + 1;175EntityCableWarp *nextNode = RSDK_GET_ENTITY(warp->nextSlot, CableWarp);176if (nextNode->classID == CableWarp->classID) {177if (nextNode->type != CABLEWARP_NODE)178warp->nextSlot -= 2;179}180else {181warp->nextSlot -= 2;182}183}184}185}186}187188void CableWarp_StateTransport_BeginEnter(void)189{190RSDK_THIS(CableWarp);191EntityPlayer *player = (EntityPlayer *)self->player;192193if (player->state == Player_State_Static) {194int32 x = self->position.x;195int32 y = self->position.y - 0x200000;196197if (player->animator.speed < 0xF0)198player->animator.speed += 8;199200player->velocity.x += ((x - player->position.x) >> 5) - (player->velocity.x >> 4);201player->velocity.y += ((y - player->position.y) >> 5) - (player->velocity.y >> 4);202203if (++self->timer == 30) {204player->position.x = x;205player->position.y = y;206player->velocity.x = 0;207player->velocity.y = 0;208self->visible = true;209self->state = CableWarp_StateTransport_Enter;210RSDK.PlaySfx(CableWarp->sfxCharge, false, 0xFF);211}212}213else {214destroyEntity(self);215}216}217218void CableWarp_StateTransport_Enter(void)219{220RSDK_THIS(CableWarp);221222EntityPlayer *player = self->player;223if (player->state == Player_State_Static) {224RSDK.ProcessAnimation(&self->animator);225226if (self->animator.frameID == 20) {227player->visible = false;228player->velocity.y = 0x60000;229RSDK.PlaySfx(CableWarp->sfxPulse, false, 0xFF);230}231else if (self->animator.frameID == self->animator.frameCount - 1) {232RSDK.SetSpriteAnimation(CableWarp->aniFrames, 2, &self->animator, true, 0);233self->inkEffect = INK_ADD;234EntityCableWarp *nextNode = RSDK_GET_ENTITY(self->nextSlot, CableWarp);235int32 angle = RSDK.ATan2((nextNode->position.x - player->position.x) >> 16, (nextNode->position.y - player->position.y) >> 16);236self->angle = angle;237self->rotation = 2 * angle;238player->velocity.x = RSDK.Cos256(self->angle) << 12;239player->velocity.y = RSDK.Sin256(self->angle) << 12;240self->drawFX = FX_ROTATE | FX_FLIP;241self->state = CableWarp_StateTransport_MoveToNextNode;242}243}244else {245destroyEntity(self);246}247}248249void CableWarp_StateTransport_MoveToNextNode(void)250{251RSDK_THIS(CableWarp);252253EntityPlayer *player = self->player;254if (player->state == Player_State_Static) {255RSDK.ProcessAnimation(&self->animator);256self->position.x = player->position.x;257self->position.y = player->position.y;258RSDK_GET_ENTITY(self->slotID, CableWarp);259260EntityCableWarp *nextNode = RSDK_GET_ENTITY(self->nextSlot, CableWarp);261int32 rx = (nextNode->position.x - player->position.x) >> 16;262int32 ry = (nextNode->position.y - player->position.y) >> 16;263if (rx * rx + ry * ry < 0x100) {264player->position.x = nextNode->position.x;265player->position.y = nextNode->position.y;266267if (self->slotID >= self->nextSlot) {268self->nextSlot--;269self->slotID--;270}271else {272self->nextSlot++;273self->slotID++;274}275276nextNode = RSDK_GET_ENTITY(self->nextSlot, CableWarp);277int32 angle = RSDK.ATan2((nextNode->position.x - player->position.x) >> 16, (nextNode->position.y - player->position.y) >> 16);278self->angle = angle;279self->rotation = 2 * angle + 128;280player->velocity.x = RSDK.Cos256(self->angle) << 12;281player->velocity.y = (RSDK.Sin256(self->angle) << 12);282if (nextNode->type != CABLEWARP_NODE)283self->state = CableWarp_StateTransport_EndNode;284}285}286else {287destroyEntity(self);288}289}290291void CableWarp_StateTransport_EndNode(void)292{293RSDK_THIS(CableWarp);294EntityPlayer *player = (EntityPlayer *)self->player;295296if (player->state == Player_State_Static) {297RSDK.ProcessAnimation(&self->animator);298self->position.x = player->position.x;299self->position.y = player->position.y;300301RSDK_GET_ENTITY(self->slotID, CableWarp);302EntityCableWarp *nextNode = RSDK_GET_ENTITY(self->nextSlot, CableWarp);303304int32 rx = (nextNode->position.x - player->position.x) >> 16;305int32 ry = (nextNode->position.y - player->position.y) >> 16;306if (rx * rx + ry * ry < 0x100) {307player->position.x = nextNode->position.x;308player->position.y = nextNode->position.y;309player->velocity.x = 0;310player->velocity.y = -0x80000;311if (nextNode->state == CableWarp_State_CablePlug) {312EntityDebris *debris = CREATE_ENTITY(Debris, Debris_State_Fall, nextNode->position.x - 0x80000, nextNode->position.y - 0x80000);313debris->velocity.x = -0x20000;314debris->velocity.y = -0x20000;315debris->gravityStrength = 0x3800;316debris->drawGroup = Zone->playerDrawGroup[1];317RSDK.SetSpriteAnimation(CableWarp->aniFrames, 0, &debris->animator, true, 3);318319debris = CREATE_ENTITY(Debris, Debris_State_Fall, nextNode->position.x + 0x80000, nextNode->position.y - 0x80000);320debris->velocity.x = 0x20000;321debris->velocity.y = -0x20000;322debris->gravityStrength = 0x3800;323debris->drawGroup = Zone->playerDrawGroup[1];324325RSDK.SetSpriteAnimation(CableWarp->aniFrames, 0, &debris->animator, true, 4);326RSDK.PlaySfx(CableWarp->sfxLedgeBreak, false, 255);327RSDK.SetSpriteAnimation(CableWarp->aniFrames, 0, &nextNode->animator, true, 1);328nextNode->state = CableWarp_State_CheckPlayerEntry;329}330RSDK.SetSpriteAnimation(CableWarp->aniFrames, 3, &self->animator, true, 0);331self->timer = 0;332self->state = CableWarp_StateTransport_Exit;333self->inkEffect = INK_NONE;334RSDK.PlaySfx(CableWarp->sfxPulse, false, 255);335}336}337else {338destroyEntity(self);339}340}341342void CableWarp_StateTransport_Exit(void)343{344RSDK_THIS(CableWarp);345EntityPlayer *player = (EntityPlayer *)self->player;346347RSDK.ProcessAnimation(&self->animator);348++self->timer;349if (self->animator.frameID == self->animator.frameCount - 1) {350player->state = Player_State_Air;351player->visible = true;352player->tileCollisions = TILECOLLISION_DOWN;353player->interaction = true;354player->applyJumpCap = false;355player->velocity.y = -0xA0000;356player->position.y = self->position.y - 0x180000;357destroyEntity(self);358}359}360361#if GAME_INCLUDE_EDITOR362void CableWarp_EditorDraw(void)363{364RSDK_THIS(CableWarp);365366self->updateRange.x = 0x400000;367self->updateRange.y = 0x400000;368switch (self->type) {369case CABLEWARP_ENTRY: RSDK.SetSpriteAnimation(CableWarp->aniFrames, 0, &self->animator, true, 0); break;370case CABLEWARP_EXIT: RSDK.SetSpriteAnimation(CableWarp->aniFrames, 0, &self->animator, true, 2); break;371case CABLEWARP_NODE: RSDK.SetSpriteAnimation(CableWarp->aniFrames, 4, &self->animator, true, 2); break;372default: break;373}374375CableWarp_Draw();376377if (showGizmos()) {378RSDK_DRAWING_OVERLAY(true);379380self->inkEffect = INK_BLEND;381382int32 slotID = SceneInfo->entitySlot;383int32 nextSlot = -1;384switch (self->type) {385case CABLEWARP_ENTRY: {386nextSlot = slotID + 1;387EntityCableWarp *nextNode = RSDK_GET_ENTITY(nextSlot, CableWarp);388if (nextNode && nextNode->classID == CableWarp->classID) {389if (nextNode->type != CABLEWARP_NODE)390nextSlot -= 2;391}392else {393nextSlot -= 2;394}395break;396}397398case CABLEWARP_EXIT: {399nextSlot = slotID - 1;400EntityCableWarp *nextNode = RSDK_GET_ENTITY(nextSlot, CableWarp);401if (nextNode && (nextNode->classID != CableWarp->classID || nextNode->type != CABLEWARP_NODE))402nextSlot += 2;403break;404}405406default: break;407}408409if (nextSlot != -1) {410EntityCableWarp *lastNode = RSDK_GET_ENTITY(slotID, CableWarp);411while (lastNode) {412EntityCableWarp *nextNode = RSDK_GET_ENTITY(nextSlot, CableWarp);413if (!nextNode)414break;415416DrawHelpers_DrawArrow(lastNode->position.x, lastNode->position.y, nextNode->position.x, nextNode->position.y, 0xFFFF00, INK_NONE,4170xFF);418419if (nextNode->type != CABLEWARP_NODE)420break;421422if (slotID >= nextSlot) {423nextSlot--;424slotID--;425}426else {427nextSlot++;428slotID++;429}430431lastNode = nextNode;432}433}434435self->inkEffect = INK_NONE;436437RSDK_DRAWING_OVERLAY(false);438}439}440441void CableWarp_EditorLoad(void)442{443CableWarp->aniFrames = RSDK.LoadSpriteAnimation("SPZ2/CableWarp.bin", SCOPE_STAGE);444445RSDK_ACTIVE_VAR(CableWarp, type);446RSDK_ENUM_VAR("Entry", CABLEWARP_ENTRY);447RSDK_ENUM_VAR("Exit", CABLEWARP_EXIT);448RSDK_ENUM_VAR("Warp Node", CABLEWARP_NODE);449}450#endif451452void CableWarp_Serialize(void) { RSDK_EDITABLE_VAR(CableWarp, VAR_ENUM, type); }453454455