Path: blob/master/SonicMania/Objects/HCZ/DCEvent.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: DCEvent Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectDCEvent *DCEvent;1011void DCEvent_Update(void)12{13RSDK_THIS(DCEvent);1415StateMachine_Run(self->state);16}1718void DCEvent_LateUpdate(void) {}1920void DCEvent_StaticUpdate(void) {}2122void DCEvent_Draw(void)23{24RSDK_THIS(DCEvent);2526RSDK.DrawSprite(&self->animator, NULL, false);27}2829void DCEvent_Create(void *data)30{31RSDK_THIS(DCEvent);3233self->drawFX = FX_FLIP;34if (!SceneInfo->inEditor) {35self->visible = true;3637int32 type = VOID_TO_INT(data);38if (self->type == DCEVENT_BUBBLE)39type = DCEVENT_BUBBLE;4041switch (type) {42case DCEVENT_EGGMAN:43self->visible = false;44self->drawGroup = Zone->playerDrawGroup[0] + 2;45self->updateRange.x = 0x800000;46self->updateRange.y = 0x800000;47self->startY = self->position.y;48self->remainingBombs = 2;49RSDK.SetSpriteAnimation(DCEvent->aniFrames, 0, &self->animator, true, 0);5051if (self->type == DCEVENT_EGGMAN_SWIMMING) {52self->active = ACTIVE_BOUNDS;53self->state = DCEvent_StateEggmanSwim_AwaitPlayer;54}55else {56self->active = ACTIVE_XBOUNDS;57self->state = DCEvent_StateEggmanBomber_AwaitPlayer;58}59break;6061case DCEVENT_BOMB:62self->active = ACTIVE_NORMAL;63self->drawGroup = Zone->playerDrawGroup[0] + 1;64self->timer = 480;65RSDK.SetSpriteAnimation(DCEvent->aniFrames, 5, &self->animator, true, 0);66self->state = DCEvent_State_Bomb;67break;6869case DCEVENT_BUBBLE: {70EntityWater *water = (EntityWater *)self;71int32 x = self->position.x;72int32 y = self->position.y;73RSDK.ResetEntity(water, Water->classID, INT_TO_VOID(WATER_BUBBLE));7475water->position.x = x;76water->bubbleX = x;77water->position.y = y;78water->childPtr = 0;79water->speed = -1;80RSDK.SetSpriteAnimation(Water->aniFrames, 3, &water->animator, true, 0);81break;82}83}84}85}8687void DCEvent_StageLoad(void)88{89if (RSDK.CheckSceneFolder("HCZ")) {90DCEvent->aniFrames = RSDK.LoadSpriteAnimation("HCZ/DiveEggman.bin", SCOPE_STAGE);91// Never actually used92DCEvent->eggmanFrames = RSDK.LoadSpriteAnimation("Eggman/EggmanHCZ1.bin", SCOPE_STAGE);93}9495DCEvent->canExplodeBombs = false;9697// Both unused, who knows what they could've been used for tbh98// Maybe bomb hitboxes???99DCEvent->unusedHitbox1.left = -8;100DCEvent->unusedHitbox1.top = -8;101DCEvent->unusedHitbox1.right = 8;102DCEvent->unusedHitbox1.bottom = 8;103104// This is one's educated guess based on the fact that HCZ/DiveEggman is very similary laid out to this object105// Still unused tho106DCEvent->hitboxBomb.left = -8;107DCEvent->hitboxBomb.top = -8;108DCEvent->hitboxBomb.right = 8;109DCEvent->hitboxBomb.bottom = 8;110111DCEvent->sfxExplosion = RSDK.GetSfx("Stage/Explosion2.wav");112DCEvent->sfxRumble = RSDK.GetSfx("Stage/Rumble.wav");113DCEvent->sfxImpact6 = RSDK.GetSfx("Stage/Impact6.wav");114DCEvent->sfxImpact4 = RSDK.GetSfx("Stage/Impact4.wav");115}116117void DCEvent_State_Collapse(void)118{119RSDK_THIS(DCEvent);120121TileLayer *move = RSDK.GetTileLayer(Zone->moveLayer);122move->scrollPos -= 0x8000;123124foreach_active(Player, player)125{126player->collisionLayers |= Zone->moveLayerMask;127player->moveLayerPosition.x = move->scrollInfo[0].scrollPos;128player->moveLayerPosition.y = move->scrollPos;129}130131int32 slot = SceneInfo->entitySlot + 1;132for (int32 i = 0; i < self->numChildren; ++i) {133Entity *child = RSDK_GET_ENTITY_GEN(slot + i);134child->position.y += 0x8000;135}136137if (!(Zone->timer & 3))138Camera_ShakeScreen(0, 0, 2);139140if (!(Zone->timer & 7))141RSDK.PlaySfx(DCEvent->sfxRumble, false, 255);142143if (++self->timer >= 2176 || DCEvent->canExplodeBombs) {144RSDK.PlaySfx(DCEvent->sfxImpact4, false, 255);145destroyEntity(self);146}147}148149void DCEvent_StateEggmanBomber_AwaitPlayer(void)150{151RSDK_THIS(DCEvent);152153RSDK.ProcessAnimation(&self->animator);154155EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);156157if (player1->position.x > self->position.x - 0x100000)158player1->stateInput = DCEvent_Input_MoveRight;159160if (player1->position.x > self->position.x) {161player1->velocity.x = 0;162player1->velocity.y = 0;163player1->groundVel = 0;164player1->nextAirState = StateMachine_None;165player1->nextGroundState = StateMachine_None;166player1->stateInput = DCEvent_Input_LookDown;167Music_TransitionTrack(TRACK_MINIBOSS, 0.0125);168RSDK.SetSpriteAnimation(DCEvent->aniFrames, 1, &self->animator, true, 0);169170TileLayer *moveLayer = RSDK.GetTileLayer(Zone->moveLayer);171moveLayer->drawGroup[0] = 6;172173self->position.x -= 0x1000000;174self->timer = 172;175self->direction = FLIP_X;176self->velocity.x = 0x10000;177self->active = ACTIVE_NORMAL;178self->visible = true;179self->state = DCEvent_StateEggmanBomber_WaitForLookDown;180}181}182183void DCEvent_Input_MoveRight(void)184{185RSDK_THIS(Player);186187Player_Input_P1();188self->up = false;189self->down = false;190self->left = false;191self->right = true;192self->jumpPress = false;193self->jumpHold = false;194}195196void DCEvent_Input_LookDown(void)197{198RSDK_THIS(Player);199200Player_Input_P1();201self->drownTimer = 0;202self->up = false;203self->down = true;204self->left = false;205self->right = false;206self->jumpPress = false;207self->jumpHold = false;208209if (self->onGround)210RSDK.SetSpriteAnimation(self->aniFrames, ANI_CROUCH, &self->animator, false, 1);211}212213void DCEvent_StateEggmanBomber_WaitForLookDown(void)214{215RSDK_THIS(DCEvent);216217EntityCamera *camera = RSDK_GET_ENTITY(SLOT_PLAYER1, Player)->camera;218if (camera->lookPos.y >= 96)219self->state = DCEvent_StateEggmanBomber_Swimming;220}221222void DCEvent_StateEggmanBomber_Swimming(void)223{224RSDK_THIS(DCEvent);225226RSDK.ProcessAnimation(&self->animator);227228self->position.x += self->velocity.x;229230if (self->velocity.y > 0) {231self->position.y += self->velocity.y;232self->velocity.y -= 0x400;233}234235if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_LWALL, 0, 0x200000, 0, true)236|| RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_RWALL, 0, -0x200000, 0, true)) {237self->direction ^= FLIP_X;238self->velocity.x = -self->velocity.x;239}240241if (--self->timer <= 0) {242switch (self->remainingBombs) {243case 0:244DCEvent->canExplodeBombs = true;245self->state = DCEvent_StateEggmanBomber_PlacedAllBombs;246break;247248case 1:249self->remainingBombs--;250RSDK.SetSpriteAnimation(DCEvent->aniFrames, 4, &self->animator, false, 0);251self->state = DCEvent_StateEggmanBomber_PlaceBomb;252break;253254case 2:255self->direction = FLIP_NONE;256self->remainingBombs--;257RSDK.SetSpriteAnimation(DCEvent->aniFrames, 4, &self->animator, false, 0);258self->state = DCEvent_StateEggmanBomber_PlaceBomb;259break;260}261}262}263264void DCEvent_StateEggmanBomber_PlaceBomb(void)265{266RSDK_THIS(DCEvent);267268RSDK.ProcessAnimation(&self->animator);269270if (self->animator.frameID >= self->animator.frameCount - 1) {271EntityDCEvent *bomb = CREATE_ENTITY(DCEvent, INT_TO_VOID(DCEVENT_BOMB), self->position.x, self->position.y + 0x20000);272if (self->direction)273bomb->position.x += 0x1A0000;274else275bomb->position.x -= 0x1A0000;276277RSDK.SetSpriteAnimation(DCEvent->aniFrames, 1, &self->animator, false, 0);278279if (self->remainingBombs == 1)280self->direction = FLIP_X;281282self->timer = 160;283self->state = DCEvent_StateEggmanBomber_Swimming;284}285}286287void DCEvent_StateEggmanBomber_PlacedAllBombs(void)288{289RSDK_THIS(DCEvent);290291if (!DCEvent->canExplodeBombs) {292EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);293player1->stateInput = Player_Input_P1;294295Water->targetWaterLevel = 0x8DC0000;296Water->waterMoveSpeed = 0x8000;297Music_TransitionTrack(TRACK_STAGE, 0.0125);298self->state = DCEvent_State_Collapse;299}300}301302void DCEvent_StateEggmanSwim_AwaitPlayer(void)303{304RSDK_THIS(DCEvent);305306EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);307308RSDK.ProcessAnimation(&self->animator);309310if (player1->position.y < self->position.y) {311RSDK.SetSpriteAnimation(DCEvent->aniFrames, 1, &self->animator, true, 0);312self->timer = 900;313self->direction = FLIP_X;314self->velocity.y = -0x8000;315self->active = ACTIVE_NORMAL;316self->visible = true;317self->state = DCEvent_StateEggmanSwim_Swimming;318}319}320321void DCEvent_StateEggmanSwim_Swimming(void)322{323RSDK_THIS(DCEvent);324325RSDK.ProcessAnimation(&self->animator);326327self->position.y += self->velocity.y;328if (--self->timer <= 0)329destroyEntity(self);330}331332void DCEvent_State_Bomb(void)333{334RSDK_THIS(DCEvent);335336if (self->velocity.x) {337if (self->velocity.x <= 0)338self->velocity.x += 0x2000;339else340self->velocity.x -= 0x2000;341}342343if (self->velocity.y > 0) {344self->position.y += self->velocity.y;345self->velocity.y -= 0x400;346}347348RSDK.ProcessAnimation(&self->animator);349350if (DCEvent->canExplodeBombs) {351CREATE_ENTITY(Explosion, INT_TO_VOID(EXPLOSION_BOSS), self->position.x, self->position.y)->drawGroup = Zone->objectDrawGroup[1];352RSDK.PlaySfx(DCEvent->sfxImpact6, false, 255);353RSDK.PlaySfx(DCEvent->sfxExplosion, false, 255);354Camera_ShakeScreen(0, 4, 0);355356EntityWater *water = CREATE_ENTITY(Water, INT_TO_VOID(WATER_BUBBLE), self->position.x, self->position.y);357water->velocity.y = -0x8800;358water->childPtr = 0;359water->angle = 2 * RSDK.Rand(0, 256);360water->bubbleX = water->position.x;361RSDK.SetSpriteAnimation(Water->aniFrames, 3, &water->animator, true, 0);362363EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);364if (self->position.x >= player1->position.x)365self->position.x += 0x260000;366else367self->position.x -= 0x260000;368369// Spawn Bricks370for (int32 i = 0; i < 8; ++i) {371EntityDebris *debris = CREATE_ENTITY(Debris, Debris_State_Fall, self->position.x, self->position.y);372373RSDK.SetSpriteAnimation(WaterGush->aniFrames, 4, &debris->animator, true, 0);374debris->position.x += RSDK.Rand(-8, 8) << 16;375debris->position.y += RSDK.Rand(-8, 8) << 16;376debris->velocity.x = RSDK.Rand(-8, 8) << 16;377debris->velocity.y = RSDK.Rand(-8, 8) << 16;378if (self->position.x >= player1->position.x)379debris->velocity.x = RSDK.Rand(-8, 0) << 15;380else381debris->velocity.x = RSDK.Rand(1, 9) << 15;382debris->velocity.y = RSDK.Rand(-8, 5) << 16;383debris->direction = RSDK.Rand(0, 4);384debris->drawFX = FX_FLIP;385debris->drawGroup = Zone->objectDrawGroup[1];386debris->gravityStrength = 0x3800;387388RSDK.CopyTileLayer(Zone->moveLayer, 1038, 146, Zone->moveLayer, 1068, 8, 20, 6);389}390391self->state = DCEvent_State_BombExplode;392}393}394395void DCEvent_State_BombExplode(void)396{397RSDK_THIS(DCEvent);398399if (!(Zone->timer & 3)) {400self->position.y -= 0x100000;401CREATE_ENTITY(Explosion, INT_TO_VOID(EXPLOSION_BOSS), (RSDK.Rand(-16, 17) << 17) + self->position.x, self->position.y)->drawGroup =402Zone->objectDrawGroup[1];403404RSDK.PlaySfx(DCEvent->sfxExplosion, false, 255);405406// a bit hacky but sure407if (++self->remainingBombs == 16) {408DCEvent->canExplodeBombs = false;409destroyEntity(self);410}411}412}413414#if GAME_INCLUDE_EDITOR415void DCEvent_EditorDraw(void)416{417RSDK_THIS(DCEvent);418419switch (self->type) {420case DCEVENT_EGGMAN_PLACEBOMB:421case DCEVENT_EGGMAN_SWIMMING: RSDK.SetSpriteAnimation(DCEvent->aniFrames, 0, &self->animator, true, 0); break;422423case DCEVENT_BUBBLE:424if (Water)425RSDK.SetSpriteAnimation(Water->aniFrames, 3, &self->animator, true, 0);426break;427}428429DCEvent_Draw();430431if (showGizmos() && self->type == DCEVENT_EGGMAN_PLACEBOMB) {432RSDK_DRAWING_OVERLAY(true);433434int32 slot = SceneInfo->entitySlot + 1;435for (int32 i = 0; i < self->numChildren; ++i) {436Entity *child = RSDK_GET_ENTITY_GEN(slot + i);437if (!child)438continue;439440DrawHelpers_DrawArrow(self->position.x, self->position.y, child->position.x, child->position.y, 0xFFFF00, INK_NONE, 0xFF);441}442443RSDK_DRAWING_OVERLAY(false);444}445}446447void DCEvent_EditorLoad(void)448{449DCEvent->aniFrames = RSDK.LoadSpriteAnimation("HCZ/DiveEggman.bin", SCOPE_STAGE);450451RSDK_ACTIVE_VAR(DCEvent, type);452RSDK_ENUM_VAR("Placing Bombs", DCEVENT_EGGMAN_PLACEBOMB);453RSDK_ENUM_VAR("Swimming Upwards", DCEVENT_EGGMAN_SWIMMING);454RSDK_ENUM_VAR("Bubble", DCEVENT_BUBBLE);455}456#endif457458void DCEvent_Serialize(void)459{460RSDK_EDITABLE_VAR(DCEvent, VAR_UINT8, numChildren);461RSDK_EDITABLE_VAR(DCEvent, VAR_UINT8, type);462}463464465