Path: blob/master/SonicMania/Objects/CPZ/Bubbler.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: Bubbler Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectBubbler *Bubbler = NULL;1011// NOTE: this object is basically a port of the Bubbler & Bubbler's mother debug objects in S2 '13, though it's unused12// It's not in any stage lists, and the sprites for it aren't aligned correctly, though they are at different positions from S2 '13s1314void Bubbler_Update(void)15{16RSDK_THIS(Bubbler);1718StateMachine_Run(self->state);19}2021void Bubbler_LateUpdate(void) {}2223void Bubbler_StaticUpdate(void) {}2425void Bubbler_Draw(void)26{27RSDK_THIS(Bubbler);2829RSDK.DrawSprite(&self->bodyHitbox, NULL, false);30if (self->startPos.x)31RSDK.DrawSprite(&self->flameAnimator, NULL, false);32}3334void Bubbler_Create(void *data)35{36RSDK_THIS(Bubbler);3738self->visible = true;39self->drawGroup = Zone->objectDrawGroup[0];40self->drawFX |= FX_FLIP;41self->active = ACTIVE_BOUNDS;42self->updateRange.x = 0x800000;43self->updateRange.y = 0x800000;4445if (data) {46RSDK.SetSpriteAnimation(Bubbler->aniFrames, 3, &self->bodyHitbox, true, 0);47self->state = Bubbler_StateProjectile_Seed;48}49else {50self->startPos = self->position;51self->startDir = self->direction;52self->velocity.x = !self->direction ? -0x4000 : 0x4000;53self->velocity.y = 0;54self->timer = 0;55self->spawnTimer = 32;56RSDK.SetSpriteAnimation(Bubbler->aniFrames, 0, &self->bodyHitbox, true, 0);57RSDK.SetSpriteAnimation(Bubbler->aniFrames, 1, &self->flameAnimator, true, 0);58self->state = Bubbler_State_Init;59}60}6162void Bubbler_StageLoad(void)63{64if (RSDK.CheckSceneFolder("CPZ"))65Bubbler->aniFrames = RSDK.LoadSpriteAnimation("CPZ/Bubbler.bin", SCOPE_STAGE);6667Bubbler->hitboxBadnik.left = -16;68Bubbler->hitboxBadnik.top = -12;69Bubbler->hitboxBadnik.right = 16;70Bubbler->hitboxBadnik.bottom = 12;7172Bubbler->hitboxRange.left = -160;73Bubbler->hitboxRange.top = -12;74Bubbler->hitboxRange.right = 16;75Bubbler->hitboxRange.bottom = 96;7677Bubbler->hitboxProjectile.left = -2;78Bubbler->hitboxProjectile.top = -2;79Bubbler->hitboxProjectile.right = 2;80Bubbler->hitboxProjectile.bottom = 2;8182DEBUGMODE_ADD_OBJ(Bubbler);83}8485void Bubbler_DebugSpawn(void)86{87RSDK_THIS(Bubbler);8889CREATE_ENTITY(Bubbler, NULL, self->position.x, self->position.y);90}9192void Bubbler_DebugDraw(void)93{94RSDK.SetSpriteAnimation(Bubbler->aniFrames, 0, &DebugMode->animator, true, 0);95RSDK.DrawSprite(&DebugMode->animator, NULL, false);96}9798void Bubbler_HandleInteractions(void)99{100RSDK_THIS(Bubbler);101102foreach_active(Player, player)103{104if (Player_CheckBadnikTouch(player, self, &Bubbler->hitboxBadnik))105Player_CheckBadnikBreak(player, self, true);106}107}108109void Bubbler_HandleProjectileInteractions(void)110{111RSDK_THIS(Bubbler);112113int32 distance = 0x7FFFFFFF;114foreach_active(Player, player)115{116if (abs(player->position.x - self->position.x) < distance) {117distance = abs(player->position.x - self->position.x);118self->direction = player->position.x >= self->position.x;119}120121if (Player_CheckCollisionTouch(player, self, &Bubbler->hitboxProjectile))122Player_Hurt(player, self);123}124}125126void Bubbler_CheckOffScreen(void)127{128RSDK_THIS(Bubbler);129130if (!RSDK.CheckOnScreen(self, NULL) && !RSDK.CheckPosOnScreen(&self->startPos, &self->updateRange)) {131self->position = self->startPos;132self->direction = self->startDir;133Bubbler_Create(NULL);134}135}136137void Bubbler_State_Init(void)138{139RSDK_THIS(Bubbler);140141self->active = ACTIVE_NORMAL;142self->velocity.x = -0x10000;143self->state = Bubbler_State_MotherPatrol;144Bubbler_State_MotherPatrol();145}146147void Bubbler_State_MotherPatrol(void)148{149RSDK_THIS(Bubbler);150151self->position.x += self->velocity.x;152RSDK.ProcessAnimation(&self->flameAnimator);153154if (!--self->timer) {155self->direction ^= FLIP_X;156self->velocity.x = -self->velocity.x;157self->timer = 0x200;158}159160foreach_active(Player, player)161{162if (Player_CheckCollisionTouch(player, self, &Bubbler->hitboxRange)) {163self->timer = 16;164self->state = Bubbler_State_FoundPlayer;165if (self->direction == FLIP_NONE)166self->velocity.x = -0x28000;167else168self->velocity.x = 0x28000;169}170}171172Bubbler_HandleInteractions();173Bubbler_CheckOffScreen();174}175176void Bubbler_State_FoundPlayer(void)177{178RSDK_THIS(Bubbler);179180RSDK.ProcessAnimation(&self->flameAnimator);181182if (--self->timer < 0) {183RSDK.SetSpriteAnimation(Bubbler->aniFrames, 2, &self->flameAnimator, true, 0);184self->state = Bubbler_State_AttackPlayer;185}186187Bubbler_HandleInteractions();188Bubbler_CheckOffScreen();189}190191void Bubbler_State_AttackPlayer(void)192{193RSDK_THIS(Bubbler);194195RSDK.ProcessAnimation(&self->flameAnimator);196197self->position.x += self->velocity.x;198self->position.y += self->velocity.y;199200if (++self->spawnTimer >= 30) {201self->spawnTimer = 0;202int32 spawnX = self->position.x + 0x60000;203if (self->direction)204spawnX = self->position.x - 0x60000;205CREATE_ENTITY(Bubbler, INT_TO_VOID(true), spawnX, self->position.y + 0xA0000)->active = ACTIVE_NORMAL;206}207208Bubbler_HandleInteractions();209Bubbler_CheckOffScreen();210}211212void Bubbler_StateProjectile_Seed(void)213{214RSDK_THIS(Bubbler);215216RSDK.ProcessAnimation(&self->bodyHitbox);217self->position.y += 0x10000;218219Bubbler_HandleProjectileInteractions();220221if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0, false)) {222RSDK.SetSpriteAnimation(Bubbler->aniFrames, 4, &self->bodyHitbox, true, 0);223self->state = Bubbler_StateProjectile_Bubbler;224}225226if (!RSDK.CheckOnScreen(self, &self->updateRange))227destroyEntity(self);228}229230void Bubbler_StateProjectile_Bubbler(void)231{232RSDK_THIS(Bubbler);233234RSDK.ProcessAnimation(&self->bodyHitbox);235236if (self->bodyHitbox.frameID >= 7)237destroyEntity(self);238else if (self->bodyHitbox.frameID < 6)239Bubbler_HandleProjectileInteractions();240}241242#if GAME_INCLUDE_EDITOR243void Bubbler_EditorDraw(void)244{245RSDK_THIS(Bubbler);246247self->startPos = self->position;248RSDK.SetSpriteAnimation(Bubbler->aniFrames, 0, &self->bodyHitbox, true, 0);249RSDK.SetSpriteAnimation(Bubbler->aniFrames, 1, &self->flameAnimator, true, 0);250251Bubbler_Draw();252}253254void Bubbler_EditorLoad(void)255{256Bubbler->aniFrames = RSDK.LoadSpriteAnimation("CPZ/Bubbler.bin", SCOPE_STAGE);257258RSDK_ACTIVE_VAR(Bubbler, direction);259RSDK_ENUM_VAR("Left", FLIP_NONE);260RSDK_ENUM_VAR("Right", FLIP_X);261}262#endif263264void Bubbler_Serialize(void) { RSDK_EDITABLE_VAR(Bubbler, VAR_UINT8, direction); }265266267