Path: blob/master/SonicMania/Objects/PGZ/Press.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: Press Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectPress *Press;1011void Press_Update(void)12{13RSDK_THIS(Press);1415StateMachine_Run(self->state);16}1718void Press_LateUpdate(void) {}1920void Press_StaticUpdate(void)21{22#if MANIA_USE_PLUS23Press->canSuper = true;24EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);2526if (player->classID == Player->classID) {27foreach_active(Press, press)28{29Hitbox hitboxRange;30hitboxRange.top = -4 * press->size;31hitboxRange.bottom = 4 * press->size;32hitboxRange.left = -112;33hitboxRange.right = 112;34if (Player_CheckCollisionTouch(player, press, &hitboxRange)) {35Press->canSuper = false;36foreach_break;37}38}39}40else41Press->canSuper = false;42#endif43}4445void Press_Draw(void)46{47RSDK_THIS(Press);4849if (self->rotation <= 0x100)50Press_DrawHandle();5152// threads53Vector2 drawPos = self->drawPos;54SpriteFrame *frame = RSDK.GetFrame(Press->aniFrames, 1, self->threadAnimator.frameID);55frame->height = 56;56frame->sprY = (self->threadSprY >> 8) + 182;57for (uint32 i = 0; i < self->threads; ++i) {58RSDK.DrawSprite(&self->threadAnimator, &drawPos, false);59drawPos.y += 0x380000;60}61frame->height = self->height;62RSDK.DrawSprite(&self->threadAnimator, &drawPos, false);6364// crusher platforms65drawPos = self->position;66drawPos.y += self->offTop;67self->crusherAnimator.frameID = 3;68RSDK.DrawSprite(&self->crusherAnimator, &drawPos, false);6970self->crusherAnimator.frameID = 4;71RSDK.DrawSprite(&self->crusherAnimator, &drawPos, false);7273drawPos.y -= self->offTop;74drawPos.y += self->offBottom;75self->crusherAnimator.frameID = 3;76RSDK.DrawSprite(&self->crusherAnimator, &drawPos, false);7778self->crusherAnimator.frameID = 5;79RSDK.DrawSprite(&self->crusherAnimator, &drawPos, false);8081// bumper82drawPos.y = self->drawPos.y - 0x80000;83RSDK.DrawSprite(&self->bumperAnimator, &drawPos, false);8485drawPos.y += (self->size + 16) << 16;86RSDK.DrawSprite(&self->bumperAnimator, &drawPos, false);8788if (self->rotation > 0x100)89Press_DrawHandle();90}9192void Press_Create(void *data)93{94RSDK_THIS(Press);9596self->active = ACTIVE_BOUNDS;97self->visible = true;98self->drawGroup = Zone->objectDrawGroup[0];99100if (!SceneInfo->inEditor) {101self->size *= 8;102int32 size = self->size;103self->speed <<= 15;104int32 step = size / 7;105int32 count = (size - step) / 2;106self->threads = (step + count) / 32;107self->scale.y = 0x200;108self->height = size - 0x38 * self->threads;109110size <<= 15;111self->updateRange.x = 0x1000000;112self->updateRange.y = 0x380000 * self->threads + 0x1000000;113self->drawPos.x = self->position.x;114self->drawPos.y = self->position.y - size;115self->offTop = (self->offTop << 16) - size;116self->offBottom = (self->offBottom << 16) - size + 0xFFFF;117118RSDK.SetSpriteAnimation(Press->aniFrames, 0, &self->crusherAnimator, true, 0);119RSDK.SetSpriteAnimation(Press->aniFrames, 1, &self->threadAnimator, true, 0);120RSDK.SetSpriteAnimation(Press->aniFrames, 2, &self->bumperAnimator, true, 0);121self->state = Press_State_Crush;122}123}124125void Press_StageLoad(void)126{127if (RSDK.CheckSceneFolder("PSZ1"))128Press->aniFrames = RSDK.LoadSpriteAnimation("PSZ1/Press.bin", SCOPE_STAGE);129130Press->hitbox.left = -112;131Press->hitbox.top = -16;132Press->hitbox.right = 112;133Press->hitbox.bottom = 16;134135#if MANIA_USE_PLUS136Player->canSuperCB = Press_CheckCanSuper;137#endif138139Press->sfxImpact = RSDK.GetSfx("Stage/Impact2.wav");140Press->sfxPress = RSDK.GetSfx("PSZ/Press.wav");141}142143#if MANIA_USE_PLUS144bool32 Press_CheckCanSuper(bool32 isHUD) { return Press->canSuper; }145#endif146147void Press_DrawHandle(void)148{149RSDK_THIS(Press);150151Vector2 drawPos = self->drawPos;152153self->scale.x = abs(RSDK.Cos512(self->rotation)) + 1;154int32 scaleX = abs(RSDK.Sin512(self->rotation)) + 1;155156drawPos.x += 0x2500 * RSDK.Cos512(self->rotation);157drawPos.y -= 0x80000;158self->crusherAnimator.frameID = 0;159RSDK.DrawSprite(&self->crusherAnimator, &drawPos, false);160161self->drawFX |= FX_SCALE;162drawPos.x = 0x1B80 * RSDK.Cos512(self->rotation) + self->drawPos.x;163164switch (self->rotation >> 7) {165case 0:166case 2:167drawPos.x += (scaleX << 9);168self->crusherAnimator.frameID = 2;169RSDK.DrawSprite(&self->crusherAnimator, &drawPos, false);170171drawPos.x += -0xC00 * self->scale.x - (scaleX << 9);172break;173174case 1:175case 3:176drawPos.x -= (scaleX << 9);177self->crusherAnimator.frameID = 2;178RSDK.DrawSprite(&self->crusherAnimator, &drawPos, false);179180drawPos.x += (scaleX + 2 * (3 * self->scale.x - 32)) << 9;181break;182183default: break;184}185186self->scale.x = scaleX;187self->crusherAnimator.frameID = 1;188RSDK.DrawSprite(&self->crusherAnimator, &drawPos, false);189190self->drawFX &= ~FX_SCALE;191}192193void Press_Move(void)194{195RSDK_THIS(Press);196197self->stoodPlayersRoof = 0;198self->stoodPlayersFloor = 0;199200int32 playerID = 0;201foreach_active(Player, player)202{203self->position.y += self->offBottom;204205if (Player_CheckCollisionBox(player, self, &Press->hitbox) == C_TOP) {206if (self->state == Press_State_Crush && !player->sidekick) {207if (abs(self->position.x - player->position.x) <= 0x600000) {208RSDK.PlaySfx(Press->sfxPress, false, 255);209self->state = Press_HandleMovement;210self->active = ACTIVE_NORMAL;211}212}213214self->stoodPlayersFloor |= 1 << playerID;215}216217self->position.y += self->offTop - self->offBottom;218219int32 collide = Player_CheckCollisionBox(player, self, &Press->hitbox);220if (collide == C_BOTTOM)221player->collisionFlagV |= 2;222else if (collide == C_TOP)223self->stoodPlayersRoof |= 1 << playerID;224225++playerID;226self->position.y -= self->offTop;227}228}229230void Press_State_Crush(void)231{232// fun press fact!233Press_Move();234}235void Press_State_FinalCrush(void)236{237// every second you don't move the press only gets closer238Press_Move();239}240void Press_HandleMovement(void)241{242RSDK_THIS(Press);243244RSDK.ProcessAnimation(&self->threadAnimator);245RSDK.ProcessAnimation(&self->bumperAnimator);246247Press_Move();248249int32 oldBottom = self->offBottom;250int32 newBottom = oldBottom - self->speed;251self->offBottom = oldBottom - self->speed;252253self->threadSprY += (self->speed >> 11);254self->threadSprY &= 0x7FF;255256int32 oldTop = self->offTop;257int32 newTop = self->speed + self->offTop + self->topOffset;258259self->rotation = (self->rotation - (self->speed >> 15)) & 0x1FF;260self->offTop = newTop;261self->topOffset = 0;262263if (newTop + 0x100000 >= newBottom - 0x100000) {264int32 diff = newTop - newBottom + 0x200000;265if (diff > 0) {266diff >>= 1;267self->offTop = newTop - diff;268self->offBottom = newBottom + diff;269}270271RSDK.PlaySfx(Press->sfxImpact, false, 255);272self->active = ACTIVE_BOUNDS;273Camera_ShakeScreen(0, 0, 5);274self->state = Press_State_FinalCrush;275}276277uint32 waitTime = 0;278self->topOffset = self->offTop;279280bool32 top = false, bottom = false;281int32 floorOffset = (oldBottom & 0xFFFF0000) - (self->offBottom & 0xFFFF0000);282int32 actualPos = self->position.y;283284foreach_active(Crate, crate)285{286self->position.y += self->offBottom;287288if (MathHelpers_CheckBoxCollision(self, &Press->hitbox, crate, &crate->hitbox) == C_TOP) {289bottom = true;290Crate_MoveY(crate, -floorOffset);291}292293self->position.y += self->offTop - self->offBottom;294if (MathHelpers_CheckBoxCollision(crate, &crate->hitbox, self, &Press->hitbox) == C_TOP) {295top = true;296297switch (crate->frameID) {298default: break;299case 0: waitTime += 60; break;300case 1: waitTime += 30; break;301case 2: waitTime += 90; break;302case 3: waitTime += 60; break;303}304}305306self->offTop = self->position.y - actualPos;307self->position.y = actualPos;308}309310self->topOffset -= self->offTop;311312if (bottom && top) {313RSDK.PlaySfx(Press->sfxImpact, false, 255);314Camera_ShakeScreen(0, 0, 3);315316self->state = Press_State_HandleCrates;317self->timerStart = waitTime;318self->timer = waitTime;319}320321int32 playerID = 1;322int32 roofOffset = (oldTop & 0xFFFF0000) - (self->offTop & 0xFFFF0000);323foreach_active(Player, player)324{325if (playerID & self->stoodPlayersFloor)326player->position.y -= floorOffset;327if (playerID & self->stoodPlayersRoof)328player->position.y -= roofOffset;329330playerID <<= 1;331}332}333334void Press_State_HandleCrates(void)335{336RSDK_THIS(Press);337338Press_Move();339340if (self->timer <= 0) {341foreach_active(Crate, crate)342{343self->position.y += self->offTop + 0x80000;344345if (RSDK.CheckObjectCollisionTouchBox(self, &Press->hitbox, crate, &crate->hitbox))346Crate_Break(crate);347348self->position.y += -0x80000 - self->offTop;349}350351self->state = Press_HandleMovement;352}353else {354int32 percentDone = ((self->timerStart - self->timer) << 16) / self->timerStart;355int32 crateOff = 0;356357foreach_active(Crate, crate)358{359self->position.y += self->offTop + 0x80000;360if (RSDK.CheckObjectCollisionTouchBox(self, &Press->hitbox, crate, &crate->hitbox) && percentDone > 0x8000) {361int32 percent = percentDone >> 9;362int32 percent2 = percent * percent;363int32 angle = crateOff + ((percent * self->timerStart * (percent2 >> 8)) >> 8);364365crateOff += 0x100;366crate->drawPos.x = (RSDK.Sin512(angle & 0x1FF) << 7) + crate->centerPos.x;367}368369self->position.y += -0x80000 - self->offTop;370}371372--self->timer;373}374}375376#if GAME_INCLUDE_EDITOR377void Press_EditorDraw(void)378{379RSDK_THIS(Press);380381int32 sizeStore = self->size;382int32 offT = self->offTop;383int32 offB = self->offBottom;384385self->size *= 8;386int32 size = self->size;387388int32 step = size / 7;389int32 count = (size - step) / 2;390self->threads = (step + count) / 32;391self->scale.y = 0x200;392self->height = size - 0x38 * self->threads;393394size <<= 15;395self->updateRange.x = 0x1000000;396self->updateRange.y = 0x380000 * self->threads + 0x1000000;397self->drawPos.x = self->position.x;398self->drawPos.y = self->position.y - size;399self->offTop = (self->offTop << 16) - size;400self->offBottom = (self->offBottom << 16) - size + 0xFFFF;401402RSDK.SetSpriteAnimation(Press->aniFrames, 0, &self->crusherAnimator, true, 0);403RSDK.SetSpriteAnimation(Press->aniFrames, 1, &self->threadAnimator, true, 0);404RSDK.SetSpriteAnimation(Press->aniFrames, 2, &self->bumperAnimator, true, 0);405406Press_Draw();407408self->size = sizeStore;409self->offTop = offT;410self->offBottom = offB;411}412413void Press_EditorLoad(void) { Press->aniFrames = RSDK.LoadSpriteAnimation("PSZ1/Press.bin", SCOPE_STAGE); }414#endif415416void Press_Serialize(void)417{418RSDK_EDITABLE_VAR(Press, VAR_UINT16, size);419RSDK_EDITABLE_VAR(Press, VAR_UINT32, speed);420RSDK_EDITABLE_VAR(Press, VAR_ENUM, offTop);421RSDK_EDITABLE_VAR(Press, VAR_ENUM, offBottom);422}423424425