Path: blob/master/SonicMania/Objects/MSZ/Bumpalo.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: Bumpalo Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectBumpalo *Bumpalo;1011void Bumpalo_Update(void)12{13RSDK_THIS(Bumpalo);1415RSDK.ProcessAnimation(&self->huffAnimator);1617StateMachine_Run(self->state);18}1920void Bumpalo_LateUpdate(void) {}2122void Bumpalo_StaticUpdate(void) {}2324void Bumpalo_Draw(void)25{26RSDK_THIS(Bumpalo);2728RSDK.DrawSprite(&self->badnikAnimator, NULL, false);29RSDK.DrawSprite(&self->huffAnimator, NULL, false);3031if (self->state == Bumpalo_State_Charging)32RSDK.DrawSprite(&self->dustAnimator, NULL, false);33}3435void Bumpalo_Create(void *data)36{37RSDK_THIS(Bumpalo);3839self->visible = true;40self->drawGroup = Zone->objectDrawGroup[0] + 1;41self->drawFX = FX_FLIP;42self->startPos = self->position;43self->startDir = self->direction;44self->active = ACTIVE_BOUNDS;45self->updateRange.x = 0x800000;46self->updateRange.y = 0x800000;4748RSDK.SetSpriteAnimation(Bumpalo->aniFrames, 1, &self->badnikAnimator, true, 0);49self->state = Bumpalo_State_Init;50}5152void Bumpalo_StageLoad(void)53{54if (RSDK.CheckSceneFolder("MSZ"))55Bumpalo->aniFrames = RSDK.LoadSpriteAnimation("MSZ/Bumpalo.bin", SCOPE_STAGE);5657Bumpalo->hitboxBadnik.left = -20;58Bumpalo->hitboxBadnik.top = 0;59Bumpalo->hitboxBadnik.right = 20;60Bumpalo->hitboxBadnik.bottom = 16;6162Bumpalo->hitboxBumper.left = -10;63Bumpalo->hitboxBumper.top = -16;64Bumpalo->hitboxBumper.right = 12;65Bumpalo->hitboxBumper.bottom = 0;6667Bumpalo->hitboxRange.left = -128;68Bumpalo->hitboxRange.top = -64;69Bumpalo->hitboxRange.right = -16;70Bumpalo->hitboxRange.bottom = 96;7172Bumpalo->hitboxCharge.left = -17;73Bumpalo->hitboxCharge.top = -14;74Bumpalo->hitboxCharge.right = 10;75Bumpalo->hitboxCharge.bottom = 0;7677Bumpalo->hitboxUnused.left = -24;78Bumpalo->hitboxUnused.top = -10;79Bumpalo->hitboxUnused.right = -8;80Bumpalo->hitboxUnused.bottom = 0;8182Bumpalo->sfxBumper = RSDK.GetSfx("Stage/Bumper.wav");83Bumpalo->sfxHuff = RSDK.GetSfx("Stage/Huff.wav");84Bumpalo->sfxClack = RSDK.GetSfx("Stage/Clack.wav");85Bumpalo->sfxImpact = RSDK.GetSfx("Stage/Impact5.wav");8687DEBUGMODE_ADD_OBJ(Bumpalo);88}8990void Bumpalo_DebugSpawn(void)91{92RSDK_THIS(DebugMode);9394EntityBumpalo *bumpalo = CREATE_ENTITY(Bumpalo, NULL, self->position.x, self->position.y);95bumpalo->direction = self->direction;96bumpalo->startDir = self->direction;97}9899void Bumpalo_DebugDraw(void)100{101RSDK.SetSpriteAnimation(Bumpalo->aniFrames, 0, &DebugMode->animator, true, 0);102RSDK.DrawSprite(&DebugMode->animator, NULL, false);103}104105void Bumpalo_CheckOffScreen(void)106{107RSDK_THIS(Bumpalo);108109if (!RSDK.CheckOnScreen(self, NULL) && !RSDK.CheckPosOnScreen(&self->startPos, &self->updateRange)) {110self->position = self->startPos;111self->direction = self->startDir;112Bumpalo_Create(NULL);113}114}115116void Bumpalo_BumpPlayer(EntityPlayer *player)117{118RSDK_THIS(Bumpalo);119120RSDK.PlaySfx(Bumpalo->sfxBumper, false, 0xFF);121122int32 angle = RSDK.ATan2(player->position.x - self->position.x, player->position.y - self->position.y);123int32 velX = 0x700 * RSDK.Cos256(angle);124int32 velY = 0x700 * RSDK.Sin256(angle);125126if (player->state == Player_State_FlyCarried)127RSDK_GET_ENTITY(SLOT_PLAYER2, Player)->flyCarryTimer = 30;128129int32 anim = player->animator.animationID;130if (anim != ANI_FLY && anim != ANI_FLY_LIFT_TIRED) {131if (player->state != Player_State_TailsFlight) {132if (player->state != Player_State_DropDash)133player->state = Player_State_Air;134if (anim != ANI_JUMP && anim != ANI_JOG && anim != ANI_RUN && anim != ANI_DASH)135player->animator.animationID = ANI_WALK;136}137}138139if (player->animator.animationID != ANI_FLY) {140player->velocity.x = velX;141player->groundVel = velX;142player->applyJumpCap = false;143}144145player->velocity.y = velY;146player->onGround = false;147player->tileCollisions = TILECOLLISION_DOWN;148149if (self->badnikAnimator.animationID == 3)150self->velocity.x >>= 1;151152RSDK.SetSpriteAnimation(Bumpalo->aniFrames, 4, &self->badnikAnimator, true, 0);153154if (self->state != Bumpalo_State_Falling && self->state != Bumpalo_State_Bumped)155self->velocity.x = 0;156157self->state = Bumpalo_State_Bumped;158}159160void Bumpalo_CheckPlayerCollisions(void)161{162RSDK_THIS(Bumpalo);163164foreach_active(Player, player)165{166if (self->badnikAnimator.animationID == 3) {167if (abs(self->velocity.x) <= 0x10000) {168if (Player_CheckBadnikTouch(player, self, &Bumpalo->hitboxBadnik)) {169if (Player_CheckBadnikTouch(player, self, &Bumpalo->hitboxBadnik)) {170Player_CheckBadnikBreak(player, self, true);171}172}173else if (Player_CheckBadnikTouch(player, self, &Bumpalo->hitboxBumper)) {174#if MANIA_USE_PLUS175if (player->state == Player_State_MightyHammerDrop) {176RSDK.PlaySfx(Bumpalo->sfxBumper, false, 255);177Player_CheckBadnikBreak(player, self, true);178}179else180#endif181Bumpalo_BumpPlayer(player);182}183else if (Player_CheckCollisionTouch(player, self, &Bumpalo->hitboxCharge)) {184#if MANIA_USE_PLUS185if (Player_CheckMightyUnspin(player, 0x300, 2, &player->uncurlTimer)) {186RSDK.PlaySfx(Bumpalo->sfxImpact, false, 255);187RSDK.SetSpriteAnimation(Bumpalo->aniFrames, 4, &self->badnikAnimator, true, 0);188self->state = Bumpalo_State_Bumped;189self->velocity.x = self->direction == FLIP_NONE ? 0x10000 : -0x10000;190self->velocity.y = -0x20000;191}192else193#endif194Player_Hurt(player, self);195}196}197else if (Player_CheckBadnikTouch(player, self, &Bumpalo->hitboxBumper)) {198#if MANIA_USE_PLUS199if (player->state == Player_State_MightyHammerDrop) {200RSDK.PlaySfx(Bumpalo->sfxBumper, false, 255);201Player_CheckBadnikBreak(player, self, true);202}203else204#endif205Bumpalo_BumpPlayer(player);206}207else if (Player_CheckCollisionTouch(player, self, &Bumpalo->hitboxCharge)) {208#if MANIA_USE_PLUS209if (Player_CheckMightyUnspin(player, 0x400, 2, &player->uncurlTimer)) {210RSDK.PlaySfx(Bumpalo->sfxImpact, false, 255);211RSDK.SetSpriteAnimation(Bumpalo->aniFrames, 4, &self->badnikAnimator, true, 0);212self->state = Bumpalo_State_Bumped;213self->velocity.x = self->direction == FLIP_NONE ? 0x10000 : -0x10000;214self->velocity.y = -0x20000;215}216else217#endif218Player_Hurt(player, self);219}220else if (Player_CheckBadnikTouch(player, self, &Bumpalo->hitboxBadnik)) {221Player_CheckBadnikBreak(player, self, true);222}223}224else {225if (Player_CheckBadnikTouch(player, self, &Bumpalo->hitboxBadnik)) {226if (Player_CheckBadnikTouch(player, self, &Bumpalo->hitboxBadnik)) {227Player_CheckBadnikBreak(player, self, true);228}229}230else {231if (Player_CheckBadnikTouch(player, self, &Bumpalo->hitboxBumper)) {232#if MANIA_USE_PLUS233if (player->state == Player_State_MightyHammerDrop) {234RSDK.PlaySfx(Bumpalo->sfxBumper, false, 255);235Player_CheckBadnikBreak(player, self, true);236}237else238#endif239Bumpalo_BumpPlayer(player);240}241else {242if (Player_CheckCollisionTouch(player, self, &Bumpalo->hitboxCharge)) {243#if MANIA_USE_PLUS244if (Player_CheckMightyUnspin(player, 0x400, 2, &player->uncurlTimer)) {245RSDK.PlaySfx(Bumpalo->sfxImpact, false, 255);246RSDK.SetSpriteAnimation(Bumpalo->aniFrames, 4, &self->badnikAnimator, true, 0);247self->state = Bumpalo_State_Bumped;248self->velocity.x = self->direction == FLIP_NONE ? 0x10000 : -0x10000;249self->velocity.y = -0x20000;250}251else252#endif253Player_Hurt(player, self);254}255}256}257}258}259}260261void Bumpalo_HandlePlatformCollisions(EntityPlatform *platform)262{263RSDK_THIS(Bumpalo);264265if (platform->state != Platform_State_Falling2 && platform->state != Platform_State_Hold) {266platform->position.x = platform->drawPos.x - platform->collisionOffset.x;267platform->position.y = platform->drawPos.y - platform->collisionOffset.y;268269bool32 collided = false;270if (platform->collision) {271if (platform->collision != PLATFORM_C_SOLID) {272if (platform->collision == PLATFORM_C_TILED273&& RSDK.CheckObjectCollisionTouchBox(platform, &platform->hitbox, self, &Bumpalo->hitboxBadnik)) {274if ((self->collisionLayers & Zone->moveLayerMask) != 0) {275TileLayer *move = RSDK.GetTileLayer(Zone->moveLayer);276move->position.x = -(platform->drawPos.x + platform->tileOrigin.x) >> 16;277move->position.y = -(platform->drawPos.y + platform->tileOrigin.y) >> 16;278}279280if (self->velocity.y >= 0)281self->onGround |= true;282}283collided = true;284}285}286else {287Hitbox *solid = RSDK.GetHitbox(&platform->animator, 0);288self->onGround |= RSDK.CheckObjectCollisionPlatform(platform, solid, self, &Bumpalo->hitboxBadnik, true);289}290291if (!collided) {292Hitbox *platformHitbox = RSDK.GetHitbox(&platform->animator, 1);293int32 velX = self->velocity.x;294295switch (RSDK.CheckObjectCollisionBox(platform, platformHitbox, self, &Bumpalo->hitboxBadnik, true)) {296default:297case C_NONE:298case C_BOTTOM: break;299300case C_TOP:301if (self->velocity.y > 0)302self->onGround |= true;303break;304305case C_LEFT:306if (velX > 0)307self->wallCollided |= true;308break;309310case C_RIGHT:311if (velX < 0)312self->wallCollided |= true;313break;314}315}316317platform->position.x = platform->centerPos.x;318platform->position.y = platform->centerPos.y;319}320}321322void Bumpalo_HandleObjectCollisions(void)323{324RSDK_THIS(Bumpalo);325326foreach_all(Platform, platform) { Bumpalo_HandlePlatformCollisions(platform); }327328foreach_all(Spikes, spikes)329{330int32 velX = self->velocity.x;331332switch (RSDK.CheckObjectCollisionBox(platform, &platform->hitbox, self, &Bumpalo->hitboxBadnik, true)) {333default:334case C_NONE:335case C_BOTTOM: break;336337case C_TOP:338if (self->velocity.y > 0)339self->onGround |= true;340break;341342case C_LEFT:343if (velX > 0)344self->wallCollided |= true;345break;346347case C_RIGHT:348if (velX < 0)349self->wallCollided |= true;350break;351}352}353354foreach_all(BreakableWall, wall)355{356int32 velX = self->velocity.x;357358switch (RSDK.CheckObjectCollisionBox(wall, &wall->hitbox, self, &Bumpalo->hitboxBadnik, true)) {359default:360case C_NONE:361case C_BOTTOM: break;362363case C_TOP:364if (self->velocity.y > 0)365self->onGround |= true;366break;367368case C_LEFT:369if (velX > 0)370self->wallCollided |= true;371break;372373case C_RIGHT:374if (velX < 0)375self->wallCollided |= true;376break;377}378}379380if (self->direction)381self->wallCollided |= RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_LWALL, 0, 0x140000, 0, true);382else383self->wallCollided |= RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_RWALL, 0, -0x140000, 0, true);384}385386void Bumpalo_State_Init(void)387{388RSDK_THIS(Bumpalo);389390self->active = ACTIVE_NORMAL;391self->velocity.x = self->direction == FLIP_NONE ? -0x10000 : 0x10000;392393self->state = Bumpalo_State_Moving;394Bumpalo_State_Moving();395}396397void Bumpalo_State_Moving(void)398{399RSDK_THIS(Bumpalo);400401self->position.x += self->velocity.x;402self->onGround = false;403self->wallCollided = false;404Bumpalo_HandleObjectCollisions();405406self->onGround |= RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0xF0000, 8);407if (!self->onGround) {408if (self->ignoreCliffs) {409self->state = Bumpalo_State_Falling;410}411else {412if (self->badnikAnimator.animationID == 3)413self->velocity.x >>= 1;414415RSDK.SetSpriteAnimation(Bumpalo->aniFrames, 0, &self->badnikAnimator, true, 0);416self->timer = 0;417self->onGround = self->direction ? RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_FLOOR, 0, -0x40000, 0xF0000, 8)418: RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0x40000, 0xF0000, 8);419if (!self->onGround) {420self->state = Bumpalo_State_Falling;421}422else {423self->position.x -= self->velocity.x;424self->state = Bumpalo_State_Idle;425}426}427}428else if (self->badnikAnimator.animationID == 3) {429if (self->wallCollided) {430RSDK.PlaySfx(Bumpalo->sfxImpact, false, 0xFF);431RSDK.SetSpriteAnimation(Bumpalo->aniFrames, 4, &self->badnikAnimator, true, 0);432433self->state = Bumpalo_State_Bumped;434self->velocity.x = self->direction == FLIP_NONE ? 0x10000 : -0x10000;435self->velocity.y = -0x20000;436}437}438else if (self->wallCollided) {439RSDK.SetSpriteAnimation(Bumpalo->aniFrames, 0, &self->badnikAnimator, true, 0);440self->timer = 0;441self->state = Bumpalo_State_Idle;442}443else {444foreach_active(Player, player)445{446if (Player_CheckCollisionTouch(player, self, &Bumpalo->hitboxRange)) {447self->timer = 92;448RSDK.PlaySfx(Bumpalo->sfxClack, false, 0xFF);449RSDK.SetSpriteAnimation(Bumpalo->aniFrames, 2, &self->badnikAnimator, true, 0);450RSDK.SetSpriteAnimation(Bumpalo->aniFrames, 6, &self->huffAnimator, true, 0);451RSDK.SetSpriteAnimation(Bumpalo->aniFrames, 7, &self->dustAnimator, true, 0);452self->state = Bumpalo_State_Charging;453}454}455}456457RSDK.ProcessAnimation(&self->badnikAnimator);458459Bumpalo_CheckPlayerCollisions();460Bumpalo_CheckOffScreen();461}462463void Bumpalo_State_Idle(void)464{465RSDK_THIS(Bumpalo);466467RSDK.ProcessAnimation(&self->badnikAnimator);468469if (++self->timer == 48) {470RSDK.SetSpriteAnimation(Bumpalo->aniFrames, 5, &self->badnikAnimator, true, 0);471self->state = Bumpalo_State_Turning;472}473474Bumpalo_CheckPlayerCollisions();475Bumpalo_CheckOffScreen();476}477478void Bumpalo_State_Charging(void)479{480RSDK_THIS(Bumpalo);481482RSDK.ProcessAnimation(&self->badnikAnimator);483RSDK.ProcessAnimation(&self->dustAnimator);484485if (--self->timer == 83) {486RSDK.PlaySfx(Bumpalo->sfxHuff, false, 0xFF);487}488else if (self->timer <= 0) {489RSDK.SetSpriteAnimation(Bumpalo->aniFrames, 3, &self->badnikAnimator, true, 0);490self->state = Bumpalo_State_Moving;491self->velocity.x *= 2;492}493494Bumpalo_CheckPlayerCollisions();495Bumpalo_CheckOffScreen();496}497498void Bumpalo_State_Turning(void)499{500RSDK_THIS(Bumpalo);501502RSDK.ProcessAnimation(&self->badnikAnimator);503504if (self->badnikAnimator.frameID == self->badnikAnimator.frameCount - 1) {505RSDK.SetSpriteAnimation(Bumpalo->aniFrames, 1, &self->badnikAnimator, true, 0);506507self->state = Bumpalo_State_Moving;508self->direction ^= FLIP_X;509self->velocity.x = self->direction == FLIP_NONE ? -0x10000 : 0x10000;510Bumpalo_State_Moving();511}512else {513Bumpalo_CheckPlayerCollisions();514Bumpalo_CheckOffScreen();515}516}517518void Bumpalo_State_Bumped(void)519{520RSDK_THIS(Bumpalo);521522RSDK.ProcessAnimation(&self->badnikAnimator);523524self->position.x += self->velocity.x;525self->position.y += self->velocity.y;526self->velocity.y += 0x3800;527528self->onGround = false;529self->wallCollided = false;530Bumpalo_HandleObjectCollisions();531self->onGround |= RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0xF0000, true);532533if (self->velocity.y >= 0 && self->onGround) {534self->velocity.x = 0;535self->velocity.y = 0;536}537538if (self->badnikAnimator.frameID == self->badnikAnimator.frameCount - 1) {539RSDK.SetSpriteAnimation(Bumpalo->aniFrames, 1, &self->badnikAnimator, true, 0);540if (self->onGround) {541self->velocity.x = self->direction == FLIP_NONE ? -0x10000 : 0x10000;542543if (RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0xF0000, 8)) {544self->state = Bumpalo_State_Moving;545Bumpalo_State_Moving();546}547else {548RSDK.SetSpriteAnimation(Bumpalo->aniFrames, 5, &self->badnikAnimator, true, 0);549self->state = Bumpalo_State_Turning;550Bumpalo_State_Turning();551}552}553else {554self->state = Bumpalo_State_Falling;555Bumpalo_State_Falling();556}557}558else {559Bumpalo_CheckPlayerCollisions();560Bumpalo_CheckOffScreen();561}562}563564void Bumpalo_State_Falling(void)565{566RSDK_THIS(Bumpalo);567568RSDK.ProcessAnimation(&self->badnikAnimator);569570self->position.x += self->velocity.x;571self->position.y += self->velocity.y;572self->velocity.y += 0x3800;573574self->onGround = false;575self->wallCollided = false;576Bumpalo_HandleObjectCollisions();577578self->onGround |= RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0xF0000, true);579if (self->onGround) {580self->velocity.y = 0;581RSDK.PlaySfx(Player->sfxLand, false, 255);582RSDK.SetSpriteAnimation(Bumpalo->aniFrames, 4, &self->badnikAnimator, true, 0);583self->state = Bumpalo_State_Bumped;584}585else {586Bumpalo_CheckPlayerCollisions();587Bumpalo_CheckOffScreen();588}589}590591#if GAME_INCLUDE_EDITOR592void Bumpalo_EditorDraw(void)593{594RSDK_THIS(Bumpalo);595596RSDK.DrawSprite(&self->badnikAnimator, NULL, false);597}598599void Bumpalo_EditorLoad(void)600{601Bumpalo->aniFrames = RSDK.LoadSpriteAnimation("MSZ/Bumpalo.bin", SCOPE_STAGE);602603RSDK_ACTIVE_VAR(Bumpalo, direction);604RSDK_ENUM_VAR("Left", FLIP_NONE);605RSDK_ENUM_VAR("Right", FLIP_X);606}607#endif608609void Bumpalo_Serialize(void)610{611RSDK_EDITABLE_VAR(Bumpalo, VAR_UINT8, direction);612RSDK_EDITABLE_VAR(Bumpalo, VAR_BOOL, ignoreCliffs);613}614615616