Path: blob/master/SonicMania/Objects/HCZ/TurboSpiker.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: TurboSpiker Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectTurboSpiker *TurboSpiker;1011// back in 3mixed, i was assigned this object12// i was never able to get it properly working13// here it is. :smirk2: -rmg14// hello rmg, this is rdc. there were MULTIPLE easy to find/fix bugs here so don't u dare smirk1516void TurboSpiker_Update(void)17{18RSDK_THIS(TurboSpiker);1920StateMachine_Run(self->state);21}2223void TurboSpiker_LateUpdate(void) {}2425void TurboSpiker_StaticUpdate(void) {}2627void TurboSpiker_Draw(void)28{29RSDK_THIS(TurboSpiker);3031RSDK.DrawSprite(&self->shellAnimator, NULL, false);32RSDK.DrawSprite(&self->animator, NULL, false);33}3435void TurboSpiker_Create(void *data)36{37RSDK_THIS(TurboSpiker);3839self->playedLaunchSfx = false;40self->visible = true;41self->drawFX |= FX_FLIP;42self->drawGroup = Zone->objectDrawGroup[0] + 1;43self->startPos = self->position;44self->active = ACTIVE_BOUNDS;45self->updateRange.x = 0x800000;46self->updateRange.y = 0x800000;47self->startDir = self->direction;4849if (data) {50self->active = ACTIVE_NORMAL;51}52else {53self->unused = 16;54RSDK.SetSpriteAnimation(TurboSpiker->aniFrames, 1, &self->shellAnimator, true, 0);55self->state = TurboSpiker_State_Init;56}57}5859void TurboSpiker_StageLoad(void)60{61if (RSDK.CheckSceneFolder("HCZ"))62TurboSpiker->aniFrames = RSDK.LoadSpriteAnimation("HCZ/TurboSpiker.bin", SCOPE_STAGE);6364TurboSpiker->hitboxBadnik.left = -14;65TurboSpiker->hitboxBadnik.top = -14;66TurboSpiker->hitboxBadnik.right = 14;67TurboSpiker->hitboxBadnik.bottom = 14;6869TurboSpiker->hitboxSpike.left = -5;70TurboSpiker->hitboxSpike.top = -31;71TurboSpiker->hitboxSpike.right = 9;72TurboSpiker->hitboxSpike.bottom = 2;7374TurboSpiker->hitboxRange.left = -128;75TurboSpiker->hitboxRange.top = -512;76TurboSpiker->hitboxRange.right = 128;77TurboSpiker->hitboxRange.bottom = 512;7879TurboSpiker->sfxLaunch = RSDK.GetSfx("Stage/Launch.wav");80TurboSpiker->sfxSplash = RSDK.GetSfx("Stage/Splash.wav");8182DEBUGMODE_ADD_OBJ(TurboSpiker);83}8485void TurboSpiker_DebugDraw(void)86{87RSDK.SetSpriteAnimation(TurboSpiker->aniFrames, 0, &DebugMode->animator, true, 0);88RSDK.DrawSprite(&DebugMode->animator, NULL, false);89}9091void TurboSpiker_DebugSpawn(void)92{93RSDK_THIS(TurboSpiker);94CREATE_ENTITY(TurboSpiker, NULL, self->position.x, self->position.y);95}9697void TurboSpiker_Hermit_Collide(void)98{99RSDK_THIS(TurboSpiker);100foreach_active(Player, player)101{102if (Player_CheckBadnikTouch(player, self, &TurboSpiker->hitboxBadnik) && Player_CheckBadnikBreak(player, self, false)) {103if (self->spike)104destroyEntity(self->spike);105106destroyEntity(self);107}108}109}110111void TurboSpiker_Hermit_CheckOffScreen(void)112{113RSDK_THIS(TurboSpiker);114if (!RSDK.CheckOnScreen(self, NULL) && !RSDK.CheckPosOnScreen(&self->startPos, &self->updateRange)) {115self->position.x = self->startPos.x;116self->position.y = self->startPos.y;117if (self->spike)118destroyEntity(self->spike);119120self->direction = self->startDir;121TurboSpiker_Create(NULL);122}123}124125void TurboSpiker_HandleMovement(void)126{127RSDK_THIS(TurboSpiker);128129self->position.x += self->velocity.x;130131if (!RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0x80000, 8)) {132RSDK.SetSpriteAnimation(TurboSpiker->aniFrames, 1, &self->shellAnimator, true, 0);133self->timer = 0;134if (RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0x20000 * (self->direction ? -1 : 1), 0x80000, 8))135self->state = TurboSpiker_State_Turning;136else137self->state = TurboSpiker_State_Falling;138}139}140141void TurboSpiker_State_Init(void)142{143RSDK_THIS(TurboSpiker);144145self->active = ACTIVE_NORMAL;146147if (self->type == TURBOSPIKER_HIDDEN) {148RSDK.SetSpriteAnimation(TurboSpiker->aniFrames, 1, &self->animator, true, 0);149RSDK.SetSpriteAnimation(TurboSpiker->aniFrames, 3, &self->shellAnimator, true, 0);150self->drawGroup = Zone->fgDrawGroup[0] + 1;151if (Player_GetNearestPlayer())152self->direction = Player_GetNearestPlayer()->position.x >= self->position.x;153}154155EntityTurboSpiker *spike = CREATE_ENTITY(TurboSpiker, INT_TO_VOID(true), self->position.x, self->position.y);156spike->isPermanent = true;157spike->direction = self->direction;158spike->drawGroup = self->drawGroup - 1;159RSDK.SetSpriteAnimation(TurboSpiker->aniFrames, 3, &spike->shellAnimator, true, 0);160spike->state = TurboSpiker_HandleSpikeCollisions;161self->spike = spike;162163if (self->type == TURBOSPIKER_VISIBLE) {164self->timer = 64;165self->state = TurboSpiker_State_Idle;166self->velocity.x = 0x10000 * (self->direction ? 1 : -1);167TurboSpiker_State_Idle();168self->velocity.y = 0;169}170else {171self->state = TurboSpiker_State_Hidden;172TurboSpiker_State_Hidden();173self->velocity.y = 0;174}175}176void TurboSpiker_State_Idle(void)177{178RSDK_THIS(TurboSpiker);179180foreach_active(Player, player)181{182if (Player_CheckCollisionTouch(player, self, &TurboSpiker->hitboxRange)) {183self->timer = 1;184self->state = TurboSpiker_State_FireShell;185TurboSpiker_Hermit_Collide();186TurboSpiker_Hermit_CheckOffScreen();187foreach_return;188}189}190191TurboSpiker_HandleMovement();192193if (self->spike) {194self->spike->position.x = self->position.x;195self->spike->position.y = self->position.y;196}197198if (self->state == TurboSpiker_State_Idle && !--self->timer) {199RSDK.SetSpriteAnimation(TurboSpiker->aniFrames, 1, &self->shellAnimator, true, 0);200self->timer = 0;201self->state = TurboSpiker_State_Turning;202}203204RSDK.ProcessAnimation(&self->shellAnimator);205TurboSpiker_Hermit_Collide();206TurboSpiker_Hermit_CheckOffScreen();207}208209void TurboSpiker_State_Hidden(void)210{211RSDK_THIS(TurboSpiker);212213foreach_active(Player, player)214{215if (Player_CheckCollisionTouch(player, self, &TurboSpiker->hitboxRange)) {216CREATE_ENTITY(Water, INT_TO_VOID(WATER_SPLASH), self->position.x, self->position.y + 0x80000)->childPtr = INT_TO_VOID(true);217RSDK.PlaySfx(TurboSpiker->sfxSplash, false, 0xFF);218RSDK.SetSpriteAnimation(-1, 0, &self->animator, true, 0);219RSDK.SetSpriteAnimation(TurboSpiker->aniFrames, 1, &self->shellAnimator, true, 0);220self->drawGroup = Zone->objectDrawGroup[0] + 1;221if (self->spike)222self->spike->drawGroup = Zone->objectDrawGroup[0];223224EntityTurboSpiker *ember = CREATE_ENTITY(TurboSpiker, INT_TO_VOID(true), self->position.x, self->position.y);225ember->direction = self->direction;226ember->drawGroup = self->drawGroup + 1;227RSDK.SetSpriteAnimation(TurboSpiker->aniFrames, 6, &ember->shellAnimator, true, 0);228ember->state = TurboSpiker_State_Ember;229self->timer = 60;230self->state = TurboSpiker_State_FireShell;231TurboSpiker_State_FireShell();232foreach_return;233}234}235236RSDK.ProcessAnimation(&self->animator);237TurboSpiker_Hermit_Collide();238TurboSpiker_Hermit_CheckOffScreen();239}240241void TurboSpiker_State_Moving(void)242{243RSDK_THIS(TurboSpiker);244245TurboSpiker_HandleMovement();246247if (self->spike) {248self->spike->position.x = self->position.x;249self->spike->position.y = self->position.y;250}251252RSDK.ProcessAnimation(&self->shellAnimator);253TurboSpiker_Hermit_Collide();254TurboSpiker_Hermit_CheckOffScreen();255}256257void TurboSpiker_State_Turning(void)258{259RSDK_THIS(TurboSpiker);260RSDK.ProcessAnimation(&self->shellAnimator);261262if (++self->timer == 15) {263RSDK.SetSpriteAnimation(TurboSpiker->aniFrames, 2, &self->shellAnimator, true, 0);264self->state = TurboSpiker_State_FinishTurning;265}266267TurboSpiker_Hermit_Collide();268TurboSpiker_Hermit_CheckOffScreen();269}270271void TurboSpiker_State_FinishTurning(void)272{273RSDK_THIS(TurboSpiker);274275RSDK.ProcessAnimation(&self->shellAnimator);276277if (self->shellAnimator.frameID == self->shellAnimator.frameCount - 1) {278RSDK.SetSpriteAnimation(TurboSpiker->aniFrames, 0, &self->shellAnimator, true, 0);279self->direction ^= FLIP_X;280self->velocity.x = -self->velocity.x;281282if (self->spike) {283self->spike->direction = self->direction;284self->timer = 128;285self->state = TurboSpiker_State_Idle;286TurboSpiker_State_Idle();287}288else {289self->state = TurboSpiker_State_Moving;290TurboSpiker_State_Moving();291}292}293else {294TurboSpiker_Hermit_Collide();295TurboSpiker_Hermit_CheckOffScreen();296}297}298299void TurboSpiker_State_Falling(void)300{301RSDK_THIS(TurboSpiker);302303RSDK.ProcessAnimation(&self->shellAnimator);304305self->position.x += self->velocity.x;306self->position.y += self->velocity.y;307self->velocity.y += 0x3800;308309if (self->spike) {310self->spike->position.x = self->position.x;311self->spike->position.y = self->position.y;312}313314if (RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0x80000, 8)) {315self->velocity.y = 0;316RSDK.SetSpriteAnimation(TurboSpiker->aniFrames, 0, &self->shellAnimator, true, 0);317self->state = TurboSpiker_State_Moving;318TurboSpiker_State_Moving();319}320else {321TurboSpiker_Hermit_Collide();322TurboSpiker_Hermit_CheckOffScreen();323}324}325326void TurboSpiker_State_FireShell(void)327{328RSDK_THIS(TurboSpiker);329330if (!--self->timer) {331if (Player_GetNearestPlayer())332self->direction = Player_GetNearestPlayer()->position.x < self->position.x;333334if (self->spike) {335RSDK.PlaySfx(TurboSpiker->sfxLaunch, false, 0xFF);336RSDK.SetSpriteAnimation(TurboSpiker->aniFrames, 4, &self->spike->animator, true, 0);337self->spike->direction = self->direction;338self->spike->velocity.x = 0x14000 * (self->direction ? -1 : 1);339self->spike->velocity.y = -0x30000;340self->spike->state = TurboSpiker_State_Spike;341self->spike = NULL;342}343344self->velocity.x = 0x20000 * (self->direction ? 1 : -1);345RSDK.SetSpriteAnimation(TurboSpiker->aniFrames, 0, &self->shellAnimator, true, 0);346self->state = TurboSpiker_State_Moving;347self->shellAnimator.speed = 2;348TurboSpiker_HandleMovement();349}350351RSDK.ProcessAnimation(&self->shellAnimator);352353TurboSpiker_Hermit_Collide();354TurboSpiker_Hermit_CheckOffScreen();355}356357void TurboSpiker_HandleSpikeCollisions(void)358{359RSDK_THIS(TurboSpiker);360361foreach_active(Player, player)362{363if (Player_CheckCollisionTouch(player, self, &TurboSpiker->hitboxSpike)) {364#if MANIA_USE_PLUS365if (!Player_CheckMightyUnspin(player, 0x400, 2, &player->uncurlTimer))366#endif367Player_Hurt(player, self);368}369}370}371372void TurboSpiker_State_Spike(void)373{374RSDK_THIS(TurboSpiker);375376if (!self->playedLaunchSfx) {377RSDK.PlaySfx(TurboSpiker->sfxLaunch, false, 0xFF);378self->playedLaunchSfx = true;379}380381if (!self->onScreen) {382RSDK.StopSfx(TurboSpiker->sfxLaunch);383self->playedLaunchSfx = false;384}385386self->position.x += self->velocity.x;387self->position.y += self->velocity.y;388TurboSpiker_HandleSpikeCollisions();389390if (!(Zone->timer & 3)) {391int32 x = self->position.x + (RSDK.Rand(-4, 4) << 16);392int32 y = self->position.y + (RSDK.Rand(-2, 3) << 16);393EntityTurboSpiker *ember = CREATE_ENTITY(TurboSpiker, INT_TO_VOID(true), x, y);394ember->direction = self->direction;395ember->drawGroup = self->drawGroup - 1;396RSDK.SetSpriteAnimation(TurboSpiker->aniFrames, 5, &ember->shellAnimator, true, 0);397ember->state = TurboSpiker_State_Ember;398}399400RSDK.ProcessAnimation(&self->animator);401if (!RSDK.CheckOnScreen(self, NULL))402destroyEntity(self);403}404405void TurboSpiker_State_Ember(void)406{407RSDK_THIS(TurboSpiker);408409RSDK.ProcessAnimation(&self->shellAnimator);410if (self->shellAnimator.frameID == self->shellAnimator.frameCount - 1)411destroyEntity(self);412}413414#if GAME_INCLUDE_EDITOR415void TurboSpiker_EditorDraw(void)416{417RSDK_THIS(TurboSpiker);418419RSDK.SetSpriteAnimation(TurboSpiker->aniFrames, 1, &self->animator, true, 0);420RSDK.SetSpriteAnimation(self->type == TURBOSPIKER_VISIBLE ? TurboSpiker->aniFrames : -1, 3, &self->shellAnimator, true, 0);421422RSDK.DrawSprite(&self->shellAnimator, NULL, false);423RSDK.DrawSprite(&self->animator, NULL, false);424}425426void TurboSpiker_EditorLoad(void)427{428TurboSpiker->aniFrames = RSDK.LoadSpriteAnimation("HCZ/TurboSpiker.bin", SCOPE_STAGE);429430RSDK_ACTIVE_VAR(TurboSpiker, type);431RSDK_ENUM_VAR("Always Visible", TURBOSPIKER_VISIBLE);432RSDK_ENUM_VAR("Hidden Behind Waterfall", TURBOSPIKER_HIDDEN);433434RSDK_ACTIVE_VAR(TurboSpiker, direction);435RSDK_ENUM_VAR("Left", FLIP_NONE);436RSDK_ENUM_VAR("Right", FLIP_X);437}438#endif439440void TurboSpiker_Serialize(void)441{442RSDK_EDITABLE_VAR(TurboSpiker, VAR_ENUM, type);443RSDK_EDITABLE_VAR(TurboSpiker, VAR_UINT8, direction);444}445446