Path: blob/master/SonicMania/Objects/HCZ/BreakBar.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: BreakBar Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectBreakBar *BreakBar;1011void BreakBar_Update(void)12{13RSDK_THIS(BreakBar);1415StateMachine_Run(self->state);16}1718void BreakBar_LateUpdate(void) { BreakBar_CheckPlayerCollisions(); }1920void BreakBar_StaticUpdate(void) {}2122void BreakBar_Draw(void) { BreakBar_DrawSprites(); }2324void BreakBar_Create(void *data)25{26RSDK_THIS(BreakBar);2728self->active = ACTIVE_BOUNDS;29self->drawGroup = Zone->objectDrawGroup[0];30self->startPos = self->position;31self->visible = true;32self->updateRange.x = 0x800000;33self->updateRange.y = 0x800000;3435self->hitbox.left = 24;36self->hitbox.top = 24;37self->hitbox.right = 32;38self->hitbox.bottom = 32;3940if (self->orientation == BREAKBAR_V) {41self->hitbox.top = -8 - ((8 * self->length) >> 1);42self->hitbox.bottom = ((8 * self->length) >> 1) + 8;43}44else {45self->hitbox.left = -8 - ((8 * self->length) >> 1);46self->hitbox.right = ((8 * self->length) >> 1) + 8;47}4849self->state = BreakBar_State_Init;50}5152void BreakBar_StageLoad(void)53{54BreakBar->aniFrames = RSDK.LoadSpriteAnimation("HCZ/BreakBar.bin", SCOPE_STAGE);5556BreakBar->sfxBreak = RSDK.GetSfx("Stage/LedgeBreak.wav");57}5859void BreakBar_DrawSprites(void)60{61RSDK_THIS(BreakBar);6263Vector2 drawPos = self->position;6465if (self->orientation != BREAKBAR_V) {66drawPos.x += -0x40000 - (((8 * self->length) >> 1) << 16);67RSDK.SetSpriteAnimation(BreakBar->aniFrames, 1, &self->animator, true, 0);68RSDK.DrawSprite(&self->animator, &drawPos, false);6970drawPos.x += 0x80000;71RSDK.SetSpriteAnimation(BreakBar->aniFrames, 1, &self->animator, true, 1);72for (int32 i = 0; i < self->length; ++i) {73RSDK.DrawSprite(&self->animator, &drawPos, false);74drawPos.x += 0x80000;75}7677RSDK.SetSpriteAnimation(BreakBar->aniFrames, 1, &self->animator, true, 2);78}79else {80drawPos.y += -0x40000 - (((8 * self->length) >> 1) << 16);81RSDK.SetSpriteAnimation(BreakBar->aniFrames, 0, &self->animator, true, 0);82RSDK.DrawSprite(&self->animator, &drawPos, false);8384drawPos.y += 0x80000;85RSDK.SetSpriteAnimation(BreakBar->aniFrames, 0, &self->animator, true, 1);86for (int32 i = 0; i < self->length; ++i) {87RSDK.DrawSprite(&self->animator, &drawPos, false);88drawPos.y += 0x80000;89}9091RSDK.SetSpriteAnimation(BreakBar->aniFrames, 0, &self->animator, true, 2);92}9394RSDK.DrawSprite(&self->animator, &drawPos, false);95}9697void BreakBar_CheckPlayerCollisions(void)98{99RSDK_THIS(BreakBar);100101foreach_active(Player, player)102{103int32 playerID = RSDK.GetEntitySlot(player);104if (((1 << playerID) & self->activePlayersGrabbed) && !((1 << playerID) & self->activePlayersReleased)) {105if (!Player_CheckValidState(player)) {106self->activePlayersGrabbed &= ~(1 << playerID);107}108else {109player->direction = FLIP_NONE;110111if (self->orientation != BREAKBAR_V) {112player->position.y = self->startPos.y;113114if (player->velocity.y <= 0) {115player->position.y -= 0x140000;116player->rotation = 0x180;117}118else {119player->position.y += 0x140000;120player->rotation = 0x080;121}122}123else {124player->position.x = self->startPos.x;125126if (player->velocity.x <= 0) {127player->position.x -= 0x140000;128player->rotation = 0x100;129}130else {131player->position.x += 0x140000;132player->rotation = 0x000;133}134}135}136}137}138}139140void BreakBar_HandlePlayerInteractions(EntityPlayer *player)141{142RSDK_THIS(BreakBar);143144if (!self->isBroken) {145int32 spawnX = self->position.x;146int32 spawnY = self->position.y;147148if (self->orientation != BREAKBAR_V)149spawnX += -0x40000 - ((8 * self->length) >> 1 << 16);150else151spawnY += -0x40000 - ((8 * self->length) >> 1 << 16);152153if (self->length != 0xFFFE) {154int32 len = (self->length + 2) << 19;155for (int32 i = 0; i < self->length + 2; ++i) {156int32 frame = i == self->length + 1 ? 2 : (i != 0);157EntityDebris *debris = CREATE_ENTITY(Debris, Debris_State_Move, spawnX, spawnY);158159debris->drawGroup = Zone->objectDrawGroup[0];160debris->gravityStrength = player->underwater ? 0x2000 : 0x3800;161debris->velocity.x = player->velocity.x >> 3;162debris->velocity.y = player->velocity.y >> 3;163164if (self->orientation != BREAKBAR_V) {165RSDK.SetSpriteAnimation(BreakBar->aniFrames, 1, &debris->animator, true, frame);166debris->velocity.x = abs(debris->position.x - player->position.x) >> 6;167168if (debris->position.x < player->position.x)169debris->velocity.x = -(abs(debris->position.x - player->position.x) >> 6);170171if (len > abs(debris->position.x - player->position.x))172debris->velocity.y += (2 * (player->velocity.y > 0) - 1) * (MAX(len - abs(debris->position.x - player->position.x), 0) >> 5);173174debris->velocity.y = (3 * ((RSDK.Rand(-12, 12) << 10) + debris->velocity.y)) >> 3;175spawnX += 0x80000;176}177else {178RSDK.SetSpriteAnimation(BreakBar->aniFrames, 0, &debris->animator, true, frame);179180debris->velocity.y = abs(debris->position.y - player->position.y) >> 6;181182if (debris->position.y < player->position.y)183debris->velocity.y = -debris->velocity.y;184185if (len > abs(debris->position.y - player->position.y))186debris->velocity.x += (2 * (player->velocity.x > 0) - 1) * (MAX(len - abs(debris->position.y - player->position.y), 0) >> 5);187188debris->velocity.x = (3 * ((RSDK.Rand(-12, 12) << 10) + debris->velocity.x)) >> 3;189spawnY += 0x80000;190}191}192}193194RSDK.PlaySfx(BreakBar->sfxBreak, false, 255);195self->isBroken = true;196}197}198199void BreakBar_State_Init(void)200{201RSDK_THIS(BreakBar);202203self->activePlayersGrabbed = 0;204self->activePlayersReleased = 0;205self->releaseTimer = 0;206self->state = BreakBar_State_Main;207}208209void BreakBar_State_Main(void)210{211RSDK_THIS(BreakBar);212213foreach_active(Player, player)214{215int32 playerID = RSDK.GetEntitySlot(player);216217if ((player->sidekick && Player->respawnTimer >= 239) || !Player_CheckValidState(player)) {218self->activePlayersReleased &= ~(1 << playerID);219self->activePlayersGrabbed &= ~(1 << playerID);220self->playerTimers[playerID] = 8;221}222else {223if (self->playerTimers[playerID]) {224self->playerTimers[playerID]--;225}226else if (!((1 << playerID) & self->activePlayersGrabbed) && !((1 << playerID) & self->activePlayersReleased)) {227self->direction = FLIP_NONE;228229if (player->velocity.x < 0)230self->direction = FLIP_X;231232if (player->velocity.y < 0)233self->direction |= FLIP_Y;234235if (Player_CheckCollisionTouch(player, self, &self->hitbox)) {236self->activePlayersGrabbed |= 1 << playerID;237RSDK.PlaySfx(Player->sfxGrab, false, 255);238}239}240241if (((1 << playerID) & self->activePlayersGrabbed)) {242if (!((1 << playerID) & self->activePlayersReleased)) {243if (player->jumpPress || self->releaseTimer >= 240 || self->isBroken) {244self->activePlayersReleased |= 1 << playerID;245}246else {247RSDK.SetSpriteAnimation(player->aniFrames, ANI_CLING, &player->animator, false, 0);248player->onGround = false;249player->nextGroundState = StateMachine_None;250player->nextAirState = StateMachine_None;251player->state = Player_State_Static;252}253254if (!player->sidekick && globals->gameMode != MODE_COMPETITION)255++self->releaseTimer;256}257}258259if (((1 << playerID) & self->activePlayersReleased)) {260if (globals->gameMode == MODE_COMPETITION) {261self->activePlayersReleased &= ~(1 << playerID);262self->activePlayersGrabbed &= ~(1 << playerID);263self->playerTimers[playerID] = 8;264}265else if (!player->sidekick && !self->isBroken) {266BreakBar_HandlePlayerInteractions(player);267}268269RSDK.SetSpriteAnimation(player->aniFrames, ANI_FAN, &player->animator, false, 0);270player->state = Player_State_Static;271}272}273}274275if (self->isBroken)276destroyEntity(self);277}278279#if GAME_INCLUDE_EDITOR280void BreakBar_EditorDraw(void) { BreakBar_DrawSprites(); }281282void BreakBar_EditorLoad(void)283{284BreakBar->aniFrames = RSDK.LoadSpriteAnimation("HCZ/BreakBar.bin", SCOPE_STAGE);285286RSDK_ACTIVE_VAR(BreakBar, orientation);287RSDK_ENUM_VAR("Vertical", BREAKBAR_V);288RSDK_ENUM_VAR("Horizontal", BREAKBAR_H);289}290#endif291292void BreakBar_Serialize(void)293{294RSDK_EDITABLE_VAR(BreakBar, VAR_UINT8, orientation);295RSDK_EDITABLE_VAR(BreakBar, VAR_UINT16, length);296}297298299