Path: blob/master/SonicMania/Objects/FBZ/Blaster.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: Blaster Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectBlaster *Blaster;1011void Blaster_Update(void)12{13RSDK_THIS(Blaster);1415StateMachine_Run(self->state);16}1718void Blaster_LateUpdate(void) {}1920void Blaster_StaticUpdate(void) {}2122void Blaster_Draw(void)23{24RSDK_THIS(Blaster);2526RSDK.DrawSprite(&self->animator, NULL, false);27}2829void Blaster_Create(void *data)30{31RSDK_THIS(Blaster);3233self->visible = true;34self->drawGroup = Zone->objectDrawGroup[0];35self->drawFX |= FX_FLIP;36self->active = ACTIVE_BOUNDS;37self->updateRange.x = 0x800000;38self->updateRange.y = 0x800000;3940if (data) {41if (data == INT_TO_VOID(BLASTER_SHOT)) {42self->active = ACTIVE_NORMAL;43RSDK.SetSpriteAnimation(Blaster->aniFrames, 4, &self->animator, true, 0);44self->state = Blaster_State_BeginShot;45}46else if (data == INT_TO_VOID(BLASTER_SHELL)) {47self->active = ACTIVE_NORMAL;48RSDK.SetSpriteAnimation(Blaster->aniFrames, 5, &self->animator, true, 0);49self->state = Blaster_State_Shell;50}51}52else {53self->startPos = self->position;54self->startDir = self->direction;55RSDK.SetSpriteAnimation(Blaster->aniFrames, 1, &self->animator, true, 0);56self->state = Blaster_State_Init;57}58}5960void Blaster_StageLoad(void)61{62if (RSDK.CheckSceneFolder("FBZ"))63Blaster->aniFrames = RSDK.LoadSpriteAnimation("FBZ/Blaster.bin", SCOPE_STAGE);6465Blaster->hitboxBadnik.left = -16;66Blaster->hitboxBadnik.top = -8;67Blaster->hitboxBadnik.right = 24;68Blaster->hitboxBadnik.bottom = 16;6970Blaster->hitboxRange.left = -128;71Blaster->hitboxRange.top = -128;72Blaster->hitboxRange.right = 0;73Blaster->hitboxRange.bottom = 0;7475Blaster->hitboxProjectile.left = -4;76Blaster->hitboxProjectile.top = -4;77Blaster->hitboxProjectile.right = 4;78Blaster->hitboxProjectile.bottom = 4;7980DEBUGMODE_ADD_OBJ(Blaster);81}8283void Blaster_DebugSpawn(void)84{85RSDK_THIS(Blaster);8687CREATE_ENTITY(Blaster, NULL, self->position.x, self->position.y);88}8990void Blaster_DebugDraw(void)91{92RSDK.SetSpriteAnimation(Blaster->aniFrames, 0, &DebugMode->animator, true, 0);93RSDK.DrawSprite(&DebugMode->animator, NULL, false);94}9596void Blaster_HandlePlayerInteractions(void)97{98RSDK_THIS(Blaster);99100foreach_active(Player, player)101{102if (Player_CheckBadnikTouch(player, self, &Blaster->hitboxBadnik))103Player_CheckBadnikBreak(player, self, true);104105if (self->state != Blaster_State_AttackPlayer && self->state != Blaster_State_Fall && self->animator.animationID != 3) {106if (Player_CheckCollisionTouch(player, self, &Blaster->hitboxRange)) {107self->attackTimer = 0;108RSDK.SetSpriteAnimation(Blaster->aniFrames, 0, &self->animator, true, 0);109self->state = Blaster_State_AttackPlayer;110}111}112}113}114115void Blaster_CheckOffScreen(void)116{117RSDK_THIS(Blaster);118119if (!RSDK.CheckOnScreen(self, NULL) && !RSDK.CheckPosOnScreen(&self->startPos, &self->updateRange)) {120self->position = self->startPos;121self->direction = self->startDir;122Blaster_Create(NULL);123}124}125126void Blaster_State_Init(void)127{128RSDK_THIS(Blaster);129self->active = ACTIVE_NORMAL;130self->velocity.x = self->direction == FLIP_NONE ? -0x8000 : 0x8000;131self->velocity.y = 0;132self->timer = 256;133134self->state = Blaster_State_Move;135Blaster_State_Move();136}137138void Blaster_State_Move(void)139{140RSDK_THIS(Blaster);141142self->position.x += self->velocity.x;143RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0x100000, 8);144145if (!--self->timer) {146self->state = Blaster_State_HandleTurn;147self->timer = 30;148RSDK.SetSpriteAnimation(Blaster->aniFrames, 0, &self->animator, true, 0);149}150else if (self->velocity.x < 0 && !RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, -0xE0000, 0x140000, false)) {151self->state = Blaster_State_HandleTurn;152self->timer = 30;153RSDK.SetSpriteAnimation(Blaster->aniFrames, 0, &self->animator, true, 0);154}155else if (self->velocity.x > 0 && !RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0xE0000, 0x140000, false)) {156self->state = Blaster_State_HandleTurn;157self->timer = 30;158RSDK.SetSpriteAnimation(Blaster->aniFrames, 0, &self->animator, true, 0);159}160161RSDK.ProcessAnimation(&self->animator);162163Blaster_HandlePlayerInteractions();164Blaster_CheckOffScreen();165}166167void Blaster_State_HandleTurn(void)168{169RSDK_THIS(Blaster);170171RSDK.ProcessAnimation(&self->animator);172Blaster_HandlePlayerInteractions();173Blaster_CheckOffScreen();174175switch (--self->timer) {176case 15: RSDK.SetSpriteAnimation(Blaster->aniFrames, 3, &self->animator, true, 0); break;177178case 7:179self->direction ^= FLIP_X;180self->velocity.x = -self->velocity.x;181break;182183case 0:184self->state = Blaster_State_Move;185self->timer = 512;186Blaster_State_Move();187RSDK.SetSpriteAnimation(Blaster->aniFrames, 1, &self->animator, true, 0);188break;189}190}191192void Blaster_State_AttackPlayer(void)193{194RSDK_THIS(Blaster);195196switch (++self->attackTimer) {197case 18: {198EntityBlaster *shot = NULL;199if (self->direction) {200shot = CREATE_ENTITY(Blaster, INT_TO_VOID(BLASTER_SHOT), self->position.x + 0x170000, self->position.y - 0x150000);201shot->velocity.x = 0x20000;202}203else {204shot = CREATE_ENTITY(Blaster, INT_TO_VOID(BLASTER_SHOT), self->position.x - 0x170000, self->position.y - 0x150000);205shot->velocity.x = -0x20000;206}207shot->velocity.y = -0x48000;208break;209}210211case 20: RSDK.SetSpriteAnimation(Blaster->aniFrames, 2, &self->animator, true, 0); break;212213case 24: {214EntityBlaster *shell = NULL;215if (self->direction) {216shell = CREATE_ENTITY(Blaster, INT_TO_VOID(BLASTER_SHELL), self->position.x + 0x60000, self->position.y - 0x30000);217shell->velocity.x = -0x10000;218}219else {220shell = CREATE_ENTITY(Blaster, INT_TO_VOID(BLASTER_SHELL), self->position.x - 0x60000, self->position.y - 0x30000);221shell->velocity.x = 0x10000;222}223shell->velocity.y = -0x20000;224break;225}226227case 60:228RSDK.SetSpriteAnimation(Blaster->aniFrames, 1, &self->animator, true, 0);229self->state = Blaster_State_Move;230self->timer = 512;231break;232233default: break;234}235236RSDK.ProcessAnimation(&self->animator);237238Blaster_HandlePlayerInteractions();239Blaster_CheckOffScreen();240}241242void Blaster_State_MagnetAttract(void)243{244RSDK_THIS(Blaster);245246self->position.y += self->velocity.y;247self->velocity.y -= 0x3800;248if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_ROOF, 0, 0, -0xC0000, 8))249self->velocity.y = 0;250251Blaster_HandlePlayerInteractions();252253if (!RSDK.CheckOnScreen(self, NULL)) {254Blaster_CheckOffScreen();255}256257// Always set us to released state, the electro magnet should reset the state before the next frame258self->state = Blaster_State_MagnetReleased;259}260261void Blaster_State_MagnetReleased(void)262{263RSDK_THIS(Blaster);264265self->position.y += self->velocity.y;266self->velocity.y += 0x3800;267268Blaster_HandlePlayerInteractions();269Blaster_CheckOffScreen();270271if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0x100000, 8)) {272self->velocity.y = 0;273self->state = Blaster_State_Move;274}275else {276self->state = Blaster_State_MagnetReleased;277}278}279280void Blaster_State_BeginShot(void)281{282RSDK_THIS(Blaster);283284RSDK.ProcessAnimation(&self->animator);285286if (self->animator.frameID == 2)287self->state = Blaster_State_Shot;288}289290void Blaster_State_Shot(void)291{292RSDK_THIS(Blaster);293294self->position.x += self->velocity.x;295self->position.y += self->velocity.y;296self->velocity.y += 0x3800;297298if (RSDK.CheckOnScreen(self, &self->updateRange)) {299RSDK.ProcessAnimation(&self->animator);300foreach_active(Player, player)301{302if (Player_CheckCollisionTouch(player, self, &Blaster->hitboxProjectile)) {303Player_ProjectileHurt(player, self);304}305}306}307else {308destroyEntity(self);309}310}311312void Blaster_State_Fall(void)313{314RSDK_THIS(Blaster);315316self->position.x += self->velocity.x;317self->position.y += self->velocity.y;318self->velocity.y += 0x3800;319320if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0x100000, 8)) {321self->startPos.x = self->position.x;322self->startPos.y = self->position.y;323self->direction = self->direction;324self->velocity.y = 0;325self->state = Blaster_State_Init;326}327328Blaster_HandlePlayerInteractions();329}330331void Blaster_State_Shell(void)332{333RSDK_THIS(Blaster);334335self->position.x += self->velocity.x;336self->position.y += self->velocity.y;337self->velocity.y += 0x3800;338339RSDK.ProcessAnimation(&self->animator);340341if (!RSDK.CheckOnScreen(self, &self->updateRange))342destroyEntity(self);343}344345#if GAME_INCLUDE_EDITOR346void Blaster_EditorDraw(void)347{348RSDK_THIS(Blaster);349350RSDK.SetSpriteAnimation(Blaster->aniFrames, 1, &self->animator, true, 0);351352Blaster_Draw();353}354355void Blaster_EditorLoad(void)356{357Blaster->aniFrames = RSDK.LoadSpriteAnimation("FBZ/Blaster.bin", SCOPE_STAGE);358359RSDK_ACTIVE_VAR(Blaster, direction);360RSDK_ENUM_VAR("Left", FLIP_NONE);361RSDK_ENUM_VAR("Right", FLIP_X);362}363#endif364365void Blaster_Serialize(void) { RSDK_EDITABLE_VAR(Blaster, VAR_UINT8, direction); }366367368