Path: blob/master/SonicMania/Objects/Common/CollapsingPlatform.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: CollapsingPlatform Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectCollapsingPlatform *CollapsingPlatform;1011void CollapsingPlatform_Update(void)12{13RSDK_THIS(CollapsingPlatform);1415self->visible = false;16if (DebugMode)17self->visible = DebugMode->debugActive;1819bool32 runState = false;2021if (self->collapseDelay) {22#if MANIA_USE_PLUS23if (Player) {24foreach_active(Player, player)25{26if (Player_CheckCollisionTouch(player, self, &self->hitboxTrigger) && player->characterID == ID_MIGHTY27&& player->jumpAbilityState > 1) {28runState = true;29foreach_break;30}31}32}33#endif3435if (!runState && --self->collapseDelay == 0)36runState = true;37}38else {39if (Player) {40self->direction = FLIP_NONE;41foreach_active(Player, player)42{43if (Player_CheckCollisionTouch(player, self, &self->hitboxTrigger)44#if MANIA_USE_PLUS45&& (!self->mightyOnly || (player->characterID == ID_MIGHTY && player->state == Player_State_MightyHammerDrop))46#endif47&& !player->sidekick && player->onGround && !player->collisionMode && !self->eventOnly && self->delay < 0xFFFF) {48self->stoodPos.x = player->position.x;49#if MANIA_USE_PLUS50if (player->characterID == ID_MIGHTY && player->jumpAbilityState > 1) {51runState = true;52foreach_break;53}54#endif55}56}57}5859if (!runState && self->stoodPos.x) {60self->collapseDelay = self->delay;61if (!self->delay)62runState = true;63}64}6566if (runState) {67StateMachine_Run(self->state);6869RSDK.PlaySfx(CollapsingPlatform->sfxCrumble, false, 0xFF);70if (self->respawn) {71self->collapseDelay = 0;72self->stoodPos.x = 0;73}74else {75destroyEntity(self);76}77}78}7980void CollapsingPlatform_LateUpdate(void) {}8182void CollapsingPlatform_StaticUpdate(void) {}8384void CollapsingPlatform_Draw(void)85{86RSDK_THIS(CollapsingPlatform);87Vector2 drawPos;8889drawPos.x = self->position.x - (self->size.x >> 1);90drawPos.y = self->position.y - (self->size.y >> 1);91RSDK.DrawLine(drawPos.x - TO_FIXED(1), drawPos.y - TO_FIXED(1), drawPos.x + self->size.x, drawPos.y - TO_FIXED(1), 0xE0E0E0, 0x00, INK_NONE,92false);93RSDK.DrawLine(drawPos.x - TO_FIXED(1), self->size.y + drawPos.y, drawPos.x + self->size.x, self->size.y + drawPos.y, 0xE0E0E0, 0x00, INK_NONE,94false);95RSDK.DrawLine(drawPos.x - TO_FIXED(1), drawPos.y - TO_FIXED(1), drawPos.x - TO_FIXED(1), drawPos.y + self->size.y, 0xE0E0E0, 0x00, INK_NONE,96false);97RSDK.DrawLine(drawPos.x + self->size.x, drawPos.y - TO_FIXED(1), drawPos.x + self->size.x, drawPos.y + self->size.y, 0xE0E0E0, 0x00, INK_NONE,98false);99100self->direction = FLIP_NONE;101RSDK.DrawSprite(&CollapsingPlatform->animator, &drawPos, false);102103drawPos.x += self->size.x;104self->direction = FLIP_X;105RSDK.DrawSprite(&CollapsingPlatform->animator, &drawPos, false);106107drawPos.y += self->size.y;108self->direction = FLIP_XY;109RSDK.DrawSprite(&CollapsingPlatform->animator, &drawPos, false);110111drawPos.x -= self->size.x;112self->direction = FLIP_Y;113RSDK.DrawSprite(&CollapsingPlatform->animator, &drawPos, false);114}115116void CollapsingPlatform_Create(void *data)117{118RSDK_THIS(CollapsingPlatform);119120self->visible = true;121self->position.x &= 0xFFF80000;122self->position.y &= 0xFFF80000;123self->drawFX |= FX_FLIP;124self->drawGroup = Zone->objectDrawGroup[0];125126if (self->targetLayer == COLLAPSEPLAT_TARGET_LOW) {127self->targetLayer = Zone->fgLayer[0];128self->drawGroup = Zone->objectDrawGroup[0];129}130else {131self->targetLayer = Zone->fgLayer[1];132self->drawGroup = Zone->objectDrawGroup[1];133}134135if (!SceneInfo->inEditor) {136self->active = ACTIVE_BOUNDS;137self->updateRange.x = TO_FIXED(128);138self->updateRange.y = TO_FIXED(128);139int32 xOff = (self->position.x >> 20) - (self->size.x >> 21);140int32 yOff = (self->position.y >> 20) - (self->size.y >> 21);141142if ((self->size.y & 0xFFF00000) && !(self->size.y & 0xFFF00000 & 0x80000000)) {143int32 sx = self->size.x >> 20;144int32 sy = self->size.y >> 20;145for (int32 y = 0; y < sy; ++y) {146for (int32 x = 0; x < sx; ++x) {147self->storedTiles[x + y * (self->size.x >> 20)] = RSDK.GetTile(self->targetLayer, x + xOff, y + yOff);148}149}150}151152self->hitboxTrigger.left = -(self->size.x >> 17);153self->hitboxTrigger.top = -16 - (self->size.y >> 17);154self->hitboxTrigger.right = self->size.x >> 17;155self->hitboxTrigger.bottom = self->size.y >> 17;156}157158switch (self->type) {159default:160case COLLAPSEPLAT_LEFT: self->state = CollapsingPlatform_State_Left; break;161case COLLAPSEPLAT_RIGHT: self->state = CollapsingPlatform_State_Right; break;162case COLLAPSEPLAT_CENTER: self->state = CollapsingPlatform_State_Center; break;163case COLLAPSEPLAT_LR: self->state = CollapsingPlatform_State_LeftRight; break;164case COLLAPSEPLAT_LRC: self->state = CollapsingPlatform_State_LeftRightCenter; break;165}166}167168void CollapsingPlatform_StageLoad(void)169{170CollapsingPlatform->aniFrames = RSDK.LoadSpriteAnimation("Global/TicMark.bin", SCOPE_STAGE);171RSDK.SetSpriteAnimation(CollapsingPlatform->aniFrames, 0, &CollapsingPlatform->animator, true, 0);172173if (RSDK.CheckSceneFolder("OOZ1") || RSDK.CheckSceneFolder("OOZ2"))174CollapsingPlatform->shift = 1;175176if (RSDK.CheckSceneFolder("FBZ") || RSDK.CheckSceneFolder("HCZ") || RSDK.CheckSceneFolder("LRZ1") || RSDK.CheckSceneFolder("LRZ2")177|| RSDK.CheckSceneFolder("AIZ")) {178CollapsingPlatform->sfxCrumble = RSDK.GetSfx("Stage/LedgeBreak3.wav");179}180else {181CollapsingPlatform->sfxCrumble = RSDK.GetSfx("Stage/LedgeBreak.wav");182}183}184185void CollapsingPlatform_State_Left(void)186{187RSDK_THIS(CollapsingPlatform);188189uint16 *tiles = self->storedTiles;190int32 startTX = (self->position.x >> 20) - (self->size.x >> 21);191int32 startTY = (self->position.y >> 20) - (self->size.y >> 21);192int32 tx = self->position.x - (self->size.x >> 1) + TO_FIXED(8);193int32 ty = self->position.y - (self->size.y >> 1) + TO_FIXED(8);194195int32 sx = self->size.x >> 20;196int32 sy = self->size.y >> 20;197198for (int32 y = 0; y < sy; ++y) {199for (int32 x = 0; x < sx; ++x) {200EntityBreakableWall *tile = CREATE_ENTITY(BreakableWall, INT_TO_VOID(BREAKWALL_TILE_DYNAMIC), tx, ty);201tile->targetLayer = self->targetLayer;202tile->tileInfo = *tiles;203tile->drawGroup = self->drawGroup;204tile->tilePos.x = x + startTX;205tile->tilePos.y = y + startTY;206int32 timerX = x >> CollapsingPlatform->shift;207int32 timerY = y >> CollapsingPlatform->shift;208tile->timer = 3 * (sy + 2 * timerX - timerY);209210++tiles;211tx += 0x100000;212}213214tx -= self->size.x;215ty += 0x100000;216}217}218void CollapsingPlatform_State_Right(void)219{220RSDK_THIS(CollapsingPlatform);221222uint16 *tiles = self->storedTiles;223int32 startTX = (self->position.x >> 20) - (self->size.x >> 21);224int32 startTY = (self->position.y >> 20) - (self->size.y >> 21);225int32 tx = self->position.x - (self->size.x >> 1) + TO_FIXED(8);226int32 ty = self->position.y - (self->size.y >> 1) + TO_FIXED(8);227228int32 timerSX = self->size.x >> CollapsingPlatform->shift >> 20;229230int32 sx = self->size.x >> 20;231int32 sy = self->size.y >> 20;232233for (int32 y = 0; y < sy; ++y) {234for (int32 x = 0; x < sx; ++x) {235EntityBreakableWall *tile = CREATE_ENTITY(BreakableWall, INT_TO_VOID(BREAKWALL_TILE_DYNAMIC), tx, ty);236tile->targetLayer = self->targetLayer;237tile->tileInfo = *tiles;238tile->drawGroup = self->drawGroup;239tile->tilePos.x = x + startTX;240tile->tilePos.y = y + startTY;241int32 timerX = x >> CollapsingPlatform->shift;242int32 timerY = y >> CollapsingPlatform->shift;243tile->timer = 3 * (sy + 2 * (timerSX - timerX) - timerY);244245++tiles;246tx += 0x100000;247}248249tx -= self->size.x;250ty += 0x100000;251}252}253void CollapsingPlatform_State_Center(void)254{255RSDK_THIS(CollapsingPlatform);256257uint16 *tiles = self->storedTiles;258int32 startTX = (self->position.x >> 20) - (self->size.x >> 21);259int32 startTY = (self->position.y >> 20) - (self->size.y >> 21);260int32 tx = self->position.x - (self->size.x >> 1) + TO_FIXED(8);261int32 ty = self->position.y - (self->size.y >> 1) + TO_FIXED(8);262263int32 timerSX = self->size.x >> CollapsingPlatform->shift >> 20;264int32 timerSY = self->size.y >> CollapsingPlatform->shift >> 20;265266int32 sx = self->size.x >> 20;267int32 sy = self->size.y >> 20;268269for (int32 y = 0; y < sy; ++y) {270for (int32 x = 0; x < sx; ++x) {271EntityBreakableWall *tile = CREATE_ENTITY(BreakableWall, INT_TO_VOID(BREAKWALL_TILE_DYNAMIC), tx, ty);272tile->targetLayer = self->targetLayer;273tile->tileInfo = *tiles;274tile->drawGroup = self->drawGroup;275tile->tilePos.x = x + startTX;276tile->tilePos.y = y + startTY;277int32 timerX = abs((timerSX >> 1) - (x >> CollapsingPlatform->shift));278int32 timerY = y >> CollapsingPlatform->shift;279tile->timer = 3 * (timerSY + 2 * timerX - timerY);280281if (!(timerSX & 1) && x >> CollapsingPlatform->shift < (timerSX >> 1))282tile->timer -= 6;283284++tiles;285tx += 0x100000;286}287288tx -= self->size.x;289ty += 0x100000;290}291}292void CollapsingPlatform_State_LeftRight(void)293{294RSDK_THIS(CollapsingPlatform);295296int32 px = self->stoodPos.x;297int32 x = self->position.x;298299if (px < x)300CollapsingPlatform_State_Left();301else302CollapsingPlatform_State_Right();303}304void CollapsingPlatform_State_LeftRightCenter(void)305{306RSDK_THIS(CollapsingPlatform);307308int32 px = self->stoodPos.x;309int32 x = self->position.x;310311if (abs(px - x) < self->size.x / 6)312CollapsingPlatform_State_Center();313else if (px < x)314CollapsingPlatform_State_Left();315else316CollapsingPlatform_State_Right();317}318319#if GAME_INCLUDE_EDITOR320void CollapsingPlatform_EditorDraw(void)321{322RSDK_THIS(CollapsingPlatform);323324DrawHelpers_DrawRectOutline(self->position.x, self->position.y, self->size.x, self->size.y, 0xFFFF00);325326Vector2 drawPos;327drawPos.x = self->position.x - (self->size.x >> 1);328drawPos.y = self->position.y - (self->size.y >> 1);329330self->direction = FLIP_NONE;331RSDK.DrawSprite(&CollapsingPlatform->animator, &drawPos, false);332333drawPos.x += self->size.x;334self->direction = FLIP_X;335RSDK.DrawSprite(&CollapsingPlatform->animator, &drawPos, false);336337drawPos.y += self->size.y;338self->direction = FLIP_XY;339RSDK.DrawSprite(&CollapsingPlatform->animator, &drawPos, false);340341drawPos.x -= self->size.x;342self->direction = FLIP_Y;343RSDK.DrawSprite(&CollapsingPlatform->animator, &drawPos, false);344}345346void CollapsingPlatform_EditorLoad(void)347{348CollapsingPlatform->aniFrames = RSDK.LoadSpriteAnimation("Global/TicMark.bin", SCOPE_STAGE);349RSDK.SetSpriteAnimation(CollapsingPlatform->aniFrames, 0, &CollapsingPlatform->animator, true, 0);350351RSDK_ACTIVE_VAR(CollapsingPlatform, type);352RSDK_ENUM_VAR("Left", COLLAPSEPLAT_LEFT);353RSDK_ENUM_VAR("Right", COLLAPSEPLAT_RIGHT);354RSDK_ENUM_VAR("Center", COLLAPSEPLAT_CENTER);355RSDK_ENUM_VAR("Left or Right", COLLAPSEPLAT_LR);356RSDK_ENUM_VAR("Base on Player Position", COLLAPSEPLAT_LRC);357358RSDK_ACTIVE_VAR(CollapsingPlatform, targetLayer);359RSDK_ENUM_VAR("Low", COLLAPSEPLAT_TARGET_LOW);360RSDK_ENUM_VAR("High", COLLAPSEPLAT_TARGET_HIGH);361}362#endif363364void CollapsingPlatform_Serialize(void)365{366RSDK_EDITABLE_VAR(CollapsingPlatform, VAR_VECTOR2, size);367RSDK_EDITABLE_VAR(CollapsingPlatform, VAR_BOOL, respawn);368RSDK_EDITABLE_VAR(CollapsingPlatform, VAR_UINT16, targetLayer);369RSDK_EDITABLE_VAR(CollapsingPlatform, VAR_UINT8, type);370RSDK_EDITABLE_VAR(CollapsingPlatform, VAR_ENUM, delay);371RSDK_EDITABLE_VAR(CollapsingPlatform, VAR_BOOL, eventOnly);372RSDK_EDITABLE_VAR(CollapsingPlatform, VAR_BOOL, mightyOnly);373}374375376