Path: blob/master/SonicMania/Objects/FBZ/Clucker.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: Clucker Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectClucker *Clucker;1011void Clucker_Update(void)12{13RSDK_THIS(Clucker);14StateMachine_Run(self->state);15}1617void Clucker_LateUpdate(void) {}1819void Clucker_StaticUpdate(void) {}2021void Clucker_Draw(void)22{23RSDK_THIS(Clucker);24Vector2 drawPos;2526if (self->state == Clucker_State_Egg) {27RSDK.DrawSprite(&self->animator, NULL, false);28}29else {30drawPos.x = self->position.x;31drawPos.y = self->position.y;32if (self->direction & FLIP_Y)33drawPos.y -= self->yOffset;34else35drawPos.y += self->yOffset;3637if (self->state != Clucker_State_Turn) {38if (self->yOffset == -0x180000) {39if (self->direction & FLIP_X)40drawPos.x -= self->xOffset;41else42drawPos.x += self->xOffset;4344self->animator.frameID = 2;45RSDK.DrawSprite(&self->animator, &drawPos, false);4647if (self->direction & FLIP_X)48drawPos.x += self->xOffset;49else50drawPos.x -= self->xOffset;51}52RSDK.GetFrame(Clucker->aniFrames, 0, 1)->height = 9 - (self->yOffset >> 16);53self->animator.frameID = 1;54}55RSDK.DrawSprite(&self->animator, &drawPos, false);5657if (!self->hasParent) {58int32 frame = self->animator.frameID;59self->animator.frameID = 0;60RSDK.DrawSprite(&self->animator, NULL, false);61self->animator.frameID = frame;62}63}64}6566void Clucker_Create(void *data)67{68RSDK_THIS(Clucker);6970self->drawFX = FX_FLIP;71if (!SceneInfo->inEditor) {72EntityPlatform *platform = RSDK_GET_ENTITY(SceneInfo->entitySlot - 1, Platform);73if (platform->classID == Platform->classID) {74if (platform->childCount > 0)75self->hasParent = true;76}77else {78self->direction *= FLIP_Y;79}8081self->visible = true;82self->active = ACTIVE_BOUNDS;8384if (data) {85self->drawGroup = Zone->objectDrawGroup[0];86self->updateRange.x = 0x400000;87self->updateRange.y = 0x400000;88self->active = ACTIVE_NORMAL;89RSDK.SetSpriteAnimation(Clucker->aniFrames, 1, &self->animator, true, 0);90self->state = Clucker_State_Egg;91}92else {93self->updateRange.x = 0x800000;94self->updateRange.y = 0x800000;95self->drawGroup = Zone->objectDrawGroup[0] + 1;96if (!self->delay)97self->delay = 68;98RSDK.SetSpriteAnimation(Clucker->aniFrames, 0, &self->animator, true, 0);99self->state = Clucker_State_Init;100}101}102}103104void Clucker_StageLoad(void)105{106Clucker->aniFrames = RSDK.LoadSpriteAnimation("FBZ/Clucker.bin", SCOPE_STAGE);107108Clucker->hitboxBadnik.left = -16;109Clucker->hitboxBadnik.top = -8;110Clucker->hitboxBadnik.right = 16;111Clucker->hitboxBadnik.bottom = 8;112113Clucker->hitboxRange.left = -128;114Clucker->hitboxRange.top = -256;115Clucker->hitboxRange.right = 128;116Clucker->hitboxRange.bottom = 32;117118Clucker->hitboxSolid.left = -16;119Clucker->hitboxSolid.top = -8;120Clucker->hitboxSolid.right = 16;121Clucker->hitboxSolid.bottom = 8;122123Clucker->hitboxEgg.left = -4;124Clucker->hitboxEgg.top = -4;125Clucker->hitboxEgg.right = 4;126Clucker->hitboxEgg.bottom = 4;127128Clucker->sfxShot = RSDK.GetSfx("Stage/Shot.wav");129130DEBUGMODE_ADD_OBJ(Clucker);131}132133void Clucker_DebugSpawn(void)134{135RSDK_THIS(Clucker);136CREATE_ENTITY(Clucker, NULL, self->position.x, self->position.y);137}138139void Clucker_DebugDraw(void)140{141RSDK.SetSpriteAnimation(Clucker->aniFrames, 0, &DebugMode->animator, true, 0);142RSDK.DrawSprite(&DebugMode->animator, NULL, false);143}144145void Clucker_HandlePlayerInteractions(void)146{147RSDK_THIS(Clucker);148int32 posY = self->position.y;149150foreach_active(Player, player)151{152if (!self->hasParent)153Player_CheckCollisionBox(player, self, &Clucker->hitboxSolid);154155if ((self->direction & FLIP_Y))156self->position.y -= self->yOffset;157else158self->position.y += self->yOffset;159160if (Player_CheckBadnikTouch(player, self, &Clucker->hitboxBadnik)) {161if (self->hasParent) {162Player_CheckBadnikBreak(player, self, true);163}164else if (Player_CheckBadnikBreak(player, self, false)) {165self->yOffset = -0x7FFFFFFF;166self->state = Clucker_State_Destroyed;167}168}169170self->position.y = posY;171}172}173174void Clucker_CheckOffScreen(void)175{176RSDK_THIS(Clucker);177178if (!RSDK.CheckOnScreen(self, &self->updateRange)) {179self->direction = self->direction >> 1;180Clucker_Create(NULL);181}182}183184void Clucker_State_Init(void)185{186RSDK_THIS(Clucker);187188self->active = ACTIVE_NORMAL;189if (!self->hasParent) {190self->yOffset = 0x80000;191self->xOffset = 0x80000;192self->state = Clucker_State_CheckForPlayer;193Clucker_State_CheckForPlayer();194}195else {196self->yOffset = -0x180000;197self->xOffset = 0;198self->state = Clucker_State_Shoot;199Clucker_State_Shoot();200}201}202203void Clucker_State_CheckForPlayer(void)204{205RSDK_THIS(Clucker);206207foreach_active(Player, player)208{209if (Player_CheckCollisionTouch(player, self, &Clucker->hitboxRange)) {210if (player->position.x >= self->position.x)211self->direction |= FLIP_X;212else213self->direction &= ~FLIP_X;214215self->state = Clucker_State_Appear;216}217}218Clucker_CheckOffScreen();219}220221void Clucker_State_Appear(void)222{223RSDK_THIS(Clucker);224225self->yOffset -= 0x20000;226if (self->yOffset == -0x180000)227self->state = Clucker_State_ShootDelay;228229Clucker_HandlePlayerInteractions();230Clucker_CheckOffScreen();231}232233void Clucker_State_ShootDelay(void)234{235RSDK_THIS(Clucker);236237self->xOffset -= 0x10000;238if (!self->xOffset) {239self->timer = 14;240self->state = Clucker_State_Shoot;241}242243Clucker_HandlePlayerInteractions();244Clucker_CheckOffScreen();245}246247void Clucker_State_Shoot(void)248{249RSDK_THIS(Clucker);250251--self->timer;252if (self->timer == 4) {253self->xOffset += 0x20000;254}255else if (!self->timer) {256self->xOffset -= 0x20000;257int32 spawnY = self->position.y;258if (self->direction & FLIP_Y)259spawnY += 0xD0000;260else261spawnY -= 0xD0000;262263EntityClucker *projectile = CREATE_ENTITY(Clucker, INT_TO_VOID(true), self->position.x, spawnY);264if (self->direction & FLIP_X) {265projectile->position.x += 0x100000;266projectile->velocity.x = 0x20000;267}268else {269projectile->position.x -= 0x100000;270projectile->velocity.x = -0x20000;271}272projectile->direction = self->direction;273274self->timer = self->delay;275RSDK.PlaySfx(Clucker->sfxShot, false, 255);276}277278EntityPlayer *player = Player_GetNearestPlayer();279if (player) {280if (player->position.x >= self->position.x) {281if (!(self->direction & FLIP_X)) {282RSDK.SetSpriteAnimation(Clucker->aniFrames, 2, &self->animator, true, 1);283self->state = Clucker_State_Turn;284self->timer = 68;285}286}287else if ((self->direction & FLIP_X)) {288RSDK.SetSpriteAnimation(Clucker->aniFrames, 2, &self->animator, true, 1);289self->state = Clucker_State_Turn;290self->timer = 68;291}292}293294Clucker_HandlePlayerInteractions();295Clucker_CheckOffScreen();296}297298void Clucker_State_Turn(void)299{300RSDK_THIS(Clucker);301302RSDK.ProcessAnimation(&self->animator);303304if (self->animator.frameID == self->animator.frameCount - 1) {305self->direction ^= FLIP_X;306RSDK.SetSpriteAnimation(Clucker->aniFrames, 0, &self->animator, true, 1);307self->state = Clucker_State_Shoot;308}309310Clucker_HandlePlayerInteractions();311Clucker_CheckOffScreen();312}313314void Clucker_State_Destroyed(void)315{316RSDK_THIS(Clucker);317318EntityPlatform *platform = RSDK_GET_ENTITY(SceneInfo->entitySlot - 1, Platform);319int32 offsetX = 0;320int32 offsetY = 0;321if (platform->classID == Platform->classID) {322offsetX = platform->collisionOffset.x;323offsetY = platform->collisionOffset.y;324}325326foreach_active(Player, player)327{328if (Player_CheckCollisionBox(player, self, &Clucker->hitboxSolid)) {329player->position.x += offsetX;330player->position.y += offsetY;331}332}333}334335void Clucker_State_Egg(void)336{337RSDK_THIS(Clucker);338339self->position.x += self->velocity.x;340self->position.y += self->velocity.y;341342if (RSDK.CheckOnScreen(self, NULL)) {343RSDK.ProcessAnimation(&self->animator);344345foreach_active(Player, player)346{347if (Player_CheckCollisionTouch(player, self, &Clucker->hitboxEgg))348Player_ProjectileHurt(player, self);349}350351if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0, false))352destroyEntity(self);353}354else {355destroyEntity(self);356}357}358359#if GAME_INCLUDE_EDITOR360void Clucker_EditorDraw(void)361{362RSDK_THIS(Clucker);363RSDK.SetSpriteAnimation(Clucker->aniFrames, 0, &self->animator, true, 0);364365self->yOffset = -0x180000;366int32 dir = self->direction;367self->direction *= FLIP_Y;368Clucker_Draw();369self->direction = dir;370}371372void Clucker_EditorLoad(void)373{374Clucker->aniFrames = RSDK.LoadSpriteAnimation("FBZ/Clucker.bin", SCOPE_STAGE);375376RSDK_ACTIVE_VAR(Clucker, direction);377RSDK_ENUM_VAR("Rightside Up", FLIP_NONE);378RSDK_ENUM_VAR("Upside Down", FLIP_X);379}380#endif381382void Clucker_Serialize(void)383{384RSDK_EDITABLE_VAR(Clucker, VAR_UINT8, direction);385RSDK_EDITABLE_VAR(Clucker, VAR_UINT16, delay);386}387388389