Path: blob/master/SonicMania/Objects/MMZ/SpikeCorridor.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: SpikeCorridor Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectSpikeCorridor *SpikeCorridor;1011void SpikeCorridor_Update(void)12{13RSDK_THIS(SpikeCorridor);1415StateMachine_Run(self->state);16}1718void SpikeCorridor_LateUpdate(void) {}1920void SpikeCorridor_StaticUpdate(void) {}2122void SpikeCorridor_Draw(void)23{24RSDK_THIS(SpikeCorridor);2526StateMachine_Run(self->stateDraw);27}2829void SpikeCorridor_Create(void *data)30{31RSDK_THIS(SpikeCorridor);3233self->visible = true;34self->drawGroup = Zone->objectDrawGroup[0];35self->active = ACTIVE_BOUNDS;3637if (SceneInfo->inEditor) {38if (self->colWidth < 20)39self->colWidth = 20;4041if (self->rowHeight < 1)42self->rowHeight = 1;4344if (self->yOffset < 64)45self->yOffset = 64;46}4748self->updateRange.x = 0x2000000;49self->updateRange.y = 0x2000000;50self->state = SpikeCorridor_StateDropper_Setup;51}5253void SpikeCorridor_StageLoad(void)54{55SpikeCorridor->aniFrames = RSDK.LoadSpriteAnimation("MMZ/SpikeCorridor.bin", SCOPE_STAGE);5657SpikeCorridor->sfxDrop = RSDK.GetSfx("Stage/Drop.wav");58SpikeCorridor->sfxImpact = RSDK.GetSfx("Stage/Impact2.wav");59SpikeCorridor->sfxIndicator = RSDK.GetSfx("MMZ/Indicator.wav");60}6162void SpikeCorridor_SetupHitboxes(void)63{64RSDK_THIS(SpikeCorridor);6566int32 size = (-8 * self->colWidth) >> 1;6768self->hitboxes[0].left = size;69self->hitboxes[0].top = 0;70self->hitboxes[0].right = size + 8 * self->size;71self->hitboxes[0].bottom = 24;7273self->hitboxes[1].left = size + 8 * (self->size + 6);74self->hitboxes[1].top = 0;75self->hitboxes[1].bottom = 24;76self->hitboxes[1].right = size + 8 * self->colWidth;77}7879void SpikeCorridor_HandleDrawing(Animator *animator, int32 offsetY, int8 size, bool32 useWarnAnim)80{81RSDK_THIS(SpikeCorridor);8283int32 startX = self->position.x - (self->colWidth << 18);8485Vector2 drawPos;86drawPos.x = 0;87drawPos.y = self->position.y + offsetY;8889int32 anim = useWarnAnim ? 5 : 0;9091for (int32 x = 0; x < self->colWidth;) {92drawPos.x = startX;9394int32 w = 0;95bool32 useOpeningAnim = false;96if (x >= size) {97if (x < size + 6)98useOpeningAnim = true;99else100w = self->colWidth;101}102else {103w = size;104}105106if (useOpeningAnim) {107RSDK.SetSpriteAnimation(SpikeCorridor->aniFrames, anim, animator, true, 0);108x += 2;109startX += 0x100000;110}111else {112switch (w - x) {113case 0:114RSDK.SetSpriteAnimation(SpikeCorridor->aniFrames, anim, animator, true, 0);115x += 2;116startX += 0x100000;117break;118119case 1: RSDK.SetSpriteAnimation(SpikeCorridor->aniFrames, anim + 1, animator, true, 0); break;120121case 2:122RSDK.SetSpriteAnimation(SpikeCorridor->aniFrames, anim + 2, animator, true, 0);123++x;124startX += 0x80000;125break;126127case 3:128RSDK.SetSpriteAnimation(SpikeCorridor->aniFrames, anim + 3, animator, true, 0);129x += 2;130startX += 0x100000;131break;132133default:134case 4:135RSDK.SetSpriteAnimation(SpikeCorridor->aniFrames, anim + 4, animator, true, 0);136x += 3;137startX += 0x180000;138break;139}140}141142++x;143RSDK.DrawSprite(animator, &drawPos, false);144startX += 0x80000;145}146}147148void SpikeCorridor_SetupNextSpikeRow(void)149{150RSDK_THIS(SpikeCorridor);151152int32 max = (int8)(self->colWidth - 9);153int32 size = RSDK.Rand(3, max);154155if (self->lastSize <= -1) {156self->size = size;157self->lastSize = size;158}159else {160while (true) {161if (abs(size - self->lastSize) >= 6 || abs(size - self->lastSize) == 3)162break;163164size = RSDK.Rand(3, max);165}166167self->size = size;168self->lastSize = size;169}170}171172void SpikeCorridor_CheckPlayerCollisions(void)173{174RSDK_THIS(SpikeCorridor);175176foreach_active(Player, player)177{178for (int32 i = 0; i < 2; ++i) {179int32 side = Player_CheckCollisionBox(player, self, &self->hitboxes[i]);180181if (side == C_BOTTOM) {182Player_Hurt(player, self);183player->collisionFlagV |= 2;184}185else if (side == C_TOP) {186player->collisionFlagV |= 1;187}188}189}190}191192void SpikeCorridor_StateDropper_Setup(void)193{194RSDK_THIS(SpikeCorridor);195196self->hitbox.left = -((8 * self->colWidth) >> 1);197self->hitbox.top = self->yOffset;198self->hitbox.right = (8 * self->colWidth) >> 1;199self->hitbox.bottom = self->yOffset + 24 * self->rowHeight;200201self->startPos = self->position;202self->active = ACTIVE_BOUNDS;203self->visible = true;204self->rowID = 0;205self->lastSize = -1;206self->timer = 0;207208SpikeCorridor_StateDropper_CheckForPlayer();209self->state = SpikeCorridor_StateDropper_CheckForPlayer;210211self->stateDraw = StateMachine_None;212}213214void SpikeCorridor_StateDropper_CheckForPlayer(void)215{216RSDK_THIS(SpikeCorridor);217218foreach_active(Player, player)219{220if (player->sidekick)221continue;222223if (Player_CheckCollisionTouch(player, self, &self->hitbox)) {224Hitbox *playerHitbox = Player_GetHitbox(player);225226if (player->position.x <= self->position.x) {227if (player->position.x + (playerHitbox->left << 16) >= self->position.x + (self->hitbox.left << 16)) {228SpikeCorridor_SetupNextSpikeRow();229230self->state = SpikeCorridor_StateDropper_DropWarn;231self->stateDraw = SpikeCorridor_Draw_DropWarn;232}233}234else if (player->position.x + (playerHitbox->right << 16) <= self->position.x + (self->hitbox.right << 16)) {235SpikeCorridor_SetupNextSpikeRow();236237self->state = SpikeCorridor_StateDropper_DropWarn;238self->stateDraw = SpikeCorridor_Draw_DropWarn;239}240}241}242}243244void SpikeCorridor_StateDropper_DropWarn(void)245{246RSDK_THIS(SpikeCorridor);247248if (self->timer >= 120) {249self->state = SpikeCorridor_StateDropper_SpawnSpikes;250self->stateDraw = 0;251}252else {253if (!(self->timer % 40))254RSDK.PlaySfx(SpikeCorridor->sfxIndicator, false, 255);255256++self->timer;257}258}259260void SpikeCorridor_StateDropper_SpawnSpikes(void)261{262RSDK_THIS(SpikeCorridor);263264RSDK.PlaySfx(SpikeCorridor->sfxDrop, false, 255);265266EntitySpikeCorridor *fallRow = CREATE_ENTITY(SpikeCorridor, self, self->startPos.x, self->startPos.y);267fallRow->isPermanent = true;268fallRow->state = SpikeCorridor_StateSpikes_Setup;269fallRow->active = ACTIVE_NORMAL;270fallRow->storedRowID = self->rowID;271fallRow->size = self->size;272fallRow->parent = self;273fallRow->drawGroup = self->drawGroup;274fallRow->colWidth = self->colWidth;275fallRow->yOffset = 0;276fallRow->fallOffset = (self->yOffset + 24 * (self->rowHeight - self->rowID++ - 1)) << 16;277278self->timer = 0;279280if (self->rowID >= self->rowHeight) {281self->interaction = false;282self->state = StateMachine_None;283}284else {285self->state = SpikeCorridor_StateDropper_DropWait;286}287}288289void SpikeCorridor_StateDropper_DropWait(void)290{291RSDK_THIS(SpikeCorridor);292293if (self->timer >= 60) {294SpikeCorridor_SetupNextSpikeRow();295self->timer = 0;296self->state = SpikeCorridor_StateDropper_DropWarn;297self->stateDraw = SpikeCorridor_Draw_DropWarn;298}299else {300self->timer++;301}302}303304void SpikeCorridor_StateSpikes_Setup(void)305{306RSDK_THIS(SpikeCorridor);307308SpikeCorridor_SetupHitboxes();309310self->active = ACTIVE_NORMAL;311self->visible = true;312self->stateDraw = SpikeCorridor_Draw_Spikes;313314self->state = SpikeCorridor_StateSpikes_Fall;315SpikeCorridor_StateSpikes_Fall();316}317318void SpikeCorridor_StateSpikes_Fall(void)319{320RSDK_THIS(SpikeCorridor);321322if (self->yOffset >= self->fallOffset) {323RSDK.StopSfx(SpikeCorridor->sfxDrop);324RSDK.PlaySfx(SpikeCorridor->sfxImpact, false, 255);325326Camera_ShakeScreen(0, 0, 5);327self->active = ACTIVE_ALWAYS;328self->state = SpikeCorridor_StateSpikes_Land;329}330else {331self->velocity.y += 0x3800;332self->yOffset += self->velocity.y;333334if (self->yOffset > self->fallOffset)335self->yOffset = self->fallOffset;336337self->position.y = self->yOffset + self->parent->startPos.y;338}339340SpikeCorridor_CheckPlayerCollisions();341}342343void SpikeCorridor_StateSpikes_Land(void) { SpikeCorridor_CheckPlayerCollisions(); }344345void SpikeCorridor_Draw_DropWarn(void)346{347RSDK_THIS(SpikeCorridor);348349Animator animator;350memset(&animator, 0, sizeof(Animator));351352int32 yOff = 0;353if ((ScreenInfo->position.y << 16) - self->startPos.y > 0)354yOff = (ScreenInfo->position.y << 16) - self->startPos.y;355356SpikeCorridor_HandleDrawing(&animator, yOff, self->size, true);357}358359void SpikeCorridor_Draw_Spikes(void)360{361RSDK_THIS(SpikeCorridor);362363Animator animator;364memset(&animator, 0, sizeof(Animator));365366SpikeCorridor_HandleDrawing(&animator, 0, self->size, false);367}368369#if GAME_INCLUDE_EDITOR370void SpikeCorridor_EditorDraw(void)371{372RSDK_THIS(SpikeCorridor);373374Animator animator;375memset(&animator, 0, sizeof(Animator));376377self->inkEffect = INK_NONE;378SpikeCorridor_HandleDrawing(&animator, 0, self->colWidth, true);379380if (showGizmos()) {381RSDK_DRAWING_OVERLAY(true);382383int32 yOffset = 0;384self->fallOffset = (self->yOffset + 24 * (self->rowHeight - 1)) << 16;385386while (yOffset < self->fallOffset) {387self->velocity.y += 0x3800;388yOffset += self->velocity.y;389if (yOffset > self->fallOffset)390yOffset = self->fallOffset;391}392393self->inkEffect = INK_BLEND;394SpikeCorridor_HandleDrawing(&animator, yOffset, self->colWidth, false);395396RSDK_DRAWING_OVERLAY(false);397}398}399400void SpikeCorridor_EditorLoad(void) { SpikeCorridor->aniFrames = RSDK.LoadSpriteAnimation("MMZ/SpikeCorridor.bin", SCOPE_STAGE); }401#endif402403void SpikeCorridor_Serialize(void)404{405RSDK_EDITABLE_VAR(SpikeCorridor, VAR_INT8, colWidth);406RSDK_EDITABLE_VAR(SpikeCorridor, VAR_INT8, rowHeight);407RSDK_EDITABLE_VAR(SpikeCorridor, VAR_INT32, yOffset);408}409410411