Path: blob/master/SonicMania/Objects/Common/Button.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: Button Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectButton *Button;1011void Button_Update(void)12{13RSDK_THIS(Button);1415self->down = false;16self->currentlyActive = false;1718switch (self->type) {19case BUTTON_FLOOR:20Button_HandleFloor();2122if (Button->hasEggman)23Button_CheckEggmanCollisions();24if (Button->hasPhantomRider)25Button_CheckPRiderCollisions();26break;2728case BUTTON_ROOF: Button_HandleRoof(); break;29case BUTTON_RWALL: Button_HandleRWall(); break;30case BUTTON_LWALL: Button_HandleLWall(); break;3132default: break;33}3435if (!self->down)36self->wasActivated = false;3738self->baseAnimator.frameID = self->down + 1;39}4041void Button_LateUpdate(void) {}4243void Button_StaticUpdate(void) {}4445void Button_Draw(void)46{47RSDK_THIS(Button);4849Vector2 drawPos;5051drawPos.x = self->position.x;52drawPos.y = self->position.y;5354if (self->type >= BUTTON_RWALL)55drawPos.x -= self->pressPos;56else57drawPos.y += self->pressPos;5859RSDK.DrawSprite(&self->buttonAnimator, &drawPos, false);60RSDK.DrawSprite(&self->baseAnimator, NULL, false);61}6263void Button_Create(void *data)64{65RSDK_THIS(Button);6667self->drawFX = FX_FLIP;68if (!SceneInfo->inEditor) {69switch (self->type) {70case BUTTON_FLOOR:71self->direction = FLIP_NONE;72RSDK.SetSpriteAnimation(Button->aniFrames, 0, &self->buttonAnimator, true, 0);73RSDK.SetSpriteAnimation(Button->aniFrames, 0, &self->baseAnimator, true, 1);7475self->hitboxButton.left = Button->hitboxV.left;76self->hitboxButton.top = Button->hitboxV.top;77self->hitboxButton.right = Button->hitboxV.right;78self->hitboxButton.bottom = Button->hitboxV.bottom;79break;8081case BUTTON_ROOF:82self->direction = FLIP_Y;83RSDK.SetSpriteAnimation(Button->aniFrames, 0, &self->buttonAnimator, true, 0);84RSDK.SetSpriteAnimation(Button->aniFrames, 0, &self->baseAnimator, true, 1);8586self->hitboxButton.left = Button->hitboxV.left;87self->hitboxButton.top = Button->hitboxV.top;88self->hitboxButton.right = Button->hitboxV.right;89self->hitboxButton.bottom = Button->hitboxV.bottom;90break;9192case BUTTON_RWALL:93self->direction = FLIP_NONE;94RSDK.SetSpriteAnimation(Button->aniFrames, 1, &self->buttonAnimator, true, 0);95RSDK.SetSpriteAnimation(Button->aniFrames, 1, &self->baseAnimator, true, 1);9697self->hitboxButton.left = Button->hitboxH.left;98self->hitboxButton.top = Button->hitboxH.top;99self->hitboxButton.right = Button->hitboxH.right;100self->hitboxButton.bottom = Button->hitboxH.bottom;101break;102103case BUTTON_LWALL:104self->direction = FLIP_X;105RSDK.SetSpriteAnimation(Button->aniFrames, 1, &self->buttonAnimator, true, 0);106RSDK.SetSpriteAnimation(Button->aniFrames, 1, &self->baseAnimator, true, 1);107108self->hitboxButton.left = Button->hitboxH.left;109self->hitboxButton.top = Button->hitboxH.top;110self->hitboxButton.right = Button->hitboxH.right;111self->hitboxButton.bottom = Button->hitboxH.bottom;112break;113114default: break;115}116117self->active = ACTIVE_BOUNDS;118self->updateRange.x = TO_FIXED(32);119self->updateRange.y = TO_FIXED(32);120self->visible = true;121self->drawGroup = Zone->objectDrawGroup[0];122}123}124125void Button_StageLoad(void)126{127if (RSDK.CheckSceneFolder("MMZ")) {128Button->aniFrames = RSDK.LoadSpriteAnimation("MMZ/Button.bin", SCOPE_STAGE);129Button->activatePos = TO_FIXED(8);130Button->buttonOffset = TO_FIXED(5);131Button->hitboxOffset = 13;132Button->unused1 = 5;133}134else if (RSDK.CheckSceneFolder("FBZ")) {135Button->aniFrames = RSDK.LoadSpriteAnimation("FBZ/Button.bin", SCOPE_STAGE);136Button->activatePos = TO_FIXED(8);137Button->buttonOffset = TO_FIXED(5);138Button->hitboxOffset = 13;139Button->unused1 = 5;140}141else if (RSDK.CheckSceneFolder("LRZ1")) {142Button->aniFrames = RSDK.LoadSpriteAnimation("LRZ1/Button.bin", SCOPE_STAGE);143Button->activatePos = TO_FIXED(4);144Button->buttonOffset = TO_FIXED(3);145Button->hitboxOffset = 7;146Button->unused1 = 3;147}148else if (RSDK.CheckSceneFolder("LRZ2")) {149Button->aniFrames = RSDK.LoadSpriteAnimation("LRZ2/Button.bin", SCOPE_STAGE);150Button->activatePos = TO_FIXED(4);151Button->buttonOffset = TO_FIXED(3);152Button->hitboxOffset = 7;153Button->unused1 = 3;154}155else if (RSDK.CheckSceneFolder("HCZ")) {156Button->aniFrames = RSDK.LoadSpriteAnimation("HCZ/Button.bin", SCOPE_STAGE);157Button->activatePos = TO_FIXED(3);158Button->buttonOffset = TO_FIXED(3);159Button->hitboxOffset = 9;160Button->unused1 = 6;161}162else if (RSDK.CheckSceneFolder("TMZ3")) {163Button->aniFrames = RSDK.LoadSpriteAnimation("TMZ1/Button.bin", SCOPE_STAGE);164Button->activatePos = TO_FIXED(3);165Button->buttonOffset = TO_FIXED(3);166Button->hitboxOffset = 9;167Button->unused1 = 6;168}169else {170Button->activatePos = TO_FIXED(8);171Button->buttonOffset = TO_FIXED(5);172Button->hitboxOffset = 13;173Button->unused1 = 5;174}175176Button->hitboxH.left = -3;177Button->hitboxH.top = -16;178Button->hitboxH.right = 8;179Button->hitboxH.bottom = 16;180181Button->hitboxV.left = -16;182Button->hitboxV.top = -8;183Button->hitboxV.right = 16;184Button->hitboxV.bottom = 3;185186if (RSDK.FindObject("Eggman"))187Button->hasEggman = true;188189if (RSDK.FindObject("PhantomRider"))190Button->hasPhantomRider = true;191192Button->sfxButton = RSDK.GetSfx("Stage/Button.wav");193}194195void Button_CheckEggmanCollisions(void)196{197RSDK_THIS(Button);198199foreach_active(Eggman, eggman)200{201self->hitboxButton.top = (Button->activatePos >> 16) - (Button->hitboxOffset & 0xFFFF);202if (RSDK.CheckObjectCollisionPlatform(self, &self->hitboxButton, eggman, &eggman->hitbox, true)) {203eggman->onGround = true;204self->pressPos = Button->activatePos;205206if (!self->wasActivated) {207RSDK.PlaySfx(Button->sfxButton, false, 0xFF);208self->currentlyActive = true;209self->toggled ^= true;210}211212self->wasActivated = true;213self->down = true;214self->activated = true;215}216}217}218219void Button_CheckPRiderCollisions(void)220{221RSDK_THIS(Button);222223foreach_active(PhantomRider, rider)224{225self->hitboxButton.top = (Button->activatePos >> 16) - (Button->hitboxOffset & 0xFFFF);226if (RSDK.CheckObjectCollisionPlatform(self, &self->hitboxButton, rider, &rider->hitbox, true)) {227self->pressPos = Button->activatePos;228229if (!self->wasActivated) {230RSDK.PlaySfx(Button->sfxButton, false, 0xFF);231self->currentlyActive = true;232self->toggled ^= true;233}234235self->wasActivated = true;236self->down = true;237self->activated = true;238}239}240}241242void Button_HandleFloor(void)243{244RSDK_THIS(Button);245246int32 startPressPos = self->pressPos;247self->pressPos = 0;248249foreach_active(Player, player)250{251self->hitboxButton.top = (startPressPos >> 16) - (Button->hitboxOffset & 0xFFFF);252self->hitboxButton.bottom = self->hitboxButton.top + 32;253254int32 playerX = player->position.x;255int32 playerY = player->position.y;256int32 xVel = player->velocity.x;257int32 yVel = player->velocity.y;258int32 vel = player->groundVel;259bool32 grounded = player->onGround;260bool32 groundedStore = player->groundedStore;261StateMachine(nextGState) = player->nextGroundState;262StateMachine(nextAState) = player->nextAirState;263StateMachine(state) = player->state;264265if (Player_CheckCollisionBox(player, self, &self->hitboxButton) == C_TOP || self->walkOnto) {266player->position.x = playerX;267player->position.y = playerY;268player->velocity.x = xVel;269player->velocity.y = yVel;270player->groundVel = vel;271player->onGround = grounded;272player->groundedStore = groundedStore;273player->nextGroundState = nextGState;274player->nextAirState = nextAState;275player->state = state;276277self->hitboxButton.top -= (startPressPos >> 16);278self->hitboxButton.top += (Button->activatePos >> 16);279int32 newPressPos = self->pressPos;280281if (Player_CheckCollisionPlatform(player, self, &self->hitboxButton) == C_TOP) {282self->pressPos = Button->activatePos;283}284else {285self->position.y -= Button->activatePos;286if (Player_CheckCollisionTouch(player, self, &self->hitboxButton)) {287Hitbox *playerHitbox = Player_GetHitbox(player);288self->pressPos = Button->buttonOffset + (player->position.y & 0xFFFF0000) + (playerHitbox->bottom << 16) - self->position.y;289self->pressPos = CLAMP(self->pressPos, 0, Button->activatePos) & 0xFFFF0000;290}291292self->position.y += Button->activatePos;293}294295if (self->pressPos == Button->activatePos) {296Player_CheckCollisionBox(player, self, &self->hitboxButton);297player->angle = 0;298if (!self->wasActivated) {299RSDK.PlaySfx(Button->sfxButton, false, 255);300self->currentlyActive = true;301self->toggled ^= true;302}303self->wasActivated = true;304self->down = true;305self->activated = true;306}307308if (newPressPos > self->pressPos)309self->pressPos = newPressPos;310}311312if (self->pressPos)313startPressPos = self->pressPos;314}315}316void Button_HandleRoof(void)317{318RSDK_THIS(Button);319320int32 startPressPos = self->pressPos;321self->pressPos = 0;322323foreach_active(Player, player)324{325self->hitboxButton.top = -1 - (Button->hitboxOffset & 0xFFFF) - (startPressPos >> 16);326self->hitboxButton.bottom = self->hitboxButton.top + 32;327328int32 playerX = player->position.x;329int32 playerY = player->position.y;330int32 xVel = player->velocity.x;331int32 yVel = player->velocity.y;332int32 vel = player->groundVel;333bool32 grounded = player->onGround;334bool32 groundedStore = player->groundedStore;335StateMachine(nextGState) = player->nextGroundState;336StateMachine(nextAState) = player->nextAirState;337StateMachine(state) = player->state;338339if (Player_CheckCollisionBox(player, self, &self->hitboxButton) == C_BOTTOM || self->walkOnto) {340player->position.x = playerX;341player->position.y = playerY;342player->velocity.x = xVel;343player->velocity.y = yVel;344player->groundVel = vel;345player->onGround = grounded;346player->groundedStore = groundedStore;347player->nextGroundState = nextGState;348player->nextAirState = nextAState;349player->state = state;350351self->hitboxButton.top += (startPressPos >> 16);352self->hitboxButton.top += (Button->activatePos >> 16);353int32 newPressPos = self->pressPos;354355if (Player_CheckCollisionBox(player, self, &self->hitboxButton) == C_BOTTOM) {356self->pressPos = -Button->activatePos;357}358else {359self->position.y += Button->activatePos;360if (Player_CheckCollisionTouch(player, self, &self->hitboxButton)) {361Hitbox *playerHitbox = Player_GetHitbox(player);362self->pressPos = (player->position.y & 0xFFFF0000) + (playerHitbox->top << 16) - Button->buttonOffset - self->position.y;363self->pressPos = CLAMP(self->pressPos, -Button->activatePos, 0) & 0xFFFF0000;364}365366self->position.y -= Button->activatePos;367}368369if (self->pressPos == -Button->activatePos) {370if (!self->wasActivated) {371RSDK.PlaySfx(Button->sfxButton, false, 255);372self->currentlyActive = true;373self->toggled ^= true;374}375376self->wasActivated = true;377self->down = true;378self->activated = true;379}380381if (newPressPos < self->pressPos)382self->pressPos = newPressPos;383}384385if (self->pressPos)386startPressPos = self->pressPos;387}388}389void Button_HandleRWall(void)390{391RSDK_THIS(Button);392393int32 startPressPos = self->pressPos;394self->pressPos = 0;395396foreach_active(Player, player)397{398self->hitboxButton.right = (Button->hitboxOffset & 0xFFFF) - (startPressPos >> 16) + 1;399self->hitboxButton.left = self->hitboxButton.right - 16;400401int32 playerX = player->position.x;402int32 playerY = player->position.y;403int32 xVel = player->velocity.x;404int32 yVel = player->velocity.y;405int32 vel = player->groundVel;406bool32 grounded = player->onGround;407bool32 groundedStore = player->groundedStore;408StateMachine(nextGState) = player->nextGroundState;409StateMachine(nextAState) = player->nextAirState;410StateMachine(state) = player->state;411412if (Player_CheckCollisionBox(player, self, &self->hitboxButton) == C_RIGHT || self->walkOnto) {413player->position.x = playerX;414player->position.y = playerY;415player->velocity.x = xVel;416player->velocity.y = yVel;417player->groundVel = vel;418player->onGround = grounded;419player->groundedStore = groundedStore;420player->nextGroundState = nextGState;421player->nextAirState = nextAState;422player->state = state;423424self->hitboxButton.right += (startPressPos >> 16);425self->hitboxButton.right = self->hitboxButton.right - (Button->activatePos >> 16) - 1;426int32 newPressPos = self->pressPos;427428if (Player_CheckCollisionBox(player, self, &self->hitboxButton) == C_RIGHT) {429self->pressPos = Button->activatePos;430}431else {432self->position.x += Button->activatePos;433if (Player_CheckCollisionTouch(player, self, &self->hitboxButton)) {434Hitbox *playerHitbox = Player_GetHitbox(player);435self->pressPos = Button->buttonOffset - (playerHitbox->left << 16) - (player->position.x & 0xFFFF0000) + self->position.x;436self->pressPos = CLAMP(self->pressPos, 0, Button->activatePos) & 0xFFFF0000;437}438self->position.x -= Button->activatePos;439}440441if (self->pressPos == Button->activatePos) {442if (!self->wasActivated) {443RSDK.PlaySfx(Button->sfxButton, false, 255);444self->currentlyActive = true;445self->toggled ^= true;446}447448self->wasActivated = true;449self->down = true;450self->activated = true;451}452453if (newPressPos > self->pressPos)454self->pressPos = newPressPos;455}456457if (self->pressPos)458startPressPos = self->pressPos;459}460}461void Button_HandleLWall(void)462{463RSDK_THIS(Button);464int32 startPressPos = self->pressPos;465self->pressPos = 0;466467foreach_active(Player, player)468{469self->hitboxButton.right = (startPressPos >> 16) + (Button->hitboxOffset & 0xFFFF);470self->hitboxButton.left = self->hitboxButton.right - 16;471472int32 playerX = player->position.x;473int32 playerY = player->position.y;474int32 xVel = player->velocity.x;475int32 yVel = player->velocity.y;476int32 vel = player->groundVel;477bool32 grounded = player->onGround;478bool32 groundedStore = player->groundedStore;479StateMachine(nextGState) = player->nextGroundState;480StateMachine(nextAState) = player->nextAirState;481StateMachine(state) = player->state;482483if (Player_CheckCollisionBox(player, self, &self->hitboxButton) == C_LEFT || self->walkOnto) {484player->position.x = playerX;485player->position.y = playerY;486player->velocity.x = xVel;487player->velocity.y = yVel;488player->groundVel = vel;489player->onGround = grounded;490player->groundedStore = groundedStore;491player->nextGroundState = nextGState;492player->nextAirState = nextAState;493player->state = state;494495self->hitboxButton.right -= (startPressPos >> 16);496self->hitboxButton.right -= (Button->activatePos >> 16);497int32 newPressPos = self->pressPos;498499if (Player_CheckCollisionBox(player, self, &self->hitboxButton) == C_LEFT) {500self->pressPos = -Button->activatePos;501}502else {503self->position.x -= Button->activatePos;504if (Player_CheckCollisionTouch(player, self, &self->hitboxButton)) {505Hitbox *playerHitbox = Player_GetHitbox(player);506self->pressPos = self->position.x - (playerHitbox->right << 16) - (player->position.x & 0xFFFF0000) - Button->buttonOffset;507self->pressPos = CLAMP(self->pressPos, -Button->activatePos, 0) & 0xFFFF0000;508}509510self->position.x += Button->activatePos;511}512513if (self->pressPos == -Button->activatePos) {514if (!self->wasActivated) {515RSDK.PlaySfx(Button->sfxButton, false, 255);516self->currentlyActive = true;517self->toggled ^= true;518}519self->wasActivated = true;520self->down = true;521self->activated = true;522}523524if (newPressPos < self->pressPos)525self->pressPos = newPressPos;526}527528if (self->pressPos)529startPressPos = self->pressPos;530}531532self->hitboxButton.right = (Button->hitboxOffset & 0xFFFF) + (startPressPos >> 16);533self->hitboxButton.left = self->hitboxButton.left - 16;534}535536#if GAME_INCLUDE_EDITOR537void Button_EditorDraw(void)538{539RSDK_THIS(Button);540541switch (self->type) {542case BUTTON_FLOOR:543self->direction = FLIP_NONE;544RSDK.SetSpriteAnimation(Button->aniFrames, 0, &self->buttonAnimator, true, 0);545RSDK.SetSpriteAnimation(Button->aniFrames, 0, &self->baseAnimator, true, 1);546break;547548case BUTTON_ROOF:549self->direction = FLIP_Y;550RSDK.SetSpriteAnimation(Button->aniFrames, 0, &self->buttonAnimator, true, 0);551RSDK.SetSpriteAnimation(Button->aniFrames, 0, &self->baseAnimator, true, 1);552break;553554case BUTTON_RWALL:555self->direction = FLIP_NONE;556RSDK.SetSpriteAnimation(Button->aniFrames, 1, &self->buttonAnimator, true, 0);557RSDK.SetSpriteAnimation(Button->aniFrames, 1, &self->baseAnimator, true, 1);558break;559560case BUTTON_LWALL:561self->direction = FLIP_X;562RSDK.SetSpriteAnimation(Button->aniFrames, 1, &self->buttonAnimator, true, 0);563RSDK.SetSpriteAnimation(Button->aniFrames, 1, &self->baseAnimator, true, 1);564break;565566default: break;567}568569RSDK.DrawSprite(&self->buttonAnimator, NULL, false);570RSDK.DrawSprite(&self->baseAnimator, NULL, false);571}572573void Button_EditorLoad(void)574{575if (RSDK.CheckSceneFolder("MMZ"))576Button->aniFrames = RSDK.LoadSpriteAnimation("MMZ/Button.bin", SCOPE_STAGE);577else if (RSDK.CheckSceneFolder("FBZ"))578Button->aniFrames = RSDK.LoadSpriteAnimation("FBZ/Button.bin", SCOPE_STAGE);579else if (RSDK.CheckSceneFolder("LRZ1"))580Button->aniFrames = RSDK.LoadSpriteAnimation("LRZ1/Button.bin", SCOPE_STAGE);581else if (RSDK.CheckSceneFolder("LRZ2"))582Button->aniFrames = RSDK.LoadSpriteAnimation("LRZ2/Button.bin", SCOPE_STAGE);583else if (RSDK.CheckSceneFolder("HCZ"))584Button->aniFrames = RSDK.LoadSpriteAnimation("HCZ/Button.bin", SCOPE_STAGE);585else if (RSDK.CheckSceneFolder("TMZ3"))586Button->aniFrames = RSDK.LoadSpriteAnimation("TMZ1/Button.bin", SCOPE_STAGE);587588RSDK_ACTIVE_VAR(Button, type);589RSDK_ENUM_VAR("Floor", BUTTON_FLOOR);590RSDK_ENUM_VAR("Ceiling", BUTTON_ROOF);591RSDK_ENUM_VAR("Right Wall", BUTTON_RWALL);592RSDK_ENUM_VAR("Left Wall", BUTTON_LWALL);593}594#endif595596void Button_Serialize(void)597{598RSDK_EDITABLE_VAR(Button, VAR_ENUM, type);599RSDK_EDITABLE_VAR(Button, VAR_BOOL, walkOnto);600RSDK_EDITABLE_VAR(Button, VAR_UINT8, tag);601}602603604